]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbKbDxe/keyboard.c
Merged in the following trackers from EDK:
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbKbDxe / keyboard.c
index 87179a4c6bbac6255814901fec4388643141e2ad..72fafd9472277404ba2f6a5f7108dd2053d293eb 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
-Copyright (c) 2004 - 2005, Intel Corporation\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
 All rights reserved. This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -24,129 +24,316 @@ Revision History
 \r
 #include "keyboard.h"\r
 #include <Library/UsbLib.h>\r
+\r
+//\r
+// Static English keyboard layout\r
+// Format:<efi key>, <unicode without shift>, <unicode with shift>, <Modifier>, <AffectedAttribute>\r
+//\r
+STATIC\r
+UINT8 KeyboardLayoutTable[USB_KEYCODE_MAX_MAKE + 8][5] = {\r
+  {EfiKeyC1,         'a',      'A',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x04\r
+  {EfiKeyB5,         'b',      'B',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x05\r
+  {EfiKeyB3,         'c',      'C',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x06\r
+  {EfiKeyC3,         'd',      'D',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x07\r
+  {EfiKeyD3,         'e',      'E',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x08\r
+  {EfiKeyC4,         'f',      'F',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x09\r
+  {EfiKeyC5,         'g',      'G',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x0A\r
+  {EfiKeyC6,         'h',      'H',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x0B\r
+  {EfiKeyD8,         'i',      'I',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x0C\r
+  {EfiKeyC7,         'j',      'J',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x0D\r
+  {EfiKeyC8,         'k',      'K',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x0E\r
+  {EfiKeyC9,         'l',      'L',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x0F\r
+  {EfiKeyB7,         'm',      'M',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x10\r
+  {EfiKeyB6,         'n',      'N',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x11\r
+  {EfiKeyD9,         'o',      'O',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x12\r
+  {EfiKeyD10,        'p',      'P',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x13\r
+  {EfiKeyD1,         'q',      'Q',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x14\r
+  {EfiKeyD4,         'r',      'R',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x15\r
+  {EfiKeyC2,         's',      'S',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x16\r
+  {EfiKeyD5,         't',      'T',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x17\r
+  {EfiKeyD7,         'u',      'U',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x18\r
+  {EfiKeyB4,         'v',      'V',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x19\r
+  {EfiKeyD2,         'w',      'W',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x1A\r
+  {EfiKeyB2,         'x',      'X',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x1B\r
+  {EfiKeyD6,         'y',      'Y',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x1C\r
+  {EfiKeyB1,         'z',      'Z',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_CAPS_LOCK},   // 0x1D\r
+  {EfiKeyE1,         '1',      '!',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x1E\r
+  {EfiKeyE2,         '2',      '@',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x1F\r
+  {EfiKeyE3,         '3',      '#',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x20\r
+  {EfiKeyE4,         '4',      '$',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x21\r
+  {EfiKeyE5,         '5',      '%',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x22\r
+  {EfiKeyE6,         '6',      '^',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x23\r
+  {EfiKeyE7,         '7',      '&',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x24\r
+  {EfiKeyE8,         '8',      '*',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x25\r
+  {EfiKeyE9,         '9',      '(',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x26\r
+  {EfiKeyE10,        '0',      ')',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x27\r
+  {EfiKeyEnter,      0x0d,     0x0d,  EFI_NULL_MODIFIER,   0},                                // 0x28   Enter\r
+  {EfiKeyEsc,        0x1b,     0x1b,  EFI_NULL_MODIFIER,   0},                                // 0x29   Esc\r
+  {EfiKeyBackSpace,  0x08,     0x08,  EFI_NULL_MODIFIER,   0},                                // 0x2A   Backspace\r
+  {EfiKeyTab,        0x09,     0x09,  EFI_NULL_MODIFIER,   0},                                // 0x2B   Tab\r
+  {EfiKeySpaceBar,   ' ',      ' ',   EFI_NULL_MODIFIER,   0},                                // 0x2C   Spacebar\r
+  {EfiKeyE11,        '-',      '_',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x2D\r
+  {EfiKeyE12,        '=',      '+',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x2E\r
+  {EfiKeyD11,        '[',      '{',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x2F\r
+  {EfiKeyD12,        ']',      '}',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x30\r
+  {EfiKeyD13,        '\\',     '|',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x31\r
+  {EfiKeyC12,        '\\',     '|',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x32  Keyboard Non-US # and ~\r
+  {EfiKeyC10,        ';',      ':',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x33\r
+  {EfiKeyC11,        '\'',     '"',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x34\r
+  {EfiKeyE0,         '`',      '~',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x35  Keyboard Grave Accent and Tlide\r
+  {EfiKeyB8,         ',',      '<',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x36\r
+  {EfiKeyB9,         '.',      '>',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x37\r
+  {EfiKeyB10,        '/',      '?',   EFI_NULL_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT},   // 0x38\r
+  {EfiKeyCapsLock,   0x00,     0x00,  EFI_CAPS_LOCK_MODIFIER,            0},                  // 0x39   CapsLock\r
+  {EfiKeyF1,         0x00,     0x00,  EFI_FUNCTION_KEY_ONE_MODIFIER,     0},                  // 0x3A\r
+  {EfiKeyF2,         0x00,     0x00,  EFI_FUNCTION_KEY_TWO_MODIFIER,     0},                  // 0x3B\r
+  {EfiKeyF3,         0x00,     0x00,  EFI_FUNCTION_KEY_THREE_MODIFIER,   0},                  // 0x3C\r
+  {EfiKeyF4,         0x00,     0x00,  EFI_FUNCTION_KEY_FOUR_MODIFIER,    0},                  // 0x3D\r
+  {EfiKeyF5,         0x00,     0x00,  EFI_FUNCTION_KEY_FIVE_MODIFIER,    0},                  // 0x3E\r
+  {EfiKeyF6,         0x00,     0x00,  EFI_FUNCTION_KEY_SIX_MODIFIER,     0},                  // 0x3F\r
+  {EfiKeyF7,         0x00,     0x00,  EFI_FUNCTION_KEY_SEVEN_MODIFIER,   0},                  // 0x40\r
+  {EfiKeyF8,         0x00,     0x00,  EFI_FUNCTION_KEY_EIGHT_MODIFIER,   0},                  // 0x41\r
+  {EfiKeyF9,         0x00,     0x00,  EFI_FUNCTION_KEY_NINE_MODIFIER,    0},                  // 0x42\r
+  {EfiKeyF10,        0x00,     0x00,  EFI_FUNCTION_KEY_TEN_MODIFIER,     0},                  // 0x43\r
+  {EfiKeyF11,        0x00,     0x00,  EFI_FUNCTION_KEY_ELEVEN_MODIFIER,  0},                  // 0x44   F11\r
+  {EfiKeyF12,        0x00,     0x00,  EFI_FUNCTION_KEY_TWELVE_MODIFIER,  0},                  // 0x45   F12\r
+  {EfiKeyPrint,      0x00,     0x00,  EFI_PRINT_MODIFIER,                0},                  // 0x46   PrintScreen\r
+  {EfiKeySLck,       0x00,     0x00,  EFI_SCROLL_LOCK_MODIFIER,          0},                  // 0x47   Scroll Lock\r
+  {EfiKeyPause,      0x00,     0x00,  EFI_PAUSE_MODIFIER,                0},                  // 0x48   Pause\r
+  {EfiKeyIns,        0x00,     0x00,  EFI_INSERT_MODIFIER,               0},                  // 0x49\r
+  {EfiKeyHome,       0x00,     0x00,  EFI_HOME_MODIFIER,                 0},                  // 0x4A\r
+  {EfiKeyPgUp,       0x00,     0x00,  EFI_PAGE_UP_MODIFIER,              0},                  // 0x4B\r
+  {EfiKeyDel,        0x00,     0x00,  EFI_DELETE_MODIFIER,               0},                  // 0x4C\r
+  {EfiKeyEnd,        0x00,     0x00,  EFI_END_MODIFIER,                  0},                  // 0x4D\r
+  {EfiKeyPgDn,       0x00,     0x00,  EFI_PAGE_DOWN_MODIFIER,            0},                  // 0x4E\r
+  {EfiKeyRightArrow, 0x00,     0x00,  EFI_RIGHT_ARROW_MODIFIER,          0},                  // 0x4F\r
+  {EfiKeyLeftArrow,  0x00,     0x00,  EFI_LEFT_ARROW_MODIFIER,           0},                  // 0x50\r
+  {EfiKeyDownArrow,  0x00,     0x00,  EFI_DOWN_ARROW_MODIFIER,           0},                  // 0x51\r
+  {EfiKeyUpArrow,    0x00,     0x00,  EFI_UP_ARROW_MODIFIER,             0},                  // 0x52\r
+  {EfiKeyNLck,       0x00,     0x00,  EFI_NUM_LOCK_MODIFIER,             0},                  // 0x53   NumLock\r
+  {EfiKeySlash,      '/',      '/',   EFI_NULL_MODIFIER,                 0},                  // 0x54\r
+  {EfiKeyAsterisk,   '*',      '*',   EFI_NULL_MODIFIER,                 0},                  // 0x55\r
+  {EfiKeyMinus,      '-',      '-',   EFI_NULL_MODIFIER,                 0},                  // 0x56\r
+  {EfiKeyPlus,       '+',      '+',   EFI_NULL_MODIFIER,                 0},                  // 0x57\r
+  {EfiKeyEnter,      0x0d,     0x0d,  EFI_NULL_MODIFIER,                 0},                  // 0x58\r
+  {EfiKeyOne,        '1',      '1',   EFI_END_MODIFIER,         EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},   // 0x59\r
+  {EfiKeyTwo,        '2',      '2',   EFI_DOWN_ARROW_MODIFIER,  EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},   // 0x5A\r
+  {EfiKeyThree,      '3',      '3',   EFI_PAGE_DOWN_MODIFIER,   EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},   // 0x5B\r
+  {EfiKeyFour,       '4',      '4',   EFI_LEFT_ARROW_MODIFIER,  EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},   // 0x5C\r
+  {EfiKeyFive,       '5',      '5',   EFI_NULL_MODIFIER,        EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},   // 0x5D\r
+  {EfiKeySix,        '6',      '6',   EFI_RIGHT_ARROW_MODIFIER, EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},   // 0x5E\r
+  {EfiKeySeven,      '7',      '7',   EFI_HOME_MODIFIER,        EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},   // 0x5F\r
+  {EfiKeyEight,      '8',      '8',   EFI_UP_ARROW_MODIFIER,    EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},   // 0x60\r
+  {EfiKeyNine,       '9',      '9',   EFI_PAGE_UP_MODIFIER,     EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},   // 0x61\r
+  {EfiKeyZero,       '0',      '0',   EFI_INSERT_MODIFIER,      EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},   // 0x62\r
+  {EfiKeyPeriod,     '.',      '.',   EFI_DELETE_MODIFIER,      EFI_AFFECTED_BY_STANDARD_SHIFT | EFI_AFFECTED_BY_NUM_LOCK},   // 0x63\r
+  {EfiKeyB0,         '\\',     '|',   EFI_NULL_MODIFIER,        EFI_AFFECTED_BY_STANDARD_SHIFT}, // 0x64 Keyboard Non-US \ and |\r
+  {EfiKeyA4,         0x00,     0x00,  EFI_NULL_MODIFIER,        0},                              // 0x65 Keyboard Application\r
+\r
+  {EfiKeyLCtrl,      0,        0,     EFI_LEFT_CONTROL_MODIFIER,    0},  // 0xe0\r
+  {EfiKeyLShift,     0,        0,     EFI_LEFT_SHIFT_MODIFIER,      0},  // 0xe1\r
+  {EfiKeyLAlt,       0,        0,     EFI_LEFT_ALT_MODIFIER,        0},  // 0xe2\r
+  {EfiKeyA0,         0,        0,     EFI_NULL_MODIFIER,            0},  // 0xe3\r
+  {EfiKeyRCtrl,      0,        0,     EFI_RIGHT_CONTROL_MODIFIER,   0},  // 0xe4\r
+  {EfiKeyRShift,     0,        0,     EFI_RIGHT_SHIFT_MODIFIER,     0},  // 0xe5\r
+  {EfiKeyA2,         0,        0,     EFI_RIGHT_ALT_MODIFIER,       0},  // 0xe6\r
+  {EfiKeyA3,         0,        0,     EFI_NULL_MODIFIER,            0},  // 0xe7\r
+};\r
+\r
+VOID\r
+LoadDefaultKeyboardLayout (\r
+  IN USB_KB_DEV                 *UsbKeyboardDevice\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Initialize KeyConvertionTable by using default keyboard layout.\r
+\r
+  Arguments:\r
+    UsbKeyboardDevice    The USB_KB_DEV instance.\r
+\r
+  Returns:\r
+    None.\r
+\r
+--*/\r
+{\r
+  UINTN               Index;\r
+  EFI_KEY_DESCRIPTOR  *KeyDescriptor;\r
+\r
+  //\r
+  // Construct KeyConvertionTable by default keyboard layout\r
+  //\r
+  KeyDescriptor = &UsbKeyboardDevice->KeyConvertionTable[0];\r
+\r
+  for (Index = 0; Index < (USB_KEYCODE_MAX_MAKE + 8); Index++) {\r
+    KeyDescriptor->Key                 = (EFI_KEY) KeyboardLayoutTable[Index][0];\r
+    KeyDescriptor->Unicode             = KeyboardLayoutTable[Index][1];\r
+    KeyDescriptor->ShiftedUnicode      = KeyboardLayoutTable[Index][2];\r
+    KeyDescriptor->AltGrUnicode        = 0;\r
+    KeyDescriptor->ShiftedAltGrUnicode = 0;\r
+    KeyDescriptor->Modifier            = KeyboardLayoutTable[Index][3];\r
+    KeyDescriptor->AffectedAttribute   = KeyboardLayoutTable[Index][4];\r
+\r
+    KeyDescriptor++;\r
+  }\r
+}\r
+\r
+//\r
+// EFI_KEY to USB Scan Code convertion table\r
+//\r
+STATIC\r
+UINT8 UsbScanCodeConvertionTable[] = {\r
+  0xe0,  //  EfiKeyLCtrl\r
+  0xe3,  //  EfiKeyA0\r
+  0xe2,  //  EfiKeyLAlt\r
+  0x2c,  //  EfiKeySpaceBar\r
+  0xe6,  //  EfiKeyA2\r
+  0xe7,  //  EfiKeyA3\r
+  0x65,  //  EfiKeyA4\r
+  0xe4,  //  EfiKeyRCtrl\r
+  0x50,  //  EfiKeyLeftArrow\r
+  0x51,  //  EfiKeyDownArrow\r
+  0x4F,  //  EfiKeyRightArrow\r
+  0x62,  //  EfiKeyZero\r
+  0x63,  //  EfiKeyPeriod\r
+  0x28,  //  EfiKeyEnter\r
+  0xe1,  //  EfiKeyLShift\r
+  0x64,  //  EfiKeyB0\r
+  0x1D,  //  EfiKeyB1\r
+  0x1B,  //  EfiKeyB2\r
+  0x06,  //  EfiKeyB3\r
+  0x19,  //  EfiKeyB4\r
+  0x05,  //  EfiKeyB5\r
+  0x11,  //  EfiKeyB6\r
+  0x10,  //  EfiKeyB7\r
+  0x36,  //  EfiKeyB8\r
+  0x37,  //  EfiKeyB9\r
+  0x38,  //  EfiKeyB10\r
+  0xe5,  //  EfiKeyRShift\r
+  0x52,  //  EfiKeyUpArrow\r
+  0x59,  //  EfiKeyOne\r
+  0x5A,  //  EfiKeyTwo\r
+  0x5B,  //  EfiKeyThree\r
+  0x39,  //  EfiKeyCapsLock\r
+  0x04,  //  EfiKeyC1\r
+  0x16,  //  EfiKeyC2\r
+  0x07,  //  EfiKeyC3\r
+  0x09,  //  EfiKeyC4\r
+  0x0A,  //  EfiKeyC5\r
+  0x0B,  //  EfiKeyC6\r
+  0x0D,  //  EfiKeyC7\r
+  0x0E,  //  EfiKeyC8\r
+  0x0F,  //  EfiKeyC9\r
+  0x33,  //  EfiKeyC10\r
+  0x34,  //  EfiKeyC11\r
+  0x32,  //  EfiKeyC12\r
+  0x5C,  //  EfiKeyFour\r
+  0x5D,  //  EfiKeyFive\r
+  0x5E,  //  EfiKeySix\r
+  0x57,  //  EfiKeyPlus\r
+  0x2B,  //  EfiKeyTab\r
+  0x14,  //  EfiKeyD1\r
+  0x1A,  //  EfiKeyD2\r
+  0x08,  //  EfiKeyD3\r
+  0x15,  //  EfiKeyD4\r
+  0x17,  //  EfiKeyD5\r
+  0x1C,  //  EfiKeyD6\r
+  0x18,  //  EfiKeyD7\r
+  0x0C,  //  EfiKeyD8\r
+  0x12,  //  EfiKeyD9\r
+  0x13,  //  EfiKeyD10\r
+  0x2F,  //  EfiKeyD11\r
+  0x30,  //  EfiKeyD12\r
+  0x31,  //  EfiKeyD13\r
+  0x4C,  //  EfiKeyDel\r
+  0x4D,  //  EfiKeyEnd\r
+  0x4E,  //  EfiKeyPgDn\r
+  0x5F,  //  EfiKeySeven\r
+  0x60,  //  EfiKeyEight\r
+  0x61,  //  EfiKeyNine\r
+  0x35,  //  EfiKeyE0\r
+  0x1E,  //  EfiKeyE1\r
+  0x1F,  //  EfiKeyE2\r
+  0x20,  //  EfiKeyE3\r
+  0x21,  //  EfiKeyE4\r
+  0x22,  //  EfiKeyE5\r
+  0x23,  //  EfiKeyE6\r
+  0x24,  //  EfiKeyE7\r
+  0x25,  //  EfiKeyE8\r
+  0x26,  //  EfiKeyE9\r
+  0x27,  //  EfiKeyE10\r
+  0x2D,  //  EfiKeyE11\r
+  0x2E,  //  EfiKeyE12\r
+  0x2A,  //  EfiKeyBackSpace\r
+  0x49,  //  EfiKeyIns\r
+  0x4A,  //  EfiKeyHome\r
+  0x4B,  //  EfiKeyPgUp\r
+  0x53,  //  EfiKeyNLck\r
+  0x54,  //  EfiKeySlash\r
+  0x55,  //  EfiKeyAsterisk\r
+  0x56,  //  EfiKeyMinus\r
+  0x29,  //  EfiKeyEsc\r
+  0x3A,  //  EfiKeyF1\r
+  0x3B,  //  EfiKeyF2\r
+  0x3C,  //  EfiKeyF3\r
+  0x3D,  //  EfiKeyF4\r
+  0x3E,  //  EfiKeyF5\r
+  0x3F,  //  EfiKeyF6\r
+  0x40,  //  EfiKeyF7\r
+  0x41,  //  EfiKeyF8\r
+  0x42,  //  EfiKeyF9\r
+  0x43,  //  EfiKeyF10\r
+  0x44,  //  EfiKeyF11\r
+  0x45,  //  EfiKeyF12\r
+  0x46,  //  EfiKeyPrint\r
+  0x47,  //  EfiKeySLck\r
+  0x48   //  EfiKeyPause\r
+};\r
+\r
 //\r
-// USB Key Code to Efi key mapping table\r
-// Format:<efi scan code>, <unicode without shift>, <unicode with shift>\r
+// Keyboard Layout Modifier to EFI Scan Code convertion table\r
 //\r
 STATIC\r
-UINT8 KeyConvertionTable[USB_KEYCODE_MAX_MAKE][3] = {\r
-  { SCAN_NULL,      'a',      'A' },      // 0x04\r
-  { SCAN_NULL,      'b',      'B' },      // 0x05\r
-  { SCAN_NULL,      'c',      'C' },      // 0x06\r
-  { SCAN_NULL,      'd',      'D' },      // 0x07\r
-  { SCAN_NULL,      'e',      'E' },      // 0x08\r
-  { SCAN_NULL,      'f',      'F' },      // 0x09\r
-  { SCAN_NULL,      'g',      'G' },      // 0x0A\r
-  { SCAN_NULL,      'h',      'H' },      // 0x0B\r
-  { SCAN_NULL,      'i',      'I' },      // 0x0C\r
-  { SCAN_NULL,      'j',      'J' },      // 0x0D\r
-  { SCAN_NULL,      'k',      'K' },      // 0x0E\r
-  { SCAN_NULL,      'l',      'L' },      // 0x0F\r
-  { SCAN_NULL,      'm',      'M' },      // 0x10\r
-  { SCAN_NULL,      'n',      'N' },      // 0x11\r
-  { SCAN_NULL,      'o',      'O' },      // 0x12\r
-  { SCAN_NULL,      'p',      'P' },      // 0x13\r
-  { SCAN_NULL,      'q',      'Q' },      // 0x14\r
-  { SCAN_NULL,      'r',      'R' },      // 0x15\r
-  { SCAN_NULL,      's',      'S' },      // 0x16\r
-  { SCAN_NULL,      't',      'T' },      // 0x17\r
-  { SCAN_NULL,      'u',      'U' },      // 0x18\r
-  { SCAN_NULL,      'v',      'V' },      // 0x19\r
-  { SCAN_NULL,      'w',      'W' },      // 0x1A\r
-  { SCAN_NULL,      'x',      'X' },      // 0x1B\r
-  { SCAN_NULL,      'y',      'Y' },      // 0x1C\r
-  { SCAN_NULL,      'z',      'Z' },      // 0x1D\r
-  { SCAN_NULL,      '1',      '!' },      // 0x1E\r
-  { SCAN_NULL,      '2',      '@' },      // 0x1F\r
-  { SCAN_NULL,      '3',      '#' },      // 0x20\r
-  { SCAN_NULL,      '4',      '$' },      // 0x21\r
-  { SCAN_NULL,      '5',      '%' },      // 0x22\r
-  { SCAN_NULL,      '6',      '^' },      // 0x23\r
-  { SCAN_NULL,      '7',      '&' },      // 0x24\r
-  { SCAN_NULL,      '8',      '*' },      // 0x25\r
-  { SCAN_NULL,      '9',      '(' },      // 0x26\r
-  { SCAN_NULL,      '0',      ')' },      // 0x27\r
-  { SCAN_NULL,      0x0d,     0x0d },     // 0x28   Enter\r
-  { SCAN_ESC,       0x00,     0x00 },     // 0x29   Esc\r
-  { SCAN_NULL,      0x08,     0x08 },     // 0x2A   Backspace\r
-  { SCAN_NULL,      0x09,     0x09 },     // 0x2B   Tab\r
-  { SCAN_NULL,      ' ',      ' ' },      // 0x2C   Spacebar\r
-  { SCAN_NULL,      '-',      '_' },      // 0x2D\r
-  { SCAN_NULL,      '=',      '+' },      // 0x2E\r
-  { SCAN_NULL,      '[',      '{' },      // 0x2F\r
-  { SCAN_NULL,      ']',      '}' },      // 0x30\r
-  { SCAN_NULL,      '\\',     '|' },      // 0x31\r
-  { SCAN_NULL,      '\\',     '|' },      // 0x32  Keyboard US \ and |\r
-  { SCAN_NULL,      ';',      ':' },      // 0x33\r
-  { SCAN_NULL,      '\'',     '"' },      // 0x34\r
-  { SCAN_NULL,      '`',      '~' },      // 0x35  Keyboard Grave Accent and Tlide\r
-  { SCAN_NULL,      ',',      '<' },      // 0x36\r
-  { SCAN_NULL,      '.',      '>' },      // 0x37\r
-  { SCAN_NULL,      '/',      '?' },      // 0x38\r
-  { SCAN_NULL,      0x00,     0x00 },     // 0x39   CapsLock\r
-  { SCAN_F1,        0x00,     0x00 },     // 0x3A\r
-  { SCAN_F2,        0x00,     0x00 },     // 0x3B\r
-  { SCAN_F3,        0x00,     0x00 },     // 0x3C\r
-  { SCAN_F4,        0x00,     0x00 },     // 0x3D\r
-  { SCAN_F5,        0x00,     0x00 },     // 0x3E\r
-  { SCAN_F6,        0x00,     0x00 },     // 0x3F\r
-  { SCAN_F7,        0x00,     0x00 },     // 0x40\r
-  { SCAN_F8,        0x00,     0x00 },     // 0x41\r
-  { SCAN_F9,        0x00,     0x00 },     // 0x42\r
-  { SCAN_F10,       0x00,     0x00 },     // 0x43\r
-  { SCAN_F11,       0x00,     0x00 },     // 0x44   F11\r
-  { SCAN_F12,       0x00,     0x00 },     // 0x45   F12\r
-  { SCAN_NULL,      0x00,     0x00 },     // 0x46   PrintScreen\r
-  { SCAN_NULL,      0x00,     0x00 },     // 0x47   Scroll Lock\r
-  { SCAN_NULL,      0x00,     0x00 },     // 0x48   Pause\r
-  { SCAN_INSERT,    0x00,     0x00 },     // 0x49\r
-  { SCAN_HOME,      0x00,     0x00 },     // 0x4A\r
-  { SCAN_PAGE_UP,   0x00,     0x00 },     // 0x4B\r
-  { SCAN_DELETE,    0x00,     0x00 },     // 0x4C\r
-  { SCAN_END,       0x00,     0x00 },     // 0x4D\r
-  { SCAN_PAGE_DOWN, 0x00,     0x00 },     // 0x4E\r
-  { SCAN_RIGHT,     0x00,     0x00 },     // 0x4F\r
-  { SCAN_LEFT,      0x00,     0x00 },     // 0x50\r
-  { SCAN_DOWN,      0x00,     0x00 },     // 0x51\r
-  { SCAN_UP,        0x00,     0x00 },     // 0x52\r
-  { SCAN_NULL,      0x00,     0x00 },     // 0x53   NumLock\r
-  { SCAN_NULL,      '/',      '/' },      // 0x54\r
-  { SCAN_NULL,      '*',      '*' },      // 0x55\r
-  { SCAN_NULL,      '-',      '-' },      // 0x56\r
-  { SCAN_NULL,      '+',      '+' },      // 0x57\r
-  { SCAN_NULL,      0x0d,     0x0d },     // 0x58\r
-  { SCAN_END,       '1',      '1' },      // 0x59\r
-  { SCAN_DOWN,      '2',      '2' },      // 0x5A\r
-  { SCAN_PAGE_DOWN, '3',      '3' },      // 0x5B\r
-  { SCAN_LEFT,      '4',      '4' },      // 0x5C\r
-  { SCAN_NULL,      '5',      '5' },      // 0x5D\r
-  { SCAN_RIGHT,     '6',      '6' },      // 0x5E\r
-  { SCAN_HOME,      '7',      '7' },      // 0x5F\r
-  { SCAN_UP,        '8',      '8' },      // 0x60\r
-  { SCAN_PAGE_UP,   '9',      '9' },      // 0x61\r
-  { SCAN_INSERT,    '0',      '0' },      // 0x62\r
-  { SCAN_DELETE,    '.',      '.' },      // 0x63\r
-  { SCAN_NULL,      '\\',     '|' },      // 0x64 Keyboard Non-US \ and |\r
-  { SCAN_NULL,      0x00,     0x00 },     // 0x65 Keyboard Application\r
-  { SCAN_NULL,      0x00,     0x00 },     // 0x66 Keyboard Power\r
-  { SCAN_NULL,      '=' ,     '='  },     // 0x67 Keypad =\r
-  { SCAN_F13,       0x00,     0x00 },     // 0x68\r
-  { SCAN_F14,       0x00,     0x00 },     // 0x69\r
-  { SCAN_F15,       0x00,     0x00 },     // 0x6A  \r
-  { SCAN_F16,       0x00,     0x00 },     // 0x6B  \r
-  { SCAN_F17,       0x00,     0x00 },     // 0x6C\r
-  { SCAN_F18,       0x00,     0x00 },     // 0x6D\r
-  { SCAN_F19,       0x00,     0x00 },     // 0x6E\r
-  { SCAN_F20,       0x00,     0x00 },     // 0x6F\r
-  { SCAN_F21,       0x00,     0x00 },     // 0x70\r
-  { SCAN_F22,       0x00,     0x00 },     // 0x71\r
-  { SCAN_F23,       0x00,     0x00 },     // 0x72\r
-  { SCAN_F24,       0x00,     0x00 },     // 0x73\r
-  { SCAN_MUTE,      0x00,     0x00 },     // 0x7F\r
-  { SCAN_VOLUME_UP, 0x00,     0x00 },     // 0x80\r
-  { SCAN_VOLUME_DOWN, 0x00,   0x00 },     // 0x81\r
+UINT8 EfiScanCodeConvertionTable[] = {\r
+  SCAN_NULL,       // EFI_NULL_MODIFIER\r
+  SCAN_NULL,       // EFI_LEFT_CONTROL_MODIFIER\r
+  SCAN_NULL,       // EFI_RIGHT_CONTROL_MODIFIER\r
+  SCAN_NULL,       // EFI_LEFT_ALT_MODIFIER\r
+  SCAN_NULL,       // EFI_RIGHT_ALT_MODIFIER\r
+  SCAN_NULL,       // EFI_ALT_GR_MODIFIER\r
+  SCAN_INSERT,     // EFI_INSERT_MODIFIER\r
+  SCAN_DELETE,     // EFI_DELETE_MODIFIER\r
+  SCAN_PAGE_DOWN,  // EFI_PAGE_DOWN_MODIFIER\r
+  SCAN_PAGE_UP,    // EFI_PAGE_UP_MODIFIER\r
+  SCAN_HOME,       // EFI_HOME_MODIFIER\r
+  SCAN_END,        // EFI_END_MODIFIER\r
+  SCAN_NULL,       // EFI_LEFT_SHIFT_MODIFIER\r
+  SCAN_NULL,       // EFI_RIGHT_SHIFT_MODIFIER\r
+  SCAN_NULL,       // EFI_CAPS_LOCK_MODIFIER\r
+  SCAN_NULL,       // EFI_NUM_LOCK_MODIFIER\r
+  SCAN_LEFT,       // EFI_LEFT_ARROW_MODIFIER\r
+  SCAN_RIGHT,      // EFI_RIGHT_ARROW_MODIFIER\r
+  SCAN_DOWN,       // EFI_DOWN_ARROW_MODIFIER\r
+  SCAN_UP,         // EFI_UP_ARROW_MODIFIER\r
+  SCAN_NULL,       // EFI_NS_KEY_MODIFIER\r
+  SCAN_NULL,       // EFI_NS_KEY_DEPENDENCY_MODIFIER\r
+  SCAN_F1,         // EFI_FUNCTION_KEY_ONE_MODIFIER\r
+  SCAN_F2,         // EFI_FUNCTION_KEY_TWO_MODIFIER\r
+  SCAN_F3,         // EFI_FUNCTION_KEY_THREE_MODIFIER\r
+  SCAN_F4,         // EFI_FUNCTION_KEY_FOUR_MODIFIER\r
+  SCAN_F5,         // EFI_FUNCTION_KEY_FIVE_MODIFIER\r
+  SCAN_F6,         // EFI_FUNCTION_KEY_SIX_MODIFIER\r
+  SCAN_F7,         // EFI_FUNCTION_KEY_SEVEN_MODIFIER\r
+  SCAN_F8,         // EFI_FUNCTION_KEY_EIGHT_MODIFIER\r
+  SCAN_F9,         // EFI_FUNCTION_KEY_NINE_MODIFIER\r
+  SCAN_F10,        // EFI_FUNCTION_KEY_TEN_MODIFIER\r
+  SCAN_F11,        // EFI_FUNCTION_KEY_ELEVEN_MODIFIER\r
+  SCAN_F12,        // EFI_FUNCTION_KEY_TWELVE_MODIFIER\r
 };\r
 \r
+EFI_GUID  mKeyboardLayoutEventGuid = EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID;\r
+\r
+\r
 STATIC KB_MODIFIER  KB_Mod[8] = {\r
   { MOD_CONTROL_L,  0xe0 }, // 11100000\r
   { MOD_CONTROL_R,  0xe4 }, // 11100100\r
@@ -200,6 +387,387 @@ IsUSBKeyboard (
 }\r
 \r
 \r
+EFI_HII_KEYBOARD_LAYOUT *\r
+GetCurrentKeyboardLayout (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Get current keyboard layout from HII database.\r
+\r
+  Arguments:\r
+    None.\r
+\r
+  Returns:\r
+    Pointer to EFI_HII_KEYBOARD_LAYOUT.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
+  EFI_HII_KEYBOARD_LAYOUT   *KeyboardLayout;\r
+  UINT16                    Length;\r
+\r
+  //\r
+  // Locate Hii database protocol\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &HiiDatabase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Get current keyboard layout from HII database\r
+  //\r
+  Length = 0;\r
+  KeyboardLayout = NULL;\r
+  Status = HiiDatabase->GetKeyboardLayout (\r
+                          HiiDatabase,\r
+                          NULL,\r
+                          &Length,\r
+                          KeyboardLayout\r
+                          );\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    KeyboardLayout = AllocatePool (Length);\r
+    ASSERT (KeyboardLayout != NULL);\r
+\r
+    Status = HiiDatabase->GetKeyboardLayout (\r
+                            HiiDatabase,\r
+                            NULL,\r
+                            &Length,\r
+                            KeyboardLayout\r
+                            );\r
+    if (EFI_ERROR (Status)) {\r
+      gBS->FreePool (KeyboardLayout);\r
+      KeyboardLayout = NULL;\r
+    }\r
+  }\r
+\r
+  return KeyboardLayout;\r
+}\r
+\r
+EFI_KEY_DESCRIPTOR *\r
+GetKeyDescriptor (\r
+  IN USB_KB_DEV        *UsbKeyboardDevice,\r
+  IN UINT8             ScanCode\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Find Key Descriptor in KeyConvertionTable given its scan code.\r
+\r
+  Arguments:\r
+    UsbKeyboardDevice  -  The USB_KB_DEV instance.\r
+    ScanCode           -  USB scan code.\r
+\r
+  Returns:\r
+    The Key descriptor in KeyConvertionTable.\r
+\r
+--*/\r
+{\r
+  UINT8  Index;\r
+\r
+  if (((ScanCode > 0x65) && (ScanCode < 0xe0)) || (ScanCode > 0xe7)) {\r
+    return NULL;\r
+  }\r
+\r
+  if (ScanCode <= 0x65) {\r
+    Index = (UINT8) (ScanCode - 4);\r
+  } else {\r
+    Index = (UINT8) (ScanCode - 0xe0 + USB_KEYCODE_MAX_MAKE);\r
+  }\r
+\r
+  return &UsbKeyboardDevice->KeyConvertionTable[Index];\r
+}\r
+\r
+USB_NS_KEY *\r
+FindUsbNsKey (\r
+  IN USB_KB_DEV          *UsbKeyboardDevice,\r
+  IN EFI_KEY_DESCRIPTOR  *KeyDescriptor\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Find Non-Spacing key for given KeyDescriptor.\r
+\r
+  Arguments:\r
+    UsbKeyboardDevice  -  The USB_KB_DEV instance.\r
+    KeyDescriptor      -  Key descriptor.\r
+\r
+  Returns:\r
+    The Non-Spacing key.\r
+\r
+--*/\r
+{\r
+  LIST_ENTRY      *Link;\r
+  USB_NS_KEY      *UsbNsKey;\r
+\r
+  Link = GetFirstNode (&UsbKeyboardDevice->NsKeyList);\r
+  while (!IsNull (&UsbKeyboardDevice->NsKeyList, Link)) {\r
+    UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);\r
+\r
+    if (UsbNsKey->NsKey[0].Key == KeyDescriptor->Key) {\r
+      return UsbNsKey;\r
+    }\r
+\r
+    Link = GetNextNode (&UsbKeyboardDevice->NsKeyList, Link);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+EFI_KEY_DESCRIPTOR *\r
+FindPhysicalKey (\r
+  IN USB_NS_KEY          *UsbNsKey,\r
+  IN EFI_KEY_DESCRIPTOR  *KeyDescriptor\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Find physical key definition for a given Key stroke.\r
+\r
+  Arguments:\r
+    UsbNsKey        -  The Non-Spacing key information.\r
+    KeyDescriptor   -  The key stroke.\r
+\r
+  Returns:\r
+    The physical key definition.\r
+\r
+--*/\r
+{\r
+  UINTN               Index;\r
+  EFI_KEY_DESCRIPTOR  *PhysicalKey;\r
+\r
+  PhysicalKey = &UsbNsKey->NsKey[1];\r
+  for (Index = 0; Index < UsbNsKey->KeyCount; Index++) {\r
+    if (KeyDescriptor->Key == PhysicalKey->Key) {\r
+      return PhysicalKey;\r
+    }\r
+\r
+    PhysicalKey++;\r
+  }\r
+\r
+  //\r
+  // No children definition matched, return original key\r
+  //\r
+  return KeyDescriptor;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+SetKeyboardLayoutEvent (\r
+  EFI_EVENT                  Event,\r
+  VOID                       *Context\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    The notification function for SET_KEYBOARD_LAYOUT_EVENT.\r
+\r
+  Arguments:\r
+\r
+  Returns:\r
+\r
+--*/\r
+{\r
+  USB_KB_DEV                *UsbKeyboardDevice;\r
+  EFI_HII_KEYBOARD_LAYOUT   *KeyboardLayout;\r
+  EFI_KEY_DESCRIPTOR        TempKey;\r
+  EFI_KEY_DESCRIPTOR        *KeyDescriptor;\r
+  EFI_KEY_DESCRIPTOR        *TableEntry;\r
+  EFI_KEY_DESCRIPTOR        *NsKey;\r
+  USB_NS_KEY                *UsbNsKey;\r
+  UINTN                     Index;\r
+  UINTN                     Index2;\r
+  UINTN                     KeyCount;\r
+  UINT8                     ScanCode;\r
+\r
+  UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
+\r
+  //\r
+  // Try to get current Keyboard Layout from HII database\r
+  //\r
+  KeyboardLayout = GetCurrentKeyboardLayout ();\r
+  if (KeyboardLayout == NULL) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Allocate resource for KeyConvertionTable\r
+  //\r
+  ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
+  UsbKeyboardDevice->KeyConvertionTable = AllocateZeroPool ((USB_KEYCODE_MAX_MAKE + 8) * sizeof (EFI_KEY_DESCRIPTOR));\r
+  ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);\r
+\r
+  KeyDescriptor = (EFI_KEY_DESCRIPTOR *) (((UINT8 *) KeyboardLayout) + sizeof (EFI_HII_KEYBOARD_LAYOUT));\r
+  for (Index = 0; Index < KeyboardLayout->DescriptorCount; Index++) {\r
+    //\r
+    // Copy from HII keyboard layout package binary for alignment\r
+    //\r
+    CopyMem (&TempKey, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));\r
+\r
+    //\r
+    // Fill the key into KeyConvertionTable (which use USB Scan Code as index)\r
+    //\r
+    ScanCode = UsbScanCodeConvertionTable [(UINT8) (TempKey.Key)];\r
+    TableEntry = GetKeyDescriptor (UsbKeyboardDevice, ScanCode);\r
+    CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));\r
+\r
+    if (TempKey.Modifier == EFI_NS_KEY_MODIFIER) {\r
+      //\r
+      // Non-spacing key\r
+      //\r
+      UsbNsKey = AllocatePool (sizeof (USB_NS_KEY));\r
+      ASSERT (UsbNsKey != NULL);\r
+\r
+      //\r
+      // Search for sequential children physical key definitions\r
+      //\r
+      KeyCount = 0;\r
+      NsKey = KeyDescriptor + 1;\r
+      for (Index2 = Index + 1; Index2 < KeyboardLayout->DescriptorCount; Index2++) {\r
+        CopyMem (&TempKey, NsKey, sizeof (EFI_KEY_DESCRIPTOR));\r
+        if (TempKey.Modifier & EFI_NS_KEY_DEPENDENCY_MODIFIER) {\r
+          KeyCount++;\r
+        } else {\r
+          break;\r
+        }\r
+        NsKey++;\r
+      }\r
+\r
+      UsbNsKey->Signature = USB_NS_KEY_SIGNATURE;\r
+      UsbNsKey->KeyCount = KeyCount;\r
+      UsbNsKey->NsKey = AllocateCopyPool (\r
+                          (KeyCount + 1) * sizeof (EFI_KEY_DESCRIPTOR),\r
+                          KeyDescriptor\r
+                          );\r
+      InsertTailList (&UsbKeyboardDevice->NsKeyList, &UsbNsKey->Link);\r
+\r
+      //\r
+      // Skip over the child physical keys\r
+      //\r
+      Index += KeyCount;\r
+      KeyDescriptor += KeyCount;\r
+    }\r
+\r
+    KeyDescriptor++;\r
+  }\r
+\r
+  //\r
+  // There are two EfiKeyEnter, duplicate its Key Descriptor\r
+  //\r
+  TableEntry = GetKeyDescriptor (UsbKeyboardDevice, 0x58);\r
+  KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, 0x28);\r
+  CopyMem (TableEntry, KeyDescriptor, sizeof (EFI_KEY_DESCRIPTOR));\r
+\r
+  gBS->FreePool (KeyboardLayout);\r
+}\r
+\r
+VOID\r
+ReleaseKeyboardLayoutResources (\r
+  IN USB_KB_DEV              *UsbKeyboardDevice\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Destroy resources for Keyboard layout.\r
+\r
+  Arguments:\r
+    UsbKeyboardDevice  -  The USB_KB_DEV instance.\r
+\r
+  Returns:\r
+    None.\r
+\r
+--*/\r
+{\r
+  USB_NS_KEY      *UsbNsKey;\r
+  LIST_ENTRY      *Link;\r
+\r
+  SafeFreePool (UsbKeyboardDevice->KeyConvertionTable);\r
+  UsbKeyboardDevice->KeyConvertionTable = NULL;\r
+\r
+  while (!IsListEmpty (&UsbKeyboardDevice->NsKeyList)) {\r
+    Link = GetFirstNode (&UsbKeyboardDevice->NsKeyList);\r
+    UsbNsKey = USB_NS_KEY_FORM_FROM_LINK (Link);\r
+    RemoveEntryList (&UsbNsKey->Link);\r
+\r
+    gBS->FreePool (UsbNsKey->NsKey);\r
+    gBS->FreePool (UsbNsKey);\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+InitKeyboardLayout (\r
+  IN USB_KB_DEV   *UsbKeyboardDevice\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Initialize USB Keyboard layout.\r
+\r
+  Arguments:\r
+    UsbKeyboardDevice    The USB_KB_DEV instance.\r
+\r
+  Returns:\r
+    EFI_SUCCESS  - Success\r
+    Other        - Keyboard layout initial failed.\r
+--*/\r
+{\r
+  EFI_HII_KEYBOARD_LAYOUT   *KeyboardLayout;\r
+  EFI_STATUS                Status;\r
+\r
+  UsbKeyboardDevice->KeyConvertionTable = AllocateZeroPool ((USB_KEYCODE_MAX_MAKE + 8) * sizeof (EFI_KEY_DESCRIPTOR));\r
+  ASSERT (UsbKeyboardDevice->KeyConvertionTable != NULL);\r
+\r
+  InitializeListHead (&UsbKeyboardDevice->NsKeyList);\r
+  UsbKeyboardDevice->CurrentNsKey = NULL;\r
+  UsbKeyboardDevice->KeyboardLayoutEvent = NULL;\r
+\r
+  //\r
+  // Register SET_KEYBOARD_LAYOUT_EVENT notification\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                  EFI_EVENT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  SetKeyboardLayoutEvent,\r
+                  UsbKeyboardDevice,\r
+                  &mKeyboardLayoutEventGuid,\r
+                  &UsbKeyboardDevice->KeyboardLayoutEvent\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Try to get current keyboard layout from HII database\r
+  //\r
+  KeyboardLayout = GetCurrentKeyboardLayout ();\r
+  if (KeyboardLayout != NULL) {\r
+    //\r
+    // Force to initialize the keyboard layout\r
+    //\r
+    gBS->SignalEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
+  } else {\r
+    if (FeaturePcdGet (PcdDisableDefaultKeyboardLayoutInUsbKbDriver)) {\r
+      return EFI_NOT_READY;\r
+    } else {\r
+\r
+      //\r
+      // Fail to get keyboard layout from HII database,\r
+      // use default keyboard layout\r
+      //\r
+      LoadDefaultKeyboardLayout (UsbKeyboardDevice);\r
+    }\r
+  }\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
 \r
 /**\r
   Initialize USB Keyboard device and all private data structures.\r
@@ -304,14 +872,18 @@ InitUSBKeyboard (
   \r
   UsbKeyboardDevice->LeftCtrlOn   = 0;\r
   UsbKeyboardDevice->LeftAltOn    = 0;\r
-  UsbKeyboardDevice->LeftShiftOn  = 0;  \r
-  UsbKeyboardDevice->LeftLogoOn   = 0;  \r
+  UsbKeyboardDevice->LeftShiftOn  = 0;\r
+  UsbKeyboardDevice->LeftLogoOn   = 0;\r
   UsbKeyboardDevice->RightCtrlOn  = 0;\r
   UsbKeyboardDevice->RightAltOn   = 0;\r
-  UsbKeyboardDevice->RightShiftOn = 0;  \r
-  UsbKeyboardDevice->RightLogoOn  = 0;  \r
+  UsbKeyboardDevice->RightShiftOn = 0;\r
+  UsbKeyboardDevice->RightLogoOn  = 0;\r
   UsbKeyboardDevice->MenuKeyOn    = 0;\r
-  UsbKeyboardDevice->SysReqOn     = 0;  \r
+  UsbKeyboardDevice->SysReqOn     = 0;\r
+\r
+  UsbKeyboardDevice->AltGrOn      = 0;\r
+\r
+  UsbKeyboardDevice->CurrentNsKey = NULL;\r
 \r
   //\r
   // Sync the initial state of lights\r
@@ -390,6 +962,7 @@ KeyboardHandler (
   USB_KEY             UsbKey;\r
   UINT8               NewRepeatKey;\r
   UINT32              UsbStatus;\r
+  EFI_KEY_DESCRIPTOR  *KeyDescriptor;\r
 \r
   ASSERT (Context);\r
 \r
@@ -573,7 +1146,8 @@ KeyboardHandler (
       //\r
       // NumLock pressed or CapsLock pressed\r
       //\r
-      if (CurKeyCodeBuffer[Index] == 0x53 || CurKeyCodeBuffer[Index] == 0x39) {\r
+      KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, CurKeyCodeBuffer[Index]);\r
+      if (KeyDescriptor->Modifier == EFI_NUM_LOCK_MODIFIER || KeyDescriptor->Modifier == EFI_CAPS_LOCK_MODIFIER) {\r
         UsbKeyboardDevice->RepeatKey = 0;\r
       } else {\r
         NewRepeatKey = CurKeyCodeBuffer[Index];\r
@@ -602,10 +1176,12 @@ KeyboardHandler (
   while (Index != SavedTail) {\r
     RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);\r
 \r
-    switch (UsbKey.KeyCode) {\r
+    KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);\r
 \r
-    case 0xe0:\r
-    case 0xe4:\r
+    switch (KeyDescriptor->Modifier) {\r
+\r
+    case EFI_LEFT_CONTROL_MODIFIER:\r
+    case EFI_RIGHT_CONTROL_MODIFIER:\r
       if (UsbKey.Down) {\r
         UsbKeyboardDevice->CtrlOn = 1;\r
       } else {\r
@@ -613,8 +1189,8 @@ KeyboardHandler (
       }\r
       break;\r
 \r
-    case 0xe2:\r
-    case 0xe6:\r
+    case EFI_LEFT_ALT_MODIFIER:\r
+    case EFI_RIGHT_ALT_MODIFIER:\r
       if (UsbKey.Down) {\r
         UsbKeyboardDevice->AltOn = 1;\r
       } else {\r
@@ -622,11 +1198,18 @@ KeyboardHandler (
       }\r
       break;\r
 \r
+    case EFI_ALT_GR_MODIFIER:\r
+      if (UsbKey.Down) {\r
+        UsbKeyboardDevice->AltGrOn = 1;\r
+      } else {\r
+        UsbKeyboardDevice->AltGrOn = 0;\r
+      }\r
+      break;\r
+\r
     //\r
     // Del Key Code\r
     //\r
-    case 0x4c:\r
-    case 0x63:\r
+    case EFI_DELETE_MODIFIER:\r
       if (UsbKey.Down) {\r
         if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {\r
           gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
@@ -688,7 +1271,8 @@ USBParseKey (
   OUT     UINT8       *KeyChar\r
   )\r
 {\r
-  USB_KEY UsbKey;\r
+  USB_KEY             UsbKey;\r
+  EFI_KEY_DESCRIPTOR  *KeyDescriptor;\r
 \r
   *KeyChar = 0;\r
 \r
@@ -698,17 +1282,18 @@ USBParseKey (
     //\r
     RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);\r
 \r
+    KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, UsbKey.KeyCode);\r
     if (!UsbKey.Down) {\r
-      switch (UsbKey.KeyCode) {\r
+      switch (KeyDescriptor->Modifier) {\r
 \r
       //\r
       // CTRL release\r
       //\r
-      case 0xe0:\r
+      case EFI_LEFT_CONTROL_MODIFIER:\r
         UsbKeyboardDevice->LeftCtrlOn = 0;\r
         UsbKeyboardDevice->CtrlOn = 0;\r
         break;\r
-      case 0xe4:\r
+      case EFI_RIGHT_CONTROL_MODIFIER:\r
         UsbKeyboardDevice->RightCtrlOn = 0;\r
         UsbKeyboardDevice->CtrlOn = 0;\r
         break;\r
@@ -716,11 +1301,11 @@ USBParseKey (
       //\r
       // Shift release\r
       //\r
-      case 0xe1:\r
+      case EFI_LEFT_SHIFT_MODIFIER:\r
         UsbKeyboardDevice->LeftShiftOn = 0;\r
         UsbKeyboardDevice->ShiftOn = 0;\r
         break;\r
-      case 0xe5:\r
+      case EFI_RIGHT_SHIFT_MODIFIER:\r
         UsbKeyboardDevice->RightShiftOn = 0;\r
         UsbKeyboardDevice->ShiftOn = 0;\r
         break;\r
@@ -728,38 +1313,50 @@ USBParseKey (
       //\r
       // Alt release\r
       //\r
-      case 0xe2:\r
+      case EFI_LEFT_ALT_MODIFIER:\r
         UsbKeyboardDevice->LeftAltOn = 0;\r
         UsbKeyboardDevice->AltOn = 0;\r
         break;\r
-      case 0xe6:\r
+      case EFI_RIGHT_ALT_MODIFIER:\r
         UsbKeyboardDevice->RightAltOn = 0;\r
         UsbKeyboardDevice->AltOn = 0;\r
         break;\r
 \r
       //\r
-      // Logo release\r
+      // Left Logo release\r
       //\r
-     case 0xe3:\r
+      case EFI_LEFT_LOGO_MODIFIER:\r
         UsbKeyboardDevice->LeftLogoOn = 0;\r
         break;\r
-      case 0xe7:\r
+\r
+      //\r
+      // Right Logo release\r
+      //\r
+      case EFI_RIGHT_LOGO_MODIFIER:\r
         UsbKeyboardDevice->RightLogoOn = 0;\r
         break;\r
 \r
       //\r
-      // Menu key (App/Apps) release\r
+      // Menu key release\r
       //\r
-      case 0x65:\r
+      case EFI_MENU_MODIFIER:\r
         UsbKeyboardDevice->MenuKeyOn = 0;\r
         break;\r
 \r
       //\r
       // SysReq release\r
       //\r
-      case 0x46:\r
+      case EFI_SYS_REQUEST_MODIFIER:\r
         UsbKeyboardDevice->SysReqOn = 0;\r
         break;\r
+\r
+      //\r
+      // AltGr release\r
+      //\r
+      case EFI_ALT_GR_MODIFIER:\r
+        UsbKeyboardDevice->AltGrOn = 0;\r
+        break;\r
+\r
       default:\r
         break;\r
       }\r
@@ -770,14 +1367,17 @@ USBParseKey (
     //\r
     // Analyzes key pressing situation\r
     //\r
-    switch (UsbKey.KeyCode) {\r
+    switch (KeyDescriptor->Modifier) {\r
 \r
-    case 0xe0:\r
+    //\r
+    // CTRL press\r
+    //\r
+    case EFI_LEFT_CONTROL_MODIFIER:\r
       UsbKeyboardDevice->LeftCtrlOn = 1;\r
       UsbKeyboardDevice->CtrlOn = 1;\r
-      continue;      \r
+      continue;\r
       break;\r
-    case 0xe4:\r
+    case EFI_RIGHT_CONTROL_MODIFIER:\r
       UsbKeyboardDevice->RightCtrlOn = 1;\r
       UsbKeyboardDevice->CtrlOn = 1;\r
       continue;\r
@@ -786,13 +1386,13 @@ USBParseKey (
     //\r
     // Shift press\r
     //\r
-    case 0xe1:\r
+    case EFI_LEFT_SHIFT_MODIFIER:\r
       UsbKeyboardDevice->LeftShiftOn = 1;\r
       UsbKeyboardDevice->ShiftOn = 1;\r
       continue;\r
       break;\r
-    case 0xe5:\r
-      UsbKeyboardDevice->RightShiftOn = 1;      \r
+    case EFI_RIGHT_SHIFT_MODIFIER:\r
+      UsbKeyboardDevice->RightShiftOn = 1;\r
       UsbKeyboardDevice->ShiftOn = 1;\r
       continue;\r
       break;\r
@@ -800,46 +1400,54 @@ USBParseKey (
     //\r
     // Alt press\r
     //\r
-    case 0xe2:\r
+    case EFI_LEFT_ALT_MODIFIER:\r
       UsbKeyboardDevice->LeftAltOn = 1;\r
       UsbKeyboardDevice->AltOn = 1;\r
       continue;\r
       break;\r
-    case 0xe6:\r
-      UsbKeyboardDevice->RightAltOn = 1;      \r
+    case EFI_RIGHT_ALT_MODIFIER:\r
+      UsbKeyboardDevice->RightAltOn = 1;\r
       UsbKeyboardDevice->AltOn = 1;\r
       continue;\r
       break;\r
 \r
     //\r
-    // Logo press\r
+    // Left Logo press\r
     //\r
-    case 0xe3:\r
+    case EFI_LEFT_LOGO_MODIFIER:\r
       UsbKeyboardDevice->LeftLogoOn = 1;\r
-      continue;      \r
       break;\r
-    case 0xe7:\r
+\r
+    //\r
+    // Right Logo press\r
+    //\r
+    case EFI_RIGHT_LOGO_MODIFIER:\r
       UsbKeyboardDevice->RightLogoOn = 1;\r
-      continue;\r
       break;\r
 \r
     //\r
-    // Menu key (App/Apps) press\r
+    // Menu key press\r
     //\r
-    case 0x65:\r
+    case EFI_MENU_MODIFIER:\r
       UsbKeyboardDevice->MenuKeyOn = 1;\r
-      continue;      \r
       break;\r
 \r
     //\r
     // SysReq press\r
     //\r
-    case 0x46:\r
+    case EFI_SYS_REQUEST_MODIFIER:\r
       UsbKeyboardDevice->SysReqOn = 1;\r
-      continue;      \r
+      continue;\r
+      break;\r
+\r
+    //\r
+    // AltGr press\r
+    //\r
+    case EFI_ALT_GR_MODIFIER:\r
+      UsbKeyboardDevice->AltGrOn = 1;\r
       break;\r
 \r
-    case 0x53:\r
+    case EFI_NUM_LOCK_MODIFIER:\r
       UsbKeyboardDevice->NumLockOn ^= 1;\r
       //\r
       // Turn on the NumLock light on KB\r
@@ -848,7 +1456,7 @@ USBParseKey (
       continue;\r
       break;\r
 \r
-    case 0x39:\r
+    case EFI_CAPS_LOCK_MODIFIER:\r
       UsbKeyboardDevice->CapsOn ^= 1;\r
       //\r
       // Turn on the CapsLock light on KB\r
@@ -857,7 +1465,7 @@ USBParseKey (
       continue;\r
       break;\r
 \r
-    case 0x47:\r
+    case EFI_SCROLL_LOCK_MODIFIER:\r
       UsbKeyboardDevice->ScrollOn ^= 1;\r
       //\r
       // Turn on the ScrollLock light on KB\r
@@ -867,22 +1475,17 @@ USBParseKey (
       break;\r
 \r
     //\r
-    // PrintScreen,Pause,Application,Power\r
-    // keys are not valid EFI key\r
-    //\r
-\r
-    //\r
-    // PrintScreen/SysRq key and Application key\r
-    // Should be handled by UEFI2.1 compliant code\r
-\r
-    case 0x48:\r
-    //\r
-    // fall through\r
-    //\r
-    case 0x66:\r
-    //\r
-    // fall through\r
+    // F11,F12,PrintScreen,Pause/Break\r
+    // could not be retrieved via SimpleTxtInEx protocol\r
     //\r
+    case EFI_FUNCTION_KEY_ELEVEN_MODIFIER:\r
+    case EFI_FUNCTION_KEY_TWELVE_MODIFIER:\r
+    case EFI_PRINT_MODIFIER:\r
+    case EFI_PAUSE_MODIFIER:\r
+    case EFI_BREAK_MODIFIER:\r
+      //\r
+      // fall through\r
+      //\r
       continue;\r
       break;\r
 \r
@@ -893,7 +1496,7 @@ USBParseKey (
     //\r
     // When encountered Del Key...\r
     //\r
-    if (UsbKey.KeyCode == 0x4c || UsbKey.KeyCode == 0x63) {\r
+    if (KeyDescriptor->Modifier == EFI_DELETE_MODIFIER) {\r
       if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {\r
         gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
       }\r
@@ -904,7 +1507,6 @@ USBParseKey (
   }\r
 \r
   return EFI_NOT_READY;\r
-\r
 }\r
 \r
 \r
@@ -929,7 +1531,8 @@ USBKeyCodeToEFIScanCode (
   OUT EFI_INPUT_KEY   *Key\r
   )\r
 {\r
-  UINT8 Index;\r
+  UINT8               Index;\r
+  EFI_KEY_DESCRIPTOR  *KeyDescriptor;\r
 \r
   if (!USBKBD_VALID_KEYCODE (KeyChar)) {\r
     return EFI_NOT_READY;\r
@@ -944,68 +1547,100 @@ USBKeyCodeToEFIScanCode (
     return EFI_NOT_READY;\r
   }\r
 \r
+  KeyDescriptor = GetKeyDescriptor (UsbKeyboardDevice, KeyChar);\r
+\r
   //\r
-  // Undefined entries from 0x74 to 0x7E\r
+  // Check for Non-spacing key\r
   //\r
-  if (KeyChar > USB_KEYCODE_MAX_MAKE) {\r
-    Index = (UINT8) (Index - 11);\r
+  if (KeyDescriptor->Modifier == EFI_NS_KEY_MODIFIER) {\r
+    UsbKeyboardDevice->CurrentNsKey = FindUsbNsKey (UsbKeyboardDevice, KeyDescriptor);\r
+    return EFI_NOT_READY;\r
   }\r
 \r
-  Key->ScanCode = KeyConvertionTable[Index][0];\r
+  //\r
+  // Check whether this keystroke follows a Non-spacing key\r
+  //\r
+  if (UsbKeyboardDevice->CurrentNsKey != NULL) {\r
+    KeyDescriptor = FindPhysicalKey (UsbKeyboardDevice->CurrentNsKey, KeyDescriptor);\r
+    UsbKeyboardDevice->CurrentNsKey = NULL;\r
+  }\r
 \r
-  if (UsbKeyboardDevice->ShiftOn) {\r
+  Key->ScanCode = EfiScanCodeConvertionTable[KeyDescriptor->Modifier];\r
+  Key->UnicodeChar = KeyDescriptor->Unicode;\r
 \r
-    Key->UnicodeChar = KeyConvertionTable[Index][2];\r
-    //\r
-    // Need not return associated shift state if a class of printable characters that\r
-    // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'\r
-    //\r
-    if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {\r
-      UsbKeyboardDevice->LeftShiftOn = 0;\r
-      UsbKeyboardDevice->RightShiftOn = 0;\r
-    }\r
+  if (KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_STANDARD_SHIFT) {\r
+    if (UsbKeyboardDevice->ShiftOn) {\r
+      Key->UnicodeChar = KeyDescriptor->ShiftedUnicode;\r
 \r
-  } else {\r
+      //\r
+      // Need not return associated shift state if a class of printable characters that\r
+      // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'\r
+      //\r
+      if (KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) {\r
+        UsbKeyboardDevice->LeftShiftOn = 0;\r
+        UsbKeyboardDevice->RightShiftOn = 0;\r
+      }\r
+\r
+      if (UsbKeyboardDevice->AltGrOn) {\r
+        Key->UnicodeChar = KeyDescriptor->ShiftedAltGrUnicode;\r
+      }\r
+    } else {\r
+      //\r
+      // Shift off\r
+      //\r
+      Key->UnicodeChar = KeyDescriptor->Unicode;\r
 \r
-    Key->UnicodeChar = KeyConvertionTable[Index][1];\r
+      if (UsbKeyboardDevice->AltGrOn) {\r
+        Key->UnicodeChar = KeyDescriptor->AltGrUnicode;\r
+      }\r
+    }\r
   }\r
 \r
-  if (UsbKeyboardDevice->CapsOn) {\r
+  if (KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_CAPS_LOCK) {\r
+    if (UsbKeyboardDevice->CapsOn) {\r
 \r
-    if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') {\r
+      if (Key->UnicodeChar == KeyDescriptor->Unicode) {\r
 \r
-      Key->UnicodeChar = KeyConvertionTable[Index][2];\r
+        Key->UnicodeChar = KeyDescriptor->ShiftedUnicode;\r
 \r
-    } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {\r
+      } else if (Key->UnicodeChar == KeyDescriptor->ShiftedUnicode) {\r
 \r
-      Key->UnicodeChar = KeyConvertionTable[Index][1];\r
+        Key->UnicodeChar = KeyDescriptor->Unicode;\r
 \r
+      }\r
     }\r
   }\r
+\r
   //\r
   // Translate the CTRL-Alpha characters to their corresponding control value  (ctrl-a = 0x0001 through ctrl-Z = 0x001A)\r
   //\r
   if (UsbKeyboardDevice->CtrlOn) {\r
     if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') {\r
-      Key->UnicodeChar = (UINT16) (Key->UnicodeChar - 'a' + 1);\r
+      Key->UnicodeChar = (UINT8) (Key->UnicodeChar - 'a' + 1);\r
     } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {\r
-      Key->UnicodeChar = (UINT16) (Key->UnicodeChar - 'A' + 1);\r
+      Key->UnicodeChar = (UINT8) (Key->UnicodeChar - 'A' + 1);\r
     }\r
   }\r
-  \r
-  \r
-  if (KeyChar >= 0x59 && KeyChar <= 0x63) {\r
+\r
+  if (KeyDescriptor->AffectedAttribute & EFI_AFFECTED_BY_NUM_LOCK) {\r
 \r
     if (UsbKeyboardDevice->NumLockOn && !UsbKeyboardDevice->ShiftOn) {\r
 \r
       Key->ScanCode = SCAN_NULL;\r
 \r
     } else {\r
-\r
       Key->UnicodeChar = 0x00;\r
     }\r
   }\r
 \r
+  //\r
+  // Translate Unicode 0x1B (ESC) to EFI Scan Code\r
+  //\r
+  if (Key->UnicodeChar == 0x1B && Key->ScanCode == SCAN_NULL) {\r
+    Key->ScanCode = SCAN_ESC;\r
+    Key->UnicodeChar = 0x00;\r
+  }\r
+\r
   if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {\r
     return EFI_NOT_READY;\r
   }\r
@@ -1043,7 +1678,7 @@ USBKeyCodeToEFIScanCode (
   }\r
   if (UsbKeyboardDevice->SysReqOn == 1) {\r
     UsbKeyboardDevice->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;\r
-  }  \r
+  }\r
 \r
   if (UsbKeyboardDevice->ScrollOn == 1) {\r
     UsbKeyboardDevice->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r