Reviewed-by: Jaben Carsey <jaben.car...@intel.com>

> -----Original Message-----
> From: Ni, Ruiyu
> Sent: Monday, February 12, 2018 7:34 AM
> To: edk2-devel@lists.01.org
> Cc: Felix <fel...@mail.ru>; Carsey, Jaben <jaben.car...@intel.com>
> Subject: [PATCH] ShellPkg/[hex]edit: use SimpleTextInEx to read console
> Importance: High
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=682
> 
> Edit and HexEdit commands assume that SimpleTxtIn translates
> Ctrl+<Alpha-Key> key combinations into Unicode control characters
> (0x1-0x1A).
> 
> Such translation does not seem to be required by the UEFI spec.
> Shell should not rely on implementation specific behavior.
> It should instead use SimpleTextInEx to read Ctrl+<Alpha-Key> key
> combinations.
> 
> The patch changes edit and hexedit to only consumes SimpleTextInEx.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Ruiyu Ni <ruiyu...@intel.com>
> Reported-by: Felix <fel...@mail.ru>
> Cc: Felix <fel...@mail.ru>
> Cc: Jaben Carsey <jaben.car...@intel.com>
> ---
>  .../Edit/MainTextEditor.c                          | 135 +++++++++-----
>  .../Edit/TextEditorTypes.h                         |  21 ++-
>  .../UefiShellDebug1CommandsLib/EditInputBar.c      |  34 +++-
>  .../UefiShellDebug1CommandsLib/EditInputBar.h      |   6 +-
>  .../UefiShellDebug1CommandsLib/EditMenuBar.c       |  38 +++-
>  .../UefiShellDebug1CommandsLib/EditMenuBar.h       |   6 +-
>  .../HexEdit/HexEditorTypes.h                       |  25 +--
>  .../HexEdit/MainHexEditor.c                        | 205 
> +++++++++++++--------
>  8 files changed, 309 insertions(+), 161 deletions(-)
> 
> diff --git
> a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
> b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
> index 14f51dff19..a197f80a40 100644
> --- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
> +++
> b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
> @@ -1,7 +1,7 @@
>  /** @file
>    Implements editor interface functions.
> 
> -  Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved. <BR>
> +  Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD
> License
>    which accompanies this distribution.  The full text of the license may be
> found at
> @@ -1362,7 +1362,9 @@ MainCommandDisplayHelp (
>  {
>    INT32           CurrentLine;
>    CHAR16          *InfoString;
> -  EFI_INPUT_KEY   Key;
> +  EFI_KEY_DATA    KeyData;
> +  EFI_STATUS      Status;
> +  UINTN           EventIndex;
> 
>    //
>    // print helpInfo
> @@ -1371,14 +1373,39 @@ MainCommandDisplayHelp (
>      InfoString = HiiGetString(gShellDebug1HiiHandle,
> MainMenuHelpInfo[CurrentLine], NULL);
>      ShellPrintEx (0, CurrentLine+1, L"%E%s%N", InfoString);
>    }
> -
> +
>    //
>    // scan for ctrl+w
>    //
> -  do {
> -    gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
> -  } while(SCAN_CONTROL_W != Key.UnicodeChar);
> +  while (TRUE) {
> +    Status = gBS->WaitForEvent (1, &MainEditor.TextInputEx->WaitForKeyEx,
> &EventIndex);
> +    if (EFI_ERROR (Status) || (EventIndex != 0)) {
> +      continue;
> +    }
> +    Status = MainEditor.TextInputEx->ReadKeyStrokeEx
> (MainEditor.TextInputEx, &KeyData);
> +    if (EFI_ERROR (Status)) {
> +      continue;
> +    }
> 
> +    if ((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) {
> +      //
> +      // For consoles that don't support shift state reporting,
> +      // CTRL+W is translated to L'W' - L'A' + 1.
> +      //
> +      if (KeyData.Key.UnicodeChar == L'W' - L'A' + 1) {
> +        break;
> +      }
> +    } else if (((KeyData.KeyState.KeyShiftState &
> (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) &&
> +               ((KeyData.KeyState.KeyShiftState & ~(EFI_SHIFT_STATE_VALID |
> EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) == 0)) {
> +      //
> +      // For consoles that supports shift state reporting,
> +      // make sure that only CONTROL shift key is pressed.
> +      //
> +      if ((KeyData.Key.UnicodeChar == 'w') || (KeyData.Key.UnicodeChar ==
> 'W')) {
> +        break;
> +      }
> +    }
> +  }
>    //
>    // update screen with file buffer's info
>    //
> @@ -1407,6 +1434,7 @@ EFI_EDITOR_GLOBAL_EDITOR      MainEditorConst =
> {
>      0
>    },
>    NULL,
> +  NULL,
>    FALSE,
>    NULL
>  };
> @@ -1452,6 +1480,19 @@ MainEditorInit (
>          &(MainEditor.ScreenSize.Row)
>          );
> 
> +  //
> +  // Find TextInEx in System Table ConsoleInHandle
> +  // Per UEFI Spec, TextInEx is required for a console capable platform.
> +  //
> +  Status = gBS->HandleProtocol (
> +              gST->ConsoleInHandle,
> +              &gEfiSimpleTextInputExProtocolGuid,
> +              (VOID**)&MainEditor.TextInputEx
> +              );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
>    //
>    // Find mouse in System Table ConsoleInHandle
>    //
> @@ -1521,7 +1562,7 @@ MainEditorInit (
>      return EFI_LOAD_ERROR;
>    }
> 
> -  InputBarInit ();
> +  InputBarInit (MainEditor.TextInputEx);
> 
>    Status = FileBufferInit ();
>    if (EFI_ERROR (Status)) {
> @@ -1794,9 +1835,11 @@ MainEditorKeyInput (
>    VOID
>    )
>  {
> -  EFI_INPUT_KEY             Key;
> +  EFI_KEY_DATA              KeyData;
>    EFI_STATUS                Status;
>    EFI_SIMPLE_POINTER_STATE  MouseState;
> +  UINTN                     EventIndex;
> +  BOOLEAN                   NoShiftState;
> 
>    do {
> 
> @@ -1831,46 +1874,52 @@ MainEditorKeyInput (
>        }
>      }
> 
> -    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
> -    if (!EFI_ERROR (Status)) {
> -      //
> -      // dispatch to different components' key handling function
> -      // so not everywhere has to set this variable
> -      //
> -      FileBufferMouseNeedRefresh = TRUE;
> -      //
> -      // clear previous status string
> -      //
> -      StatusBarSetRefresh();
> -
> -      //
> -      // dispatch to different components' key handling function
> -      //
> -      if (EFI_NOT_FOUND != MenuBarDispatchControlHotKey(&Key)) {
> -        Status = EFI_SUCCESS;
> -      } else if ((Key.ScanCode == SCAN_NULL) || ((Key.ScanCode >=
> SCAN_UP) && (Key.ScanCode <= SCAN_PAGE_DOWN))) {
> -        Status = FileBufferHandleInput (&Key);
> -      } else if ((Key.ScanCode >= SCAN_F1) && (Key.ScanCode <= SCAN_F12))
> {
> -        Status = MenuBarDispatchFunctionKey (&Key);
> -      } else {
> -        StatusBarSetStatusString (L"Unknown Command");
> -        FileBufferMouseNeedRefresh = FALSE;
> -      }
> -
> -      if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {
> +    Status = gBS->WaitForEvent (1, &MainEditor.TextInputEx->WaitForKeyEx,
> &EventIndex);
> +    if (!EFI_ERROR (Status) && EventIndex == 0) {
> +      Status = MainEditor.TextInputEx->ReadKeyStrokeEx
> (MainEditor.TextInputEx, &KeyData);
> +      if (!EFI_ERROR (Status)) {
> +        //
> +        // dispatch to different components' key handling function
> +        // so not everywhere has to set this variable
> +        //
> +        FileBufferMouseNeedRefresh = TRUE;
>          //
> -        // not already has some error status
> +        // clear previous status string
>          //
> -        if (StatusBarGetString() != NULL && StrCmp (L"", 
> StatusBarGetString())
> == 0) {
> -          StatusBarSetStatusString (L"Disk Error. Try Again");
> +        StatusBarSetRefresh();
> +        //
> +        // NoShiftState: TRUE when no shift key is pressed.
> +        //
> +        NoShiftState = ((KeyData.KeyState.KeyShiftState &
> EFI_SHIFT_STATE_VALID) == 0) || (KeyData.KeyState.KeyShiftState ==
> EFI_SHIFT_STATE_VALID);
> +        //
> +        // dispatch to different components' key handling function
> +        //
> +        if (EFI_NOT_FOUND != MenuBarDispatchControlHotKey(&KeyData)) {
> +          Status = EFI_SUCCESS;
> +        } else if (NoShiftState && ((KeyData.Key.ScanCode == SCAN_NULL) ||
> ((KeyData.Key.ScanCode >= SCAN_UP) && (KeyData.Key.ScanCode <=
> SCAN_PAGE_DOWN)))) {
> +          Status = FileBufferHandleInput (&KeyData.Key);
> +        } else if (NoShiftState && (KeyData.Key.ScanCode >= SCAN_F1) &&
> (KeyData.Key.ScanCode <= SCAN_F12)) {
> +          Status = MenuBarDispatchFunctionKey (&KeyData.Key);
> +        } else {
> +          StatusBarSetStatusString (L"Unknown Command");
> +          FileBufferMouseNeedRefresh = FALSE;
> +        }
> +
> +        if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {
> +          //
> +          // not already has some error status
> +          //
> +          if (StatusBarGetString() != NULL && StrCmp (L"", 
> StatusBarGetString())
> == 0) {
> +            StatusBarSetStatusString (L"Disk Error. Try Again");
> +          }
>          }
> -      }
> 
> +      }
> +      //
> +      // after handling, refresh editor
> +      //
> +      MainEditorRefresh ();
>      }
> -    //
> -    // after handling, refresh editor
> -    //
> -    MainEditorRefresh ();
> 
>    } while (Status != EFI_OUT_OF_RESOURCES && !EditorExit);
> 
> diff --git
> a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h
> b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h
> index dfd56dd9a6..4cabba7b13 100644
> --- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h
> +++
> b/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h
> @@ -1,7 +1,7 @@
>  /** @file
>    Declares editor types.
> 
> -  Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
> +  Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD
> License
>    which accompanies this distribution.  The full text of the license may be
> found at
> @@ -87,15 +87,16 @@ typedef struct {
>  } EFI_EDITOR_FILE_BUFFER;
> 
>  typedef struct {
> -  EFI_EDITOR_FILE_BUFFER      *FileBuffer;
> -
> -  EFI_EDITOR_COLOR_UNION      ColorAttributes;
> -  EFI_EDITOR_POSITION         ScreenSize; // row number and column number
> -  EFI_EDITOR_LINE             *CutLine;   // clip board
> -  BOOLEAN                     MouseSupported;
> -  EFI_SIMPLE_POINTER_PROTOCOL *MouseInterface;
> -  INT32                       MouseAccumulatorX;
> -  INT32                       MouseAccumulatorY;
> +  EFI_EDITOR_FILE_BUFFER            *FileBuffer;
> +
> +  EFI_EDITOR_COLOR_UNION            ColorAttributes;
> +  EFI_EDITOR_POSITION               ScreenSize; // row number and column
> number
> +  EFI_EDITOR_LINE                   *CutLine;   // clip board
> +  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
> +  BOOLEAN                           MouseSupported;
> +  EFI_SIMPLE_POINTER_PROTOCOL       *MouseInterface;
> +  INT32                             MouseAccumulatorX;
> +  INT32                             MouseAccumulatorY;
> 
>  } EFI_EDITOR_GLOBAL_EDITOR;
> 
> diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.c
> b/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.c
> index 26f70d719a..6c6fc70bab 100644
> --- a/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.c
> +++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.c
> @@ -1,7 +1,7 @@
>  /** @file
>    Implements inputbar interface functions.
> 
> -  Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved. <BR>
> +  Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD
> License
>    which accompanies this distribution.  The full text of the license may be
> found at
> @@ -18,18 +18,22 @@
>  CHAR16  *mPrompt;        // Input bar mPrompt string.
>  CHAR16  *mReturnString;  // The returned string.
>  UINTN   StringSize;      // Size of mReturnString space size.
> +EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *mTextInEx;
> 
>  /**
>    Initialize the input bar.
> +
> +  @param[in] TextInEx  Pointer to SimpleTextInEx instance in System Table.
>  **/
>  VOID
>  InputBarInit (
> -  VOID
> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx
>    )
>  {
>    mPrompt       = NULL;
>    mReturnString = NULL;
>    StringSize    = 0;
> +  mTextInEx     = TextInEx;
>  }
> 
>  /**
> @@ -125,7 +129,7 @@ InputBarRefresh (
>  {
>    INPUT_BAR_COLOR_UNION   Orig;
>    INPUT_BAR_COLOR_UNION   New;
> -  EFI_INPUT_KEY           Key;
> +  EFI_KEY_DATA            KeyData;
>    UINTN                   Size;
>    EFI_STATUS              Status;
>    BOOLEAN                 NoDisplay;
> @@ -174,15 +178,25 @@ InputBarRefresh (
>    // wait for user input
>    //
>    for (;;) {
> -    gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
> -    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
> +    Status = gBS->WaitForEvent (1, &mTextInEx->WaitForKeyEx,
> &EventIndex);
> +    if (EFI_ERROR (Status) || (EventIndex != 0)) {
> +      continue;
> +    }
> +    Status = mTextInEx->ReadKeyStrokeEx (mTextInEx, &KeyData);
>      if (EFI_ERROR (Status)) {
>        continue;
>      }
> +    if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) &&
> +        (KeyData.KeyState.KeyShiftState != EFI_SHIFT_STATE_VALID)) {
> +      //
> +      // Shift key pressed.
> +      //
> +      continue;
> +    }
>      //
>      // pressed ESC
>      //
> -    if (Key.ScanCode == SCAN_ESC) {
> +    if (KeyData.Key.ScanCode == SCAN_ESC) {
>        Size    = 0;
>        Status  = EFI_NOT_READY;
>        break;
> @@ -190,9 +204,9 @@ InputBarRefresh (
>      //
>      // return pressed
>      //
> -    if (Key.UnicodeChar == CHAR_LINEFEED || Key.UnicodeChar ==
> CHAR_CARRIAGE_RETURN) {
> +    if (KeyData.Key.UnicodeChar == CHAR_LINEFEED ||
> KeyData.Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
>        break;
> -    } else if (Key.UnicodeChar == CHAR_BACKSPACE) {
> +    } else if (KeyData.Key.UnicodeChar == CHAR_BACKSPACE) {
>        //
>        // backspace
>        //
> @@ -205,11 +219,11 @@ InputBarRefresh (
> 
>          }
>        }
> -    } else if (Key.UnicodeChar <= 127 && Key.UnicodeChar >= 32) {
> +    } else if (KeyData.Key.UnicodeChar <= 127 && KeyData.Key.UnicodeChar
> >= 32) {
>        //
>        // VALID ASCII char pressed
>        //
> -      mReturnString[Size] = Key.UnicodeChar;
> +      mReturnString[Size] = KeyData.Key.UnicodeChar;
> 
>        //
>        // should be less than specified length
> diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.h
> b/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.h
> index f4aaee9ac5..e7e6c78680 100644
> --- a/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.h
> +++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.h
> @@ -1,7 +1,7 @@
>  /** @file
>    Declares imputbar interface functions.
> 
> -  Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
> +  Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD
> License
>    which accompanies this distribution.  The full text of the license may be
> found at
> @@ -17,10 +17,12 @@
> 
>  /**
>    Initialize the input bar.
> +
> +  @param[in] TextInEx  Pointer to SimpleTextInEx instance in System Table.
>  **/
>  VOID
>  InputBarInit (
> -  VOID
> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx
>    );
> 
>  /**
> diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.c
> b/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.c
> index 2e00b90c6b..b86594bb28 100644
> --- a/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.c
> +++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.c
> @@ -1,7 +1,7 @@
>  /** @file
>    implements menubar interface functions.
> 
> -  Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
> +  Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD
> License
>    which accompanies this distribution.  The full text of the license may be
> found at
> @@ -165,7 +165,7 @@ MenuBarDispatchFunctionKey (
>  /**
>    Function to dispatch the correct function based on a control-based key
> (ctrl+o...)
> 
> -  @param[in] Key                The pressed key.
> +  @param[in] KeyData                The pressed key.
> 
>    @retval EFI_NOT_FOUND         The key was not a valid control-based key
>                                  (an error was sent to the status bar).
> @@ -173,17 +173,41 @@ MenuBarDispatchFunctionKey (
>  **/
>  EFI_STATUS
>  MenuBarDispatchControlHotKey (
> -  IN CONST EFI_INPUT_KEY   *Key
> +  IN CONST EFI_KEY_DATA   *KeyData
>    )
>  {
> -
> -  if ((SCAN_CONTROL_Z < Key->UnicodeChar)
> -    ||(NULL == ControlBasedMenuFunctions[Key->UnicodeChar]))
> +  UINT16                  ControlIndex;
> +
> +  //
> +  // Set to invalid value first.
> +  //
> +  ControlIndex = MAX_UINT16;
> +
> +  if ((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) {
> +    //
> +    // For those console devices that cannot report the CONTROL state,
> +    // Ctrl+A is translated to 1 (UnicodeChar).
> +    //
> +    ControlIndex = KeyData->Key.UnicodeChar;
> +  } else if (((KeyData->KeyState.KeyShiftState &
> (EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED)) != 0) &&
> +             ((KeyData->KeyState.KeyShiftState & ~(EFI_SHIFT_STATE_VALID |
> EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED)) == 0)) {
> +    //
> +    // For those console devices that can report the CONTROL state,
> +    // make sure only CONTROL is pressed.
> +    //
> +    if ((KeyData->Key.UnicodeChar >= L'A') && (KeyData->Key.UnicodeChar
> <= L'Z')) {
> +      ControlIndex = KeyData->Key.UnicodeChar - L'A' + 1;
> +    } else if ((KeyData->Key.UnicodeChar >= L'a') && (KeyData-
> >Key.UnicodeChar <= L'z')) {
> +      ControlIndex = KeyData->Key.UnicodeChar - L'a' + 1;
> +    }
> +  }
> +  if ((SCAN_CONTROL_Z < ControlIndex)
> +    ||(NULL == ControlBasedMenuFunctions[ControlIndex]))
>    {
>        return EFI_NOT_FOUND;
>    }
> 
> -  ControlBasedMenuFunctions[Key->UnicodeChar]();
> +  ControlBasedMenuFunctions[ControlIndex]();
>    return EFI_SUCCESS;
>  }
> 
> diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.h
> b/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.h
> index d545db9346..a15617edf6 100644
> --- a/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.h
> +++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.h
> @@ -1,7 +1,7 @@
>  /** @file
>    Declares menubar interface functions.
> 
> -  Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
> +  Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD
> License
>    which accompanies this distribution.  The full text of the license may be
> found at
> @@ -105,7 +105,7 @@ MenuBarDispatchFunctionKey (
>  /**
>    Function to dispatch the correct function based on a control-based key
> (ctrl+o...)
> 
> -  @param[in] Key                The pressed key.
> +  @param[in] KeyData                The pressed key.
> 
>    @retval EFI_NOT_FOUND         The key was not a valid control-based key
>                                  (an error was sent to the status bar).
> @@ -113,7 +113,7 @@ MenuBarDispatchFunctionKey (
>  **/
>  EFI_STATUS
>  MenuBarDispatchControlHotKey (
> -  IN CONST EFI_INPUT_KEY   *Key
> +  IN CONST EFI_KEY_DATA   *KeyData
>    );
> 
>  #endif
> diff --git
> a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.
> h
> b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.
> h
> index 8f0da3b667..2a0429a4a1 100644
> ---
> a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.
> h
> +++
> b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.
> h
> @@ -1,7 +1,7 @@
>  /** @file
>    data types that are used by editor
> 
> -  Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved. <BR>
> +  Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD
> License
>    which accompanies this distribution.  The full text of the license may be
> found at
> @@ -109,17 +109,18 @@ typedef struct {
>  } HEFI_EDITOR_BUFFER_IMAGE;
> 
>  typedef struct {
> -  HEFI_EDITOR_BUFFER_IMAGE    *BufferImage;
> -
> -  HEFI_EDITOR_COLOR_UNION     ColorAttributes;
> -  HEFI_EDITOR_POSITION        ScreenSize;           // row number and column
> number
> -  BOOLEAN                     MouseSupported;
> -  EFI_SIMPLE_POINTER_PROTOCOL *MouseInterface;
> -  INT32                       MouseAccumulatorX;
> -  INT32                       MouseAccumulatorY;
> -
> -  UINTN                       SelectStart;          // starting from 1
> -  UINTN                       SelectEnd;            // starting from 1
> +  HEFI_EDITOR_BUFFER_IMAGE          *BufferImage;
> +
> +  HEFI_EDITOR_COLOR_UNION           ColorAttributes;
> +  HEFI_EDITOR_POSITION              ScreenSize;           // row number and
> column number
> +  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
> +  BOOLEAN                           MouseSupported;
> +  EFI_SIMPLE_POINTER_PROTOCOL       *MouseInterface;
> +  INT32                             MouseAccumulatorX;
> +  INT32                             MouseAccumulatorY;
> +
> +  UINTN                             SelectStart;          // starting from 1
> +  UINTN                             SelectEnd;            // starting from 1
>  } HEFI_EDITOR_GLOBAL_EDITOR;
> 
>  #endif
> diff --git
> a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c
> b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c
> index 491acb131e..065f8e95a7 100644
> ---
> a/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c
> +++
> b/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c
> @@ -4,7 +4,7 @@
>       - Instances of the other objects of the editor
>       - Main Interfaces
> 
> -  Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved. <BR>
> +  Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
>    This program and the accompanying materials
>    are licensed and made available under the terms and conditions of the BSD
> License
>    which accompanies this distribution.  The full text of the license may be
> found at
> @@ -56,6 +56,7 @@ HEFI_EDITOR_GLOBAL_EDITOR       HMainEditorConst = {
>      0,
>      0
>    },
> +  NULL,
>    FALSE,
>    NULL,
>    0,
> @@ -105,22 +106,53 @@ HMainCommandDisplayHelp (
>    VOID
>    )
>  {
> -  INT32    CurrentLine;
> -  CHAR16 * InfoString;
> -  EFI_INPUT_KEY  Key;
> -
> -  CurrentLine = 0;
> +  INT32           CurrentLine;
> +  CHAR16          *InfoString;
> +  EFI_KEY_DATA    KeyData;
> +  EFI_STATUS      Status;
> +  UINTN           EventIndex;
> +
> +  //
>    // print helpInfo
> +  //
>    for (CurrentLine = 0; 0 != HexMainMenuHelpInfo[CurrentLine];
> CurrentLine++) {
>      InfoString = HiiGetString(gShellDebug1HiiHandle,
> HexMainMenuHelpInfo[CurrentLine]
>  , NULL);
>      ShellPrintEx (0,CurrentLine+1,L"%E%s%N",InfoString);
>    }
> -
> +
> +  //
>    // scan for ctrl+w
> -  do {
> -    gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
> -  } while(SCAN_CONTROL_W != Key.UnicodeChar);
> +  //
> +  while (TRUE) {
> +    Status = gBS->WaitForEvent (1, &HMainEditor.TextInputEx-
> >WaitForKeyEx, &EventIndex);
> +    if (EFI_ERROR (Status) || (EventIndex != 0)) {
> +      continue;
> +    }
> +    Status = HMainEditor.TextInputEx->ReadKeyStrokeEx
> (HMainEditor.TextInputEx, &KeyData);
> +    if (EFI_ERROR (Status)) {
> +      continue;
> +    }
> +
> +    if ((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) {
> +      //
> +      // For consoles that don't support shift state reporting,
> +      // CTRL+W is translated to L'W' - L'A' + 1.
> +      //
> +      if (KeyData.Key.UnicodeChar == L'W' - L'A' + 1) {
> +        break;
> +      }
> +    } else if (((KeyData.KeyState.KeyShiftState &
> (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) &&
> +               ((KeyData.KeyState.KeyShiftState & ~(EFI_SHIFT_STATE_VALID |
> EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) == 0)) {
> +      //
> +      // For consoles that supports shift state reporting,
> +      // make sure that only CONTROL shift key is pressed.
> +      //
> +      if ((KeyData.Key.UnicodeChar == 'w') || (KeyData.Key.UnicodeChar ==
> 'W')) {
> +        break;
> +      }
> +    }
> +  }
> 
>    // update screen with buffer's info
>    HBufferImageNeedRefresh = TRUE;
> @@ -1633,6 +1665,19 @@ HMainEditorInit (
>          &(HMainEditor.ScreenSize.Row)
>          );
> 
> +  //
> +  // Find TextInEx in System Table ConsoleInHandle
> +  // Per UEFI Spec, TextInEx is required for a console capable platform.
> +  //
> +  Status = gBS->HandleProtocol (
> +              gST->ConsoleInHandle,
> +              &gEfiSimpleTextInputExProtocolGuid,
> +              (VOID**)&HMainEditor.TextInputEx
> +              );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
>    //
>    // Find mouse in System Table ConsoleInHandle
>    //
> @@ -1706,7 +1751,7 @@ HMainEditorInit (
>      return EFI_LOAD_ERROR;
>    }
> 
> -  InputBarInit ();
> +  InputBarInit (HMainEditor.TextInputEx);
> 
>    Status = HBufferImageInit ();
>    if (EFI_ERROR (Status)) {
> @@ -2058,9 +2103,11 @@ HMainEditorKeyInput (
>    VOID
>    )
>  {
> -  EFI_INPUT_KEY             Key;
> +  EFI_KEY_DATA              KeyData;
>    EFI_STATUS                Status;
>    EFI_SIMPLE_POINTER_STATE  MouseState;
> +  UINTN                     EventIndex;
> +  BOOLEAN                   NoShiftState;
>    BOOLEAN                   LengthChange;
>    UINTN                     Size;
>    UINTN                     OldSize;
> @@ -2219,84 +2266,94 @@ HMainEditorKeyInput (
>        }
>      }
> 
> -    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
> -    if (!EFI_ERROR (Status)) {
> -      //
> -      // dispatch to different components' key handling function
> -      // so not everywhere has to set this variable
> -      //
> -      HBufferImageMouseNeedRefresh = TRUE;
> -
> -      //
> -      // clear previous status string
> -      //
> -      StatusBarSetRefresh();
> -      if (EFI_SUCCESS == MenuBarDispatchControlHotKey(&Key)) {
> -        Status = EFI_SUCCESS;
> -      } else if (Key.ScanCode == SCAN_NULL) {
> -        Status = HBufferImageHandleInput (&Key);
> -      } else if (((Key.ScanCode >= SCAN_UP) && (Key.ScanCode <=
> SCAN_PAGE_DOWN))) {
> -        Status = HBufferImageHandleInput (&Key);
> -      } else if (((Key.ScanCode >= SCAN_F1) && Key.ScanCode <=
> (SCAN_F12))) {
> -        Status = MenuBarDispatchFunctionKey (&Key);
> -      } else {
> -        StatusBarSetStatusString (L"Unknown Command");
> -
> -        HBufferImageMouseNeedRefresh = FALSE;
> -      }
> +    Status = gBS->WaitForEvent (1, &HMainEditor.TextInputEx-
> >WaitForKeyEx, &EventIndex);
> +    if (!EFI_ERROR (Status) && EventIndex == 0) {
> +      Status = HMainEditor.TextInputEx->ReadKeyStrokeEx
> (HMainEditor.TextInputEx, &KeyData);
> +      if (!EFI_ERROR (Status)) {
> +        //
> +        // dispatch to different components' key handling function
> +        // so not everywhere has to set this variable
> +        //
> +        HBufferImageMouseNeedRefresh = TRUE;
> 
> -      if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {
>          //
> -        // not already has some error status
> +        // clear previous status string
>          //
> -        if (StrCmp (L"", StatusBarGetString()) == 0) {
> -          StatusBarSetStatusString (L"Disk Error. Try Again");
> +        StatusBarSetRefresh();
> +        //
> +        // NoShiftState: TRUE when no shift key is pressed.
> +        //
> +        NoShiftState = ((KeyData.KeyState.KeyShiftState &
> EFI_SHIFT_STATE_VALID) == 0) || (KeyData.KeyState.KeyShiftState ==
> EFI_SHIFT_STATE_VALID);
> +        //
> +        // dispatch to different components' key handling function
> +        //
> +        if (EFI_SUCCESS == MenuBarDispatchControlHotKey(&KeyData)) {
> +          Status = EFI_SUCCESS;
> +        } else if (NoShiftState && KeyData.Key.ScanCode == SCAN_NULL) {
> +          Status = HBufferImageHandleInput (&KeyData.Key);
> +        } else if (NoShiftState && ((KeyData.Key.ScanCode >= SCAN_UP) &&
> (KeyData.Key.ScanCode <= SCAN_PAGE_DOWN))) {
> +          Status = HBufferImageHandleInput (&KeyData.Key);
> +        } else if (NoShiftState && ((KeyData.Key.ScanCode >= SCAN_F1) &&
> KeyData.Key.ScanCode <= SCAN_F12)) {
> +          Status = MenuBarDispatchFunctionKey (&KeyData.Key);
> +        } else {
> +          StatusBarSetStatusString (L"Unknown Command");
> +
> +          HBufferImageMouseNeedRefresh = FALSE;
> +        }
> +
> +        if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {
> +          //
> +          // not already has some error status
> +          //
> +          if (StrCmp (L"", StatusBarGetString()) == 0) {
> +            StatusBarSetStatusString (L"Disk Error. Try Again");
> +          }
>          }
>        }
> -    }
> -    //
> -    // decide if has to set length warning
> -    //
> -    if (HBufferImage.BufferType != HBufferImageBackupVar.BufferType) {
> -      LengthChange = FALSE;
> -    } else {
>        //
> -      // still the old buffer
> +      // decide if has to set length warning
>        //
> -      if (HBufferImage.BufferType != FileTypeFileBuffer) {
> -        Size = HBufferImageGetTotalSize ();
> +      if (HBufferImage.BufferType != HBufferImageBackupVar.BufferType) {
> +        LengthChange = FALSE;
> +      } else {
> +        //
> +        // still the old buffer
> +        //
> +        if (HBufferImage.BufferType != FileTypeFileBuffer) {
> +          Size = HBufferImageGetTotalSize ();
> 
> -        switch (HBufferImage.BufferType) {
> -        case FileTypeDiskBuffer:
> -          OldSize = HBufferImage.DiskImage->Size * HBufferImage.DiskImage-
> >BlockSize;
> -          break;
> +          switch (HBufferImage.BufferType) {
> +          case FileTypeDiskBuffer:
> +            OldSize = HBufferImage.DiskImage->Size * HBufferImage.DiskImage-
> >BlockSize;
> +            break;
> 
> -        case FileTypeMemBuffer:
> -          OldSize = HBufferImage.MemImage->Size;
> -          break;
> +          case FileTypeMemBuffer:
> +            OldSize = HBufferImage.MemImage->Size;
> +            break;
> 
> -        default:
> -          OldSize = 0;
> -          break;
> -        }
> +          default:
> +            OldSize = 0;
> +            break;
> +          }
> 
> -        if (!LengthChange) {
> -          if (OldSize != Size) {
> -            StatusBarSetStatusString (L"Disk/Mem Buffer Length should not be
> changed");
> +          if (!LengthChange) {
> +            if (OldSize != Size) {
> +              StatusBarSetStatusString (L"Disk/Mem Buffer Length should not 
> be
> changed");
> +            }
>            }
> -        }
> 
> -        if (OldSize != Size) {
> -          LengthChange = TRUE;
> -        } else {
> -          LengthChange = FALSE;
> +          if (OldSize != Size) {
> +            LengthChange = TRUE;
> +          } else {
> +            LengthChange = FALSE;
> +          }
>          }
>        }
> +      //
> +      // after handling, refresh editor
> +      //
> +      HMainEditorRefresh ();
>      }
> -    //
> -    // after handling, refresh editor
> -    //
> -    HMainEditorRefresh ();
> 
>    } while (Status != EFI_OUT_OF_RESOURCES && !HEditorExit);
> 
> --
> 2.16.1.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to