Changed old event definitions reference to these new event definitions. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2729 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			3151 lines
		
	
	
		
			100 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3151 lines
		
	
	
		
			100 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**@file
 | 
						|
  Implementation for UI.
 | 
						|
 | 
						|
Copyright (c) 2006 - 2007, 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.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "Setup.h"
 | 
						|
#include "Ui.h"
 | 
						|
#include "Colors.h"
 | 
						|
 | 
						|
//
 | 
						|
// Implementation
 | 
						|
//
 | 
						|
VOID
 | 
						|
SetUnicodeMem (
 | 
						|
  IN VOID   *Buffer,
 | 
						|
  IN UINTN  Size,
 | 
						|
  IN CHAR16 Value
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Set Buffer to Value for Size bytes.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Buffer  - Memory to set.
 | 
						|
 | 
						|
  Size    - Number of bytes to set
 | 
						|
 | 
						|
  Value   - Value of the set operation.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  CHAR16  *Ptr;
 | 
						|
 | 
						|
  Ptr = Buffer;
 | 
						|
  while (Size--) {
 | 
						|
    *(Ptr++) = Value;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
UiInitMenu (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Initialize Menu option list.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  InitializeListHead (&Menu);
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
UiInitMenuList (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Initialize Menu option list.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  InitializeListHead (&gMenuList);
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
UiRemoveMenuListEntry (
 | 
						|
  IN  UI_MENU_OPTION    *Selection,
 | 
						|
  OUT UI_MENU_OPTION    **PreviousSelection
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Remove Menu option list.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UI_MENU_LIST  *UiMenuList;
 | 
						|
 | 
						|
  *PreviousSelection = AllocateZeroPool (sizeof (UI_MENU_OPTION));
 | 
						|
  ASSERT (*PreviousSelection != NULL);
 | 
						|
 | 
						|
  if (!IsListEmpty (&gMenuList)) {
 | 
						|
    UiMenuList                      = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
 | 
						|
    (*PreviousSelection)->IfrNumber = UiMenuList->Selection.IfrNumber;
 | 
						|
    (*PreviousSelection)->FormId    = UiMenuList->Selection.FormId;
 | 
						|
    (*PreviousSelection)->Tags      = UiMenuList->Selection.Tags;
 | 
						|
    (*PreviousSelection)->ThisTag   = UiMenuList->Selection.ThisTag;
 | 
						|
    (*PreviousSelection)->Handle    = UiMenuList->Selection.Handle;
 | 
						|
    gEntryNumber                    = UiMenuList->FormerEntryNumber;
 | 
						|
    RemoveEntryList (&UiMenuList->MenuLink);
 | 
						|
    FreePool (UiMenuList);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
UiFreeMenuList (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Free Menu option linked list.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UI_MENU_LIST  *UiMenuList;
 | 
						|
 | 
						|
  while (!IsListEmpty (&gMenuList)) {
 | 
						|
    UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
 | 
						|
    RemoveEntryList (&UiMenuList->MenuLink);
 | 
						|
    FreePool (UiMenuList);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
UiAddMenuListEntry (
 | 
						|
  IN UI_MENU_OPTION   *Selection
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Add one menu entry to the linked lst
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UI_MENU_LIST  *UiMenuList;
 | 
						|
 | 
						|
  UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));
 | 
						|
  ASSERT (UiMenuList != NULL);
 | 
						|
 | 
						|
  UiMenuList->Signature = UI_MENU_LIST_SIGNATURE;
 | 
						|
  CopyMem (&UiMenuList->Selection, Selection, sizeof (UI_MENU_OPTION));
 | 
						|
 | 
						|
  InsertHeadList (&gMenuList, &UiMenuList->MenuLink);
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
UiFreeMenu (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Free Menu option linked list.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UI_MENU_OPTION  *MenuOption;
 | 
						|
 | 
						|
  while (!IsListEmpty (&Menu)) {
 | 
						|
    MenuOption = CR (Menu.ForwardLink, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
    RemoveEntryList (&MenuOption->Link);
 | 
						|
 | 
						|
    //
 | 
						|
    // We allocated space for this description when we did a GetToken, free it here
 | 
						|
    //
 | 
						|
    FreePool (MenuOption->Description);
 | 
						|
    FreePool (MenuOption);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
UpdateDateAndTime (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Refresh screen with current date and/or time based on screen context
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  CHAR16              *OptionString;
 | 
						|
  MENU_REFRESH_ENTRY  *MenuRefreshEntry;
 | 
						|
  UINTN               Index;
 | 
						|
  UINTN               Loop;
 | 
						|
 | 
						|
  OptionString = NULL;
 | 
						|
 | 
						|
  if (gMenuRefreshHead != NULL) {
 | 
						|
 | 
						|
    MenuRefreshEntry = gMenuRefreshHead;
 | 
						|
 | 
						|
    do {
 | 
						|
      gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);
 | 
						|
      ProcessOptions (MenuRefreshEntry->MenuOption, FALSE, MenuRefreshEntry->FileFormTagsHead, NULL, &OptionString);
 | 
						|
 | 
						|
      if (OptionString != NULL) {
 | 
						|
        //
 | 
						|
        // If leading spaces on OptionString - remove the spaces
 | 
						|
        //
 | 
						|
        for (Index = 0; OptionString[Index] == L' '; Index++)
 | 
						|
          ;
 | 
						|
 | 
						|
        for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) {
 | 
						|
          OptionString[Loop] = OptionString[Index];
 | 
						|
          Loop++;
 | 
						|
        }
 | 
						|
 | 
						|
        OptionString[Loop] = CHAR_NULL;
 | 
						|
 | 
						|
        PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString);
 | 
						|
      }
 | 
						|
 | 
						|
      MenuRefreshEntry = MenuRefreshEntry->Next;
 | 
						|
 | 
						|
    } while (MenuRefreshEntry != NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  if (OptionString != NULL) {
 | 
						|
    FreePool (OptionString);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
UiWaitForSingleEvent (
 | 
						|
  IN EFI_EVENT                Event,
 | 
						|
  IN UINT64                   Timeout OPTIONAL
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Wait for a given event to fire, or for an optional timeout to expire.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Event            - The event to wait for
 | 
						|
 | 
						|
  Timeout          - An optional timeout value in 100 ns units.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS      - Event fired before Timeout expired.
 | 
						|
  EFI_TIME_OUT     - Timout expired before Event fired.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINTN       Index;
 | 
						|
  EFI_EVENT   TimerEvent;
 | 
						|
  EFI_EVENT   WaitList[2];
 | 
						|
 | 
						|
  if (Timeout) {
 | 
						|
    //
 | 
						|
    // Create a timer event
 | 
						|
    //
 | 
						|
    Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // Set the timer event
 | 
						|
      //
 | 
						|
      gBS->SetTimer (
 | 
						|
            TimerEvent,
 | 
						|
            TimerRelative,
 | 
						|
            Timeout
 | 
						|
            );
 | 
						|
 | 
						|
      //
 | 
						|
      // Wait for the original event or the timer
 | 
						|
      //
 | 
						|
      WaitList[0] = Event;
 | 
						|
      WaitList[1] = TimerEvent;
 | 
						|
      Status      = gBS->WaitForEvent (2, WaitList, &Index);
 | 
						|
      gBS->CloseEvent (TimerEvent);
 | 
						|
 | 
						|
      //
 | 
						|
      // If the timer expired, change the return to timed out
 | 
						|
      //
 | 
						|
      if (!EFI_ERROR (Status) && Index == 1) {
 | 
						|
        Status = EFI_TIMEOUT;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Update screen every second
 | 
						|
    //
 | 
						|
    Timeout = ONE_SECOND;
 | 
						|
 | 
						|
    do {
 | 
						|
      Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
 | 
						|
 | 
						|
      //
 | 
						|
      // Set the timer event
 | 
						|
      //
 | 
						|
      gBS->SetTimer (
 | 
						|
            TimerEvent,
 | 
						|
            TimerRelative,
 | 
						|
            Timeout
 | 
						|
            );
 | 
						|
 | 
						|
      //
 | 
						|
      // Wait for the original event or the timer
 | 
						|
      //
 | 
						|
      WaitList[0] = Event;
 | 
						|
      WaitList[1] = TimerEvent;
 | 
						|
      Status      = gBS->WaitForEvent (2, WaitList, &Index);
 | 
						|
 | 
						|
      //
 | 
						|
      // If the timer expired, update anything that needs a refresh and keep waiting
 | 
						|
      //
 | 
						|
      if (!EFI_ERROR (Status) && Index == 1) {
 | 
						|
        Status = EFI_TIMEOUT;
 | 
						|
        UpdateDateAndTime ();
 | 
						|
      }
 | 
						|
 | 
						|
      gBS->CloseEvent (TimerEvent);
 | 
						|
    } while (Status == EFI_TIMEOUT);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
UiAddMenuOption (
 | 
						|
  IN CHAR16         *String,
 | 
						|
  IN EFI_HII_HANDLE Handle,
 | 
						|
  IN EFI_TAG        *Tags,
 | 
						|
  IN VOID           *FormBinary,
 | 
						|
  IN UINTN          IfrNumber
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Add one menu option by specified description and context.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  String - String description for this option.
 | 
						|
  Context - Context data for entry.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UI_MENU_OPTION  *MenuOption;
 | 
						|
 | 
						|
  MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));
 | 
						|
  ASSERT (MenuOption);
 | 
						|
 | 
						|
  MenuOption->Signature   = UI_MENU_OPTION_SIGNATURE;
 | 
						|
  MenuOption->Description = String;
 | 
						|
  MenuOption->Handle      = Handle;
 | 
						|
  MenuOption->FormBinary  = FormBinary;
 | 
						|
  MenuOption->IfrNumber   = IfrNumber;
 | 
						|
  MenuOption->Skip        = 1;
 | 
						|
  MenuOption->Tags        = Tags;
 | 
						|
  MenuOption->TagIndex    = 0;
 | 
						|
  MenuOption->ThisTag     = &(MenuOption->Tags[MenuOption->TagIndex]);
 | 
						|
  MenuOption->EntryNumber = (UINT16) IfrNumber;
 | 
						|
 | 
						|
  InsertTailList (&Menu, &MenuOption->Link);
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
UiAddSubMenuOption (
 | 
						|
  IN CHAR16           *String,
 | 
						|
  IN EFI_HII_HANDLE   Handle,
 | 
						|
  IN EFI_TAG          *Tags,
 | 
						|
  IN UINTN            TagIndex,
 | 
						|
  IN UINT16           FormId,
 | 
						|
  IN UINT16           MenuItemCount
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Add one menu option by specified description and context.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  String - String description for this option.
 | 
						|
  Context - Context data for entry.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UI_MENU_OPTION  *MenuOption;
 | 
						|
 | 
						|
  MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));
 | 
						|
  ASSERT (MenuOption);
 | 
						|
 | 
						|
  MenuOption->Signature   = UI_MENU_OPTION_SIGNATURE;
 | 
						|
  MenuOption->Description = String;
 | 
						|
  MenuOption->Handle      = Handle;
 | 
						|
  MenuOption->Skip        = Tags[TagIndex].NumberOfLines;
 | 
						|
  MenuOption->IfrNumber   = gActiveIfr;
 | 
						|
  MenuOption->Tags        = Tags;
 | 
						|
  MenuOption->TagIndex    = TagIndex;
 | 
						|
  MenuOption->ThisTag     = &(MenuOption->Tags[MenuOption->TagIndex]);
 | 
						|
  MenuOption->Consistency = Tags[TagIndex].Consistency;
 | 
						|
  MenuOption->FormId      = FormId;
 | 
						|
  MenuOption->GrayOut     = Tags[TagIndex].GrayOut;
 | 
						|
  MenuOption->EntryNumber = MenuItemCount;
 | 
						|
 | 
						|
  InsertTailList (&Menu, &MenuOption->Link);
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
CreateDialog (
 | 
						|
  IN  UINTN                       NumberOfLines,
 | 
						|
  IN  BOOLEAN                     HotKey,
 | 
						|
  IN  UINTN                       MaximumStringSize,
 | 
						|
  OUT CHAR16                      *StringBuffer,
 | 
						|
  OUT EFI_INPUT_KEY               *KeyValue,
 | 
						|
  IN  CHAR16                      *String,
 | 
						|
  ...
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Routine used to abstract a generic dialog interface and return the selected key or string
 | 
						|
 | 
						|
Arguments:
 | 
						|
  NumberOfLines -     The number of lines for the dialog box
 | 
						|
  HotKey -            Defines whether a single character is parsed (TRUE) and returned in KeyValue
 | 
						|
                      or a string is returned in StringBuffer.  Two special characters are considered when entering a string, a SCAN_ESC and
 | 
						|
                      an CHAR_CARRIAGE_RETURN.  SCAN_ESC terminates string input and returns
 | 
						|
  MaximumStringSize - The maximum size in bytes of a typed in string (each character is a CHAR16) and the minimum string returned is two bytes
 | 
						|
  StringBuffer -      The passed in pointer to the buffer which will hold the typed in string if HotKey is FALSE
 | 
						|
  KeyValue -          The EFI_KEY value returned if HotKey is TRUE..
 | 
						|
  String -            Pointer to the first string in the list
 | 
						|
  ... -               A series of (quantity == NumberOfLines) text strings which will be used to construct the dialog box
 | 
						|
 | 
						|
Returns:
 | 
						|
  EFI_SUCCESS -           Displayed dialog and received user interaction
 | 
						|
  EFI_INVALID_PARAMETER - One of the parameters was invalid (e.g. (StringBuffer == NULL) && (HotKey == FALSE))
 | 
						|
  EFI_DEVICE_ERROR -      User typed in an ESC character to exit the routine
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  VA_LIST       Marker;
 | 
						|
  UINTN         Count;
 | 
						|
  EFI_INPUT_KEY Key;
 | 
						|
  UINTN         LargestString;
 | 
						|
  CHAR16        *TempString;
 | 
						|
  CHAR16        *BufferedString;
 | 
						|
  CHAR16        *StackString;
 | 
						|
  CHAR16        KeyPad[2];
 | 
						|
  UINTN         Start;
 | 
						|
  UINTN         Top;
 | 
						|
  UINTN         Index;
 | 
						|
  BOOLEAN       SelectionComplete;
 | 
						|
  UINTN         InputOffset;
 | 
						|
  UINTN         CurrentAttribute;
 | 
						|
  UINTN         DimensionsWidth;
 | 
						|
  UINTN         DimensionsHeight;
 | 
						|
 | 
						|
  DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
 | 
						|
  DimensionsHeight  = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
 | 
						|
 | 
						|
  SelectionComplete = FALSE;
 | 
						|
  InputOffset       = 0;
 | 
						|
  TempString        = AllocateZeroPool (MaximumStringSize * 2);
 | 
						|
  BufferedString    = AllocateZeroPool (MaximumStringSize * 2);
 | 
						|
  CurrentAttribute  = gST->ConOut->Mode->Attribute;
 | 
						|
 | 
						|
  ASSERT (TempString);
 | 
						|
  ASSERT (BufferedString);
 | 
						|
 | 
						|
  VA_START (Marker, String);
 | 
						|
 | 
						|
  //
 | 
						|
  // Zero the outgoing buffer
 | 
						|
  //
 | 
						|
  ZeroMem (StringBuffer, MaximumStringSize);
 | 
						|
 | 
						|
  if (HotKey) {
 | 
						|
    if (KeyValue == NULL) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    if (StringBuffer == NULL) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Disable cursor
 | 
						|
  //
 | 
						|
  gST->ConOut->EnableCursor (gST->ConOut, FALSE);
 | 
						|
 | 
						|
  LargestString = (GetStringWidth (String) / 2);
 | 
						|
 | 
						|
  if (LargestString == L' ') {
 | 
						|
    InputOffset = 1;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Determine the largest string in the dialog box
 | 
						|
  // Notice we are starting with 1 since String is the first string
 | 
						|
  //
 | 
						|
  for (Count = 1; Count < NumberOfLines; Count++) {
 | 
						|
    StackString = VA_ARG (Marker, CHAR16 *);
 | 
						|
 | 
						|
    if (StackString[0] == L' ') {
 | 
						|
      InputOffset = Count + 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((GetStringWidth (StackString) / 2) > LargestString) {
 | 
						|
      //
 | 
						|
      // Size of the string visually and subtract the width by one for the null-terminator
 | 
						|
      //
 | 
						|
      LargestString = (GetStringWidth (StackString) / 2);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;
 | 
						|
  Top   = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
 | 
						|
 | 
						|
  Count = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Display the Popup
 | 
						|
  //
 | 
						|
  CreateSharedPopUp (LargestString, NumberOfLines, &String);
 | 
						|
 | 
						|
  //
 | 
						|
  // Take the first key typed and report it back?
 | 
						|
  //
 | 
						|
  if (HotKey) {
 | 
						|
    WaitForKeyStroke (&Key);
 | 
						|
    CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
 | 
						|
 | 
						|
  } else {
 | 
						|
    do {
 | 
						|
      WaitForKeyStroke (&Key);
 | 
						|
 | 
						|
      switch (Key.UnicodeChar) {
 | 
						|
      case CHAR_NULL:
 | 
						|
        switch (Key.ScanCode) {
 | 
						|
        case SCAN_ESC:
 | 
						|
          FreePool (TempString);
 | 
						|
          FreePool (BufferedString);
 | 
						|
          gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
 | 
						|
          gST->ConOut->EnableCursor (gST->ConOut, TRUE);
 | 
						|
          return EFI_DEVICE_ERROR;
 | 
						|
 | 
						|
        default:
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case CHAR_CARRIAGE_RETURN:
 | 
						|
        SelectionComplete = TRUE;
 | 
						|
        FreePool (TempString);
 | 
						|
        FreePool (BufferedString);
 | 
						|
        gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
 | 
						|
        gST->ConOut->EnableCursor (gST->ConOut, TRUE);
 | 
						|
        return EFI_SUCCESS;
 | 
						|
        break;
 | 
						|
 | 
						|
      case CHAR_BACKSPACE:
 | 
						|
        if (StringBuffer[0] != CHAR_NULL) {
 | 
						|
          for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) {
 | 
						|
            TempString[Index] = StringBuffer[Index];
 | 
						|
          }
 | 
						|
          //
 | 
						|
          // Effectively truncate string by 1 character
 | 
						|
          //
 | 
						|
          TempString[Index - 1] = CHAR_NULL;
 | 
						|
          StrCpy (StringBuffer, TempString);
 | 
						|
        }
 | 
						|
 | 
						|
      default:
 | 
						|
        //
 | 
						|
        // If it is the beginning of the string, don't worry about checking maximum limits
 | 
						|
        //
 | 
						|
        if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
 | 
						|
          StrnCpy (StringBuffer, &Key.UnicodeChar, 1);
 | 
						|
          StrnCpy (TempString, &Key.UnicodeChar, 1);
 | 
						|
        } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
 | 
						|
          KeyPad[0] = Key.UnicodeChar;
 | 
						|
          KeyPad[1] = CHAR_NULL;
 | 
						|
          StrCat (StringBuffer, KeyPad);
 | 
						|
          StrCat (TempString, KeyPad);
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // If the width of the input string is now larger than the screen, we nee to
 | 
						|
        // adjust the index to start printing portions of the string
 | 
						|
        //
 | 
						|
        SetUnicodeMem (BufferedString, LargestString, L' ');
 | 
						|
 | 
						|
        PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
 | 
						|
 | 
						|
        if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) {
 | 
						|
          Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2;
 | 
						|
        } else {
 | 
						|
          Index = 0;
 | 
						|
        }
 | 
						|
 | 
						|
        for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) {
 | 
						|
          BufferedString[Count] = StringBuffer[Index];
 | 
						|
        }
 | 
						|
 | 
						|
        PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    } while (!SelectionComplete);
 | 
						|
  }
 | 
						|
 | 
						|
  gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
 | 
						|
  gST->ConOut->EnableCursor (gST->ConOut, TRUE);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
CreateSharedPopUp (
 | 
						|
  IN  UINTN                       RequestedWidth,
 | 
						|
  IN  UINTN                       NumberOfLines,
 | 
						|
  IN  CHAR16                      **ArrayOfStrings
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN   Index;
 | 
						|
  UINTN   Count;
 | 
						|
  CHAR16  Character;
 | 
						|
  UINTN   Start;
 | 
						|
  UINTN   End;
 | 
						|
  UINTN   Top;
 | 
						|
  UINTN   Bottom;
 | 
						|
  CHAR16  *String;
 | 
						|
 | 
						|
  UINTN   DimensionsWidth;
 | 
						|
  UINTN   DimensionsHeight;
 | 
						|
 | 
						|
  DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
 | 
						|
  DimensionsHeight  = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
 | 
						|
 | 
						|
  Count             = 0;
 | 
						|
 | 
						|
  gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
 | 
						|
 | 
						|
  if ((RequestedWidth + 2) > DimensionsWidth) {
 | 
						|
    RequestedWidth = DimensionsWidth - 2;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Subtract the PopUp width from total Columns, allow for one space extra on
 | 
						|
  // each end plus a border.
 | 
						|
  //
 | 
						|
  Start     = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1;
 | 
						|
  End       = Start + RequestedWidth + 1;
 | 
						|
 | 
						|
  Top       = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
 | 
						|
  Bottom    = Top + NumberOfLines + 2;
 | 
						|
 | 
						|
  Character = (CHAR16) BOXDRAW_DOWN_RIGHT;
 | 
						|
  PrintCharAt (Start, Top, Character);
 | 
						|
  Character = (CHAR16) BOXDRAW_HORIZONTAL;
 | 
						|
  for (Index = Start; Index + 2 < End; Index++) {
 | 
						|
    PrintChar (Character);
 | 
						|
  }
 | 
						|
 | 
						|
  Character = (CHAR16) BOXDRAW_DOWN_LEFT;
 | 
						|
  PrintChar (Character);
 | 
						|
  Character = (CHAR16) BOXDRAW_VERTICAL;
 | 
						|
  for (Index = Top; Index + 2 < Bottom; Index++) {
 | 
						|
    String = ArrayOfStrings[Count];
 | 
						|
    Count++;
 | 
						|
 | 
						|
    //
 | 
						|
    // This will clear the background of the line - we never know who might have been
 | 
						|
    // here before us.  This differs from the next clear in that it used the non-reverse
 | 
						|
    // video for normal printing.
 | 
						|
    //
 | 
						|
    if (GetStringWidth (String) / 2 > 1) {
 | 
						|
      ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Passing in a space results in the assumption that this is where typing will occur
 | 
						|
    //
 | 
						|
    if (String[0] == L' ') {
 | 
						|
      ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Passing in a NULL results in a blank space
 | 
						|
    //
 | 
						|
    if (String[0] == CHAR_NULL) {
 | 
						|
      ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
 | 
						|
    }
 | 
						|
 | 
						|
    PrintStringAt (
 | 
						|
      ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
 | 
						|
      Index + 1,
 | 
						|
      String
 | 
						|
      );
 | 
						|
    gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
 | 
						|
    PrintCharAt (Start, Index + 1, Character);
 | 
						|
    PrintCharAt (End - 1, Index + 1, Character);
 | 
						|
  }
 | 
						|
 | 
						|
  Character = (CHAR16) BOXDRAW_UP_RIGHT;
 | 
						|
  PrintCharAt (Start, Bottom - 1, Character);
 | 
						|
  Character = (CHAR16) BOXDRAW_HORIZONTAL;
 | 
						|
  for (Index = Start; Index + 2 < End; Index++) {
 | 
						|
    PrintChar (Character);
 | 
						|
  }
 | 
						|
 | 
						|
  Character = (CHAR16) BOXDRAW_UP_LEFT;
 | 
						|
  PrintChar (Character);
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
CreatePopUp (
 | 
						|
  IN  UINTN                       RequestedWidth,
 | 
						|
  IN  UINTN                       NumberOfLines,
 | 
						|
  IN  CHAR16                      *ArrayOfStrings,
 | 
						|
  ...
 | 
						|
  )
 | 
						|
{
 | 
						|
  CreateSharedPopUp (RequestedWidth, NumberOfLines, &ArrayOfStrings);
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
UpdateStatusBar (
 | 
						|
  IN  UINTN                       MessageType,
 | 
						|
  IN  UINT8                       Flags,
 | 
						|
  IN  BOOLEAN                     State
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN           Index;
 | 
						|
  STATIC BOOLEAN  InputError;
 | 
						|
  CHAR16          *NvUpdateMessage;
 | 
						|
  CHAR16          *InputErrorMessage;
 | 
						|
 | 
						|
  NvUpdateMessage   = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle);
 | 
						|
  InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle);
 | 
						|
 | 
						|
  switch (MessageType) {
 | 
						|
  case INPUT_ERROR:
 | 
						|
    if (State) {
 | 
						|
      gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);
 | 
						|
      PrintStringAt (
 | 
						|
        gScreenDimensions.LeftColumn + gPromptBlockWidth,
 | 
						|
        gScreenDimensions.BottomRow - 1,
 | 
						|
        InputErrorMessage
 | 
						|
        );
 | 
						|
      InputError = TRUE;
 | 
						|
    } else {
 | 
						|
      gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
 | 
						|
      for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {
 | 
						|
        PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, (CHAR16 *) L"  ");
 | 
						|
      }
 | 
						|
 | 
						|
      InputError = FALSE;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  case NV_UPDATE_REQUIRED:
 | 
						|
    if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
 | 
						|
      if (State) {
 | 
						|
        gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);
 | 
						|
        PrintStringAt (
 | 
						|
          gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,
 | 
						|
          gScreenDimensions.BottomRow - 1,
 | 
						|
          NvUpdateMessage
 | 
						|
          );
 | 
						|
        gResetRequired    = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));
 | 
						|
 | 
						|
        gNvUpdateRequired = TRUE;
 | 
						|
      } else {
 | 
						|
        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
 | 
						|
        for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {
 | 
						|
          PrintAt (
 | 
						|
            (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),
 | 
						|
            gScreenDimensions.BottomRow - 1,
 | 
						|
            (CHAR16 *) L"  "
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        gNvUpdateRequired = FALSE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  case REFRESH_STATUS_BAR:
 | 
						|
    if (InputError) {
 | 
						|
      UpdateStatusBar (INPUT_ERROR, Flags, TRUE);
 | 
						|
    }
 | 
						|
 | 
						|
    if (gNvUpdateRequired) {
 | 
						|
      UpdateStatusBar (NV_UPDATE_REQUIRED, Flags, TRUE);
 | 
						|
    }
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (InputErrorMessage);
 | 
						|
  FreePool (NvUpdateMessage);
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
FreeData (
 | 
						|
  IN EFI_FILE_FORM_TAGS           *FileFormTagsHead,
 | 
						|
  IN CHAR16                       *FormattedString,
 | 
						|
  IN CHAR16                       *OptionString
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Used to remove the allocated data instances
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_FILE_FORM_TAGS      *FileForm;
 | 
						|
  EFI_FILE_FORM_TAGS      *PreviousFileForm;
 | 
						|
  EFI_FORM_TAGS           *FormTags;
 | 
						|
  EFI_FORM_TAGS           *PreviousFormTags;
 | 
						|
  EFI_IFR_BINARY          *IfrBinary;
 | 
						|
  EFI_IFR_BINARY          *PreviousIfrBinary;
 | 
						|
  EFI_INCONSISTENCY_DATA  *Inconsistent;
 | 
						|
  EFI_VARIABLE_DEFINITION *VariableDefinition;
 | 
						|
  EFI_VARIABLE_DEFINITION *PreviousVariableDefinition;
 | 
						|
  VOID                    *Buffer;
 | 
						|
  UINTN                   Index;
 | 
						|
 | 
						|
  FileForm = FileFormTagsHead;
 | 
						|
 | 
						|
  if (FormattedString != NULL) {
 | 
						|
    FreePool (FormattedString);
 | 
						|
  }
 | 
						|
 | 
						|
  if (OptionString != NULL) {
 | 
						|
    FreePool (OptionString);
 | 
						|
  }
 | 
						|
 | 
						|
  for (; FileForm != NULL;) {
 | 
						|
    PreviousFileForm = NULL;
 | 
						|
 | 
						|
    //
 | 
						|
    // Advance FileForm to the last entry
 | 
						|
    //
 | 
						|
    for (; FileForm->NextFile != NULL; FileForm = FileForm->NextFile) {
 | 
						|
      PreviousFileForm = FileForm;
 | 
						|
    }
 | 
						|
 | 
						|
    FormTags = &FileForm->FormTags;
 | 
						|
 | 
						|
    for (; FormTags != NULL;) {
 | 
						|
      FormTags          = &FileForm->FormTags;
 | 
						|
      PreviousFormTags  = NULL;
 | 
						|
 | 
						|
      //
 | 
						|
      // Advance FormTags to the last entry
 | 
						|
      //
 | 
						|
      for (; FormTags->Next != NULL; FormTags = FormTags->Next) {
 | 
						|
        PreviousFormTags = FormTags;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Walk through each of the tags and free the IntList allocation
 | 
						|
      //
 | 
						|
      for (Index = 0; FormTags->Tags[Index].Operand != EFI_IFR_END_FORM_OP; Index++) {
 | 
						|
        //
 | 
						|
        // It is more than likely that the very last page will contain an end formset
 | 
						|
        //
 | 
						|
        if (FormTags->Tags[Index].Operand == EFI_IFR_END_FORM_SET_OP) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        if (FormTags->Tags[Index].IntList != NULL) {
 | 
						|
          FreePool (FormTags->Tags[Index].IntList);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (PreviousFormTags != NULL) {
 | 
						|
        FreePool (FormTags->Tags);
 | 
						|
        FormTags = PreviousFormTags;
 | 
						|
        FreePool (FormTags->Next);
 | 
						|
        FormTags->Next = NULL;
 | 
						|
      } else {
 | 
						|
        FreePool (FormTags->Tags);
 | 
						|
        FormTags = NULL;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Last FileForm entry's Inconsistent database
 | 
						|
    //
 | 
						|
    Inconsistent = FileForm->InconsistentTags;
 | 
						|
 | 
						|
    //
 | 
						|
    // Advance Inconsistent to the last entry
 | 
						|
    //
 | 
						|
    for (; Inconsistent->Next != NULL; Inconsistent = Inconsistent->Next)
 | 
						|
      ;
 | 
						|
 | 
						|
    for (; Inconsistent != NULL;) {
 | 
						|
      //
 | 
						|
      // Preserve the Previous pointer
 | 
						|
      //
 | 
						|
      Buffer = (VOID *) Inconsistent->Previous;
 | 
						|
 | 
						|
      //
 | 
						|
      // Free the current entry
 | 
						|
      //
 | 
						|
      FreePool (Inconsistent);
 | 
						|
 | 
						|
      //
 | 
						|
      // Restore the Previous pointer
 | 
						|
      //
 | 
						|
      Inconsistent = (EFI_INCONSISTENCY_DATA *) Buffer;
 | 
						|
    }
 | 
						|
 | 
						|
    VariableDefinition = FileForm->VariableDefinitions;
 | 
						|
 | 
						|
    for (; VariableDefinition != NULL;) {
 | 
						|
      VariableDefinition          = FileForm->VariableDefinitions;
 | 
						|
      PreviousVariableDefinition  = NULL;
 | 
						|
 | 
						|
      //
 | 
						|
      // Advance VariableDefinitions to the last entry
 | 
						|
      //
 | 
						|
      for (; VariableDefinition->Next != NULL; VariableDefinition = VariableDefinition->Next) {
 | 
						|
        PreviousVariableDefinition = VariableDefinition;
 | 
						|
      }
 | 
						|
 | 
						|
      FreePool (VariableDefinition->VariableName);
 | 
						|
 | 
						|
      if (VariableDefinition->NvRamMap != NULL) {
 | 
						|
        FreePool (VariableDefinition->NvRamMap);
 | 
						|
      }
 | 
						|
 | 
						|
      if (VariableDefinition->FakeNvRamMap != NULL) {
 | 
						|
        FreePool (VariableDefinition->FakeNvRamMap);
 | 
						|
      }
 | 
						|
 | 
						|
      if (PreviousVariableDefinition != NULL) {
 | 
						|
        VariableDefinition = PreviousVariableDefinition;
 | 
						|
        FreePool (VariableDefinition->Next);
 | 
						|
        VariableDefinition->Next = NULL;
 | 
						|
      } else {
 | 
						|
        FreePool (VariableDefinition);
 | 
						|
        VariableDefinition = NULL;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (PreviousFileForm != NULL) {
 | 
						|
      FileForm = PreviousFileForm;
 | 
						|
      FreePool (FileForm->NextFile);
 | 
						|
      FileForm->NextFile = NULL;
 | 
						|
    } else {
 | 
						|
      FreePool (FileForm);
 | 
						|
      FileForm = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  IfrBinary = gBinaryDataHead;
 | 
						|
 | 
						|
  for (; IfrBinary != NULL;) {
 | 
						|
    IfrBinary         = gBinaryDataHead;
 | 
						|
    PreviousIfrBinary = NULL;
 | 
						|
 | 
						|
    //
 | 
						|
    // Advance IfrBinary to the last entry
 | 
						|
    //
 | 
						|
    for (; IfrBinary->Next != NULL; IfrBinary = IfrBinary->Next) {
 | 
						|
      PreviousIfrBinary = IfrBinary;
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (IfrBinary->IfrPackage);
 | 
						|
 | 
						|
    if (PreviousIfrBinary != NULL) {
 | 
						|
      IfrBinary = PreviousIfrBinary;
 | 
						|
      FreePool (IfrBinary->Next);
 | 
						|
      IfrBinary->Next = NULL;
 | 
						|
    } else {
 | 
						|
      FreePool (IfrBinary);
 | 
						|
      IfrBinary = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (gPreviousValue);
 | 
						|
  gPreviousValue = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Free Browser Strings
 | 
						|
  //
 | 
						|
  FreePool (gPressEnter);
 | 
						|
  FreePool (gConfirmError);
 | 
						|
  FreePool (gConfirmPassword);
 | 
						|
  FreePool (gPromptForNewPassword);
 | 
						|
  FreePool (gPromptForPassword);
 | 
						|
  FreePool (gToggleCheckBox);
 | 
						|
  FreePool (gNumericInput);
 | 
						|
  FreePool (gMakeSelection);
 | 
						|
  FreePool (gMoveHighlight);
 | 
						|
  FreePool (gEscapeString);
 | 
						|
  FreePool (gEnterCommitString);
 | 
						|
  FreePool (gEnterString);
 | 
						|
  FreePool (gFunctionOneString);
 | 
						|
  FreePool (gFunctionTwoString);
 | 
						|
  FreePool (gFunctionNineString);
 | 
						|
  FreePool (gFunctionTenString);
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
SelectionsAreValid (
 | 
						|
  IN  UI_MENU_OPTION               *MenuOption,
 | 
						|
  IN  EFI_FILE_FORM_TAGS           *FileFormTagsHead
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Initiate late consistency checks against the current page.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  None
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  LIST_ENTRY              *Link;
 | 
						|
  EFI_TAG                 *Tag;
 | 
						|
  EFI_FILE_FORM_TAGS      *FileFormTags;
 | 
						|
  CHAR16                  *StringPtr;
 | 
						|
  CHAR16                  NullCharacter;
 | 
						|
  UINTN                   Index;
 | 
						|
  UINT16                  *NvRamMap;
 | 
						|
  STRING_REF              PopUp;
 | 
						|
  EFI_INPUT_KEY           Key;
 | 
						|
  EFI_VARIABLE_DEFINITION *VariableDefinition;
 | 
						|
 | 
						|
  StringPtr     = (CHAR16 *) L"\0";
 | 
						|
  NullCharacter = CHAR_NULL;
 | 
						|
 | 
						|
  FileFormTags  = FileFormTagsHead;
 | 
						|
 | 
						|
  for (Index = 0; Index < MenuOption->IfrNumber; Index++) {
 | 
						|
    FileFormTags = FileFormTags->NextFile;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) {
 | 
						|
    MenuOption  = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
 | 
						|
    Tag         = MenuOption->ThisTag;
 | 
						|
 | 
						|
    ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition);
 | 
						|
    NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];
 | 
						|
 | 
						|
    //
 | 
						|
    // If the op-code has a late check, ensure consistency checks are now applied
 | 
						|
    //
 | 
						|
    if (Tag->Flags & EFI_IFR_FLAG_LATE_CHECK) {
 | 
						|
      if (ValueIsNotValid (TRUE, 0, Tag, FileFormTags, &PopUp)) {
 | 
						|
        if (PopUp != 0x0000) {
 | 
						|
          StringPtr = GetToken (PopUp, MenuOption->Handle);
 | 
						|
 | 
						|
          CreatePopUp (GetStringWidth (StringPtr) / 2, 3, &NullCharacter, StringPtr, &NullCharacter);
 | 
						|
 | 
						|
          do {
 | 
						|
            WaitForKeyStroke (&Key);
 | 
						|
 | 
						|
            switch (Key.UnicodeChar) {
 | 
						|
 | 
						|
            case CHAR_CARRIAGE_RETURN:
 | 
						|
              //
 | 
						|
              // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
 | 
						|
              //
 | 
						|
              CopyMem (NvRamMap, &Tag->OldValue, Tag->StorageWidth);
 | 
						|
              FreePool (StringPtr);
 | 
						|
              break;
 | 
						|
 | 
						|
            default:
 | 
						|
              break;
 | 
						|
            }
 | 
						|
          } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
 | 
						|
        }
 | 
						|
 | 
						|
        return FALSE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
UINT16
 | 
						|
GetWidth (
 | 
						|
  IN EFI_TAG                        *Tag,
 | 
						|
  IN EFI_HII_HANDLE                 Handle
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Get the supported width for a particular op-code
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Tag - The Tag structure passed in.
 | 
						|
  Handle - The handle in the HII database being used
 | 
						|
 | 
						|
Returns:
 | 
						|
  Returns the number of CHAR16 characters that is support.
 | 
						|
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  CHAR16  *String;
 | 
						|
  UINTN   Size;
 | 
						|
 | 
						|
  Size = 0x00;
 | 
						|
 | 
						|
  //
 | 
						|
  // See if the second text parameter is really NULL
 | 
						|
  //
 | 
						|
  if ((Tag->Operand == EFI_IFR_TEXT_OP) && (Tag->TextTwo != 0)) {
 | 
						|
    String  = GetToken (Tag->TextTwo, Handle);
 | 
						|
    Size    = StrLen (String);
 | 
						|
    FreePool (String);
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Tag->Operand == EFI_IFR_SUBTITLE_OP) ||
 | 
						|
      (Tag->Operand == EFI_IFR_REF_OP) ||
 | 
						|
      (Tag->Operand == EFI_IFR_PASSWORD_OP) ||
 | 
						|
      (Tag->Operand == EFI_IFR_STRING_OP) ||
 | 
						|
      (Tag->Operand == EFI_IFR_INVENTORY_OP) ||
 | 
						|
      //
 | 
						|
      // Allow a wide display if text op-code and no secondary text op-code
 | 
						|
      //
 | 
						|
      ((Tag->Operand == EFI_IFR_TEXT_OP) && (Size == 0x0000))
 | 
						|
      ) {
 | 
						|
    return (UINT16) (gPromptBlockWidth + gOptionBlockWidth);
 | 
						|
  } else {
 | 
						|
    return (UINT16) gPromptBlockWidth;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
UINT16
 | 
						|
GetLineByWidth (
 | 
						|
  IN      CHAR16                      *InputString,
 | 
						|
  IN      UINT16                      LineWidth,
 | 
						|
  IN OUT  UINTN                       *Index,
 | 
						|
  OUT     CHAR16                      **OutputString
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Will copy LineWidth amount of a string in the OutputString buffer and return the
 | 
						|
  number of CHAR16 characters that were copied into the OutputString buffer.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  InputString - String description for this option.
 | 
						|
  LineWidth - Width of the desired string to extract in CHAR16 characters
 | 
						|
  Index - Where in InputString to start the copy process
 | 
						|
  OutputString - Buffer to copy the string into
 | 
						|
 | 
						|
Returns:
 | 
						|
  Returns the number of CHAR16 characters that were copied into the OutputString buffer.
 | 
						|
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  static BOOLEAN  Finished;
 | 
						|
  UINT16          Count;
 | 
						|
  UINT16          Count2;
 | 
						|
 | 
						|
  if (Finished) {
 | 
						|
    Finished = FALSE;
 | 
						|
    return (UINT16) 0;
 | 
						|
  }
 | 
						|
 | 
						|
  Count         = LineWidth;
 | 
						|
  Count2        = 0;
 | 
						|
 | 
						|
  *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2));
 | 
						|
 | 
						|
  //
 | 
						|
  // Ensure we have got a valid buffer
 | 
						|
  //
 | 
						|
  if (*OutputString != NULL) {
 | 
						|
 | 
						|
    //
 | 
						|
    //NARROW_CHAR can not be printed in screen, so if a line only contain  the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line  in Screen.
 | 
						|
    //To avoid displaying this  empty line in screen,  just skip  the two CHARs here.
 | 
						|
    //
 | 
						|
   if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {
 | 
						|
     *Index = *Index + 2;
 | 
						|
   }
 | 
						|
 | 
						|
    //
 | 
						|
    // Fast-forward the string and see if there is a carriage-return in the string
 | 
						|
    //
 | 
						|
    for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++)
 | 
						|
      ;
 | 
						|
 | 
						|
    //
 | 
						|
    // Copy the desired LineWidth of data to the output buffer.
 | 
						|
    // Also make sure that we don't copy more than the string.
 | 
						|
    // Also make sure that if there are linefeeds, we account for them.
 | 
						|
    //
 | 
						|
    if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) &&
 | 
						|
        (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2))
 | 
						|
        ) {
 | 
						|
      //
 | 
						|
      // Convert to CHAR16 value and show that we are done with this operation
 | 
						|
      //
 | 
						|
      LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2);
 | 
						|
      if (LineWidth != 0) {
 | 
						|
        Finished = TRUE;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      if (Count2 == LineWidth) {
 | 
						|
        //
 | 
						|
        // Rewind the string from the maximum size until we see a space to break the line
 | 
						|
        //
 | 
						|
        for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--)
 | 
						|
          ;
 | 
						|
        if (LineWidth == 0) {
 | 
						|
          LineWidth = Count;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        LineWidth = Count2;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem (*OutputString, &InputString[*Index], LineWidth * 2);
 | 
						|
 | 
						|
    //
 | 
						|
    // If currently pointing to a space, increment the index to the first non-space character
 | 
						|
    //
 | 
						|
    for (;
 | 
						|
         (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN);
 | 
						|
         (*Index)++
 | 
						|
        )
 | 
						|
      ;
 | 
						|
    *Index = (UINT16) (*Index + LineWidth);
 | 
						|
    return LineWidth;
 | 
						|
  } else {
 | 
						|
    return (UINT16) 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
UpdateOptionSkipLines (
 | 
						|
  IN EFI_IFR_DATA_ARRAY           *PageData,
 | 
						|
  IN UI_MENU_OPTION               *MenuOption,
 | 
						|
  IN EFI_FILE_FORM_TAGS           *FileFormTagsHead,
 | 
						|
  IN CHAR16                       **OptionalString,
 | 
						|
  IN UINTN                        SkipValue
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN   Index;
 | 
						|
  UINT16  Width;
 | 
						|
  UINTN   Row;
 | 
						|
  UINTN   OriginalRow;
 | 
						|
  CHAR16  *OutputString;
 | 
						|
  CHAR16  *OptionString;
 | 
						|
 | 
						|
  Row           = 0;
 | 
						|
  OptionString  = *OptionalString;
 | 
						|
  OutputString  = NULL;
 | 
						|
 | 
						|
  ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString);
 | 
						|
 | 
						|
  if (OptionString != NULL) {
 | 
						|
    Width               = (UINT16) gOptionBlockWidth;
 | 
						|
 | 
						|
    OriginalRow         = Row;
 | 
						|
 | 
						|
    for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
 | 
						|
      //
 | 
						|
      // If there is more string to process print on the next row and increment the Skip value
 | 
						|
      //
 | 
						|
      if (StrLen (&OptionString[Index])) {
 | 
						|
        if (SkipValue == 0) {
 | 
						|
          Row++;
 | 
						|
          //
 | 
						|
          // Since the Number of lines for this menu entry may or may not be reflected accurately
 | 
						|
          // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
 | 
						|
          // some testing to ensure we are keeping this in-sync.
 | 
						|
          //
 | 
						|
          // If the difference in rows is greater than or equal to the skip value, increase the skip value
 | 
						|
          //
 | 
						|
          if ((Row - OriginalRow) >= MenuOption->Skip) {
 | 
						|
            MenuOption->Skip++;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      FreePool (OutputString);
 | 
						|
      if (SkipValue != 0) {
 | 
						|
        SkipValue--;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Row = OriginalRow;
 | 
						|
  }
 | 
						|
 | 
						|
  *OptionalString = OptionString;
 | 
						|
}
 | 
						|
//
 | 
						|
// Search table for UiDisplayMenu()
 | 
						|
//
 | 
						|
SCAN_CODE_TO_SCREEN_OPERATION     gScanCodeToOperation[] = {
 | 
						|
  { SCAN_UP,        UiUp },
 | 
						|
  { SCAN_DOWN,      UiDown },
 | 
						|
  { SCAN_PAGE_UP,   UiPageUp },
 | 
						|
  { SCAN_PAGE_DOWN, UiPageDown},
 | 
						|
  { SCAN_ESC,       UiReset},
 | 
						|
  { SCAN_F2,        UiPrevious},
 | 
						|
  { SCAN_LEFT,      UiLeft },
 | 
						|
  { SCAN_RIGHT,     UiRight },
 | 
						|
  { SCAN_F9,        UiDefault},
 | 
						|
  { SCAN_F10,       UiSave }
 | 
						|
};
 | 
						|
 | 
						|
SCREEN_OPERATION_T0_CONTROL_FLAG  gScreenOperationToControlFlag[] = {
 | 
						|
  { UiNoOperation,  CfUiNoOperation },
 | 
						|
  { UiDefault,      CfUiDefault },
 | 
						|
  { UiSelect,       CfUiSelect },
 | 
						|
  { UiUp,           CfUiUp},
 | 
						|
  { UiDown,         CfUiDown },
 | 
						|
  { UiLeft,         CfUiLeft },
 | 
						|
  { UiRight,        CfUiRight },
 | 
						|
  { UiReset,        CfUiReset },
 | 
						|
  { UiSave,         CfUiSave },
 | 
						|
  { UiPrevious,     CfUiPrevious },
 | 
						|
  { UiPageUp,       CfUiPageUp },
 | 
						|
  { UiPageDown,     CfUiPageDown }
 | 
						|
};
 | 
						|
 | 
						|
UI_MENU_OPTION *
 | 
						|
UiDisplayMenu (
 | 
						|
  IN  BOOLEAN                      SubMenu,
 | 
						|
  IN  EFI_FILE_FORM_TAGS           *FileFormTagsHead,
 | 
						|
  OUT EFI_IFR_DATA_ARRAY           *PageData
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Display menu and wait for user to select one menu option, then return it.
 | 
						|
  If AutoBoot is enabled, then if user doesn't select any option,
 | 
						|
  after period of time, it will automatically return the first menu option.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  SubMenu          - Indicate is sub menu.
 | 
						|
  FileFormTagsHead - A pointer to the EFI_FILE_FORM_TAGS structure.
 | 
						|
  PageData         - A pointer to the EFI_IFR_DATA_ARRAY.
 | 
						|
 | 
						|
Returns:
 | 
						|
  Return the pointer of the menu which selected,
 | 
						|
  otherwise return NULL.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  INTN                        SkipValue;
 | 
						|
  INTN                        Difference;
 | 
						|
  INTN                        OldSkipValue;
 | 
						|
  UINTN                       Row;
 | 
						|
  UINTN                       Col;
 | 
						|
  UINTN                       Temp;
 | 
						|
  UINTN                       Temp2;
 | 
						|
  UINTN                       TopRow;
 | 
						|
  UINTN                       BottomRow;
 | 
						|
  UINTN                       OriginalRow;
 | 
						|
  UINTN                       Index;
 | 
						|
  UINTN                       DataAndTimeLineNumberPad;
 | 
						|
  UINT32                      Count;
 | 
						|
  INT16                       OriginalTimeOut;
 | 
						|
  UINT8                       *Location;
 | 
						|
  UINT16                      Width;
 | 
						|
  CHAR16                      *StringPtr;
 | 
						|
  CHAR16                      *OptionString;
 | 
						|
  CHAR16                      *OutputString;
 | 
						|
  CHAR16                      *FormattedString;
 | 
						|
  CHAR16                      YesResponse;
 | 
						|
  CHAR16                      NoResponse;
 | 
						|
  BOOLEAN                     NewLine;
 | 
						|
  BOOLEAN                     Repaint;
 | 
						|
  BOOLEAN                     SavedValue;
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  UI_MENU_LIST                *UiMenuList;
 | 
						|
  EFI_INPUT_KEY               Key;
 | 
						|
  LIST_ENTRY                  *Link;
 | 
						|
  LIST_ENTRY                  *NewPos;
 | 
						|
  LIST_ENTRY                  *TopOfScreen;
 | 
						|
  LIST_ENTRY                  *SavedListEntry;
 | 
						|
  UI_MENU_OPTION              *Selection;
 | 
						|
  UI_MENU_OPTION              *MenuOption;
 | 
						|
  UI_MENU_OPTION              *NextMenuOption;
 | 
						|
  UI_MENU_OPTION              *SavedMenuOption;
 | 
						|
  UI_MENU_OPTION              *PreviousMenuOption;
 | 
						|
  EFI_IFR_BINARY              *IfrBinary;
 | 
						|
  UI_CONTROL_FLAG             ControlFlag;
 | 
						|
  EFI_SCREEN_DESCRIPTOR       LocalScreen;
 | 
						|
  EFI_FILE_FORM_TAGS          *FileFormTags;
 | 
						|
  MENU_REFRESH_ENTRY          *MenuRefreshEntry;
 | 
						|
  MENU_REFRESH_ENTRY          *OldMenuRefreshEntry;
 | 
						|
  UI_SCREEN_OPERATION         ScreenOperation;
 | 
						|
  EFI_VARIABLE_DEFINITION     *VariableDefinition;
 | 
						|
  EFI_FORM_CALLBACK_PROTOCOL  *FormCallback;
 | 
						|
  EFI_HII_VARIABLE_PACK_LIST  *NvMapListHead;
 | 
						|
  EFI_HII_VARIABLE_PACK_LIST  *NvMapListNode;
 | 
						|
  VOID                        *NvMap;
 | 
						|
  UINTN                       NvMapSize;
 | 
						|
 | 
						|
  CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
 | 
						|
 | 
						|
  VariableDefinition  = NULL;
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  FormattedString     = NULL;
 | 
						|
  OptionString        = NULL;
 | 
						|
  ScreenOperation     = UiNoOperation;
 | 
						|
  NewLine             = TRUE;
 | 
						|
  FormCallback        = NULL;
 | 
						|
  FileFormTags        = NULL;
 | 
						|
  OutputString        = NULL;
 | 
						|
  gUpArrow            = FALSE;
 | 
						|
  gDownArrow          = FALSE;
 | 
						|
  SkipValue           = 0;
 | 
						|
  OldSkipValue        = 0;
 | 
						|
  MenuRefreshEntry    = gMenuRefreshHead;
 | 
						|
  OldMenuRefreshEntry = gMenuRefreshHead;
 | 
						|
  NextMenuOption      = NULL;
 | 
						|
  PreviousMenuOption  = NULL;
 | 
						|
  SavedMenuOption     = NULL;
 | 
						|
  IfrBinary           = NULL;
 | 
						|
  NvMap               = NULL;
 | 
						|
  NvMapSize           = 0;
 | 
						|
 | 
						|
  ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
 | 
						|
 | 
						|
  if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
 | 
						|
    TopRow  = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
 | 
						|
    Row     = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
 | 
						|
  } else {
 | 
						|
    TopRow  = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
 | 
						|
    Row     = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;
 | 
						|
  }
 | 
						|
 | 
						|
  if (SubMenu) {
 | 
						|
    Col = LocalScreen.LeftColumn;
 | 
						|
  } else {
 | 
						|
    Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS;
 | 
						|
  }
 | 
						|
 | 
						|
  BottomRow   = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1;
 | 
						|
 | 
						|
  TopOfScreen = Menu.ForwardLink;
 | 
						|
  Repaint     = TRUE;
 | 
						|
  MenuOption  = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get user's selection
 | 
						|
  //
 | 
						|
  Selection = NULL;
 | 
						|
  NewPos    = Menu.ForwardLink;
 | 
						|
  gST->ConOut->EnableCursor (gST->ConOut, FALSE);
 | 
						|
 | 
						|
  UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE);
 | 
						|
 | 
						|
  ControlFlag = CfInitialization;
 | 
						|
 | 
						|
  while (TRUE) {
 | 
						|
    switch (ControlFlag) {
 | 
						|
    case CfInitialization:
 | 
						|
      ControlFlag = CfCheckSelection;
 | 
						|
      if (gExitRequired) {
 | 
						|
        ScreenOperation = UiReset;
 | 
						|
        ControlFlag     = CfScreenOperation;
 | 
						|
      } else if (gSaveRequired) {
 | 
						|
        ScreenOperation = UiSave;
 | 
						|
        ControlFlag     = CfScreenOperation;
 | 
						|
      } else if (IsListEmpty (&Menu)) {
 | 
						|
        ControlFlag = CfReadKey;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfCheckSelection:
 | 
						|
      if (Selection != NULL) {
 | 
						|
        ControlFlag = CfExit;
 | 
						|
      } else {
 | 
						|
        ControlFlag = CfRepaint;
 | 
						|
      }
 | 
						|
 | 
						|
      FileFormTags = FileFormTagsHead;
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfRepaint:
 | 
						|
      ControlFlag = CfRefreshHighLight;
 | 
						|
 | 
						|
      if (Repaint) {
 | 
						|
        //
 | 
						|
        // Display menu
 | 
						|
        //
 | 
						|
        SavedMenuOption = MenuOption;
 | 
						|
        gDownArrow      = FALSE;
 | 
						|
        gUpArrow        = FALSE;
 | 
						|
        Row             = TopRow;
 | 
						|
 | 
						|
        Temp            = SkipValue;
 | 
						|
        Temp2           = SkipValue;
 | 
						|
 | 
						|
        ClearLines (
 | 
						|
          LocalScreen.LeftColumn,
 | 
						|
          LocalScreen.RightColumn,
 | 
						|
          TopRow - SCROLL_ARROW_HEIGHT,
 | 
						|
          BottomRow + SCROLL_ARROW_HEIGHT,
 | 
						|
          FIELD_TEXT | FIELD_BACKGROUND
 | 
						|
          );
 | 
						|
 | 
						|
        while (gMenuRefreshHead != NULL) {
 | 
						|
          OldMenuRefreshEntry = gMenuRefreshHead->Next;
 | 
						|
 | 
						|
          FreePool (gMenuRefreshHead);
 | 
						|
 | 
						|
          gMenuRefreshHead = OldMenuRefreshEntry;
 | 
						|
        }
 | 
						|
 | 
						|
        for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) {
 | 
						|
          MenuOption          = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
          MenuOption->Row     = Row;
 | 
						|
          OriginalRow         = Row;
 | 
						|
          MenuOption->Col     = Col;
 | 
						|
          MenuOption->OptCol  = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
 | 
						|
 | 
						|
          if (SubMenu) {
 | 
						|
            if (MenuOption->ThisTag->GrayOut) {
 | 
						|
              gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
 | 
						|
            } else {
 | 
						|
              if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {
 | 
						|
                gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
 | 
						|
              }
 | 
						|
            }
 | 
						|
 | 
						|
            Width       = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
 | 
						|
 | 
						|
            OriginalRow = Row;
 | 
						|
 | 
						|
            for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
 | 
						|
              if ((Temp == 0) && (Row <= BottomRow)) {
 | 
						|
                PrintStringAt (Col, Row, OutputString);
 | 
						|
              }
 | 
						|
              //
 | 
						|
              // If there is more string to process print on the next row and increment the Skip value
 | 
						|
              //
 | 
						|
              if (StrLen (&MenuOption->Description[Index])) {
 | 
						|
                if (Temp == 0) {
 | 
						|
                  Row++;
 | 
						|
                }
 | 
						|
              }
 | 
						|
 | 
						|
              FreePool (OutputString);
 | 
						|
              if (Temp != 0) {
 | 
						|
                Temp--;
 | 
						|
              }
 | 
						|
            }
 | 
						|
 | 
						|
            Temp  = 0;
 | 
						|
 | 
						|
            Row   = OriginalRow;
 | 
						|
 | 
						|
            gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
 | 
						|
            ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString);
 | 
						|
 | 
						|
            if (OptionString != NULL) {
 | 
						|
              if (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
 | 
						|
                  MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP
 | 
						|
                  ) {
 | 
						|
                //
 | 
						|
                // If leading spaces on OptionString - remove the spaces
 | 
						|
                //
 | 
						|
                for (Index = 0; OptionString[Index] == L' '; Index++) {
 | 
						|
                  MenuOption->OptCol++;
 | 
						|
                }
 | 
						|
 | 
						|
                for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
 | 
						|
                  OptionString[Count] = OptionString[Index];
 | 
						|
                  Count++;
 | 
						|
                }
 | 
						|
 | 
						|
                OptionString[Count] = CHAR_NULL;
 | 
						|
              }
 | 
						|
 | 
						|
              //
 | 
						|
              // If this is a date or time op-code and is used to reflect an RTC, register the op-code
 | 
						|
              //
 | 
						|
                if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
 | 
						|
                     MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP) &&
 | 
						|
                    (MenuOption->ThisTag->StorageStart >= FileFormTags->FormTags.Tags[0].NvDataSize)) {
 | 
						|
 | 
						|
                if (gMenuRefreshHead == NULL) {
 | 
						|
                  MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
 | 
						|
                  ASSERT (MenuRefreshEntry != NULL);
 | 
						|
                  MenuRefreshEntry->MenuOption        = MenuOption;
 | 
						|
                  MenuRefreshEntry->FileFormTagsHead  = FileFormTagsHead;
 | 
						|
                  MenuRefreshEntry->CurrentColumn     = MenuOption->OptCol;
 | 
						|
                  MenuRefreshEntry->CurrentRow        = MenuOption->Row;
 | 
						|
                  MenuRefreshEntry->CurrentAttribute  = FIELD_TEXT | FIELD_BACKGROUND;
 | 
						|
                  gMenuRefreshHead                    = MenuRefreshEntry;
 | 
						|
                } else {
 | 
						|
                  //
 | 
						|
                  // Advance to the last entry
 | 
						|
                  //
 | 
						|
                  for (MenuRefreshEntry = gMenuRefreshHead;
 | 
						|
                       MenuRefreshEntry->Next != NULL;
 | 
						|
                       MenuRefreshEntry = MenuRefreshEntry->Next
 | 
						|
                      )
 | 
						|
                    ;
 | 
						|
                  MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
 | 
						|
                  ASSERT (MenuRefreshEntry->Next != NULL);
 | 
						|
                  MenuRefreshEntry                    = MenuRefreshEntry->Next;
 | 
						|
                  MenuRefreshEntry->MenuOption        = MenuOption;
 | 
						|
                  MenuRefreshEntry->FileFormTagsHead  = FileFormTagsHead;
 | 
						|
                  MenuRefreshEntry->CurrentColumn     = MenuOption->OptCol;
 | 
						|
                  MenuRefreshEntry->CurrentRow        = MenuOption->Row;
 | 
						|
                  MenuRefreshEntry->CurrentAttribute  = FIELD_TEXT | FIELD_BACKGROUND;
 | 
						|
                }
 | 
						|
              }
 | 
						|
 | 
						|
              Width       = (UINT16) gOptionBlockWidth;
 | 
						|
 | 
						|
              OriginalRow = Row;
 | 
						|
 | 
						|
              for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
 | 
						|
                if ((Temp2 == 0) && (Row <= BottomRow)) {
 | 
						|
                  PrintStringAt (MenuOption->OptCol, Row, OutputString);
 | 
						|
                }
 | 
						|
                //
 | 
						|
                // If there is more string to process print on the next row and increment the Skip value
 | 
						|
                //
 | 
						|
                if (StrLen (&OptionString[Index])) {
 | 
						|
                  if (Temp2 == 0) {
 | 
						|
                    Row++;
 | 
						|
                    //
 | 
						|
                    // Since the Number of lines for this menu entry may or may not be reflected accurately
 | 
						|
                    // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
 | 
						|
                    // some testing to ensure we are keeping this in-sync.
 | 
						|
                    //
 | 
						|
                    // If the difference in rows is greater than or equal to the skip value, increase the skip value
 | 
						|
                    //
 | 
						|
                    if ((Row - OriginalRow) >= MenuOption->Skip) {
 | 
						|
                      MenuOption->Skip++;
 | 
						|
                    }
 | 
						|
                  }
 | 
						|
                }
 | 
						|
 | 
						|
                FreePool (OutputString);
 | 
						|
                if (Temp2 != 0) {
 | 
						|
                  Temp2--;
 | 
						|
                }
 | 
						|
              }
 | 
						|
 | 
						|
              Temp2 = 0;
 | 
						|
              Row   = OriginalRow;
 | 
						|
            }
 | 
						|
            //
 | 
						|
            // If this is a text op with secondary text information
 | 
						|
            //
 | 
						|
            if ((MenuOption->ThisTag->Operand == EFI_IFR_TEXT_OP) && (MenuOption->ThisTag->TextTwo != 0)) {
 | 
						|
              StringPtr   = GetToken (MenuOption->ThisTag->TextTwo, MenuOption->Handle);
 | 
						|
 | 
						|
              Width       = (UINT16) gOptionBlockWidth;
 | 
						|
 | 
						|
              OriginalRow = Row;
 | 
						|
 | 
						|
              for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) {
 | 
						|
                if ((Temp == 0) && (Row <= BottomRow)) {
 | 
						|
                  PrintStringAt (MenuOption->OptCol, Row, OutputString);
 | 
						|
                }
 | 
						|
                //
 | 
						|
                // If there is more string to process print on the next row and increment the Skip value
 | 
						|
                //
 | 
						|
                if (StrLen (&StringPtr[Index])) {
 | 
						|
                  if (Temp2 == 0) {
 | 
						|
                    Row++;
 | 
						|
                    //
 | 
						|
                    // Since the Number of lines for this menu entry may or may not be reflected accurately
 | 
						|
                    // since the prompt might be 1 lines and option might be many, and vice versa, we need to do
 | 
						|
                    // some testing to ensure we are keeping this in-sync.
 | 
						|
                    //
 | 
						|
                    // If the difference in rows is greater than or equal to the skip value, increase the skip value
 | 
						|
                    //
 | 
						|
                    if ((Row - OriginalRow) >= MenuOption->Skip) {
 | 
						|
                      MenuOption->Skip++;
 | 
						|
                    }
 | 
						|
                  }
 | 
						|
                }
 | 
						|
 | 
						|
                FreePool (OutputString);
 | 
						|
                if (Temp2 != 0) {
 | 
						|
                  Temp2--;
 | 
						|
                }
 | 
						|
              }
 | 
						|
 | 
						|
              Row = OriginalRow;
 | 
						|
              FreePool (StringPtr);
 | 
						|
            }
 | 
						|
          } else {
 | 
						|
            //
 | 
						|
            // For now, assume left-justified 72 width max setup entries
 | 
						|
            //
 | 
						|
            PrintStringAt (Col, Row, MenuOption->Description);
 | 
						|
          }
 | 
						|
          //
 | 
						|
          // Tracker 6210 - need to handle the bottom of the display
 | 
						|
          //
 | 
						|
          if (MenuOption->Skip > 1) {
 | 
						|
            Row += MenuOption->Skip - SkipValue;
 | 
						|
            SkipValue = 0;
 | 
						|
          } else {
 | 
						|
            Row += MenuOption->Skip;
 | 
						|
          }
 | 
						|
 | 
						|
          if (Row > BottomRow) {
 | 
						|
            if (!ValueIsScroll (FALSE, Link)) {
 | 
						|
              gDownArrow = TRUE;
 | 
						|
            }
 | 
						|
 | 
						|
            Row = BottomRow + 1;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        if (!ValueIsScroll (TRUE, TopOfScreen)) {
 | 
						|
          gUpArrow = TRUE;
 | 
						|
        }
 | 
						|
 | 
						|
        if (gUpArrow) {
 | 
						|
          gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
 | 
						|
          PrintAt (
 | 
						|
            LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
 | 
						|
            TopRow - SCROLL_ARROW_HEIGHT,
 | 
						|
            (CHAR16 *) L"%c",
 | 
						|
            ARROW_UP
 | 
						|
            );
 | 
						|
          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
 | 
						|
        }
 | 
						|
 | 
						|
        if (gDownArrow) {
 | 
						|
          gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
 | 
						|
          PrintAt (
 | 
						|
            LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
 | 
						|
            BottomRow + SCROLL_ARROW_HEIGHT,
 | 
						|
            (CHAR16 *) L"%c",
 | 
						|
            ARROW_DOWN
 | 
						|
            );
 | 
						|
          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
 | 
						|
        }
 | 
						|
 | 
						|
        if (SavedMenuOption != NULL) {
 | 
						|
          MenuOption = SavedMenuOption;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfRefreshHighLight:
 | 
						|
      ControlFlag = CfUpdateHelpString;
 | 
						|
      //
 | 
						|
      // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily
 | 
						|
      // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.
 | 
						|
      //
 | 
						|
      SavedValue  = Repaint;
 | 
						|
      Repaint     = FALSE;
 | 
						|
 | 
						|
      if (NewPos != NULL) {
 | 
						|
        gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
 | 
						|
        if (SubMenu) {
 | 
						|
          if (gLastOpr && (gEntryNumber != -1)) {
 | 
						|
            MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
            if (gEntryNumber != MenuOption->EntryNumber) {
 | 
						|
              ScreenOperation = UiDown;
 | 
						|
              ControlFlag     = CfScreenOperation;
 | 
						|
              break;
 | 
						|
            } else {
 | 
						|
              gLastOpr = FALSE;
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString);
 | 
						|
          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
 | 
						|
          if (OptionString != NULL) {
 | 
						|
            if (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
 | 
						|
                MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP
 | 
						|
                ) {
 | 
						|
              //
 | 
						|
              // If leading spaces on OptionString - remove the spaces
 | 
						|
              //
 | 
						|
              for (Index = 0; OptionString[Index] == L' '; Index++)
 | 
						|
                ;
 | 
						|
 | 
						|
              for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
 | 
						|
                OptionString[Count] = OptionString[Index];
 | 
						|
                Count++;
 | 
						|
              }
 | 
						|
 | 
						|
              OptionString[Count] = CHAR_NULL;
 | 
						|
            }
 | 
						|
 | 
						|
            Width               = (UINT16) gOptionBlockWidth;
 | 
						|
 | 
						|
            OriginalRow         = MenuOption->Row;
 | 
						|
 | 
						|
            for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
 | 
						|
              if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
 | 
						|
                PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
 | 
						|
              }
 | 
						|
              //
 | 
						|
              // If there is more string to process print on the next row and increment the Skip value
 | 
						|
              //
 | 
						|
              if (StrLen (&OptionString[Index])) {
 | 
						|
                MenuOption->Row++;
 | 
						|
              }
 | 
						|
 | 
						|
              FreePool (OutputString);
 | 
						|
            }
 | 
						|
 | 
						|
            MenuOption->Row = OriginalRow;
 | 
						|
          } else {
 | 
						|
            if (NewLine) {
 | 
						|
              if (MenuOption->ThisTag->GrayOut) {
 | 
						|
                gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
 | 
						|
              } else {
 | 
						|
                if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {
 | 
						|
                  gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND);
 | 
						|
                }
 | 
						|
              }
 | 
						|
 | 
						|
              OriginalRow = MenuOption->Row;
 | 
						|
              Width       = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
 | 
						|
 | 
						|
              for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
 | 
						|
                if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
 | 
						|
                  PrintStringAt (Col, MenuOption->Row, OutputString);
 | 
						|
                }
 | 
						|
                //
 | 
						|
                // If there is more string to process print on the next row and increment the Skip value
 | 
						|
                //
 | 
						|
                if (StrLen (&MenuOption->Description[Index])) {
 | 
						|
                  MenuOption->Row++;
 | 
						|
                }
 | 
						|
 | 
						|
                FreePool (OutputString);
 | 
						|
              }
 | 
						|
 | 
						|
              MenuOption->Row = OriginalRow;
 | 
						|
              gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
 | 
						|
            }
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
 | 
						|
          gST->ConOut->OutputString (gST->ConOut, MenuOption->Description);
 | 
						|
        }
 | 
						|
 | 
						|
        MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
 | 
						|
        if ((gPriorMenuEntry != 0) && (MenuOption->EntryNumber != gPriorMenuEntry) && (NewPos->ForwardLink != &Menu)) {
 | 
						|
          ScreenOperation = UiDown;
 | 
						|
          ControlFlag     = CfScreenOperation;
 | 
						|
          break;
 | 
						|
        } else {
 | 
						|
          gPriorMenuEntry = 0;
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // This is only possible if we entered this page and the first menu option is
 | 
						|
        // a "non-menu" item.  In that case, force it UiDown
 | 
						|
        //
 | 
						|
        if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) {
 | 
						|
          //
 | 
						|
          // If we previously hit an UP command and we are still sitting on a text operation
 | 
						|
          // we must continue going up
 | 
						|
          //
 | 
						|
          if (ScreenOperation == UiUp) {
 | 
						|
            ControlFlag = CfScreenOperation;
 | 
						|
            break;
 | 
						|
          } else {
 | 
						|
            ScreenOperation = UiDown;
 | 
						|
            ControlFlag     = CfScreenOperation;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Set reverse attribute
 | 
						|
        //
 | 
						|
        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);
 | 
						|
        gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
 | 
						|
 | 
						|
        //
 | 
						|
        // Assuming that we have a refresh linked-list created, lets annotate the
 | 
						|
        // appropriate entry that we are highlighting with its new attribute.  Just prior to this
 | 
						|
        // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh
 | 
						|
        //
 | 
						|
        if (gMenuRefreshHead != NULL) {
 | 
						|
          for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {
 | 
						|
            MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND;
 | 
						|
            if (MenuRefreshEntry->MenuOption == MenuOption) {
 | 
						|
              MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        if (SubMenu) {
 | 
						|
          ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString);
 | 
						|
          if (OptionString != NULL) {
 | 
						|
            if (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
 | 
						|
                MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP
 | 
						|
                ) {
 | 
						|
              //
 | 
						|
              // If leading spaces on OptionString - remove the spaces
 | 
						|
              //
 | 
						|
              for (Index = 0; OptionString[Index] == L' '; Index++)
 | 
						|
                ;
 | 
						|
 | 
						|
              for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
 | 
						|
                OptionString[Count] = OptionString[Index];
 | 
						|
                Count++;
 | 
						|
              }
 | 
						|
 | 
						|
              OptionString[Count] = CHAR_NULL;
 | 
						|
            }
 | 
						|
            Width               = (UINT16) gOptionBlockWidth;
 | 
						|
 | 
						|
            OriginalRow         = MenuOption->Row;
 | 
						|
 | 
						|
            for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) {
 | 
						|
              if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
 | 
						|
                PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);
 | 
						|
              }
 | 
						|
              //
 | 
						|
              // If there is more string to process print on the next row and increment the Skip value
 | 
						|
              //
 | 
						|
              if (StrLen (&OptionString[Index])) {
 | 
						|
                MenuOption->Row++;
 | 
						|
              }
 | 
						|
 | 
						|
              FreePool (OutputString);
 | 
						|
            }
 | 
						|
 | 
						|
            MenuOption->Row = OriginalRow;
 | 
						|
          } else {
 | 
						|
            if (NewLine) {
 | 
						|
              OriginalRow = MenuOption->Row;
 | 
						|
 | 
						|
              Width       = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
 | 
						|
 | 
						|
              for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) {
 | 
						|
                if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) {
 | 
						|
                  PrintStringAt (Col, MenuOption->Row, OutputString);
 | 
						|
                }
 | 
						|
                //
 | 
						|
                // If there is more string to process print on the next row and increment the Skip value
 | 
						|
                //
 | 
						|
                if (StrLen (&MenuOption->Description[Index])) {
 | 
						|
                  MenuOption->Row++;
 | 
						|
                }
 | 
						|
 | 
						|
                FreePool (OutputString);
 | 
						|
              }
 | 
						|
 | 
						|
              MenuOption->Row = OriginalRow;
 | 
						|
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          if (((NewPos->ForwardLink != &Menu) && (ScreenOperation == UiDown)) ||
 | 
						|
              ((NewPos->BackLink != &Menu) && (ScreenOperation == UiUp)) ||
 | 
						|
              (ScreenOperation == UiNoOperation)
 | 
						|
              ) {
 | 
						|
            UpdateKeyHelp (MenuOption, FALSE);
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          gST->ConOut->OutputString (gST->ConOut, MenuOption->Description);
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Clear reverse attribute
 | 
						|
        //
 | 
						|
        gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Repaint flag will be used when process CfUpdateHelpString, so restore its value
 | 
						|
      // if we didn't break halfway when process CfRefreshHighLight.
 | 
						|
      //
 | 
						|
      Repaint = SavedValue;
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfUpdateHelpString:
 | 
						|
      ControlFlag = CfPrepareToReadKey;
 | 
						|
 | 
						|
        if (SubMenu &&
 | 
						|
            (Repaint || NewLine ||
 | 
						|
             (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
 | 
						|
             (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) &&
 | 
						|
            !(gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS)) {
 | 
						|
        //
 | 
						|
        // Don't print anything if it is a NULL help token
 | 
						|
        //
 | 
						|
        if (MenuOption->ThisTag->Help == 0x00000000) {
 | 
						|
          StringPtr = (CHAR16 *) L"\0";
 | 
						|
        } else {
 | 
						|
          StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);
 | 
						|
        }
 | 
						|
 | 
						|
        ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow);
 | 
						|
 | 
						|
        gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);
 | 
						|
 | 
						|
        for (Index = 0; Index < BottomRow - TopRow; Index++) {
 | 
						|
          //
 | 
						|
          // Pad String with spaces to simulate a clearing of the previous line
 | 
						|
          //
 | 
						|
          for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth * 2]) / 2 < gHelpBlockWidth;) {
 | 
						|
            StrCat (&FormattedString[Index * gHelpBlockWidth * 2], (CHAR16 *) L" ");
 | 
						|
          }
 | 
						|
 | 
						|
          PrintStringAt (
 | 
						|
            LocalScreen.RightColumn - gHelpBlockWidth,
 | 
						|
            Index + TopRow,
 | 
						|
            &FormattedString[Index * gHelpBlockWidth * 2]
 | 
						|
            );
 | 
						|
        }
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Reset this flag every time we finish using it.
 | 
						|
      //
 | 
						|
      Repaint = FALSE;
 | 
						|
      NewLine = FALSE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfPrepareToReadKey:
 | 
						|
      ControlFlag = CfReadKey;
 | 
						|
 | 
						|
      for (Index = 0; Index < MenuOption->IfrNumber; Index++) {
 | 
						|
        FileFormTags = FileFormTags->NextFile;
 | 
						|
      }
 | 
						|
 | 
						|
      ScreenOperation = UiNoOperation;
 | 
						|
 | 
						|
      Status = gBS->HandleProtocol (
 | 
						|
                      (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle,
 | 
						|
                      &gEfiFormCallbackProtocolGuid,
 | 
						|
                      (VOID **) &FormCallback
 | 
						|
                      );
 | 
						|
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfReadKey:
 | 
						|
      ControlFlag     = CfScreenOperation;
 | 
						|
 | 
						|
      OriginalTimeOut = FrontPageTimeOutValue;
 | 
						|
      do {
 | 
						|
        if (FrontPageTimeOutValue >= 0 && (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) && FrontPageTimeOutValue != (INT16) -1) {
 | 
						|
          //
 | 
						|
          // Remember that if set to 0, must immediately boot an option
 | 
						|
          //
 | 
						|
          if (FrontPageTimeOutValue == 0) {
 | 
						|
            FrontPageTimeOutValue = 0xFFFF;
 | 
						|
            Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
 | 
						|
            if (EFI_ERROR (Status)) {
 | 
						|
              Status = EFI_TIMEOUT;
 | 
						|
            }
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
          Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);
 | 
						|
          if (Status == EFI_TIMEOUT) {
 | 
						|
            EFI_IFR_DATA_ENTRY *DataEntry;
 | 
						|
 | 
						|
            DataEntry = (EFI_IFR_DATA_ENTRY *) (PageData + 1);
 | 
						|
 | 
						|
            PageData->EntryCount  = 1;
 | 
						|
            Count                 = (UINT32) ((OriginalTimeOut - FrontPageTimeOutValue) * 100 / OriginalTimeOut);
 | 
						|
            CopyMem (&DataEntry->Data, &Count, sizeof (UINT32));
 | 
						|
 | 
						|
            if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
 | 
						|
              FormCallback->Callback (
 | 
						|
                              FormCallback,
 | 
						|
                              0xFFFF,
 | 
						|
                              (EFI_IFR_DATA_ARRAY *) PageData,
 | 
						|
                              NULL
 | 
						|
                              );
 | 
						|
            }
 | 
						|
            //
 | 
						|
            // Count down 1 second
 | 
						|
            //
 | 
						|
            FrontPageTimeOutValue--;
 | 
						|
 | 
						|
          } else {
 | 
						|
            ASSERT (!EFI_ERROR (Status));
 | 
						|
            PageData->EntryCount = 0;
 | 
						|
            if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
 | 
						|
              FormCallback->Callback (
 | 
						|
                              FormCallback,
 | 
						|
                              0xFFFE,
 | 
						|
                              (EFI_IFR_DATA_ARRAY *) PageData,
 | 
						|
                              NULL
 | 
						|
                              );
 | 
						|
            }
 | 
						|
 | 
						|
            FrontPageTimeOutValue = 0xFFFF;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // Wait for user's selection, no auto boot
 | 
						|
          //
 | 
						|
          Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0);
 | 
						|
        }
 | 
						|
      } while (Status == EFI_TIMEOUT);
 | 
						|
 | 
						|
      if (gFirstIn) {
 | 
						|
        gFirstIn = FALSE;
 | 
						|
        gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
 | 
						|
        DisableQuietBoot ();
 | 
						|
      }
 | 
						|
 | 
						|
      if (Status == EFI_TIMEOUT) {
 | 
						|
        Key.UnicodeChar = CHAR_CARRIAGE_RETURN;
 | 
						|
      } else {
 | 
						|
        Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
 | 
						|
        //
 | 
						|
        // if we encounter error, continue to read another key in.
 | 
						|
        //
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          ControlFlag = CfReadKey;
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      switch (Key.UnicodeChar) {
 | 
						|
      case CHAR_CARRIAGE_RETURN:
 | 
						|
        Selection       = MenuOption;
 | 
						|
        ScreenOperation = UiSelect;
 | 
						|
        gDirection      = 0;
 | 
						|
        break;
 | 
						|
 | 
						|
      //
 | 
						|
      // We will push the adjustment of these numeric values directly to the input handler
 | 
						|
      //
 | 
						|
      case '+':
 | 
						|
      case '-':
 | 
						|
        if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
 | 
						|
 | 
						|
          if (Key.UnicodeChar == '+') {
 | 
						|
            gDirection = SCAN_RIGHT;
 | 
						|
          } else {
 | 
						|
            gDirection = SCAN_LEFT;
 | 
						|
          }
 | 
						|
 | 
						|
          Status = ProcessOptions (MenuOption, TRUE, FileFormTagsHead, NULL, &OptionString);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
      case '^':
 | 
						|
        ScreenOperation = UiUp;
 | 
						|
        break;
 | 
						|
 | 
						|
      case 'V':
 | 
						|
      case 'v':
 | 
						|
        ScreenOperation = UiDown;
 | 
						|
        break;
 | 
						|
 | 
						|
      case ' ':
 | 
						|
        if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
 | 
						|
          if (SubMenu) {
 | 
						|
            if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !(MenuOption->ThisTag->GrayOut)) {
 | 
						|
              gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
 | 
						|
              gST->ConOut->OutputString (gST->ConOut, MenuOption->Description);
 | 
						|
              Selection       = MenuOption;
 | 
						|
              ScreenOperation = UiSelect;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
      case CHAR_NULL:
 | 
						|
        if (((Key.ScanCode == SCAN_F1) && ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE)) ||
 | 
						|
            ((Key.ScanCode == SCAN_F2) && ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO)) ||
 | 
						|
            ((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) ||
 | 
						|
            ((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN))
 | 
						|
            ) {
 | 
						|
          //
 | 
						|
          // If the function key has been disabled, just ignore the key.
 | 
						|
          //
 | 
						|
        } else {
 | 
						|
          for (Index = 0; Index < sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); Index++) {
 | 
						|
            if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {
 | 
						|
              if ((Key.ScanCode == SCAN_F9) || (Key.ScanCode == SCAN_F10)) {
 | 
						|
                if (SubMenu) {
 | 
						|
                  ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;
 | 
						|
                }
 | 
						|
              } else {
 | 
						|
                ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfScreenOperation:
 | 
						|
      IfrBinary = gBinaryDataHead;
 | 
						|
 | 
						|
      //
 | 
						|
      // Advance to the Ifr we are using
 | 
						|
      //
 | 
						|
      for (Index = 0; Index < gActiveIfr; Index++) {
 | 
						|
        IfrBinary = IfrBinary->Next;
 | 
						|
      }
 | 
						|
 | 
						|
      if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) {
 | 
						|
        //
 | 
						|
        // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset
 | 
						|
        // ignore the selection and go back to reading keys.
 | 
						|
        //
 | 
						|
        if (IsListEmpty (&Menu)) {
 | 
						|
          ControlFlag = CfReadKey;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // if there is nothing logical to place a cursor on, just move on to wait for a key.
 | 
						|
        //
 | 
						|
        for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) {
 | 
						|
          NextMenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
          if (!(NextMenuOption->ThisTag->GrayOut) && (NextMenuOption->ThisTag->Operand != EFI_IFR_SUBTITLE_OP)) {
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        if (Link == &Menu) {
 | 
						|
          ControlFlag = CfPrepareToReadKey;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      for (Index = 0;
 | 
						|
           Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);
 | 
						|
           Index++
 | 
						|
          ) {
 | 
						|
        if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {
 | 
						|
          ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfUiPrevious:
 | 
						|
      ControlFlag = CfCheckSelection;
 | 
						|
      //
 | 
						|
      // Check for tags that might have LATE_CHECK enabled.  If they do, we can't switch pages or save NV data.
 | 
						|
      //
 | 
						|
      if (MenuOption != NULL) {
 | 
						|
        if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) {
 | 
						|
          Selection = NULL;
 | 
						|
          Repaint   = TRUE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (IsListEmpty (&gMenuList)) {
 | 
						|
        Selection = NULL;
 | 
						|
        if (IsListEmpty (&Menu)) {
 | 
						|
          ControlFlag = CfReadKey;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      gLastOpr = TRUE;
 | 
						|
 | 
						|
      while (gMenuRefreshHead != NULL) {
 | 
						|
        OldMenuRefreshEntry = gMenuRefreshHead->Next;
 | 
						|
 | 
						|
        FreePool (gMenuRefreshHead);
 | 
						|
 | 
						|
        gMenuRefreshHead = OldMenuRefreshEntry;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Remove the Cached page entry, free and init the menus, flag Selection as jumping to previous page and a valid Tag
 | 
						|
      //
 | 
						|
      if (SubMenu) {
 | 
						|
        UiRemoveMenuListEntry (MenuOption, &Selection);
 | 
						|
        Selection->Previous = TRUE;
 | 
						|
        UiFreeMenu ();
 | 
						|
        UiInitMenu ();
 | 
						|
      }
 | 
						|
 | 
						|
      gActiveIfr = Selection->IfrNumber;
 | 
						|
      return Selection;
 | 
						|
 | 
						|
    case CfUiSelect:
 | 
						|
      ControlFlag = CfCheckSelection;
 | 
						|
 | 
						|
      ExtractRequestedNvMap (FileFormTags, MenuOption->ThisTag->VariableNumber, &VariableDefinition);
 | 
						|
 | 
						|
      if (SubMenu) {
 | 
						|
        if ((MenuOption->ThisTag->Operand == EFI_IFR_TEXT_OP &&
 | 
						|
            !(MenuOption->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE)) ||
 | 
						|
            (MenuOption->ThisTag->GrayOut) ||
 | 
						|
            (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
 | 
						|
            (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
 | 
						|
            Selection = NULL;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
        NewLine = TRUE;
 | 
						|
        UpdateKeyHelp (MenuOption, TRUE);
 | 
						|
        Status = ProcessOptions (MenuOption, TRUE, FileFormTagsHead, PageData, &OptionString);
 | 
						|
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          Selection = NULL;
 | 
						|
          Repaint   = TRUE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        if (OptionString != NULL) {
 | 
						|
          PrintStringAt (LocalScreen.LeftColumn + gPromptBlockWidth + 1, MenuOption->Row, OptionString);
 | 
						|
        }
 | 
						|
 | 
						|
        if (MenuOption->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
 | 
						|
          Selection = MenuOption;
 | 
						|
        }
 | 
						|
 | 
						|
        if (Selection == NULL) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        Location = (UINT8 *) &PageData->EntryCount;
 | 
						|
 | 
						|
        //
 | 
						|
        // If not a goto, dump single piece of data, otherwise dump everything
 | 
						|
        //
 | 
						|
        if (Selection->ThisTag->Operand == EFI_IFR_REF_OP) {
 | 
						|
          //
 | 
						|
          // Check for tags that might have LATE_CHECK enabled.  If they do, we can't switch pages or save NV data.
 | 
						|
          //
 | 
						|
          if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) {
 | 
						|
            Selection = NULL;
 | 
						|
            Repaint   = TRUE;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
          UiAddMenuListEntry (Selection);
 | 
						|
          gPriorMenuEntry = 0;
 | 
						|
 | 
						|
          //
 | 
						|
          // Now that we added a menu entry specific to a goto, we can always go back when someone hits the UiPrevious
 | 
						|
          //
 | 
						|
          UiMenuList                    = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE);
 | 
						|
          UiMenuList->FormerEntryNumber = MenuOption->EntryNumber;
 | 
						|
 | 
						|
          gLastOpr                      = FALSE;
 | 
						|
 | 
						|
          //
 | 
						|
          // Rewind to the beginning of the menu
 | 
						|
          //
 | 
						|
          for (; NewPos->BackLink != &Menu; NewPos = NewPos->BackLink)
 | 
						|
            ;
 | 
						|
 | 
						|
          //
 | 
						|
          // Get Total Count of Menu entries
 | 
						|
          //
 | 
						|
          for (Count = 1; NewPos->ForwardLink != &Menu; NewPos = NewPos->ForwardLink) {
 | 
						|
            Count++;
 | 
						|
          }
 | 
						|
          //
 | 
						|
          // Rewind to the beginning of the menu
 | 
						|
          //
 | 
						|
          for (; NewPos->BackLink != &Menu; NewPos = NewPos->BackLink)
 | 
						|
            ;
 | 
						|
 | 
						|
          //
 | 
						|
          // Copy the number of entries being described to the PageData location
 | 
						|
          //
 | 
						|
          CopyMem (&Location[0], &Count, sizeof (UINT32));
 | 
						|
 | 
						|
          for (Index = 4; NewPos->ForwardLink != &Menu; Index = Index + MenuOption->ThisTag->StorageWidth + 2) {
 | 
						|
 | 
						|
            MenuOption          = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
            Location[Index]     = MenuOption->ThisTag->Operand;
 | 
						|
            Location[Index + 1] = (UINT8) (MenuOption->ThisTag->StorageWidth + 4);
 | 
						|
            CopyMem (
 | 
						|
              &Location[Index + 4],
 | 
						|
              &VariableDefinition->NvRamMap[MenuOption->ThisTag->StorageStart],
 | 
						|
              MenuOption->ThisTag->StorageWidth
 | 
						|
              );
 | 
						|
            NewPos = NewPos->ForwardLink;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
 | 
						|
          gPriorMenuEntry = MenuOption->EntryNumber;
 | 
						|
 | 
						|
          Count           = 1;
 | 
						|
 | 
						|
          //
 | 
						|
          // Copy the number of entries being described to the PageData location
 | 
						|
          //
 | 
						|
          CopyMem (&Location[0], &Count, sizeof (UINT32));
 | 
						|
 | 
						|
          //
 | 
						|
          // Start at PageData[4] since the EntryCount is a UINT32
 | 
						|
          //
 | 
						|
          Index = 4;
 | 
						|
 | 
						|
          //
 | 
						|
          // Copy data to destination
 | 
						|
          //
 | 
						|
          Location[Index]     = MenuOption->ThisTag->Operand;
 | 
						|
          Location[Index + 1] = (UINT8) (MenuOption->ThisTag->StorageWidth + 4);
 | 
						|
          CopyMem (
 | 
						|
            &Location[Index + 4],
 | 
						|
            &VariableDefinition->NvRamMap[MenuOption->ThisTag->StorageStart],
 | 
						|
            MenuOption->ThisTag->StorageWidth
 | 
						|
            );
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfUiReset:
 | 
						|
      ControlFlag = CfCheckSelection;
 | 
						|
      gLastOpr    = FALSE;
 | 
						|
      if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // If NV flag is up, prompt user
 | 
						|
      //
 | 
						|
      if (gNvUpdateRequired) {
 | 
						|
        Status      = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
 | 
						|
 | 
						|
        YesResponse = gYesResponse[0];
 | 
						|
        NoResponse  = gNoResponse[0];
 | 
						|
 | 
						|
        do {
 | 
						|
          CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString);
 | 
						|
        } while
 | 
						|
        (
 | 
						|
          (Key.ScanCode != SCAN_ESC) &&
 | 
						|
          ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&
 | 
						|
          ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))
 | 
						|
        );
 | 
						|
 | 
						|
        //
 | 
						|
        // If the user hits the YesResponse key
 | 
						|
        //
 | 
						|
        if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
 | 
						|
        } else {
 | 
						|
          Repaint = TRUE;
 | 
						|
          NewLine = TRUE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Check for tags that might have LATE_CHECK enabled.  If they do, we can't switch pages or save NV data.
 | 
						|
      //
 | 
						|
      if (MenuOption != NULL) {
 | 
						|
        if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) {
 | 
						|
          Selection = NULL;
 | 
						|
          Repaint   = TRUE;
 | 
						|
          NewLine   = TRUE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
 | 
						|
      gST->ConOut->EnableCursor (gST->ConOut, TRUE);
 | 
						|
 | 
						|
      if (SubMenu) {
 | 
						|
        UiFreeMenuList ();
 | 
						|
        gST->ConOut->ClearScreen (gST->ConOut);
 | 
						|
        return NULL;
 | 
						|
      }
 | 
						|
 | 
						|
      UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE);
 | 
						|
      UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->Flags, FALSE);
 | 
						|
 | 
						|
      if (IfrBinary->UnRegisterOnExit) {
 | 
						|
        Hii->RemovePack (Hii, MenuOption->Handle);
 | 
						|
      }
 | 
						|
 | 
						|
      UiFreeMenu ();
 | 
						|
 | 
						|
      //
 | 
						|
      // Clean up the allocated data buffers
 | 
						|
      //
 | 
						|
      FreeData (FileFormTagsHead, FormattedString, OptionString);
 | 
						|
 | 
						|
      gST->ConOut->ClearScreen (gST->ConOut);
 | 
						|
      return NULL;
 | 
						|
 | 
						|
    case CfUiLeft:
 | 
						|
      ControlFlag = CfCheckSelection;
 | 
						|
      if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
 | 
						|
        if (MenuOption->Skip == 1) {
 | 
						|
          //
 | 
						|
          // In the tail of the Date/Time op-code set, go left.
 | 
						|
          //
 | 
						|
          NewPos = NewPos->BackLink;
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // In the middle of the Data/Time op-code set, go left.
 | 
						|
          //
 | 
						|
          NextMenuOption = CR (NewPos->ForwardLink, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
          if (NextMenuOption->Skip == 1) {
 | 
						|
            NewPos = NewPos->BackLink;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfUiRight:
 | 
						|
      ControlFlag = CfCheckSelection;
 | 
						|
      if ((MenuOption->Skip == 0) &&
 | 
						|
          ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP))
 | 
						|
          ) {
 | 
						|
        //
 | 
						|
        // We are in the head or middle of the Date/Time op-code set, advance right.
 | 
						|
        //
 | 
						|
        NewPos = NewPos->ForwardLink;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfUiUp:
 | 
						|
      ControlFlag = CfCheckSelection;
 | 
						|
 | 
						|
      if (NewPos->BackLink != &Menu) {
 | 
						|
        NewLine = TRUE;
 | 
						|
        //
 | 
						|
        // Adjust Date/Time position before we advance forward.
 | 
						|
        //
 | 
						|
        AdjustDateAndTimePosition (TRUE, &NewPos);
 | 
						|
 | 
						|
        //
 | 
						|
        // Caution that we have already rewind to the top, don't go backward in this situation.
 | 
						|
        //
 | 
						|
        if (NewPos->BackLink != &Menu) {
 | 
						|
          NewPos = NewPos->BackLink;
 | 
						|
        }
 | 
						|
 | 
						|
        PreviousMenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
 | 
						|
        //
 | 
						|
        // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
 | 
						|
        // to be one that back to the previous set of op-codes, we need to advance to the sencond
 | 
						|
        // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
 | 
						|
        // checking can be done.
 | 
						|
        //
 | 
						|
        DataAndTimeLineNumberPad = AdjustDateAndTimePosition (TRUE, &NewPos);
 | 
						|
 | 
						|
        if (SubMenu) {
 | 
						|
          //
 | 
						|
          // If the previous MenuOption contains a display-only op-code, skip to the next one
 | 
						|
          //
 | 
						|
          if (PreviousMenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || PreviousMenuOption->ThisTag->GrayOut) {
 | 
						|
            //
 | 
						|
            // This is ok as long as not at the end of the list
 | 
						|
            //
 | 
						|
            if (NewPos->BackLink == &Menu) {
 | 
						|
              //
 | 
						|
              // If we are at the start of the list, then this list must start with a display only
 | 
						|
              // piece of data, so do not allow the backward motion
 | 
						|
              //
 | 
						|
              ScreenOperation = UiDown;
 | 
						|
 | 
						|
              if (PreviousMenuOption->Row <= TopRow) {
 | 
						|
                if (TopOfScreen->BackLink != &Menu) {
 | 
						|
                  TopOfScreen = TopOfScreen->BackLink;
 | 
						|
                  Repaint     = TRUE;
 | 
						|
                }
 | 
						|
              }
 | 
						|
 | 
						|
              UpdateStatusBar (INPUT_ERROR, PreviousMenuOption->ThisTag->Flags, FALSE);
 | 
						|
              break;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Check the previous menu entry to see if it was a zero-length advance.  If it was,
 | 
						|
        // don't worry about a redraw.
 | 
						|
        //
 | 
						|
        if ((MenuOption->Row - PreviousMenuOption->Skip - DataAndTimeLineNumberPad < TopRow) ||
 | 
						|
            (PreviousMenuOption->Skip > MenuOption->Row)
 | 
						|
            ) {
 | 
						|
          do {
 | 
						|
            if (TopOfScreen->BackLink == &Menu) {
 | 
						|
              break;
 | 
						|
            }
 | 
						|
 | 
						|
            Repaint = TRUE;
 | 
						|
 | 
						|
            //
 | 
						|
            // Is the current top of screen a zero-advance op-code?
 | 
						|
            // If so, keep moving forward till we hit a >0 advance op-code
 | 
						|
            //
 | 
						|
            SavedMenuOption = CR (TopOfScreen->BackLink, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
            TopOfScreen     = TopOfScreen->BackLink;
 | 
						|
          } while (SavedMenuOption->Skip == 0);
 | 
						|
          //
 | 
						|
          // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
 | 
						|
          //
 | 
						|
          AdjustDateAndTimePosition (TRUE, &TopOfScreen);
 | 
						|
        }
 | 
						|
 | 
						|
        UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE);
 | 
						|
      } else {
 | 
						|
        if (SubMenu) {
 | 
						|
          SavedMenuOption = MenuOption;
 | 
						|
          MenuOption      = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
          if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) {
 | 
						|
            //
 | 
						|
            // If we are at the end of the list and sitting on a text op, we need to more forward
 | 
						|
            //
 | 
						|
            ScreenOperation = UiDown;
 | 
						|
            ControlFlag     = CfScreenOperation;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
          MenuOption = SavedMenuOption;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfUiPageUp:
 | 
						|
      ControlFlag     = CfCheckSelection;
 | 
						|
 | 
						|
      SavedListEntry  = NewPos;
 | 
						|
      Link            = TopOfScreen;
 | 
						|
      for (Index = BottomRow; Index >= TopRow + 1; Index -= MenuOption->Skip) {
 | 
						|
        if (Link->BackLink == &Menu) {
 | 
						|
          TopOfScreen = Link;
 | 
						|
          Link        = SavedListEntry;
 | 
						|
          MenuOption  = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        NewLine         = TRUE;
 | 
						|
        Repaint         = TRUE;
 | 
						|
        Link            = Link->BackLink;
 | 
						|
        MenuOption      = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
        TopOfScreen     = Link;
 | 
						|
        SavedListEntry  = Link;
 | 
						|
      }
 | 
						|
 | 
						|
      NewPos = Link;
 | 
						|
 | 
						|
      //
 | 
						|
      // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
 | 
						|
      // Don't do this when we are already in the first page.
 | 
						|
      //
 | 
						|
      if (Repaint) {
 | 
						|
        AdjustDateAndTimePosition (TRUE, &TopOfScreen);
 | 
						|
        AdjustDateAndTimePosition (TRUE, &NewPos);
 | 
						|
        MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfUiPageDown:
 | 
						|
      ControlFlag     = CfCheckSelection;
 | 
						|
 | 
						|
      SavedListEntry  = NewPos;
 | 
						|
      Link            = TopOfScreen;
 | 
						|
      NewPos          = TopOfScreen;
 | 
						|
      for (Index = TopRow; Index <= BottomRow - 1; Index += MenuOption->Skip) {
 | 
						|
        if (NewPos->ForwardLink == &Menu) {
 | 
						|
          NewPos      = SavedListEntry;
 | 
						|
          MenuOption  = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
          Link        = TopOfScreen;
 | 
						|
          NewLine     = FALSE;
 | 
						|
          Repaint     = FALSE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        NewLine     = TRUE;
 | 
						|
        Repaint     = TRUE;
 | 
						|
        MenuOption  = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
        NewPos      = NewPos->ForwardLink;
 | 
						|
        Link        = NewPos;
 | 
						|
      }
 | 
						|
 | 
						|
      TopOfScreen = Link;
 | 
						|
 | 
						|
      //
 | 
						|
      // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
 | 
						|
      // Don't do this when we are already in the last page.
 | 
						|
      //
 | 
						|
      if (Repaint) {
 | 
						|
        AdjustDateAndTimePosition (TRUE, &TopOfScreen);
 | 
						|
        AdjustDateAndTimePosition (TRUE, &NewPos);
 | 
						|
        MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfUiDown:
 | 
						|
      ControlFlag = CfCheckSelection;
 | 
						|
      //
 | 
						|
      // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
 | 
						|
      // to be one that progresses to the next set of op-codes, we need to advance to the last
 | 
						|
      // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate
 | 
						|
      // checking can be done.  The only other logic we need to introduce is that if a Date/Time
 | 
						|
      // op-code is the last entry in the menu, we need to rewind back to the first op-code of
 | 
						|
      // the Date/Time op-code.
 | 
						|
      //
 | 
						|
      DataAndTimeLineNumberPad = AdjustDateAndTimePosition (FALSE, &NewPos);
 | 
						|
 | 
						|
      if (NewPos->ForwardLink != &Menu) {
 | 
						|
        NewLine         = TRUE;
 | 
						|
        NewPos          = NewPos->ForwardLink;
 | 
						|
        NextMenuOption  = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
 | 
						|
        if (SubMenu) {
 | 
						|
          //
 | 
						|
          // If the next MenuOption contains a display-only op-code, skip to the next one
 | 
						|
          // Also if the next MenuOption is date or time,
 | 
						|
          //
 | 
						|
          if (NextMenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || NextMenuOption->ThisTag->GrayOut) {
 | 
						|
            //
 | 
						|
            // This is ok as long as not at the end of the list
 | 
						|
            //
 | 
						|
            if (NewPos == &Menu) {
 | 
						|
              //
 | 
						|
              // If we are at the end of the list, then this list must end with a display only
 | 
						|
              // piece of data, so do not allow the forward motion
 | 
						|
              //
 | 
						|
              UpdateStatusBar (INPUT_ERROR, NextMenuOption->ThisTag->Flags, FALSE);
 | 
						|
              NewPos          = NewPos->BackLink;
 | 
						|
              ScreenOperation = UiUp;
 | 
						|
              break;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // An option might be multi-line, so we need to reflect that data in the overall skip value
 | 
						|
        //
 | 
						|
        UpdateOptionSkipLines (PageData, NextMenuOption, FileFormTagsHead, &OptionString, SkipValue);
 | 
						|
 | 
						|
        if (NextMenuOption->Skip > 1) {
 | 
						|
          Temp = MenuOption->Row + MenuOption->Skip + NextMenuOption->Skip - 1;
 | 
						|
        } else {
 | 
						|
          Temp = MenuOption->Row + MenuOption->Skip + DataAndTimeLineNumberPad;
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // If we are going to scroll
 | 
						|
        //
 | 
						|
        if (Temp > BottomRow) {
 | 
						|
          do {
 | 
						|
            //
 | 
						|
            // Is the current top of screen a zero-advance op-code?
 | 
						|
            // If so, keep moving forward till we hit a >0 advance op-code
 | 
						|
            //
 | 
						|
            SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
 | 
						|
            //
 | 
						|
            // If bottom op-code is more than one line or top op-code is more than one line
 | 
						|
            //
 | 
						|
            if ((NextMenuOption->Skip > 1) || (MenuOption->Skip > 1)) {
 | 
						|
              //
 | 
						|
              // Is the bottom op-code greater than or equal in size to the top op-code?
 | 
						|
              //
 | 
						|
              if ((Temp - BottomRow) >= (SavedMenuOption->Skip - OldSkipValue)) {
 | 
						|
                //
 | 
						|
                // Skip the top op-code
 | 
						|
                //
 | 
						|
                TopOfScreen     = TopOfScreen->ForwardLink;
 | 
						|
                Difference      = (Temp - BottomRow) - (SavedMenuOption->Skip - OldSkipValue);
 | 
						|
 | 
						|
                OldSkipValue    = Difference;
 | 
						|
 | 
						|
                SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
 | 
						|
                //
 | 
						|
                // If we have a remainder, skip that many more op-codes until we drain the remainder
 | 
						|
                //
 | 
						|
                for (;
 | 
						|
                     Difference >= (INTN) SavedMenuOption->Skip;
 | 
						|
                     Difference = Difference - (INTN) SavedMenuOption->Skip
 | 
						|
                    ) {
 | 
						|
                  //
 | 
						|
                  // Since the Difference is greater than or equal to this op-code's skip value, skip it
 | 
						|
                  //
 | 
						|
                  TopOfScreen     = TopOfScreen->ForwardLink;
 | 
						|
                  SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
                  if (Difference < (INTN) SavedMenuOption->Skip) {
 | 
						|
                    Difference = SavedMenuOption->Skip - Difference - 1;
 | 
						|
                    break;
 | 
						|
                  } else {
 | 
						|
                    if (Difference == (INTN) SavedMenuOption->Skip) {
 | 
						|
                      TopOfScreen     = TopOfScreen->ForwardLink;
 | 
						|
                      SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
                      Difference      = SavedMenuOption->Skip - Difference;
 | 
						|
                      break;
 | 
						|
                    }
 | 
						|
                  }
 | 
						|
                }
 | 
						|
                //
 | 
						|
                // Since we will act on this op-code in the next routine, and increment the
 | 
						|
                // SkipValue, set the skips to one less than what is required.
 | 
						|
                //
 | 
						|
                SkipValue = Difference - 1;
 | 
						|
 | 
						|
              } else {
 | 
						|
                //
 | 
						|
                // Since we will act on this op-code in the next routine, and increment the
 | 
						|
                // SkipValue, set the skips to one less than what is required.
 | 
						|
                //
 | 
						|
                SkipValue = OldSkipValue + (Temp - BottomRow) - 1;
 | 
						|
              }
 | 
						|
            } else {
 | 
						|
              if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) {
 | 
						|
                TopOfScreen = TopOfScreen->ForwardLink;
 | 
						|
                break;
 | 
						|
              } else {
 | 
						|
                SkipValue = OldSkipValue;
 | 
						|
              }
 | 
						|
            }
 | 
						|
            //
 | 
						|
            // If the op-code at the top of the screen is more than one line, let's not skip it yet
 | 
						|
            // Let's set a skip flag to smoothly scroll the top of the screen.
 | 
						|
            //
 | 
						|
            if (SavedMenuOption->Skip > 1) {
 | 
						|
              if (SavedMenuOption == NextMenuOption) {
 | 
						|
                SkipValue = 0;
 | 
						|
              } else {
 | 
						|
                SkipValue++;
 | 
						|
              }
 | 
						|
            } else {
 | 
						|
              SkipValue   = 0;
 | 
						|
              TopOfScreen = TopOfScreen->ForwardLink;
 | 
						|
            }
 | 
						|
          } while (SavedMenuOption->Skip == 0);
 | 
						|
 | 
						|
          Repaint       = TRUE;
 | 
						|
          OldSkipValue  = SkipValue;
 | 
						|
        }
 | 
						|
 | 
						|
        UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE);
 | 
						|
 | 
						|
      } else {
 | 
						|
        if (SubMenu) {
 | 
						|
          SavedMenuOption = MenuOption;
 | 
						|
          MenuOption      = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
          if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) {
 | 
						|
            //
 | 
						|
            // If we are at the end of the list and sitting on a text op, we need to more forward
 | 
						|
            //
 | 
						|
            ScreenOperation = UiUp;
 | 
						|
            ControlFlag     = CfScreenOperation;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
          MenuOption = SavedMenuOption;
 | 
						|
          //
 | 
						|
          // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
 | 
						|
          //
 | 
						|
          AdjustDateAndTimePosition (TRUE, &NewPos);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfUiSave:
 | 
						|
      ControlFlag = CfCheckSelection;
 | 
						|
      //
 | 
						|
      // Check for tags that might have LATE_CHECK enabled.  If they do, we can't switch pages or save NV data.
 | 
						|
      //
 | 
						|
      if (MenuOption != NULL) {
 | 
						|
        if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) {
 | 
						|
          Selection = NULL;
 | 
						|
          Repaint   = TRUE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // If callbacks are active, and the callback has a Write method, try to use it
 | 
						|
      //
 | 
						|
      if (FileFormTags->VariableDefinitions->VariableName == NULL) {
 | 
						|
        if ((FormCallback != NULL) && (FormCallback->NvWrite != NULL)) {
 | 
						|
          Status = FormCallback->NvWrite (
 | 
						|
                                  FormCallback,
 | 
						|
                                  (CHAR16 *) L"Setup",
 | 
						|
                                  &FileFormTags->FormTags.Tags[0].GuidValue,
 | 
						|
                                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
 | 
						|
                                  VariableDefinition->VariableSize,
 | 
						|
                                  (VOID *) VariableDefinition->NvRamMap,
 | 
						|
                                  &gResetRequired
 | 
						|
                                  );
 | 
						|
 | 
						|
        } else {
 | 
						|
          Status = gRT->SetVariable (
 | 
						|
                          (CHAR16 *) L"Setup",
 | 
						|
                          &FileFormTags->FormTags.Tags[0].GuidValue,
 | 
						|
                          EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
 | 
						|
                          VariableDefinition->VariableSize,
 | 
						|
                          (VOID *) VariableDefinition->NvRamMap
 | 
						|
                          );
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        VariableDefinition = FileFormTags->VariableDefinitions;
 | 
						|
 | 
						|
        for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
 | 
						|
          if ((FormCallback != NULL) && (FormCallback->NvWrite != NULL)) {
 | 
						|
            Status = FormCallback->NvWrite (
 | 
						|
                                    FormCallback,
 | 
						|
                                    VariableDefinition->VariableName,
 | 
						|
                                    &VariableDefinition->Guid,
 | 
						|
                                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
 | 
						|
                                    VariableDefinition->VariableSize,
 | 
						|
                                    (VOID *) VariableDefinition->NvRamMap,
 | 
						|
                                    &gResetRequired
 | 
						|
                                    );
 | 
						|
 | 
						|
          } else {
 | 
						|
            Status = gRT->SetVariable (
 | 
						|
                            VariableDefinition->VariableName,
 | 
						|
                            &VariableDefinition->Guid,
 | 
						|
                            EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
 | 
						|
                            VariableDefinition->VariableSize,
 | 
						|
                            (VOID *) VariableDefinition->NvRamMap
 | 
						|
                            );
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE);
 | 
						|
      UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->Flags, FALSE);
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfUiDefault:
 | 
						|
      ControlFlag = CfCheckSelection;
 | 
						|
 | 
						|
      NvMapListHead = NULL;
 | 
						|
 | 
						|
      Status = Hii->GetDefaultImage (Hii, MenuOption->Handle, EFI_IFR_FLAG_DEFAULT, &NvMapListHead);
 | 
						|
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        ASSERT_EFI_ERROR (NULL != NvMapListHead);
 | 
						|
 | 
						|
        NvMapListNode = NvMapListHead;
 | 
						|
 | 
						|
        while (NULL != NvMapListNode) {
 | 
						|
          if (FileFormTags->VariableDefinitions->VariableId == NvMapListNode->VariablePack->VariableId) {
 | 
						|
            NvMap     = (VOID *) ((CHAR8 *) NvMapListNode->VariablePack + sizeof (EFI_HII_VARIABLE_PACK) + NvMapListNode->VariablePack->VariableNameLength);
 | 
						|
            NvMapSize = NvMapListNode->VariablePack->Header.Length  - sizeof (EFI_HII_VARIABLE_PACK) - NvMapListNode->VariablePack->VariableNameLength;
 | 
						|
            break;
 | 
						|
            }
 | 
						|
          NvMapListNode = NvMapListNode->NextVariablePack;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // Free the buffer that was allocated.
 | 
						|
        //
 | 
						|
        FreePool (FileFormTags->VariableDefinitions->NvRamMap);
 | 
						|
        FreePool (FileFormTags->VariableDefinitions->FakeNvRamMap);
 | 
						|
 | 
						|
        //
 | 
						|
        // Allocate, copy the NvRamMap.
 | 
						|
        //
 | 
						|
        FileFormTags->VariableDefinitions->VariableFakeSize = (UINT16) (FileFormTags->VariableDefinitions->VariableFakeSize - FileFormTags->VariableDefinitions->VariableSize);
 | 
						|
        FileFormTags->VariableDefinitions->VariableSize = (UINT16) NvMapSize;
 | 
						|
        FileFormTags->VariableDefinitions->VariableFakeSize = (UINT16) (FileFormTags->VariableDefinitions->VariableFakeSize + FileFormTags->VariableDefinitions->VariableSize);
 | 
						|
 | 
						|
        FileFormTags->VariableDefinitions->NvRamMap = AllocateZeroPool (FileFormTags->VariableDefinitions->VariableSize);
 | 
						|
        ASSERT (FileFormTags->VariableDefinitions->NvRamMap != NULL);
 | 
						|
 | 
						|
        FileFormTags->VariableDefinitions->FakeNvRamMap = AllocateZeroPool (NvMapSize + FileFormTags->VariableDefinitions->VariableFakeSize);
 | 
						|
        ASSERT (FileFormTags->VariableDefinitions->FakeNvRamMap != NULL);
 | 
						|
 | 
						|
        CopyMem (FileFormTags->VariableDefinitions->NvRamMap, NvMap, NvMapSize);
 | 
						|
        FreePool (NvMapListHead);
 | 
						|
      }
 | 
						|
 | 
						|
      UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->Flags, TRUE);
 | 
						|
      Repaint = TRUE;
 | 
						|
      //
 | 
						|
      // After the repaint operation, we should refresh the highlight.
 | 
						|
      //
 | 
						|
      NewLine = TRUE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfUiNoOperation:
 | 
						|
      ControlFlag = CfCheckSelection;
 | 
						|
      break;
 | 
						|
 | 
						|
    case CfExit:
 | 
						|
      while (gMenuRefreshHead != NULL) {
 | 
						|
        OldMenuRefreshEntry = gMenuRefreshHead->Next;
 | 
						|
 | 
						|
        FreePool (gMenuRefreshHead);
 | 
						|
 | 
						|
        gMenuRefreshHead = OldMenuRefreshEntry;
 | 
						|
      }
 | 
						|
 | 
						|
      gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);
 | 
						|
      gST->ConOut->EnableCursor (gST->ConOut, TRUE);
 | 
						|
      gST->ConOut->OutputString (gST->ConOut, (CHAR16 *) L"\n");
 | 
						|
 | 
						|
      gActiveIfr = MenuOption->IfrNumber;
 | 
						|
      return Selection;
 | 
						|
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
ValueIsScroll (
 | 
						|
  IN  BOOLEAN                 Direction,
 | 
						|
  IN  LIST_ENTRY              *CurrentPos
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Determine if the menu is the last menu that can be selected.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Direction - the scroll direction. False is down. True is up.
 | 
						|
 | 
						|
Returns:
 | 
						|
  FALSE -- the menu isn't the last menu that can be selected.
 | 
						|
  TRUE  -- the menu is the last menu that can be selected.
 | 
						|
--*/
 | 
						|
{
 | 
						|
  LIST_ENTRY      *Temp;
 | 
						|
  UI_MENU_OPTION  *MenuOption;
 | 
						|
  MenuOption  = NULL;
 | 
						|
 | 
						|
  Temp        = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;
 | 
						|
 | 
						|
  if (Temp == &Menu) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  for (; Temp != &Menu; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) {
 | 
						|
    MenuOption = CR (Temp, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
    if (!(MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut)) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
UINTN
 | 
						|
AdjustDateAndTimePosition (
 | 
						|
  IN  BOOLEAN                 DirectionUp,
 | 
						|
  IN  LIST_ENTRY              **CurrentPosition
 | 
						|
  )
 | 
						|
/*++
 | 
						|
Routine Description:
 | 
						|
  Adjust Data and Time tag position accordingly.
 | 
						|
  Data format :      [01/02/2004]      [11:22:33]
 | 
						|
  Line number :        0  0    1         0  0  1
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Direction - the up or down direction. False is down. True is up.
 | 
						|
  CurrentPos - Current position.
 | 
						|
 | 
						|
Returns:
 | 
						|
  Return line number to pad. It is possible that we stand on a zero-advance
 | 
						|
  data or time opcode, so pad one line when we judge if we are going to scroll outside.
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN           Count;
 | 
						|
  LIST_ENTRY      *NewPosition;
 | 
						|
  UI_MENU_OPTION  *MenuOption;
 | 
						|
  UINTN           PadLineNumber;
 | 
						|
 | 
						|
  PadLineNumber = 0;
 | 
						|
  NewPosition   = *CurrentPosition;
 | 
						|
  MenuOption    = CR (NewPosition, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
 | 
						|
  if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
 | 
						|
    //
 | 
						|
    // Calculate the distance from current position to the last Date/Time op-code.
 | 
						|
    //
 | 
						|
    Count = 0;
 | 
						|
    while (MenuOption->ThisTag->NumberOfLines == 0) {
 | 
						|
      Count++;
 | 
						|
      NewPosition   = NewPosition->ForwardLink;
 | 
						|
      MenuOption    = CR (NewPosition, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);
 | 
						|
      PadLineNumber = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    NewPosition = *CurrentPosition;
 | 
						|
    if (DirectionUp) {
 | 
						|
      //
 | 
						|
      // Since the behavior of hitting the up arrow on a Date/Time op-code is intended
 | 
						|
      // to be one that back to the previous set of op-codes, we need to advance to the first
 | 
						|
      // Date/Time op-code and leave the remaining logic in CfUiUp intact so the appropriate
 | 
						|
      // checking can be done.
 | 
						|
      //
 | 
						|
      while (Count++ < 2) {
 | 
						|
        NewPosition = NewPosition->BackLink;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Since the behavior of hitting the down arrow on a Date/Time op-code is intended
 | 
						|
      // to be one that progresses to the next set of op-codes, we need to advance to the last
 | 
						|
      // Date/Time op-code and leave the remaining logic in CfUiDown intact so the appropriate
 | 
						|
      // checking can be done.
 | 
						|
      //
 | 
						|
      while (Count-- > 0) {
 | 
						|
        NewPosition = NewPosition->ForwardLink;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    *CurrentPosition = NewPosition;
 | 
						|
  }
 | 
						|
 | 
						|
  return PadLineNumber;
 | 
						|
}
 |