mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-11-03 22:54:50 +00:00 
			
		
		
		
	REF: https://bugzilla.tianocore.org/show_bug.cgi?id=996 Issue: In current code logic, when a key is pressed, it will search the whole NotifyList to find whether a notification has been registered with the keystroke. if yes, it will en-queue the key for notification execution later. And now if different notification functions have been registered with the same key, then the key will be en-queued more than once. Then it will cause the notification executed more than once. This patch is to enhance the code logic to fix this issue. Cc: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Liming Gao <liming.gao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Dandan Bi <dandan.bi@intel.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
		
			
				
	
	
		
			1907 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1907 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Routines that access 8042 keyboard controller
 | 
						|
 | 
						|
Copyright (c) 2006 - 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
 | 
						|
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 "Ps2Keyboard.h"
 | 
						|
 | 
						|
struct {
 | 
						|
  UINT8   ScanCode;             ///< follows value defined in Scan Code Set1
 | 
						|
  UINT16  EfiScanCode;
 | 
						|
  CHAR16  UnicodeChar;
 | 
						|
  CHAR16  ShiftUnicodeChar;
 | 
						|
}
 | 
						|
ConvertKeyboardScanCodeToEfiKey[] = {
 | 
						|
 | 
						|
  {
 | 
						|
    0x01,  //   Escape
 | 
						|
    SCAN_ESC,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x02,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'1',
 | 
						|
    L'!'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x03,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'2',
 | 
						|
    L'@'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x04,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'3',
 | 
						|
    L'#'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x05,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'4',
 | 
						|
    L'$'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x06,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'5',
 | 
						|
    L'%'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x07,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'6',
 | 
						|
    L'^'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x08,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'7',
 | 
						|
    L'&'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x09,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'8',
 | 
						|
    L'*'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x0A,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'9',
 | 
						|
    L'('
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x0B,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'0',
 | 
						|
    L')'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x0C,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'-',
 | 
						|
    L'_'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x0D,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'=',
 | 
						|
    L'+'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x0E, //  BackSpace
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0008,
 | 
						|
    0x0008
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x0F, //  Tab
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0009,
 | 
						|
    0x0009
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x10,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'q',
 | 
						|
    L'Q'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x11,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'w',
 | 
						|
    L'W'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x12,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'e',
 | 
						|
    L'E'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x13,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'r',
 | 
						|
    L'R'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x14,
 | 
						|
    SCAN_NULL,
 | 
						|
    L't',
 | 
						|
    L'T'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x15,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'y',
 | 
						|
    L'Y'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x16,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'u',
 | 
						|
    L'U'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x17,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'i',
 | 
						|
    L'I'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x18,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'o',
 | 
						|
    L'O'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x19,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'p',
 | 
						|
    L'P'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x1a,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'[',
 | 
						|
    L'{'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x1b,
 | 
						|
    SCAN_NULL,
 | 
						|
    L']',
 | 
						|
    L'}'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x1c, //   Enter
 | 
						|
    SCAN_NULL,
 | 
						|
    0x000d,
 | 
						|
    0x000d
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x1d,
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x1e,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'a',
 | 
						|
    L'A'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x1f,
 | 
						|
    SCAN_NULL,
 | 
						|
    L's',
 | 
						|
    L'S'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x20,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'd',
 | 
						|
    L'D'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x21,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'f',
 | 
						|
    L'F'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x22,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'g',
 | 
						|
    L'G'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x23,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'h',
 | 
						|
    L'H'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x24,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'j',
 | 
						|
    L'J'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x25,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'k',
 | 
						|
    L'K'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x26,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'l',
 | 
						|
    L'L'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x27,
 | 
						|
    SCAN_NULL,
 | 
						|
    L';',
 | 
						|
    L':'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x28,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'\'',
 | 
						|
    L'"'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x29,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'`',
 | 
						|
    L'~'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x2a, //   Left Shift
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x2b,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'\\',
 | 
						|
    L'|'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x2c,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'z',
 | 
						|
    L'Z'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x2d,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'x',
 | 
						|
    L'X'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x2e,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'c',
 | 
						|
    L'C'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x2f,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'v',
 | 
						|
    L'V'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x30,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'b',
 | 
						|
    L'B'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x31,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'n',
 | 
						|
    L'N'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x32,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'm',
 | 
						|
    L'M'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x33,
 | 
						|
    SCAN_NULL,
 | 
						|
    L',',
 | 
						|
    L'<'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x34,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'.',
 | 
						|
    L'>'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x35,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'/',
 | 
						|
    L'?'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x36, //Right Shift
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x37, // Numeric Keypad *
 | 
						|
    SCAN_NULL,
 | 
						|
    L'*',
 | 
						|
    L'*'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x38,  //Left Alt/Extended Right Alt
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x39,
 | 
						|
    SCAN_NULL,
 | 
						|
    L' ',
 | 
						|
    L' '
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x3A, //CapsLock
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x3B,
 | 
						|
    SCAN_F1,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x3C,
 | 
						|
    SCAN_F2,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x3D,
 | 
						|
    SCAN_F3,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x3E,
 | 
						|
    SCAN_F4,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x3F,
 | 
						|
    SCAN_F5,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x40,
 | 
						|
    SCAN_F6,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x41,
 | 
						|
    SCAN_F7,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x42,
 | 
						|
    SCAN_F8,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x43,
 | 
						|
    SCAN_F9,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x44,
 | 
						|
    SCAN_F10,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x45, // NumLock
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x46, //  ScrollLock
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x47,
 | 
						|
    SCAN_HOME,
 | 
						|
    L'7',
 | 
						|
    L'7'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x48,
 | 
						|
    SCAN_UP,
 | 
						|
    L'8',
 | 
						|
    L'8'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x49,
 | 
						|
    SCAN_PAGE_UP,
 | 
						|
    L'9',
 | 
						|
    L'9'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x4a,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'-',
 | 
						|
    L'-'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x4b,
 | 
						|
    SCAN_LEFT,
 | 
						|
    L'4',
 | 
						|
    L'4'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x4c, //  Numeric Keypad 5
 | 
						|
    SCAN_NULL,
 | 
						|
    L'5',
 | 
						|
    L'5'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x4d,
 | 
						|
    SCAN_RIGHT,
 | 
						|
    L'6',
 | 
						|
    L'6'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x4e,
 | 
						|
    SCAN_NULL,
 | 
						|
    L'+',
 | 
						|
    L'+'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x4f,
 | 
						|
    SCAN_END,
 | 
						|
    L'1',
 | 
						|
    L'1'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x50,
 | 
						|
    SCAN_DOWN,
 | 
						|
    L'2',
 | 
						|
    L'2'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x51,
 | 
						|
    SCAN_PAGE_DOWN,
 | 
						|
    L'3',
 | 
						|
    L'3'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x52,
 | 
						|
    SCAN_INSERT,
 | 
						|
    L'0',
 | 
						|
    L'0'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x53,
 | 
						|
    SCAN_DELETE,
 | 
						|
    L'.',
 | 
						|
    L'.'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x57,
 | 
						|
    SCAN_F11,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x58,
 | 
						|
    SCAN_F12,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x5B,  //Left LOGO
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x5C,  //Right LOGO
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x5D,  //Menu key
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0000,
 | 
						|
    0x0000
 | 
						|
  },
 | 
						|
  {
 | 
						|
    TABLE_END,
 | 
						|
    TABLE_END,
 | 
						|
    SCAN_NULL,
 | 
						|
    SCAN_NULL
 | 
						|
  },
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// The WaitForValue time out
 | 
						|
//
 | 
						|
UINTN  mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
 | 
						|
 | 
						|
BOOLEAN          mEnableMouseInterface;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Return the count of scancode in the queue.
 | 
						|
 | 
						|
  @param Queue     Pointer to instance of SCAN_CODE_QUEUE.
 | 
						|
 | 
						|
  @return          Count of the scancode.
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
GetScancodeBufCount (
 | 
						|
  IN SCAN_CODE_QUEUE       *Queue
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Queue->Head <= Queue->Tail) {
 | 
						|
    return Queue->Tail - Queue->Head;
 | 
						|
  } else {
 | 
						|
    return Queue->Tail + KEYBOARD_SCAN_CODE_MAX_COUNT - Queue->Head;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Read several bytes from the scancode buffer without removing them.
 | 
						|
  This function is called to see if there are enough bytes of scancode
 | 
						|
  representing a single key.
 | 
						|
 | 
						|
  @param Queue     Pointer to instance of SCAN_CODE_QUEUE.
 | 
						|
  @param Count     Number of bytes to be read
 | 
						|
  @param Buf       Store the results
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   success to scan the keyboard code
 | 
						|
  @retval EFI_NOT_READY invalid parameter
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetScancodeBufHead (
 | 
						|
  IN  SCAN_CODE_QUEUE        *Queue,
 | 
						|
  IN  UINTN                  Count,
 | 
						|
  OUT UINT8                  *Buf
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                      Index;
 | 
						|
  UINTN                      Pos;
 | 
						|
 | 
						|
  //
 | 
						|
  // check the valid range of parameter 'Count'
 | 
						|
  //
 | 
						|
  if (GetScancodeBufCount (Queue) < Count) {
 | 
						|
    return EFI_NOT_READY;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // retrieve the values
 | 
						|
  //
 | 
						|
  for (Index = 0, Pos = Queue->Head; Index < Count; Index++, Pos = (Pos + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) {
 | 
						|
    Buf[Index] = Queue->Buffer[Pos];
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Read & remove several bytes from the scancode buffer.
 | 
						|
  This function is usually called after GetScancodeBufHead()
 | 
						|
 | 
						|
  @param Queue     Pointer to instance of SCAN_CODE_QUEUE.
 | 
						|
  @param Count     Number of bytes to be read
 | 
						|
  @param Buf       Store the results
 | 
						|
 | 
						|
  @retval EFI_SUCCESS success to scan the keyboard code
 | 
						|
  @retval EFI_NOT_READY invalid parameter
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
PopScancodeBufHead (
 | 
						|
  IN  SCAN_CODE_QUEUE       *Queue,
 | 
						|
  IN  UINTN                 Count,
 | 
						|
  OUT UINT8                 *Buf OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                     Index;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the valid range of parameter 'Count'
 | 
						|
  //
 | 
						|
  if (GetScancodeBufCount (Queue) < Count) {
 | 
						|
    return EFI_NOT_READY;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Retrieve and remove the values
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < Count; Index++, Queue->Head = (Queue->Head + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) {
 | 
						|
    if (Buf != NULL) {
 | 
						|
      Buf[Index] = Queue->Buffer[Queue->Head];
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Push one byte to the scancode buffer.
 | 
						|
 | 
						|
  @param Queue     Pointer to instance of SCAN_CODE_QUEUE.
 | 
						|
  @param Scancode  The byte to push.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
PushScancodeBufTail (
 | 
						|
  IN  SCAN_CODE_QUEUE       *Queue,
 | 
						|
  IN  UINT8                 Scancode
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (GetScancodeBufCount (Queue) == KEYBOARD_SCAN_CODE_MAX_COUNT - 1) {
 | 
						|
    PopScancodeBufHead (Queue, 1, NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  Queue->Buffer[Queue->Tail] = Scancode;
 | 
						|
  Queue->Tail = (Queue->Tail + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Read data register .
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
 | 
						|
  @return return the value
 | 
						|
 | 
						|
**/
 | 
						|
UINT8
 | 
						|
KeyReadDataRegister (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  EFI_ISA_IO_PROTOCOL                 *IsaIo;
 | 
						|
  UINT8                               Data;
 | 
						|
 | 
						|
  //
 | 
						|
  // Use IsaIo protocol to perform IO operations
 | 
						|
  //
 | 
						|
  IsaIo = ConsoleIn->IsaIo;
 | 
						|
 | 
						|
  IsaIo->Io.Read (
 | 
						|
              IsaIo,
 | 
						|
              EfiIsaIoWidthUint8,
 | 
						|
              ConsoleIn->DataRegisterAddress,
 | 
						|
              1,
 | 
						|
              &Data
 | 
						|
              );
 | 
						|
 | 
						|
  return Data;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Write data register.
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param Data      value wanted to be written
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
KeyWriteDataRegister (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  ConsoleIn->IsaIo->Io.Write (
 | 
						|
                         ConsoleIn->IsaIo,
 | 
						|
                         EfiIsaIoWidthUint8,
 | 
						|
                         ConsoleIn->DataRegisterAddress,
 | 
						|
                         1,
 | 
						|
                         &Data
 | 
						|
                         );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Read status register.
 | 
						|
 | 
						|
  @param ConsoleIn  Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
 | 
						|
  @return value in status register
 | 
						|
 | 
						|
**/
 | 
						|
UINT8
 | 
						|
KeyReadStatusRegister (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                               Data;
 | 
						|
  ConsoleIn->IsaIo->Io.Read (
 | 
						|
                         ConsoleIn->IsaIo,
 | 
						|
                         EfiIsaIoWidthUint8,
 | 
						|
                         ConsoleIn->StatusRegisterAddress,
 | 
						|
                         1,
 | 
						|
                         &Data
 | 
						|
                         );
 | 
						|
  return Data;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Write command register .
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param Data      The value wanted to be written
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
KeyWriteCommandRegister (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  ConsoleIn->IsaIo->Io.Write (
 | 
						|
                         ConsoleIn->IsaIo,
 | 
						|
                         EfiIsaIoWidthUint8,
 | 
						|
                         ConsoleIn->CommandRegisterAddress,
 | 
						|
                         1,
 | 
						|
                         &Data
 | 
						|
                         );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Display error message.
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param ErrMsg    Unicode string of error message
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
KeyboardError (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN CHAR16                  *ErrMsg
 | 
						|
  )
 | 
						|
{
 | 
						|
  ConsoleIn->KeyboardErr = TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Timer event handler: read a series of scancodes from 8042
 | 
						|
  and put them into memory scancode buffer.
 | 
						|
  it read as much scancodes to either fill
 | 
						|
  the memory buffer or empty the keyboard buffer.
 | 
						|
  It is registered as running under TPL_NOTIFY
 | 
						|
 | 
						|
  @param Event       The timer event
 | 
						|
  @param Context     A KEYBOARD_CONSOLE_IN_DEV pointer
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
KeyboardTimerHandler (
 | 
						|
  IN EFI_EVENT    Event,
 | 
						|
  IN VOID         *Context
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  UINT8                   Data;
 | 
						|
  EFI_TPL                 OldTpl;
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
 | 
						|
 | 
						|
  ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;
 | 
						|
 | 
						|
  //
 | 
						|
  // Enter critical section
 | 
						|
  //
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
 | 
						|
  if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) {
 | 
						|
    //
 | 
						|
    // Leave critical section and return
 | 
						|
    //
 | 
						|
    gBS->RestoreTPL (OldTpl);
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // To let KB driver support Hot plug, here should skip the 'resend' command  for the case that
 | 
						|
  // KB is not connected to system. If KB is not connected to system, driver will find there's something
 | 
						|
  // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since
 | 
						|
  // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
 | 
						|
  // Just skip the 'resend' process simply.
 | 
						|
  //
 | 
						|
 | 
						|
  while ((KeyReadStatusRegister (ConsoleIn) & (KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT|KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA)) ==
 | 
						|
      KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA
 | 
						|
     ) {
 | 
						|
    //
 | 
						|
    // Read one byte of the scan code and store it into the memory buffer
 | 
						|
    //
 | 
						|
    Data = KeyReadDataRegister (ConsoleIn);
 | 
						|
    PushScancodeBufTail (&ConsoleIn->ScancodeQueue, Data);
 | 
						|
  }
 | 
						|
  KeyGetchar (ConsoleIn);
 | 
						|
 | 
						|
  //
 | 
						|
  // Leave critical section and return
 | 
						|
  //
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Read key value .
 | 
						|
 | 
						|
  @param ConsoleIn - Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param Data      - Pointer to outof buffer for keeping key value
 | 
						|
 | 
						|
  @retval EFI_TIMEOUT Status resigter time out
 | 
						|
  @retval EFI_SUCCESS Success to read keyboard
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
KeyboardRead (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV  *ConsoleIn,
 | 
						|
  OUT UINT8                   *Data
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  UINT32  TimeOut;
 | 
						|
  UINT32  RegFilled;
 | 
						|
 | 
						|
  TimeOut   = 0;
 | 
						|
  RegFilled = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // wait till output buffer full then perform the read
 | 
						|
  //
 | 
						|
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
 | 
						|
    if (KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) {
 | 
						|
      RegFilled = 1;
 | 
						|
      *Data     = KeyReadDataRegister (ConsoleIn);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    MicroSecondDelay (30);
 | 
						|
  }
 | 
						|
 | 
						|
  if (RegFilled == 0) {
 | 
						|
    return EFI_TIMEOUT;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  write key to keyboard
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param Data      value wanted to be written
 | 
						|
 | 
						|
  @retval EFI_TIMEOUT   The input buffer register is full for putting new value util timeout
 | 
						|
  @retval EFI_SUCCESS   The new value is sucess put into input buffer register.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
KeyboardWrite (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  TimeOut;
 | 
						|
  UINT32  RegEmptied;
 | 
						|
 | 
						|
  TimeOut     = 0;
 | 
						|
  RegEmptied  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // wait for input buffer empty
 | 
						|
  //
 | 
						|
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
 | 
						|
    if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
 | 
						|
      RegEmptied = 1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    MicroSecondDelay (30);
 | 
						|
  }
 | 
						|
 | 
						|
  if (RegEmptied == 0) {
 | 
						|
    return EFI_TIMEOUT;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Write it
 | 
						|
  //
 | 
						|
  KeyWriteDataRegister (ConsoleIn, Data);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Issue keyboard command.
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param Data      The buff holding the command
 | 
						|
 | 
						|
  @retval EFI_TIMEOUT Keyboard is not ready to issuing
 | 
						|
  @retval EFI_SUCCESS Success to issue keyboard command
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
KeyboardCommand (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  TimeOut;
 | 
						|
  UINT32  RegEmptied;
 | 
						|
 | 
						|
  TimeOut     = 0;
 | 
						|
  RegEmptied  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Wait For Input Buffer Empty
 | 
						|
  //
 | 
						|
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
 | 
						|
    if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
 | 
						|
      RegEmptied = 1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    MicroSecondDelay (30);
 | 
						|
  }
 | 
						|
 | 
						|
  if (RegEmptied == 0) {
 | 
						|
    return EFI_TIMEOUT;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // issue the command
 | 
						|
  //
 | 
						|
  KeyWriteCommandRegister (ConsoleIn, Data);
 | 
						|
 | 
						|
  //
 | 
						|
  // Wait For Input Buffer Empty again
 | 
						|
  //
 | 
						|
  RegEmptied = 0;
 | 
						|
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
 | 
						|
    if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
 | 
						|
      RegEmptied = 1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    MicroSecondDelay (30);
 | 
						|
  }
 | 
						|
 | 
						|
  if (RegEmptied == 0) {
 | 
						|
    return EFI_TIMEOUT;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  wait for a specific value to be presented on
 | 
						|
  8042 Data register by keyboard and then read it,
 | 
						|
  used in keyboard commands ack
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param Value     the value wanted to be waited.
 | 
						|
 | 
						|
  @retval EFI_TIMEOUT Fail to get specific value in given time
 | 
						|
  @retval EFI_SUCCESS Success to get specific value in given time.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
KeyboardWaitForValue (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Value
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8   Data;
 | 
						|
  UINT32  TimeOut;
 | 
						|
  UINT32  SumTimeOut;
 | 
						|
  UINT32  GotIt;
 | 
						|
 | 
						|
  GotIt       = 0;
 | 
						|
  TimeOut     = 0;
 | 
						|
  SumTimeOut  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Make sure the initial value of 'Data' is different from 'Value'
 | 
						|
  //
 | 
						|
  Data = 0;
 | 
						|
  if (Data == Value) {
 | 
						|
    Data = 1;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read from 8042 (multiple times if needed)
 | 
						|
  // until the expected value appears
 | 
						|
  // use SumTimeOut to control the iteration
 | 
						|
  //
 | 
						|
  while (1) {
 | 
						|
    //
 | 
						|
    // Perform a read
 | 
						|
    //
 | 
						|
    for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
 | 
						|
      if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
 | 
						|
        Data = KeyReadDataRegister (ConsoleIn);
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      MicroSecondDelay (30);
 | 
						|
    }
 | 
						|
 | 
						|
    SumTimeOut += TimeOut;
 | 
						|
 | 
						|
    if (Data == Value) {
 | 
						|
      GotIt = 1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (SumTimeOut >= mWaitForValueTimeOut) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check results
 | 
						|
  //
 | 
						|
  if (GotIt == 1) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    return EFI_TIMEOUT;
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Show keyboard status lights according to
 | 
						|
  indicators in ConsoleIn.
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
 | 
						|
  @return status of updating keyboard register
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
UpdateStatusLights (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINT8       Command;
 | 
						|
 | 
						|
  //
 | 
						|
  // Send keyboard command
 | 
						|
  //
 | 
						|
  Status = KeyboardWrite (ConsoleIn, 0xed);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  KeyboardWaitForValue (ConsoleIn, 0xfa);
 | 
						|
 | 
						|
  //
 | 
						|
  // Light configuration
 | 
						|
  //
 | 
						|
  Command = 0;
 | 
						|
  if (ConsoleIn->CapsLock) {
 | 
						|
    Command |= 4;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ConsoleIn->NumLock) {
 | 
						|
    Command |= 2;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ConsoleIn->ScrollLock) {
 | 
						|
    Command |= 1;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = KeyboardWrite (ConsoleIn, Command);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  KeyboardWaitForValue (ConsoleIn, 0xfa);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Initialize the key state.
 | 
						|
 | 
						|
  @param  ConsoleIn     The KEYBOARD_CONSOLE_IN_DEV instance.
 | 
						|
  @param  KeyState      A pointer to receive the key state information.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
InitializeKeyState (
 | 
						|
  IN  KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  OUT EFI_KEY_STATE           *KeyState
 | 
						|
  )
 | 
						|
{
 | 
						|
  KeyState->KeyShiftState  = EFI_SHIFT_STATE_VALID
 | 
						|
                           | (ConsoleIn->LeftCtrl   ? EFI_LEFT_CONTROL_PRESSED  : 0)
 | 
						|
                           | (ConsoleIn->RightCtrl  ? EFI_RIGHT_CONTROL_PRESSED : 0)
 | 
						|
                           | (ConsoleIn->LeftAlt    ? EFI_LEFT_ALT_PRESSED      : 0)
 | 
						|
                           | (ConsoleIn->RightAlt   ? EFI_RIGHT_ALT_PRESSED     : 0)
 | 
						|
                           | (ConsoleIn->LeftShift  ? EFI_LEFT_SHIFT_PRESSED    : 0)
 | 
						|
                           | (ConsoleIn->RightShift ? EFI_RIGHT_SHIFT_PRESSED   : 0)
 | 
						|
                           | (ConsoleIn->LeftLogo   ? EFI_LEFT_LOGO_PRESSED     : 0)
 | 
						|
                           | (ConsoleIn->RightLogo  ? EFI_RIGHT_LOGO_PRESSED    : 0)
 | 
						|
                           | (ConsoleIn->Menu       ? EFI_MENU_KEY_PRESSED      : 0)
 | 
						|
                           | (ConsoleIn->SysReq     ? EFI_SYS_REQ_PRESSED       : 0)
 | 
						|
                           ;
 | 
						|
  KeyState->KeyToggleState = EFI_TOGGLE_STATE_VALID
 | 
						|
                           | (ConsoleIn->CapsLock   ? EFI_CAPS_LOCK_ACTIVE :   0)
 | 
						|
                           | (ConsoleIn->NumLock    ? EFI_NUM_LOCK_ACTIVE :    0)
 | 
						|
                           | (ConsoleIn->ScrollLock ? EFI_SCROLL_LOCK_ACTIVE : 0)
 | 
						|
                           | (ConsoleIn->IsSupportPartialKey ? EFI_KEY_STATE_EXPOSED : 0)
 | 
						|
                           ;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get scancode from scancode buffer and translate into EFI-scancode and unicode defined by EFI spec.
 | 
						|
 | 
						|
  The function is always called in TPL_NOTIFY.
 | 
						|
 | 
						|
  @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
KeyGetchar (
 | 
						|
  IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                     Status;
 | 
						|
  UINT16                         ScanCode;
 | 
						|
  BOOLEAN                        Extend0;
 | 
						|
  BOOLEAN                        Extend1;
 | 
						|
  UINTN                          Index;
 | 
						|
  EFI_KEY_DATA                   KeyData;
 | 
						|
  LIST_ENTRY                     *Link;
 | 
						|
  KEYBOARD_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;
 | 
						|
  //
 | 
						|
  // 3 bytes most
 | 
						|
  //
 | 
						|
  UINT8                          ScancodeArr[3];
 | 
						|
  UINT32                         ScancodeArrPos;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check if there are enough bytes of scancode representing a single key
 | 
						|
  // available in the buffer
 | 
						|
  //
 | 
						|
  while (TRUE) {
 | 
						|
    Extend0        = FALSE;
 | 
						|
    Extend1        = FALSE;
 | 
						|
    ScancodeArrPos = 0;
 | 
						|
    Status  = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return ;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED0) {
 | 
						|
      //
 | 
						|
      // E0 to look ahead 2 bytes
 | 
						|
      //
 | 
						|
      Extend0 = TRUE;
 | 
						|
      ScancodeArrPos = 1;
 | 
						|
      Status         = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        return ;
 | 
						|
      }
 | 
						|
    } else if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {
 | 
						|
      //
 | 
						|
      // E1 to look ahead 3 bytes
 | 
						|
      //
 | 
						|
      Extend1 = TRUE;
 | 
						|
      ScancodeArrPos = 2;
 | 
						|
      Status         = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        return ;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // if we reach this position, scancodes for a key is in buffer now,pop them
 | 
						|
    //
 | 
						|
    Status = PopScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    //
 | 
						|
    // store the last available byte, this byte of scancode will be checked
 | 
						|
    //
 | 
						|
    ScanCode = ScancodeArr[ScancodeArrPos];
 | 
						|
 | 
						|
    if (!Extend1) {
 | 
						|
      //
 | 
						|
      // Check for special keys and update the driver state.
 | 
						|
      //
 | 
						|
      switch (ScanCode) {
 | 
						|
 | 
						|
      case SCANCODE_CTRL_MAKE:
 | 
						|
        if (Extend0) {
 | 
						|
          ConsoleIn->RightCtrl = TRUE;
 | 
						|
        } else {
 | 
						|
          ConsoleIn->LeftCtrl  = TRUE;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      case SCANCODE_CTRL_BREAK:
 | 
						|
        if (Extend0) {
 | 
						|
          ConsoleIn->RightCtrl = FALSE;
 | 
						|
        } else {
 | 
						|
          ConsoleIn->LeftCtrl  = FALSE;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
      case SCANCODE_ALT_MAKE:
 | 
						|
          if (Extend0) {
 | 
						|
            ConsoleIn->RightAlt = TRUE;
 | 
						|
          } else {
 | 
						|
            ConsoleIn->LeftAlt  = TRUE;
 | 
						|
          }
 | 
						|
        break;
 | 
						|
      case SCANCODE_ALT_BREAK:
 | 
						|
          if (Extend0) {
 | 
						|
            ConsoleIn->RightAlt = FALSE;
 | 
						|
          } else {
 | 
						|
            ConsoleIn->LeftAlt  = FALSE;
 | 
						|
          }
 | 
						|
        break;
 | 
						|
 | 
						|
      case SCANCODE_LEFT_SHIFT_MAKE:
 | 
						|
        //
 | 
						|
        // To avoid recognize PRNT_SCRN key as a L_SHIFT key
 | 
						|
        // because PRNT_SCRN key generates E0 followed by L_SHIFT scan code.
 | 
						|
        // If it the second byte of the PRNT_ScRN skip it.
 | 
						|
        //
 | 
						|
        if (!Extend0) {
 | 
						|
          ConsoleIn->LeftShift  = TRUE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        continue;
 | 
						|
 | 
						|
      case SCANCODE_LEFT_SHIFT_BREAK:
 | 
						|
        if (!Extend0) {
 | 
						|
          ConsoleIn->LeftShift = FALSE;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
      case SCANCODE_RIGHT_SHIFT_MAKE:
 | 
						|
        ConsoleIn->RightShift = TRUE;
 | 
						|
        break;
 | 
						|
      case SCANCODE_RIGHT_SHIFT_BREAK:
 | 
						|
        ConsoleIn->RightShift = FALSE;
 | 
						|
        break;
 | 
						|
 | 
						|
      case SCANCODE_LEFT_LOGO_MAKE:
 | 
						|
        ConsoleIn->LeftLogo = TRUE;
 | 
						|
        break;
 | 
						|
      case SCANCODE_LEFT_LOGO_BREAK:
 | 
						|
        ConsoleIn->LeftLogo = FALSE;
 | 
						|
        break;
 | 
						|
 | 
						|
      case SCANCODE_RIGHT_LOGO_MAKE:
 | 
						|
        ConsoleIn->RightLogo = TRUE;
 | 
						|
        break;
 | 
						|
      case SCANCODE_RIGHT_LOGO_BREAK:
 | 
						|
        ConsoleIn->RightLogo = FALSE;
 | 
						|
        break;
 | 
						|
 | 
						|
      case SCANCODE_MENU_MAKE:
 | 
						|
        ConsoleIn->Menu = TRUE;
 | 
						|
        break;
 | 
						|
      case SCANCODE_MENU_BREAK:
 | 
						|
        ConsoleIn->Menu = FALSE;
 | 
						|
        break;
 | 
						|
 | 
						|
      case SCANCODE_SYS_REQ_MAKE:
 | 
						|
        if (Extend0) {
 | 
						|
          ConsoleIn->SysReq = TRUE;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      case SCANCODE_SYS_REQ_BREAK:
 | 
						|
        if (Extend0) {
 | 
						|
          ConsoleIn->SysReq = FALSE;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
      case SCANCODE_SYS_REQ_MAKE_WITH_ALT:
 | 
						|
        ConsoleIn->SysReq = TRUE;
 | 
						|
        break;
 | 
						|
      case SCANCODE_SYS_REQ_BREAK_WITH_ALT:
 | 
						|
        ConsoleIn->SysReq = FALSE;
 | 
						|
        break;
 | 
						|
 | 
						|
      case SCANCODE_CAPS_LOCK_MAKE:
 | 
						|
        ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;
 | 
						|
        UpdateStatusLights (ConsoleIn);
 | 
						|
        break;
 | 
						|
      case SCANCODE_NUM_LOCK_MAKE:
 | 
						|
        ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock;
 | 
						|
        UpdateStatusLights (ConsoleIn);
 | 
						|
        break;
 | 
						|
      case SCANCODE_SCROLL_LOCK_MAKE:
 | 
						|
        if (!Extend0) {
 | 
						|
          ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;
 | 
						|
          UpdateStatusLights (ConsoleIn);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // If this is above the valid range, ignore it
 | 
						|
    //
 | 
						|
    if (ScanCode >= SCANCODE_MAX_MAKE) {
 | 
						|
      continue;
 | 
						|
    } else {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Handle Ctrl+Alt+Del hotkey
 | 
						|
  //
 | 
						|
  if ((ConsoleIn->LeftCtrl || ConsoleIn->RightCtrl) &&
 | 
						|
      (ConsoleIn->LeftAlt  || ConsoleIn->RightAlt ) &&
 | 
						|
      ScanCode == SCANCODE_DELETE_MAKE
 | 
						|
     ) {
 | 
						|
    gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Save the Shift/Toggle state
 | 
						|
  //
 | 
						|
  InitializeKeyState (ConsoleIn, &KeyData.KeyState);
 | 
						|
  KeyData.Key.ScanCode    = SCAN_NULL;
 | 
						|
  KeyData.Key.UnicodeChar = CHAR_NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Key Pad "/" shares the same scancode as that of "/" except Key Pad "/" has E0 prefix
 | 
						|
  //
 | 
						|
  if (Extend0 && ScanCode == 0x35) {
 | 
						|
    KeyData.Key.UnicodeChar = L'/';
 | 
						|
    KeyData.Key.ScanCode    = SCAN_NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // PAUSE shares the same scancode as that of NUM except PAUSE has E1 prefix
 | 
						|
  //
 | 
						|
  } else if (Extend1 && ScanCode == SCANCODE_NUM_LOCK_MAKE) {
 | 
						|
    KeyData.Key.UnicodeChar = CHAR_NULL;
 | 
						|
    KeyData.Key.ScanCode    = SCAN_PAUSE;
 | 
						|
 | 
						|
  //
 | 
						|
  // PAUSE shares the same scancode as that of SCROLL except PAUSE (CTRL pressed) has E0 prefix
 | 
						|
  //
 | 
						|
  } else if (Extend0 && ScanCode == SCANCODE_SCROLL_LOCK_MAKE) {
 | 
						|
    KeyData.Key.UnicodeChar = CHAR_NULL;
 | 
						|
    KeyData.Key.ScanCode    = SCAN_PAUSE;
 | 
						|
 | 
						|
  //
 | 
						|
  // PRNT_SCRN shares the same scancode as that of Key Pad "*" except PRNT_SCRN has E0 prefix
 | 
						|
  //
 | 
						|
  } else if (Extend0 && ScanCode == SCANCODE_SYS_REQ_MAKE) {
 | 
						|
    KeyData.Key.UnicodeChar = CHAR_NULL;
 | 
						|
    KeyData.Key.ScanCode    = SCAN_NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Except the above special case, all others can be handled by convert table
 | 
						|
  //
 | 
						|
  } else {
 | 
						|
    for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index++) {
 | 
						|
      if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {
 | 
						|
        KeyData.Key.ScanCode    = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;
 | 
						|
        KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;
 | 
						|
 | 
						|
        if ((ConsoleIn->LeftShift || ConsoleIn->RightShift) &&
 | 
						|
            (ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar != ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar)) {
 | 
						|
          KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;
 | 
						|
          //
 | 
						|
          // Need not return associated shift state if a class of printable characters that
 | 
						|
          // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
 | 
						|
          //
 | 
						|
          KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // alphabetic key is affected by CapsLock State
 | 
						|
        //
 | 
						|
        if (ConsoleIn->CapsLock) {
 | 
						|
          if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
 | 
						|
            KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + L'A');
 | 
						|
          } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {
 | 
						|
            KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + L'a');
 | 
						|
          }
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // distinguish numeric key pad keys' 'up symbol' and 'down symbol'
 | 
						|
  //
 | 
						|
  if (ScanCode >= 0x47 && ScanCode <= 0x53) {
 | 
						|
    if (ConsoleIn->NumLock && !(ConsoleIn->LeftShift || ConsoleIn->RightShift) && !Extend0) {
 | 
						|
      KeyData.Key.ScanCode = SCAN_NULL;
 | 
						|
    } else if (ScanCode != 0x4a && ScanCode != 0x4e) {
 | 
						|
      KeyData.Key.UnicodeChar = CHAR_NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If the key can not be converted then just return.
 | 
						|
  //
 | 
						|
  if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
 | 
						|
    if (!ConsoleIn->IsSupportPartialKey) {
 | 
						|
      return ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Signal KeyNotify process event if this key pressed matches any key registered.
 | 
						|
  //
 | 
						|
  for (Link = GetFirstNode (&ConsoleIn->NotifyList); !IsNull (&ConsoleIn->NotifyList, Link); Link = GetNextNode (&ConsoleIn->NotifyList, Link)) {
 | 
						|
    CurrentNotify = CR (
 | 
						|
                      Link,
 | 
						|
                      KEYBOARD_CONSOLE_IN_EX_NOTIFY,
 | 
						|
                      NotifyEntry,
 | 
						|
                      KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
 | 
						|
                      );
 | 
						|
    if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
 | 
						|
      //
 | 
						|
      // The key notification function needs to run at TPL_CALLBACK
 | 
						|
      // while current TPL is TPL_NOTIFY. It will be invoked in
 | 
						|
      // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
 | 
						|
      //
 | 
						|
      PushEfikeyBufTail (&ConsoleIn->EfiKeyQueueForNotify, &KeyData);
 | 
						|
      gBS->SignalEvent (ConsoleIn->KeyNotifyProcessEvent);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  PushEfikeyBufTail (&ConsoleIn->EfiKeyQueue, &KeyData);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Perform 8042 controller and keyboard Initialization.
 | 
						|
  If ExtendedVerification is TRUE, do additional test for
 | 
						|
  the keyboard interface
 | 
						|
 | 
						|
  @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
 | 
						|
  @param ExtendedVerification - indicates a thorough initialization
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR Fail to init keyboard
 | 
						|
  @retval EFI_SUCCESS      Success to init keyboard
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
InitKeyboard (
 | 
						|
  IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN BOOLEAN                     ExtendedVerification
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_STATUS              Status1;
 | 
						|
  UINT8                   CommandByte;
 | 
						|
  EFI_PS2_POLICY_PROTOCOL *Ps2Policy;
 | 
						|
  UINT32                  TryTime;
 | 
						|
 | 
						|
  Status                 = EFI_SUCCESS;
 | 
						|
  mEnableMouseInterface  = TRUE;
 | 
						|
  TryTime                = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get Ps2 policy to set this
 | 
						|
  //
 | 
						|
  gBS->LocateProtocol (
 | 
						|
        &gEfiPs2PolicyProtocolGuid,
 | 
						|
        NULL,
 | 
						|
        (VOID **) &Ps2Policy
 | 
						|
        );
 | 
						|
 | 
						|
  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
    EFI_PROGRESS_CODE,
 | 
						|
    EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,
 | 
						|
    ConsoleIn->DevicePath
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Perform a read to cleanup the Status Register's
 | 
						|
  // output buffer full bits within MAX TRY times
 | 
						|
  //
 | 
						|
  if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) != 0) {
 | 
						|
    while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) {
 | 
						|
      Status = KeyboardRead (ConsoleIn, &CommandByte);
 | 
						|
      TryTime ++;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Exceed the max try times. The device may be error.
 | 
						|
    //
 | 
						|
    if (TryTime == KEYBOARD_MAX_TRY) {
 | 
						|
      Status = EFI_DEVICE_ERROR;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // We should disable mouse interface during the initialization process
 | 
						|
  // since mouse device output could block keyboard device output in the
 | 
						|
  // 60H port of 8042 controller.
 | 
						|
  //
 | 
						|
  // So if we are not initializing 8042 controller for the
 | 
						|
  // first time, we have to remember the previous mouse interface
 | 
						|
  // enabling state
 | 
						|
  //
 | 
						|
  // Test the system flag in to determine whether this is the first
 | 
						|
  // time initialization
 | 
						|
  //
 | 
						|
  if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG) != 0) {
 | 
						|
    if (!PcdGetBool (PcdFastPS2Detection)) {
 | 
						|
      //
 | 
						|
      // 8042 controller is already setup (by myself or by mouse driver):
 | 
						|
      //   See whether mouse interface is already enabled
 | 
						|
      //   which determines whether we should enable it later
 | 
						|
      //
 | 
						|
      //
 | 
						|
      // Read the command byte of 8042 controller
 | 
						|
      //
 | 
						|
      Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_READ);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        KeyboardError (ConsoleIn, L"\n\r");
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      Status = KeyboardRead (ConsoleIn, &CommandByte);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        KeyboardError (ConsoleIn, L"\n\r");
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Test the mouse enabling bit
 | 
						|
      //
 | 
						|
      if ((CommandByte & 0x20) != 0) {
 | 
						|
        mEnableMouseInterface = FALSE;
 | 
						|
      } else {
 | 
						|
        mEnableMouseInterface = TRUE;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      mEnableMouseInterface = FALSE;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // 8042 controller is not setup yet:
 | 
						|
    //   8042 controller selftest;
 | 
						|
    //   Don't enable mouse interface later.
 | 
						|
    //
 | 
						|
    //
 | 
						|
    // Disable keyboard and mouse interfaces
 | 
						|
    //
 | 
						|
    if (!PcdGetBool (PcdFastPS2Detection)) {
 | 
						|
      Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        KeyboardError (ConsoleIn, L"\n\r");
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        KeyboardError (ConsoleIn, L"\n\r");
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
        EFI_PROGRESS_CODE,
 | 
						|
        EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,
 | 
						|
        ConsoleIn->DevicePath
 | 
						|
        );
 | 
						|
      //
 | 
						|
      // 8042 Controller Self Test
 | 
						|
      //
 | 
						|
      Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      Status = KeyboardWaitForValue (ConsoleIn, 0x55);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Don't enable mouse interface later
 | 
						|
    //
 | 
						|
    mEnableMouseInterface = FALSE;
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  if (Ps2Policy != NULL) {
 | 
						|
    Ps2Policy->Ps2InitHardware (ConsoleIn->Handle);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Write 8042 Command Byte, set System Flag
 | 
						|
  // While at the same time:
 | 
						|
  //  1. disable mouse interface,
 | 
						|
  //  2. enable kbd interface,
 | 
						|
  //  3. enable PC/XT kbd translation mode
 | 
						|
  //  4. enable mouse and kbd interrupts
 | 
						|
  //
 | 
						|
  //  ( Command Byte bits:
 | 
						|
  //  7: Reserved
 | 
						|
  //  6: PC/XT translation mode
 | 
						|
  //  5: Disable Auxiliary device interface
 | 
						|
  //  4: Disable keyboard interface
 | 
						|
  //  3: Reserved
 | 
						|
  //  2: System Flag
 | 
						|
  //  1: Enable Auxiliary device interrupt
 | 
						|
  //  0: Enable Keyboard interrupt )
 | 
						|
  //
 | 
						|
  Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_WRITE);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = KeyboardWrite (ConsoleIn, 0x67);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Clear Memory Scancode Buffer
 | 
						|
  //
 | 
						|
  ConsoleIn->ScancodeQueue.Head = 0;
 | 
						|
  ConsoleIn->ScancodeQueue.Tail = 0;
 | 
						|
  ConsoleIn->EfiKeyQueue.Head   = 0;
 | 
						|
  ConsoleIn->EfiKeyQueue.Tail   = 0;
 | 
						|
  ConsoleIn->EfiKeyQueueForNotify.Head = 0;
 | 
						|
  ConsoleIn->EfiKeyQueueForNotify.Tail = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Reset the status indicators
 | 
						|
  //
 | 
						|
  ConsoleIn->CapsLock   = FALSE;
 | 
						|
  ConsoleIn->NumLock    = FALSE;
 | 
						|
  ConsoleIn->ScrollLock = FALSE;
 | 
						|
  ConsoleIn->LeftCtrl   = FALSE;
 | 
						|
  ConsoleIn->RightCtrl  = FALSE;
 | 
						|
  ConsoleIn->LeftAlt    = FALSE;
 | 
						|
  ConsoleIn->RightAlt   = FALSE;
 | 
						|
  ConsoleIn->LeftShift  = FALSE;
 | 
						|
  ConsoleIn->RightShift = FALSE;
 | 
						|
  ConsoleIn->LeftLogo   = FALSE;
 | 
						|
  ConsoleIn->RightLogo  = FALSE;
 | 
						|
  ConsoleIn->Menu       = FALSE;
 | 
						|
  ConsoleIn->SysReq     = FALSE;
 | 
						|
 | 
						|
  ConsoleIn->IsSupportPartialKey = FALSE;
 | 
						|
  //
 | 
						|
  // For resetting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
 | 
						|
  // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected
 | 
						|
  // to system. So we only do the real resetting for keyboard when user asks and there is a real KB connected t system,
 | 
						|
  // and normally during booting an OS, it's skipped.
 | 
						|
  //
 | 
						|
  if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {
 | 
						|
    //
 | 
						|
    // Additional verifications for keyboard interface
 | 
						|
    //
 | 
						|
    //
 | 
						|
    // Keyboard Interface Test
 | 
						|
    //
 | 
						|
    Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardWaitForValue (ConsoleIn, 0x00);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (
 | 
						|
        ConsoleIn,
 | 
						|
        L"Some specific value not aquired from 8042 controller!\n\r"
 | 
						|
        );
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Keyboard reset with a BAT(Basic Assurance Test)
 | 
						|
    //
 | 
						|
    Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_RESET);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // wait for BAT completion code
 | 
						|
    //
 | 
						|
    mWaitForValueTimeOut  = KEYBOARD_BAT_TIMEOUT;
 | 
						|
 | 
						|
    Status                = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_BAT_SUCCESS);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
 | 
						|
 | 
						|
    //
 | 
						|
    // Set Keyboard to use Scan Code Set 2
 | 
						|
    //
 | 
						|
    Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardWrite (ConsoleIn, 0x02);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
  //
 | 
						|
  // Clear Keyboard Scancode Buffer
 | 
						|
  //
 | 
						|
  Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  if (Ps2Policy != NULL) {
 | 
						|
    if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {
 | 
						|
      ConsoleIn->CapsLock = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {
 | 
						|
      ConsoleIn->NumLock = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {
 | 
						|
      ConsoleIn->ScrollLock = TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Update Keyboard Lights
 | 
						|
  //
 | 
						|
  Status = UpdateStatusLights (ConsoleIn);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r");
 | 
						|
    goto Done;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // At last, we can now enable the mouse interface if appropriate
 | 
						|
  //
 | 
						|
Done:
 | 
						|
 | 
						|
  if (mEnableMouseInterface) {
 | 
						|
    //
 | 
						|
    // Enable mouse interface
 | 
						|
    //
 | 
						|
    Status1 = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE);
 | 
						|
    if (EFI_ERROR (Status1)) {
 | 
						|
      KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
 | 
						|
  If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
 | 
						|
  should not be in system.
 | 
						|
 | 
						|
  @param[in]  ConsoleIn             Keyboard Private Data Structure
 | 
						|
 | 
						|
  @retval     TRUE                  Keyboard in System.
 | 
						|
  @retval     FALSE                 Keyboard not in System.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
CheckKeyboardConnect (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS     Status;
 | 
						|
  UINTN          WaitForValueTimeOutBcakup;
 | 
						|
 | 
						|
  //
 | 
						|
  // enable keyboard itself and wait for its ack
 | 
						|
  // If can't receive ack, Keyboard should not be connected.
 | 
						|
  //
 | 
						|
  if (!PcdGetBool (PcdFastPS2Detection)) {
 | 
						|
    Status = KeyboardWrite (
 | 
						|
               ConsoleIn,
 | 
						|
               KEYBOARD_KBEN
 | 
						|
               );
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // wait for 1s
 | 
						|
    //
 | 
						|
    WaitForValueTimeOutBcakup = mWaitForValueTimeOut;
 | 
						|
    mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
 | 
						|
    Status = KeyboardWaitForValue (
 | 
						|
               ConsoleIn,
 | 
						|
               KEYBOARD_CMDECHO_ACK
 | 
						|
               );
 | 
						|
    mWaitForValueTimeOut = WaitForValueTimeOutBcakup;
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
  } else {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
}
 | 
						|
 |