public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Dong, Eric" <eric.dong@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
	"Tan, Ming" <ming.tan@intel.com>
Subject: Re: [edk2-devel] [PATCH v3] Features/Intel/UserInterface: Add VirtualKeyboardFeaturePkg
Date: Fri, 8 May 2020 05:30:18 +0000	[thread overview]
Message-ID: <DM6PR11MB32746B0CD6B7E80C6E769C0EFEA20@DM6PR11MB3274.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20200508005044.14645-1-ming.tan@intel.com>

Reviewed-by: Eric Dong <eric.dong@intel.com>

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Tan,
> Ming
> Sent: Friday, May 8, 2020 8:51 AM
> To: devel@edk2.groups.io
> Subject: [edk2-devel] [PATCH v3] Features/Intel/UserInterface: Add
> VirtualKeyboardFeaturePkg
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2603
> 
> It add a VirtualKeyboardDxe driver.
> It is used with a touch panel, simulate a keyboard in the screen.
> 
> Signed-off-by: Ming Tan <ming.tan@intel.com>
> ---
>  .../Include/PostMemory.fdf                    |   10 +
>  .../Include/PreMemory.fdf                     |    8 +
>  .../Include/VirtualKeyboardFeature.dsc        |   96 ++
>  .../VirtualKeyboardFeaturePkg/Readme.md       |   68 +
>  .../CapitalLetterKeyboard.bmp                 |  Bin 0 -> 330454 bytes
>  .../VirtualKeyboardDxe/ComponentName.c        |  159 ++
>  .../VirtualKeyboardDxe/ComponentName.h        |   95 ++
>  .../VirtualKeyboardDxe/DigitKeyboard.bmp      |  Bin 0 -> 330454 bytes
>  .../VirtualKeyboardDxe/FullIcon.bmp           |  Bin 0 -> 5454 bytes
>  .../VirtualKeyboardDxe/Keyboard.c             | 1411 ++++++++++++++++
>  .../VirtualKeyboardDxe/KeyboardLayout.c       | 1438 +++++++++++++++++
>  .../VirtualKeyboardDxe/KeyboardLayout.idf     |   12 +
>  .../VirtualKeyboardDxe/SimpleIcon.bmp         |  Bin 0 -> 2814 bytes
>  .../VirtualKeyboardDxe/SimpleKeyboard.bmp     |  Bin 0 -> 30054 bytes
>  .../VirtualKeyboardDxe/VirtualKeyboard.h      |  829 ++++++++++
>  .../VirtualKeyboardDriver.c                   |  515 ++++++
>  .../VirtualKeyboardDxe/VirtualKeyboardDxe.inf |   78 +
>  .../VirtualKeyboardFeaturePkg.dec             |   26 +
>  .../VirtualKeyboardFeaturePkg.dsc             |   30 +
>  19 files changed, 4775 insertions(+)
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PostMe
> mory.fdf
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PreMem
> ory.fdf
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/VirtualKe
> yboardFeature.dsc
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Readme.md
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/CapitalLetterKeyboard.bmp
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/ComponentName.c
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/ComponentName.h
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/DigitKeyboard.bmp
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/FullIcon.bmp
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/Keyboard.c
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/KeyboardLayout.c
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/KeyboardLayout.idf
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/SimpleIcon.bmp
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/SimpleKeyboard.bmp
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/VirtualKeyboard.h
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/VirtualKeyboardDriver.c
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardD
> xe/VirtualKeyboardDxe.inf
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardF
> eaturePkg.dec
>  create mode 100644
> Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardF
> eaturePkg.dsc
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PostM
> emory.fdf
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PostM
> emory.fdf
> new file mode 100644
> index 0000000000..bf4a4d5078
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PostM
> emory.fdf
> @@ -0,0 +1,10 @@
> +## @file
> 
> +#  FDF file for post-memory modules that enable Virtual Keyboard.
> 
> +#
> 
> +# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#
> 
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +#
> 
> +##
> 
> +
> 
> +  INF
> UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyb
> oardDxe.inf
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PreMe
> mory.fdf
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PreMe
> mory.fdf
> new file mode 100644
> index 0000000000..c39a057f94
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PreMe
> mory.fdf
> @@ -0,0 +1,8 @@
> +## @file
> 
> +#  FDF file for pre-memory modules that enable Virtual Keyboard.
> 
> +#
> 
> +# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#
> 
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +#
> 
> +##
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/Virtual
> KeyboardFeature.dsc
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/Virtual
> KeyboardFeature.dsc
> new file mode 100644
> index 0000000000..c10fb2d567
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/Virtual
> KeyboardFeature.dsc
> @@ -0,0 +1,96 @@
> +## @file
> 
> +# This is a build description file for the Virtual Keyboard feature.
> 
> +# This file should be included into another package DSC file to build this
> feature.
> 
> +#
> 
> +# The DEC files are used by the utilities that parse DSC and
> 
> +# INF files to generate AutoGen.c and AutoGen.h files
> 
> +# for the build infrastructure.
> 
> +#
> 
> +# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#
> 
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +#
> 
> +##
> 
> +
> 
> +#########################################################
> #######################
> 
> +#
> 
> +# Defines Section - statements that will be processed to create a Makefile.
> 
> +#
> 
> +#########################################################
> #######################
> 
> +[Defines]
> 
> +!ifndef $(PEI_ARCH)
> 
> +  !error "PEI_ARCH must be specified to build this feature!"
> 
> +!endif
> 
> +!ifndef $(DXE_ARCH)
> 
> +  !error "DXE_ARCH must be specified to build this feature!"
> 
> +!endif
> 
> +
> 
> +#########################################################
> #######################
> 
> +#
> 
> +# Library Class section - list of all Library Classes needed by this feature.
> 
> +#
> 
> +#########################################################
> #######################
> 
> +[LibraryClasses]
> 
> +  #######################################
> 
> +  # Edk2 Packages
> 
> +  #######################################
> 
> +  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
> 
> +  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
> 
> +  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
> 
> +
> UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBo
> otServicesTableLib.inf
> 
> +
> UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntry
> Point.inf
> 
> +  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
> 
> +  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
> 
> +  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
> 
> +  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
> 
> +  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
> 
> +
> UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiService
> sLib.inf
> 
> +
> UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib
> /UefiRuntimeServicesTableLib.inf
> 
> +
> 
> +[LibraryClasses.common.UEFI_DRIVER]
> 
> +  #######################################
> 
> +  # Edk2 Packages
> 
> +  #######################################
> 
> +
> MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemo
> ryAllocationLib.inf
> 
> +
> 
> +#########################################################
> ##########################################
> 
> +#
> 
> +# Components Section - list of the modules and components that will be
> processed by compilation
> 
> +#                      tools and the EDK II tools to generate PE32/PE32+/Coff image
> files.
> 
> +#
> 
> +# Note: The EDK II DSC file is not used to specify how compiled binary
> images get placed
> 
> +#       into firmware volume images. This section is just a list of modules to
> compile from
> 
> +#       source into UEFI-compliant binaries.
> 
> +#       It is the FDF file that contains information on combining binary files into
> firmware
> 
> +#       volume images, whose concept is beyond UEFI and is described in PI
> specification.
> 
> +#       Binary modules do not need to be listed in this section, as they should
> be
> 
> +#       specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT
> binary (Fat.efi),
> 
> +#       Logo (Logo.bmp), and etc.
> 
> +#       There may also be modules listed in this section that are not required
> in the FDF file,
> 
> +#       When a module listed here is excluded from FDF file, then UEFI-
> compliant binary will be
> 
> +#       generated for it, but the binary will not be put into any firmware
> volume.
> 
> +#
> 
> +#########################################################
> ##########################################
> 
> +#
> 
> +# Feature DXE Components
> 
> +#
> 
> +[Components.X64]
> 
> +  #####################################
> 
> +  # Virtual Keyboard Feature Package
> 
> +  #####################################
> 
> +
> UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyb
> oardDxe.inf
> 
> +
> 
> +#########################################################
> ##########################################
> 
> +#
> 
> +# BuildOptions Section - Define the module specific tool chain flags that
> should be used as
> 
> +#                        the default flags for a module. These flags are appended to
> any
> 
> +#                        standard flags that are defined by the build process. They can
> be
> 
> +#                        applied for any modules or only those modules with the
> specific
> 
> +#                        module style (EDK or EDKII) specified in [Components] section.
> 
> +#
> 
> +#                        For advanced features, it is recommended to enable
> [BuildOptions] in
> 
> +#                        the applicable INF file so it does not affect the whole board
> package
> 
> +#                        build when this DSC file is active.
> 
> +#
> 
> +#########################################################
> ##########################################
> 
> +[BuildOptions]
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Readme.md
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Readme.md
> new file mode 100644
> index 0000000000..ae7f778748
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Readme.md
> @@ -0,0 +1,68 @@
> +# Overview
> 
> +* **Feature Name:** Virtual Keyboard
> 
> +* **PI Phase(s) Supported:** DXE
> 
> +* **SMM Required?** No
> 
> +
> 
> +## Purpose
> 
> +This feature provides a DXE virtual keyboard driver, used with a touch panel.
> 
> +
> 
> +# High-Level Theory of Operation
> 
> +This driver will use the following protocol:
> 
> +  gEfiAbsolutePointerProtocolGuid
> 
> +  gEfiGraphicsOutputProtocolGuid
> 
> +  gEdkiiTouchPanelGuid
> 
> +
> 
> +It will show a picture like a keyboard in the graphic output, then detect
> 
> +position when user touch the touch panel, then calculate the key which the
> 
> +user want to type.
> 
> +Touch panel driver use gEdkiiTouchPanelGuid to indicate the touch panel is
> ready for support virtual keyboard.
> 
> +
> 
> +## Firmware Volumes
> 
> +FvAdvancedUncompact
> 
> +FvAdvanced
> 
> +
> 
> +## Modules
> 
> +VirtualKeyboardDxe: The main driver of virtual keyboard.
> 
> +
> 
> +## VirtualKeyboardDxe
> 
> +This driver support the virtual keyboard feature.
> 
> +
> 
> +## Key Functions
> 
> +* Show a small icon in the corner to show/hide a keyboard picture in the
> screen.
> 
> +* If the user press the button in the picture, then convert it to the keyboard
> input.
> 
> +* Support general simple keyboard input.
> 
> +
> 
> +## Configuration
> 
> +There is not PCD or EFI variable used to config this feature.
> 
> +Platform maybe use its own solution to load/unload this driver.
> 
> +
> 
> +## Data Flows
> 
> +User touch the touch panel -> absolute pointer and status -> virtual
> keyboard event -> user keyboard input.
> 
> +
> 
> +## Control Flows
> 
> +This driver use AbsolutePointer protocol to get the info of user input, and
> use GraphicsOutput protocol to show the picture.
> 
> +
> 
> +## Build Flows
> 
> +There is not special build flow.
> 
> +
> 
> +## Test Point Results
> 
> +Test this driver in a device with touch panel and the BIOS support touch
> panel driver.
> 
> +If there is not touch panel, then can modify a mouse driver to support
> absolute pointer protocol to verify this driver.
> 
> +
> 
> +## Functional Exit Criteria
> 
> +* If the touch panel driver is not ready, then will not start this driver.
> 
> +* Show small icon in the corner of the screen.
> 
> +* Touch the icon, can show/hide the keyboard layout picture in the screen.
> 
> +* Touch the key in the keyboardy layout picture, can input the correct key.
> 
> +
> 
> +## Feature Enabling Checklist
> 
> +Make sure the following protocols are supported:
> 
> +  gEfiAbsolutePointerProtocolGuid
> 
> +  gEfiGraphicsOutputProtocolGuid
> 
> +  gEdkiiTouchPanelGuid
> 
> +
> 
> +## Performance Impact
> 
> +* VirtualKeyboardDxe.efi: debug version size: 734KB before compress,
> release version size: 698KB before compress.
> 
> +
> 
> +## Common Optimizations
> 
> +* The picture use bmp format, cost 684KB total. Use JPEG or other format
> can save the efi size before compress.
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/CapitalLetterKeyboard.bmp
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/CapitalLetterKeyboard.bmp
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..759c3d46a9f0cf6a69fa98563cd
> 04f7a082d3b4d
> GIT binary patch
> literal 330454
> zcmeI5zpw7cao(?FBtU``E>p0M1NK*`gbSt#SOkdw0sRRy;5G#XA}Z1nY7D4|3%
> XDn
> zwkD+z1_K0OWmyK;7zPUgqNK(K1CR{!=nT)J=g!Q|&iBW8&wJjxFYJ3~_d7fL*
> =J^V
> z-}gO7m;doU|J}d-7tenG`X2uO-{b%P-FKfo```HcJJ0?t{(ScAe|-D=uJP?3|8KpP
> z0!x9Vz*1l-a1jNbJ+o;({P4r?-qs5%QU$MMf!9fOTbW<0xfTVkv)UI`zdoE+FJ8RR
> z&nug3jI{&#?#@BrKE)IAq+nOI!0V)XLTO#7Pe_65toE%`n-161`8(hF&NORVsipx>
> zaUj*(Z@--`t>0<a&fT4J3fgrBv77bU*shc6+EiLRx1qpwR(qeSf2K}7rwQ#-
> O+%gN
> zU{ur9bsP|C-8m<wrXA`!E31va9G3zc6u8c6?^AV-
> (x%T;wLaA})QJv8)m&rkhEVIy
> zIWaZuP}f;mZT#i96xg7^byj<ysy;+FJ)Nr7r<#U3(ZQ%Tt#ss!Q0vY)F*WT_*I8L@
> z{N=b5*r335R(qdnbbRjUpQ_fUnua>j!KikuHx5Clb?2Ozns%t`tgJTva$E{*P~bY
> N
> zy-
> yVn&fPsz)%sM^P$xPV)$Ud6K!jR%&WWjMhq}(nYU3Yu)Eazs?9Oj49aZ)!$6sf)
> z_o+@S(P@7ARMSu=IvCX{Iv~`#b52Z6JJfYnRvZ7Q<0-
> }a<btd_XH+*QrgAhz?C<Zv
> zOXAg3mn2cejOvux5$e^ub52ptf@oSc*>z=Y3iTA7PfWoR3bpQ>QLUby#L-0B-
> `|5L
> z;weCC*Ho7zQ9PqMWp;#Gcg_JNH7%R$y0SKfdWy~mB!9v~*PSz})zgzYnn?T
> md+<a&
> z1xW1?6^aM16G>tyo1&nKLw5A6J7<SzyN0+-jw;K!-D-
> 1}gin4D_VleLv|d+H?H5j}
> zau!tT2D^rQ{q@(s_~MIizWL^>ufBTo%{Oaj7dbXZRCU<1o{mb?s7{#$p)T?{=M
> -2A
> z60=nI#2lUo(+}k!Bb9Tw?Pg!MTk;%j=-
> bXUR##N}h4ZUY7gXv7yMTP_t+&4X@=IJe
> z_WJtkuits+ox<Nmj?EEO5%a`HqY^c$Qzk;FU3bnYlkW=>vsCxQ9PXR<;3x+fsh
> q=Y
> zHxG*WM2C+y^lj%Ft1GJg!l_iL3o3PkJ%V%>PUqTjkz;d2HDWloe^jDIb;?`_weF
> l#
> zl$-@|#Wkud=XR^jnOe8`e6*o&HOpLAQSBGbG?8EwRO$vhg-
> kD;>9yk`$L5GCWjMWa
> zRH8<8%5(^|?wnJUoCR^kHL5J<cB{>qTDSRpw4rY`%UoAc?HA58kzf>5>IOSP7
> 8g!^
> z?YPLXIiiXT579F!QKLF#Mud8W?;QT{&&ovq{QUFJpFe+IIKcU%k3Q-
> r!4=o2vYgwk
> zHk-O>My}azE@!l%Z#BzYS5fV?bf0|kiRRsQWj&;RN+cKsmAb)pF{c-
> fF{eM<agk$l
> zMCBOz%}D#+d+&{gk4n_2Mx!?MBh(pp&gg9BFLJnb$3?3{nkz0VW~uIpIb^62
> HcDpQ
> zIkl<>pE3otq36vt+x05=bhM!lih2FR;~pe4#fgTya5lZgi_xry^TH^o)D5;qd-vUU
> zwG?s0{p@EyW6#GQe{8?Q#vXUpxyZ3OqEd#f_G_=b_St8j5ebH)V!%;}8Wr7
> +7zlOV
> zo%89ZpQbEW@jv{-
> Kk&B*?RwD)djI|RAp?8h|BwIpkE37zh*_$8Vh$rDb3z9C@G=}_
> z37%Gl=3t@X8!`tOshq=YHz{vz=q|ZtyIuvKjyCjd=NhXks-5CE!_EXIJ#I|r-)ySX
> z1(mwNX7G67;8;^saK?ACdUUwRu{ok5!#;yY93@pM#vGNXQPJ&)flv>B=R`of
> gW*RY
> zOJl#LVwUQjn8V1!grpd}c1D+~RT;;k2IEIH2N|iH!)-
> TX3eq0#59mqz8Vv9#QVJhC
> zM;rRKbB)y%)gDzskDlU4H+NR*ys1;AE~wNEHm6W9zOU3yL*;p5wW|Csa%_
> &M$gtaR
> zR4Cy1zJ64qMzwot9f(kmedp-
> ?qi7>LW~uIpIgF8+4XqA!<9intnm&b%Rq#>#AO{Br
> z8L6DZZ8x2Iqb9GHyCeSVk=y0_jfZ$mfYFA&?ObDZMYTui^azK-
> qc?hSV5di=E~wNE
> zHY1abn;nnX30fW?JW{k1&MtCnj;P3R#84`L#cO9&qDFOOYK}#yi{Cl+HLaDBX`l
> %t
> z+Q^7ms(WG%V`Qd+B~$pMwD`2fPi_{??G*<Zshq=YH>13154MHAQlCfZR4Uj
> _hS7$;
> z?ObDZMYTKW^!$dfZWB4@9Zi+GprV_b!tmS)pv-
> !Jq^AlakBkwOBiY^L+h?m`ckPTy
> z)Tnk(ssj<~Qg;qBfVDDdCcvi38s%!#A9JVzm`ye<nZk|y@Ubh@5}5vJ&JHh9Ifv
> VB
> zMs3p`r)TQ(D4qMjMjQIJbB)y%)voE&!y5{3Iu<leVXM>y72RB@AOHBrKl#Z|@
> Efh#
> zuh{MY!NCImzxa#4pg$vzj1d(h95;$<XH=p_b$n_>K&Xq{IsDn1p4OP(4tv*GuW
> Xd7
> zQGd)~jNiO-2#gKkiVKf$`EZxmdiAGt4lhzUhudz(6r?@-j`lRvxt;sKMjQIJbB)y%
> z)y}-|h;Z5-
> Y;sH5L@ISbMK|IVMserFQH(q?MpPDxC)Gh&+;DzJGb&M|ip$y2gHY$)
> zIc^>N)Mh$ySq>8!8$EKK)*R(()E{#g!!nccCW+4W;~K7x4!RI~C!x_CUZipkx80;
> @
> zuaq&`(6^mytgfhbD}V>OaBw26JI5W%qoy6gqY||Yp0ZmJ>byJ0rI&zqqK}^15k
> 7j#
> zAT+ja&{*#bMPt*QGji6?Hs+(B-
> yC+Nat^oMr1GznG1}0#oolSFsCE{>16@1rU{R?H
> zD!LJ`FxKasLY(*rvOoNtgK3c#{a}Fl($4@^ZmbR**w^#F&xx9$M}G~%eL0%Gjlj
> }a
> z#b$Ks-
> 3_^=W~%DVcdk1p*03gB5AXO9MLl=h3eeeuorx4%kF|8H0;KkcDvh?U(;ZoQ
> zGLK5ssP;|gMj_Ni?i@_Z|CLKxP5kg+XSV(%#384NDmr5hT|hKBdn_4X|Mg%0
> wGN>(
> zFG+i9{fuDi<w6``q;d|o-Bdka9ecE)Z#&mmT~X~W`+9z-2Zi(B+El3vD!O&zD>Ju$
> z9N5hMh$;r$*Hc_L2snZ?s(mxMQ3!RZJIBquyUB8B8Zn2Q+O7qB1NQyzf8YLXh
> *&c8
> z;V-
> MO#CV@DARh7iG|MgTB}W^noWpH5sn{!Jj5hRb=NhXksy!9}_m{o><PM6SJ9
> <>=
> zf{JdPDHJ#!AdJw={)mckju?EuY})E491A;wG^!(0b1Xu=@^_BOZ-1sGqcufm-
> YwJ;
> z2EHU@8ZEtaV-=e*sx0Srt4$T{)v-
> q#`c|{dbrsc~X5a0&bXTSWr=3KCQBcus8W0Xj
> zTc9?xKcec8)IQS-
> 2g65@MpegeK1HZk_|Bn7{Q2dmWZVbR+Ko?9jQo{6R<RkQ%5rYE
> z+NAQYlrh@Sx0+?HtEl!-0q8-
> FH+tMtBmZVUkzf>5bnApw)Pl2_{Sj4%r0{VU4kV3V
> z(_r`r(x{5~{YMCO-krnG05s11Tx`o?IW&!!!@fKxdOF%j<s5Fid7`jSDAZ^}-*&FC
> zx}w^P^tu1Fb#a^*LEIyix}c()8=f|=|ITS%I9T1NL`|!7`CB^?>Wn*Q>$FGwSq@
> Dj
> zR@RZ(caL?nk;*yTc5}CkPkP{JL*I6;vAUw#>x8;%hu>7!ql%|0bwNe9A`~B8`JH1
> w
> zk>=-s(I*^R&ZtC9D=ztnfl%wtIU-<tEUVazPQAM!x72LQc2ka{4Sh?QP1jOX`-Ky%
> zcm);RI(S!p=X91ppHYdLR&+aJAk?dO=dhrr#t~`VST|Rv-rbN}YC3UVk>+Sa-
> %@7N
> zwM?u1Vg;ahQz|%jz}B79QHeh5&e0+aHg!5~xY(U~cSBZlDey!U=v4dhE!K&k0-
> i;6
> znL9_xFK?Sx9fhYp2(>=vTt0*4H{6ebv*uh1JfH$+o$k}~%p964Ig4uDInBJ7+ZEh7
> z%>vo&)~T%B!FLb5PO9C@Sp$~>g#w*w-
> *j%(&IO4+I*V%EIdwYRQ^>ySbB?C&%I!{N
> zU49AINp*Q0){L)$0@qpX9V&NTrp<Ndq_T`UA^W;>9%I*c>isde)|^X$^A)(xY
> VS~u
> z4$d9@&EFvDP@SKlSwy4SvFbPkq1K%<)B7QwUuR`K#7bAprNDJodxt6>nY(+
> |onz9i
> zJLi!OgigIb655(}DR8m^*IDfys@*qC9JubBb?2PCueOEj)cdxG%X=wstqNRcwRf
> oE
> z)v>#0-8t*ddDIQssrN?(T$3*aPE+7ItGz?D`-X`F*PXNOoYQvHo<N;?-
> xGI@SqfaA
> z0@qpX9jbVB?Cx22&dYbs8*jXEeU*9w5!PjubyW+zPO1~+ULlqOL4oV6_9oTt8
> zv6y
> z+&N9Epz*_YkSZ=}M-L9<yWd;;@WT%u7W<K+V_kOVT-
> 5@vlj@ODw5Gjr1+KH&7gfLP
> zsMXtVzrEv<(IGEhytuz}@HYbEKI?;AxhK{_sd()?`U0<$>dI5O@Sdmw*IDh0s$
> Wh~
> zt0UKrT{v>**ulL1Tna1&mI6zGrNF}}aQEHX!-
> ZdwmjX+HrNB~PDL@78?;Ly+)&I=(
> zBs}AHYuA9isQOu0S}m>m3iLgnL|uLG!3X-2kQ=bEBD;3h?-
> 2BB^(0T0JdBe<o)BhH
> z^+jA-y;54?SI$m(O+{l}-QI;`ccxuCcX!TIjHl~hH|w?WFRFe<mR3uvz5;#EW?h~5
> z0i(laR3}b)ZK1Hh_MLM&yUW1t_%4oXHY>}Gdg$h&>MOjoT3YoL=zBKnYWK
> Mm2X@$u
> zDvrIG9xU+j?wqq!tTWlHtUAc)PZw2R(xuhXs;@xbvsqVX9aD(YVKb@|C%v{%S
> m5S6
> z=RZAr_D%MG|M%ImKfYhzpFDf^&*Gzx?p=QWw+r=y`)7ZCH})6Lp8c!)o<Dl_
> ?4$dD
> z_kH(&*O_cqRvqN@r;DmD>C$Rx)mNbJ*{rMkW9EdvJ8VXE!erMP0t-
> C<&iTpx<>0QS
> z|NgQHsheFp@y;>lFP}a84=)G#eXGu7v$E<Sr$3!i9sHT)KHw?UzOV;JEvmkNO
> RLkh
> ziU-c_o(`L3aQ76~KM)J--8r%p`*1S-=<+{hh}|K$g4`z=^r#yymh{f4E*#8KXYz^e
> zLQ(GovzCZYpQu*kzofCW>Z|>vwK`$@-
> G}HXW?J2kxWT`%z{Z{P^1_Qdhu?tdO=6?%
> z-mw0{&7Adfj@kJq9P_R-
> `9$meWzCPaYKi#tiE2guOBze7zS>i*@TtC2;{6#ro>M9d
> z(gADw^r@NwpQ0ONKl9G{m(QMke)q*1KhIDUy{QT}^XHxOU+$t+7Y+v0nQT
> ^89pv<<
> zQz{B~iqYhsQZ?h8>$a%+dOlIDns-
> k6g>zpV=h@WilnrP>96;JMsuL%@woq8$BiuQE
> za`zhs#ZAKR;_&5L;r6YXY3kV7tStIp#+Xu_TPe*&O{to3&UM>L)jYszg%PA)#a60
> 1
> z+F4I`Q|WPDE5oN8GKHT~osu$u5y=@T;grfoalNVW{`>ELbN~A2BmACI^-
> 3{Zr%_c=
> zp7=8?@Dc8u{^y+c?mp+lZ|Yu>-
> 6hR6o0VmwUW&W1fiibf7tJZv#>pq{1&KbIQmOOB
> z?5$L%9AMLIZl$7J?l_z_Ik01FrJB@D@9`9DN_9%g3fPozN@b&puz0lYoLZmw6t
> bUr
> z=U@W;xsA?e{rvT3*Hll~{BG^v-2aMnb?u}D#m;7Bb?VDey5{thA`*-
> #l?#5bsRx^4
> zID1Ov{LwskTEu{{XDih~B$IlY%}rFQ|JGDSL5iMDREV<`CiO3P?9r6!l$51x)|nDc
> zsccjc7LV4QQ|l9-LiUsI9Q(PA`-
> L=qSN4N@1iJAS!V_FX=D<4#|N9(%C>mZnX+g2G
> zSy`+vEu#Am&6B^s{`%{8-g#$wN)ZXhl<HonZ~y-
> 6v(E_e>8GE%r>^<QC!f&y^Uv`U
> zwm-aT$SIXB!R++37-
> <;4e24*K&sM4w2@+72i17!3?yXuVKyIQU(pzu6_2rjeGCR?D
> z?>&6B&tFrdCKX{Yjq(&z8<09%&0Bv=nd_NqWk`&#!Bq>^Rf_uVyYHHwak%5L
> =9J3Z
> z6d>9}!qn5cN-<ogQN@XFrUwf=`ObkfykT(j=>NG(BXx^+4g%WGe-
> O(3FMPgDgG-ug
> zHY>|UA)*#hJQC8L3*0%czyA6cUwpyY(>-T$aO1-
> HtFOL#^UXKEmFe!U`rPVhg$Vl6
> z;IMhF6EzyTHC?jOW`_y`LFHhysRH62e*XNqK8-e_r7-
> MlQkg&5G&@ll>xoCE;Z2b+
> zSBHu)2&+6rQNi=I*Iv^%J_<=qM#hxNkO-r}nHmL1-
> *&A#hgw~;fnqrS&cTBD;l%Eo
> z(eD8`H(n|FImhJF&qZF)QKeh|wBB_%LThP{P6gM0fjb9a+>w}lbZR>Ic#72LR!1
> v6
> zu{0Bk=k#&SN4ax&AQ?<lM%QBYajjTd6s@mPB&>P*)lL{!RB=Yt#0jX^0+%^5r
> gddV
> z6i0)Tflraa)PaQYX$m%_vQY#`4SkEMg`GO57_QT((&4w!i3L8$opVr~c;{3BUD8~
> $
> zSy?v9rrG+Qm~hxS`f?=NoKi8S8q)$-hxEN5@D#(@Q!4l)f+Cr%=YbvS>8)sZx-
> }g@
> z+U!t`z=&!ez<&GN-
> ~Q@XzXD+@4xMSFJl5HyGG~gWLb)^Ey<do*Q9)Jk^r^Ty7zK~I
> z>5j1c>bZWL%Jd<O1}BF52(49QKI_h*R@ZD`<E%SJwhVK{`o#{5)lIj;IC#3Jk@Z-L
> z`%({v^u$8UgH(`;$0rGu3UZC6roS3BPyZZE!8j2QGh8)xbTuKRG`xBGony3mvbs
> wN
> z4jv-3J5-bf29-hL;&k*>sz<qVw6+Z(zNz7!jawt=^!tvER&b*TsiE)krUyle;W~{f
> zoy&D<?o1Px8WY5oI(Mt1)rDv!Xg}iXo3%8)gN#iq@af+<SeDD1Hk*}YLsTK%XP
> N}{
> zDeU?*ol=b=YoWPq*8x6A1(o8RqgCmUMyp_d&0|TKYGrN_jI)psdF08|$*Dz7
> |7=n@
> zHcej&pbomfZ7nH@c6O*J3k;nu<$(_s!;$mzpa0x`2SU$v1xW2FmF12w8r*1^K
> @`~E
> z{_Wq|;p%|N8HewqvQa8mv<U_zcZx^n6vK6zR&i|Xp<Jd0|K#%1J0ZPuD4hyR
> PewL_
> z%S_`(PS=A4t~*DPuJY(xEB9VO-
> 9~nOnof7&C@lK5%(?BfYT{YNXa}hvl{?zCFj?%J
> zZfev#mYJzmkxJ(!q1}hBsh-i6((q=7ieo66o)gTS&Z|`y^T>cBqeG?BZRKH^X|6{w
> z?4MGZK7`TWpk>N%=Hb92gVTroZa5;4M2#txIjdaJ*3HPnIJ#Mn&OWk@Y7{~
> HO|H0D
> z`j{Z@?4p=TYpZacT$&atVsc;_pR<n)EO7IkGm3R$|F)m!VB%2%(ci2ri{RG4Dn_x
> p
> z0(YLVS)ZmOsu(BsuxdbMWfFVhDC^lrrSiJSJSTQYgitk)%{$UcsqD~lY}O<p_lj+%
> zVzV-iPT}kh6^9UyFpx{PGG|nWSaJ+FGCEY83x-
> aY^6<m6RT_7MsyBjR|CGw~A&drB
> zNbBdd?A%f|TP#V`m{P%6wMuOs%t$B;EcHaE&OWk@Y7{~HO)e*bI;3|3&kCi
> rENi_{
> zWOdWvu+#X?CpNLbYrJzJ=%i<qK=gMii^JnI+;gKtA`Y>h`ZOI;jiR}J?oK=DweZu
> E
> zgTwbxQ6Cr#Wk!E$H_)0jkIg&MN~!G7N~ef74Am?4lZDbLoZX?~5aMy_Q90F
> mGT_MQ
> zP^n5aPkfr5>mwNUPpM2FPUp^1?m-@k?9mLSY(*ZYRNz;wQd{$-
> FsU;IDGZ}Zhr3Rb
> z%W0)P>7CHLbEd&DQ5s(XQX2~#+&QWH)pkyESUB)ex;ozXI3(O>&(xot^=Ue)
> cMhK#
> zTI^u67dPc-_&zF11j9upMp652h&F2;n|Gv@QrV%Uk<DiM^aoAccG?-
> oqDQB2c87{X
> zh{t0U`Eu_LNM)%^*%)wSbf|QtO&-=&dajRP*gvH*eF&qq#0;up^i-
> 8nHd`!7)R<Di
> zS+z=S)<5uW@6NGOjDK3`KCwH;{`WSc{|HZ--KtYd$=RLCvLT}hSm4l}n{VXI{`xc>
> zQE~Xxa7Pr_I#=R8DwWiM@f~Mpb~hHyn#blHX{A(lXvO$EhunF<es}P@2s(w
> cJ5(G(
> zJgud;mDw{AlL1FYhf3F|JWdLprV2yd^ja9fuzyNr`VdBg6T_|-
> i>bv=?3B$GOA<Av
> zRB%?UQk!_lovX3vud|PAql#l=kIAK4IUf^5(+3Air?j?<^>EXxo@Gg6-
> 8pws*Et+L
> z)qa;TZE9t)#?>L(^=Ue)_ZX+>;U2YG=z#5`Dpb1iJIC<izT}qDeHNwGg*$tcLFZ=8
> zO?OU_$27QhcBpijT0%On_Uqx4p6d#b+Ec30ox=l?C%VPQ5=g=fvL~i{9~DNaR
> ;jHg
> zg9?>8rx>o&v`UA&PR$W-
> 0}2Ia3Zj{1<tuHxbEteAOL^1y4l*{ez{mM+?c~onSeZ*5
> zo6~xyXOxFM%m7mA-
> Z#+48T(Fm7o=z^l2x33&oCOekBSn(aFMy^nzFdzHIL2P$)Fut
> zE;zRrk0o`meO6=Z!kyir;t=AE&Iz6wbrKnHWOS%h1m)rBqNU|{c+BwNL9`JJ`=?
> Z<
> z4`CQQ_E=0z%H%SGDVr^pBx+2l;H+AuHtSyx`_vPiI{U~rs!;^(r#LJgGkBS#f~4=l
> z;+=zuY&dg)9$RcjaOHG17P#)5`|LYyTvIdbHlp*iW__BD>OBpWcCw(f;#h9!5On
> UN
> zx>xA;f4j)sb6T6ur)btZHt$F)rLsfIO++@Hrs_Ze)2HUCQ#iXr#UaGgD$;rNnCG5
> W
> z+9{9C)uGa`DG!y2IZYpNnImILW%>|?^V(U63g^29o5GgB{94(kY=v%9D$J!?{rJZ}
> z{>e{%;{K&RG5|8}zCXWvF~~?C?Kdh8DGZZ~T18J21m*OzpZ!cv3D`Wrl%GDV
> OzO`^
> zF!+@5|Nig)-W(7%Vz?eGaNRj~8Rx0s6w;>VC)SsG!bU(XC1;Q7-
> 31vn`6dsk#&#rF
> zQGga|AC<y8B%Tu>nQG$3qFM9Uyd$lYDyEO8_~;0y1NUFV(<z+Yq2dtYsa)K<
> oR?dC
> zgv5X&V@gF5n>6xhX~l%5=lTeS{Y@&uSQ#q`wX&GD3i_K|DO*uvQ!32G)WE
> P^=2FA0
> z=jxx;r5aL@!Z0eGcVyf0i!IMP0sqi1#Q~=-
> LHY5>UQ`=X>p(Xb<NxWO{;B=@uZTRN
> zWj_|U^UiVqJSYAwPyJ`3|LFd|dxL)aMFIPt+|WnATeJU`j{R$(KOowjp^w}YFFT
> Gu
> zw{|KECE)g=kABx?9U(JL{^*Z@)5?ktF;3dU!zu1gEvPtlAC+>tn0heOQ@erIta)tS
> zP6lK8cp&jDas;pqSEN!G?(7Z~hY*icC?Vb1##TRt4+D;jDHTaZGqSYOZ1MzB(MB
> -r
> zpHjgSJY2p7=W(bc7L%(WEyPUO5EjlPQKLy^LgCMphn+|$uNOTi*og=_`^YvbP
> Fffy
> zmnNcct{<6<#ZIY*Z+eOa?zwZ^RbbZzuNS>=>=CY=|Mv2K@zd@c{Cm@X_ws
> -5Krfbf
> zt>LNu_jX=dYMsN;Q}(lpUkVx;{Udf%={Do2-
> ou1R2ltkixpo${vyX}@!H7V*?czBa
> z{k5m&skKt7m_AY!NIc~9U{E}r!r7w?IyY+)k29usj#gJhN+Y|@DHTa<nU055G&;
> #r
> z2geYbQz{Gr4`DF-kACzc{-
> +aE3JcCvkOwtS+rh&*BB7^A#d=^xA$R=ntewWG7mn^w
> z#7Qw+r%`dz!Z5kqVhjJ`(Y4<>yl~uaI{(SDXTN>+?2ohm+>L$6(fh>i9Q0@qMz&
> 8o
> zxO4v3vuF6vw%H5u|M~8Ma-
> W61ee6=lW~Z{?%qqU0ZumD#+ZB`>FsgI|8&SC+v8l%r
> z3*X%Mo-
> aMm%x51J#e`8KZQTJiPpy?wx%6@0>s#bVK6TS6oIT2*bF(J#c&w&5(x>r_
> zLmJt2PN|#-
> I^$1&`cwWln&Rv>kj1Zwb_}sOrNR)zCk%rB)nEOU{ljjq$Qj%uWd`B)
> zmw)+}P!%s_Ls$-
> RMw5z)5zl5ZFn8yW$9(XozU6TMY161UX<;}X&RExc8qh+GlAaFP
> z-
> H8Qm`<%nOg5Q$Gx$Sb$%LG1lpKz4LiT_<4=cd8=v4{Ve9esMJvXFe93NHm6G
> <dqZ
> z>Q;9IOl!(INA<1|Qkzq|a)xtp9Wm5CDqRResllTNRD~uw#O#`<)=H^d`pBbik>l
> *>
> zp{Je=^wcSwJ<6bSvnKKMoQN~J1B@7Eq>)|cl*+{<53=^lU;fh0EqBc85Xz-
> lb_}sO
> zrNR(Ml)|`!kijV_Mf=4seqsE|26zr}Mu$q*4x5A&N`E~6H-
> Gat{A^|pF2xQYZ5oxE
> zH*Go?n-PERxO39@57dbTZo6~rPH^{$gR{%Q-
> 6zG*b9A`fMKL}<DY>wJ7@H;#ot?^p
> z8%y{P5yzIE?xPGN;0URp8qfLrC*1L)%2EfnSuOHDDqYBkkXzqs-
> |c%FWq5iI)I2tC
> zCxb41b~C38j-RPa<<f;ayF<kx#M5)a9Y{_<_p~Dvrkhf^<tq;lEjP6eVS%Z(T;|A_
> zQehw#NEihF&2N5VJPw9aL`i@5yWhos^BV9R;*1WJuH9@xQm&EV$O{q$Gp
> ac6&GcY_
> z8}6LRCk;`BR|J0i@?YgAHtusyyj$Fz<9;+Wyl{$qb}9=wX9**e+x?@OV!s}u6rny
> O
> zMpPUg4W5peS9iSgEItU;NDyH}rF+6nr_H8rD%TXLNu}wdP@}g4$_(2SOW)k<!
> kyjG
> zibIIkJh37<L)FHV%B?-}q<1ezUFOc=&MI`Eq|6{kx!o~RY^oIoa^Y%3(Kt1Yc;O(z
> zh(!C1N~gOq8w=cU=h&BK_#w;>8Zy}J0cZWct#=N8!V_;NkDz%|yHi>4*Ai}?ov
> bey
> zvBVHiF`PZ3@~e`zUM9uCz!Mi#?i{U=KscgOcp*wmon7@&`=Rd~o{KtB!g}9D|
> CmHw
> zxU)N2aR{rcb6mxP7NiVS8&j(LMSuIZ<8cM!oYACKdal<<csiwm4<vFhsF|2Sor|i
> H
> z%F0aHz^p^m?odSqtS6$f!rkl|L1!P?Mx~=}%*FyA>dtXWrQfZ^>&x8im(%#Ms
> &mC1
> zsx0K6^$YGRymNF{^$!N@0~}z?1lBmJbn8E|3ptA!dP8zMnxO~D6bWD*Dovk
> #r#@AQ
> z!2G$dYGqFgxjIxFPQ2o*f;a^;L)FHVimNum@x)u#`Lho7WUZ0#bV>yuNaSErH
> FPej
> z$_!e8DI558h}s=0w|s4;Z?D|c>R*sVDmU<!nvi|NozuSr@QLXE$giAnAb<SNPe
> J;1
> z89U95U##)d5qj{+hrh}8QYJKSYIiCN{;c1Zf*xofpkg?CM0H@o`Oq2(gd-
> }2pHH*J
> zV~W(II+#9PVAJksrJ=T{;(a?R*<4d9ANq{8E;F^KR2bFFpvK=ZM2B~%YI)qXQ(rg;
> zrL&K0qpIh9(oeC#!JVU$+%GX+0{2h+-?($^_nP&KHT{0ft{3#!|88gG#-9t(!9D`{
> z`OsEiwL6ss|7QIr6W?|9PX%KeQH|oC(m#b9QK_D%kTA#;2~&5d4yI2R*t9!T8j
> 4Ha
> zVRTfoxu#S*W}gnxWv2F&3Zt4COylqC>`+bD&TD6S;UH9p)2OENK3xYaaKoL0b
> =oDM
> zx5sGl?%Hufc<11M&ttaTD)CBjarl|X&pXOzr?N1%S@M3?`*#0SFwPOxeY|u22
> 9<k_
> zRH~_T)DbekXsD(=(n^OT@)0l%)wDZQ8tMpMU$-gM5scATU1n-
> esW7UU!8HE9&JNXR
> z$@}^{oJO@T{*xGm1#Y`@_$^ty93El8{Txm`n<YP5WdBq!l2N^n;y3$&p|9zxox
> _Mq
> z-
> I^q+8`v~d)9z3qaynzPvq_?E9V+!7*_yAy9u0T>Q>vyQo7@~jY)+{#q?y4Oe0N
> WW
> zYLgCA=MJh-
> O+!6h2P|;gor9(FV~PGK2L1RzV*d`o<>ct+aO&AC`O(@id^&|XjOx8O
> zbvlo9iXHZdN<(!p3Lg#Cv^!MIP$#-
> QQL0e^yZ$1B@zGS(j#dck7}Dl+uD(NuDrMN+
> z*<mxP-
> BVouKrC?cor6`m@4NWJ7WW0(gRj4z!>MPp<VQ=w@aYul(5ZLzzl^=8`Z_;R
> ztwsf`{acH9Dq2S?Oxk%(=juCjs8p8Yc8ATVj?Z<q5wO5LcaE*c{eb@gzisQ}YUI<Y
> zER03HAITDij{wsCCRIB2;W`&pU)v|DRj0_e7V}iJC#n_J)sd_3GZhLBrd2=Ylk>y^
> z_un}WyV_2EIzG*MKX~VKNYtlEr9&=YFRH%CORHBwt8>q|j$&3<=gxao(XhZv
> -8mh-
> zAHt`3Hmo}b;y1N=h%^;37gZsSd$hE2f)ve;R_C791q>e<)w%OtRWvN{?#_ARj
> W@XH
> zTQaaN%i(l^m%MZORF}-
> fqUx)?w0fnqI(Rtn$e)VFx_a^A1xMYIfpy*AIUj!b;Z%>O
> z=zw+EoiknF!Lr&UPM>O1*n`fCsxRQu>Xp*!;NieaV=5Z!>VpqH;HX<Nu&(<%2
> Y+L^
> zxMioRJQWA5g$d-
> fQ!MacSv6(ZO4ST|&}~um1zcLaf?DBlIOSDH7wZbg^DTYa!CLIX
> zkvqo@=Jn@NU@5Q^SPCo!9!`O~pXWSW_!W66uoPGdECrSVRN(&3!H2uzqh
> I|9V;K(y
> zzSOGyFY`2hw|1F%>sc06t&cukTB#bfy|k+J(Wg&Bt1J1D4!;ny6aL88efA3kh;w)
> 6
> z{P2fA)ST?FdF>#dJBB~d5Ej>>nku}sno2~6r4^-
> ^8cVCGM0B85S90OluP^Z0dHe0R
> z5B@@fT|0Mo4i|mIu#50WgohZrsQRidt(I1O1^S+=uC{7*@Mu4MxMlE^un4v
> 8oPIr=
> z=ec%aU(2P{(yFgO-}9R5>Xg&{#2}{CDFG2`-8ua#J<s!+>;1e{o)c+l)z@)pbsJip
> za=M=w#OmslfC#njoPL#_=ef>?zLra?rBz>nzUMX9)hVa@i9t-
> OQvxE?x^wzfdY<Ps
> z*ZX;^JSWo9s;}eH>Nd1G<#azWh}G380TJp^@0^4G>)uX%tzFnr$$XYpORK&D
> ea}@_
> zTeUjnbU!hOW$=`M2=&-^&XIM*D=X%<S?@8_rk*%&-
> P5G1gPi_!QS~KVS}m>m3iLg#
> zu8y3F4>9&cDulZ1o%0ZSFeYw^nA_&rfU%6T!-
> (_NJx!`Q$mvfPRbSFu(yCMN>E>$6
> zbxT@pdMj$qO_j{ewCZH!l0GL=A=J8a?s9!qcg~Kwo(}00{w<viZoN}|%)yN+n)
> |eB
> zV$iJsNFVj7FvX@r3;yYhoz6a0C)!y)`>3|+rXqL9jY>ydgMA_uLajUJt`d%v5{jZz
> zP3lwE`{`BIJTPi1<-eqT3RN?|{dM)Jnp4+FKRts-sQN0IXJ4zWk&pQAqk3rFjH)h%
> z%RfDl3Zd4Wb62-VN(m*fwf5_JKfR_-Ke6I^|Lo8H?8`5|{O0cU-
> h1ywhuuB3RxvCV
> z%hy&VW3*9Ep9(NrF`_?$j7YTqGE_Qa$L>=V(U{ZPC?dE=o2X(&cJw%av}sg3f<
> Nex
> z6R8mDk?x$&KKsnhr?0>M`ki;)=?M1LTW|4H`~36I<B)V;HY*EbV?dqJXzfqT{`~
> oK
> z^-
> s&E=&Y$Uve_dNQsJ17qu7%w6Y**)`cJj0VHl@rG^x1Q)Oh{%*T4AU3(7^~tFO
> L#
> z^UXIoq=^K#CKWtQE(Q4LqmMXaYP|pc`$kB-
> b2CUPot=|nYR;<;wEHTVXJ0Gxw~3mH
> zDK^OaY@4XK_Q=LsiiX<=9X6wK(`i$W0vBK1%zpRXcOzBW6VEh_Hl<SM+D52
> Hx^q;F
> z=@zs_XmO=tr~9&5S?(NFyfj7VjQcVLNDHl|ib>N#8}XojR5(qrnu-f?S{bbprrF`5
> z7^i78sTkiGS~gSZnn-
> YKQc<hs32N|UW{sVjLGTmIW=soyv@x476tk%n{SB$3n8QZl
> zG04=|MCFP~*@~ia8)1qB2cvS+X|uo4Fv{suppK3Xn|ey6gtd)Ok96l~((2{f3SN8
> d
> zHGVYWMs$lyw?ebBI$JPi%za2p0n$RNsoc8I)Iy6GuE$k6hBv`#DlWunWwc5d0
> dz%-
> z(=-aIl!S9>%{YnD=BJ;2+C+j|L8U<mqXj=Y%jtY2cMeoaQJdvN9hzFv-
> *lKNrX^>n
> zo4__vF*T7bttIPp8-WWf45M<>X;WA2;;Wn4>(2S^cU2W`EO&CN4{a4M-
> 3RbYE3R2t
> z?)2hx@ji4XnL4BZX?@jHTs4il(DbPldz2`}aGf<3ot;(&sSNd2V4S8=P^BcsqbHVW
> z65p!0RKDVO4r@kJneNSgom+~F46+7dDm8;-
> <Brg$$geqU0_#u_kMqXrifqoAO-3sW
> zqvDWgXm;w2W@A73<P)p^G?g)a+B2m}N2Q$z^+=y{fTQ9~^VU%=t+-
> }oxsu17qnAk(
> zFXc%A()y~Y;&iIjsL*&%T8TNg6vK7aRCIP)8EuEqJQ=5H6jUjR&B6phjd<HoVZC-
> <
> z<vWLhn4#H>d$V8Xmf|9Vtbv$Hy;U58W)1m8;tYEeSci&uPM?C!d1{l<3d5*$l(
> RK8
> zZjU=pHgzvFhj6SJQ!3|QG!g3Y?i?+g`heFA7oKUwH7hHYd?6bi=>g9)rT}Su)l_ln
> zW}&H@J7`l3*I84U^GGP2nu5fIpvO%*ZH}l$BrZEn2Zy9Zxb7T^qq3wsZkjc97-dj>
> zVm5WxyE{h@QN`<TKuq1CA|aJAqhNEM+GMoCFe)A8?EXg6fvQ-
> &J#`fADHT1Z20}gF
> zodY^Ox$WKg^iNlPy2P~NVr9WCzBEq9R&pXCY*9`6C{pRu2+%LI6bu11{>ZMW
> Y*b{k
> zo<8Ad_EG<c3Tme?dR|VyPf+J|=cu0i>N~x(N6AY2M;TP-n9b3-PO$h1w!Z-
> }b%)9b
> z`)n#;v~|5B+o<AL_VhOzhnR8X+L=<hxr!!2J?fpKWi`ERVu`txr4<(|D^`$;(`lv&
> zOaap3id5<r0s4iehp3(w8h>QhR5mKISx=vEH2bK3L^aBzlJHxX5w^;;?i^K#Z(h=
> S
> zdz7rSf0RLWj@i`1fp6<bh0`E{^*11<?ob(FlTFo2ZC&rkHmY>Eb!vHU{lt=<TE$#^
> zG^L{F)Ig|5y>kGlGEA?X`UpuYE>>2ops7yIL7DYjPXW^6id5?6rbBa6q4ABNZc2?
> m
> zvTG_E71^w(PdJ)=)IXvc<x!8N>84zF&M2XjQLBi~qhzK1qYSEZ%x1iEw8m1Z{sz
> R<
> z9V#R2uu+-9(DjaNqbh=^2-EV8arEr!51&%SiAFsL_1JfgO2~IJ%G(zyt+-fOv4V8E
> z+U9Z2>rwNT0;I(isnjhps7g9x^hA$3Q&NpTvTG_EmCooUr8v$o^3m+0{t?wEkI
> Yee
> zEa@fV@LsjgIS|mjG`ZJy=V(<Uap^9=az<4Y`$u&ZJrP!wfgSHdb8vdPW{ezrjLJ=?
> zP1PY4L7h{Z8)PJ795tniLq<Ia_1Jfgo&oyfKttBt#;0ysX~o6LiWTJIq)om0cvkU5
> zw;?G&EGzUxDs_thn+i>xNvQEhc1>lYBAfN-q}0b5>&|h4Oq=`^-
> 7Kw621nUPziy4I
> zx^q7M_+$NNBv{q18k;Ja0)4Gi7MoGeCBkf)eUt^Ga_iD&f1~LrXK%fBrc^F|(L|
> `n
> zzH>lV2*AR}?qqI93rceyD=SveD4_MHw@vyUIt56JD^jUj<k3Q#zPZs2!EYlq{>Z
> MW
> zY*b{k9wi(dr5C<)cwj5DzQ=K#&<YuJuOnJvET`6_xOs~vmoUO`{hbWDA+AYaZ
> oRbB
> z-
> Ke_Rp@Qt3+KiE6ENSPDCW6!?`m{r3{xuuVrA@OdiP}aLm&Ts{M&ppw;IYOUO
> Wmw<
> zN>z+?j}Yn#?i?*HS5OotEqu3{H0QChVg<Q4Y$})@45L#&1<-
> <`9jW*T1_5Yjp^avz
> zvtn~YX#9~~Q`soa;*37wX!cS6h-#EazJ=-
> 3j9W!)Zl!Ym45&%bTB>cH2QKWWInrw6
> zANvVh-#PtK#}pl^m`zpe*T4QXg>pv(fH9V@xS~-
> {hswqxIAt+I*|^2vHkzy7Z&YqN
> zZR$p&CeD~15eTSnzM`Z$BkU=a^DmkRbp>}00C~4?lc7@+J5>e#Y0hJ1#R^Ilin
> *Ph
> zVJSdbZjnmeB9FpM3rd~2AvFHTuBmKPWV0Tfv?d(QKI$J)jq=FD5*x858LdV8w
> ^BKO
> zhSFkYQux#vyf(QVT-
> Z@_q}9kj_LGD%re)tRbxhHrirI9EQ4^$fB;e^(rq7hkMB6lb
> zRNi__D`p`Y{f!pKx}JWhDV2*{G!g1L?woY>tor8Rk>)(sd#s>TAzp*_9-?!4r2uJh
> zMJjcRJgGj>&3aPZH2%o0sch6}(mvs6_EG<cYLrJM868feRmA?SRMFpJx)U@`q
> &+-e
> zFMsDyRaViJ+&R!kx8!s`#zeTDQC&GVG^q)5lxDNP{o@quF)B_J4K44f2ywXUp
> ``Vj
> z`YDwQTQm{sI_{kGgC6zZ&MTIJM`_MuWyK1LVKuSM*+&4ZCN(0JKCOACg+|
> @<w9xn?
> zyQZ>Hk<EHkv6^r+`>20JHOiyb()9OEM$2LUR;uW4q0&=|vp8ejIS?c&rkT~+cIsI
> (
> zCc^cM>dLvH87nQaVbb*ciP7pFqe@p~o&Akg1mPoATD?=IR17#Z5bCmb4$@
> +;h{o01
> z8J}jAqY$J{9iPU^!dS)`8JgJsd*vfk1cni*l&3z?)l=(8<B#m9RrHK()}!;*gfV8_
> zGomW;$XY7ChZ!xz^^e#_RMFo8*7fWrB|qQq#IR{kpDG=WPO5r^pL3v+%2;1
> JqXn|R
> zuN5_6niNCN2L|757!@aqMt`Hlv9TvsTJ%BBlqwySb|Tbe?;NHg;%FLiXq{E^v9e
> +X
> zMHo%2)>QP=9z^B>Ya>#rzs59Md5RNV-
> w3+nR^yNCn#x8+woQa^9?d@LA5j%~bUGA@
> zjh4gytyIz9LTPzVD=MA@F>Km1(kgXMJE`hf8xXT}s5mc`A1S7Lfp;=T(MVUPog
> FIk
> z@3U$AeYR0?717Y;A1Q2$94jr(h@L4`Ix6i%sH?ei0LU+e@Z}<HeY4I*pbDBPjg=
> KE
> zh+%1Hy{7>5RO1L$x*P`Y6q+*Q!g1R%jqf_6R?Y!UA~~Z&XhUMmx~HIW4BAv
> 4s8R1u
> zNcT_w^iTR93}vVhTS4W9SiNa>)}7-
> dLNo5lLNVTl$n0o)#wlFS)(o;FV2s$@6g!$m
> zrE@u33%jmr8wjmN66q>NJ{Dw3<sgeDLS56H!&3U~Z-
> 4u%U;PRNg;%QUk<&d^cd8IC
> zJusx7;w|}lejK4n%adSrp=s^hX_n}g#&?~aT}UKnC?Oe~VRh{$oi+<9$KaYQCt}1}
> zBDTAt8ES-AP`M#iZ<-
> ^m8BU}|eD~>Mj+%X{Q3UP|s+Sgjztk~Nhl=x3hgva8gyg0_
> z{~j%n{T(WE?z1uYZo{Z3LNr*hSa_`G=+8X5TSetXsJbSnRB_%>4?<njo#Va|ffA
> #W
> zpkMN_vSJ0L@<bT$#Fysk2vu671k*x`46!E`V;bLeMy;F!nnZF&hw#F84hTC`rrx
> O1
> zq5{^_(aJon-
> gJv=%{UpY$pe*CBMjHyr*Z??<nG{Eb)9z(gwl6~QBtmGWc0P7CQQ~S
> zo1?k<{YJ%!qR}a7y<V8dcuKH`WfrHio+;I6VC+YzYr1m)$lYdor0-
> zhcI0%A6%>VG
> zkJdF)qy~x|0r_ecSF_%U(J3^e(sJW)7#*+<mBv)NLkPC-
> eeZi667?ylD7%tGdzwT@
> zH`;beqIN;0Zm<Cfq|qrAY0<-7Kq?n=)a+A@BB0-
> pcvfBQo#WmWy7yVd0_{;>E6bo}
> zYLw0Cq*Di@(z%@7+-T3AKj*-D2y2Y~(U?-
> jA)_9IdZarC+NV$|Pg?9Y3RN)8o;k$I
> ziWQWSXeZAAy=~0Kozo;yw@9T=X_G-
> ^i45o|w6Y+KSr{EEBJD8xSyRZfs74yrdrnEz
> z?ogS()!XQlN@Zldkxi#A>^@Zy#E`E4&H<;Yid~?ec8UesqfJ`5H0ivXCT&u=>9jd2
> zV?7qqH=fFD&eKDK^O{y{9x)K=%I=)zYWk;FtgIb(PC?Zt(Q=Da`jmDt@770*Sr{
> Fv
> zt@En?!)c|noNJHd>S$$SPpP*NhU@QBxq;g32)HSg9ja4QQgU5UYImqOP$L&
> M{dXHi
> zRZQ_Hk4~gQsCDNYOX8-@$4YG0`w_GqU>&LpBSEo;riv@-
> NY|mVbR*j66{n6p7|XJm
> z8hxrFRAh)fr&A$doaIPQu|RvYNvkHwbkeDVQ8lN#nA?d|2(|8<V~N|e`B-
> tydOw1;
> z1FS=JVI(Nlp`x%@_3jsgbc{_@qktVTv7FKH*#C5?u*{AcSaRPp>Z3iIwCb?IN8|6
> a
> zjjB1_#oSJ$La24;9827$BY|butoI{mJHVP$T*YOK8>Z^ycT*lu(ds&>SZola^P>OA
> z*rXL^?8q{jtKV-_ow+XQb0QT&J>H$uDV)NmnZ`|()r@)Etx0vHtRUT1&L-
> 8?um}Bb
> zn5rmmebg856s<Z{x2d{Lq3Vm!^xQ;+^>$=wPF=VeRcEeC`kY9GP>*-
> #6vChQXj5gK
> zIBy-
> QNp+;GHk}Ga+oY<OcKXvr)t7W>^*~y!I|rq8<T&EkyEyoxpQyrf)q5e1d$hE2
> zf)vfARUwXhw6t=96wPbaiYN4y7^c-JFbK6i=M-i6V2`f3-XCnyI|DDR`ob-(ZbPe6
> zPWKaoSY4eG5TVwc)34I=JlEOK*K%pKwCXF+_q^u1I^}dfF^Fk(N<f4<`_6gejW
> _yf
> ze`rs@m|BZ!D)rK8DiIx)R+M6DEUl&z(ScgMc=6(t1OAjCfO&vB=Z8Q1A=kanpjs
> b(
> z_~E_?4>1Zbrq-
> gG%Dc3hN<@dH6{VOOORK3wbf8ureDJ|3*TpG80Ar`<+i$;pFrZyu
> zcb{_*^2oKr3x@|hdMM<h7yw`b7ge2trB$tuK3!U=8nwN&s`b&QQ7fGEkN#-
> ~0K9OH
> zUpw-
> 7$%3svmjX+HrNB~PDe%w=+<(q_=y_KBrNB~PDX<h+3f$j0_$Ep}>phkozYu#Y
> z5}kKZsT#Gtw5s*dr%NkUqqdh;wLbdPX>}z(9pcw?cXtjL75Q;(3bv@GiC9`qC8E
> R9
> zic(CCrPWj-I$XI{S90OlFCW;ob9d)Zzbi59<L8yY5MxnMim9=*no2~6r4^-^8aJR7
> z{u!O-zoetTBxa-
> HpM_$kl?J&68&vDgDYEwRqZ_FAmlyPat)*38+@;kkqSfg~KCYlb
> zI;*SGCp{PtR9o(xgR|-ILMl93yRg<rpDwLbjoMyX)%xhurIo5t+fA+X06fti-8@Eh
> z;zXx}0#)zMIb}8ta!L;CAg4cVR@UkB)&VzBp*%GUBfFll^K=tcC*UbQi>fc<(&|L
> 5
> zn)`0FAM5^g=hXV#Kdtk*>b=%SpKj8sS^FA)pS_7{-
> xNDWEvmj~ORE#LYVN!H({c0P
> zDXL{~bF2p*0ICQ3ob&qYuYd8y7vIS1(@#I;dQy?tx$2!#OpQ%i?WlbWiLZ01rqR
> xF
> z*re52lTPC-s;NYDc#2wK`|#X*AcOj-VOl-VjJv~v>H+SYc-
> z>;v+f+Nh_mcXyYQ6q
> zN02G}CaP()vm6#xU&*D_Sz4X4>FP5+MYRmp126v+RA=8gZ@u-
> _mtTG<pKktOzOr`?
> zif+>@t)Nlorn3PU$EyrMMlkH(M8#1LZ7iz3!n?KV6j-
> N(Qq<j4X|%ICYpUj^gBxER
> z4b>-Ih*7EAHQ1m!_0D<s-
> FN?R#eDP4=bwN6{Q2{Ap{YphtaC`WG_vbN8tH$~Xj0iM
> zEFTySY1-
> Vxxs_@<`_!Q$=_aa8>pkMUsQT*d)@oWmaOjj!in@uaL!v(EjGfM!syG4g
> z2(Qi*=A*P~rxA=w-
> LAm~)p>W0UN~QW{q;NVyi+VO6^Wg74(V3J=OfE1n}xx!Bcn-W
> z!!d6$SN&)NkoI4Uip-
> r|vWY5P*F$tJs=lhbwPKwVMyG^Q)J;?cK>cVdUQJaT1?d`#
> z&JlJx#HdC?9;+Wz<(<>#(y!FM`s%AU-
> +XgAHr2^G(;Q9%p6=iXQ!3}fW>IKUP6p{1
> z7o#F}XGd<La?3>g&dZJJG<Q>hhs!UF4ny?mQ`NE*VEQNmq&<BqH(ci$*;t4h)
> of0w
> zRHD)B)Bde^H5H<zGj5#)5^V})RO!@@*a@lwcg}0Cz4qB>pXrxru&1AJxZI-
> 3(j0PN
> zG~R#zePR?}=waX|pL{}3{rOUii5^FoQaK-
> Mx@e<csvwCOAAR(Z8yFelbbTs}WzFh)
> zg!kTiFV1T{>W0i(XJ@aZRHIo&{aRoytsRDgTIq1=W~lr~@2Xvg^zBruba*P1=7<
> &5
> zdEZxS*r#%+P9h?iVZ~NY?E-
> 3ZO64*Y71OhVY;Nmq#jB|bBt03(P|Q9Gl@2kgsKDd)
> zfNIyBqlW?W=8UZ;`n0kNsq`js$AFG<*wcNfNU-b5QfHkMwpNx?Nt-
> M>9j;+hyHADT
> ztXVy%Mt6>ri*9LwJGPWc*VVBVVBI-
> T*ome|)Iy?NS9qPrG=nb7Y11HiEfdC!N4#_N
> zlyFqm)Ea|0_Da|2I%};E$0d$UJsG(D;qT(JISQ2yF)Geg8>t|>JBztMwf)YSRys-R
> zlBbZ-NOL$^hvv<uX7=0=M_$}cHqe2kRL;kmZr(^piPT83)A-
> uir@|=KtV+Sl#9`~P
> zq3<Bl0#_v1DV2*qZC=TpL(vFKWn2lt6E7#lw3%v^jv@dIGH3}!+YxGn8nsX5P;H
> 74
> z-lN<(%?$|koLsd;TzIV&f~f3jD;T$bG3h8&I>e}Sx{)2r=3vigBJ_i5<DH{tm2tTf
> z%Q+O+4l@>wG>4;g#Ol@qQb)y))y%WH(RN@dmGiMCBbbp^mh%}k)A-
> uir@|=Ktft9j
> zFfzL&rUkA@up`xIfkpq5yK}IXjyO}ToCBNGN-
> GN6&?QK9!&80x&InV~m_cIHhEBn~
> zx$i8G6HTdD;lyxSK@eB)x)+?7&1}|G5h-
> QkSyW6q3Y88qD$X@Buw;1R&l6vxxzLZf
> zw%j?*T1H?!-A5%K3yM8y4oB<YN9N!C?sxV-
> 4RTwM1L^teU;o+!9<kXF@|clQIUj3s
> zMl-
> bPSy|3!)J)@RXP*kAShKp%+!izvY6YR3Lt5a91UpiV7FhIay}3+v7#vbc6@6k4
> zMI-
> 9yD22lgu&7mJupR>F{_4ELN~^9$?Nd2gLc$mcRZr~#YI92ElBFetN_JJGs46Ml
> znw&M2L()k{Cj*AqOV<t?ojRO0`kg15Mn#|0fF|Y!!#UW`>L~@EQc^r(rx^%hF
> W0Y4
> zOt<CEVFe*@WYNH|i$lviqe$#YbLiq*lL7$g<Bvb)zqaF!NjPhIfBy5I*SAwjm{O5
> h
> z4Tq{zr@P<zYg5CfcApBvS+n(>qlu13T3X<aEmG;Cnzkm_)mw+bA)y(mqEGChX
> vC&I
> z?(I7qc7XM%44{yOgfOOVHEN&ADW(h~q3Wq!Ky6N`T(StT`^eJSM|Mr+kW`=
> P$$+tZ
> z+3Y%;HhdzRQPC$Fc0a%kMtn*(cVyY+oW8HOfN3<w$8_yGM@u+vHHM@?
> WFWW$!+fGh
> z>`8OT$ZEK=lNX)S2}9@!_#ge~NBoVucsnsZdCW+uoR2jb!3>omf;nf`Oyg^3p9-
> TG
> zoN6FDP64G&D=RH<MS>lvICbC9l8YteX6!U0)pQgV8-
> aO}r5mB6kIvhtG7`;QT~2)O
> zz9Wx)DqRa~m1`u_R*5*pluGlZ^^;~wQDJN4v)(v$VboNLRLoeXl8U(q*5p%#G
> ^*4e
> zo!I#1P+Sp~K9!CVxkJNdK`48TCPhCcZQnUs>G8d9Itfc&sp+ZmI6KWD2dd$wV
> 2!h6
> z=uA(0#M`M@ONYw&Sd){Q!9*b;b!EAMXr}SCGu28R)Mk9mrYj#R16udUhNlIt
> v%rp2
> zoVsu5nGqA}X6!U0)pS&PV6e>6!tUs!^Y*DsI?g^y5EZ894$eN6t_3z{hcN=!DiN
> oc
> zQfa=l$ct^Rz&s_W7^g0bno5y$F4+B(fr_~Z*5p%#G^*4em19p~qz>$~(}3!^Cf
> &?H
> zG<&&zZDQW`ox}1$)buFQz-
> DXC<5{cnI6KW@jE^23kai|<MwX0?($mXGxSV*HaiR{D
> z^RXr)n9;8+HxSJ<zILWsse{^#PoXrMsuKER%4~RA;5rNJNX4o9hVsNTxfwgnNH
> ram
> z9vG~;RHcqSI&YuKq+{v2B9FqRS*Baf*{9OAz-D|HBh-
> 3o7f_p1D$N&XPt&BFwBwKt
> zYE7j`oX8A4835^CJn79DaYmuguPT{sRBlEzF^fHd5udsq65`A^anjGsHj4Z%h&C~
> G
> z`_75)05no+lNT&bKln$H*puckPNDJbfYeh;k4*Kn3zOTi*tq1;9J<c5=}>icrE+d*
> zGmWpEsaEQsHmBh7StiaXIMV{xSzt#hPTe;&n~!qmq+48%C5V=8!Hz^!ENaC^
> &M@f+
> zP?WBDYL?^s#2T_sl|t62_0%q)Hm6jYvQv(%4r)!MNUr$xWN;gh&3JOUAZVtL
> M&+Cl
> z*7{+%N28|I8;b2WzxfSD#X{mhGP5Tdn7w`H@V(u%(m9VR8kN&ha(0?ShNZ#
> Hr%JHU
> zbVhpegwXSBbiQ_|oR2k0Xol**v^Zmw$uz!prdp|k+62?n$dOocqzNLV1+KHej
> #Qkw
> zZ)lF<or5@T(rGhN)k7kxB2hQ3G!CgF>(f4!1!pl&ccNxF7FeCfK9#NoHWh$Tpt@
> 1b
> z=9Eeg_*0IoS|!7tQmH0tcTNVBSz7!WCxtXBb+d|%{pyq2R5C4f4&jbqPc$(5_B)
> 5i
> zc8uqGRM7}qR9VcSi)>9Qp-
> 9|k+DT8%9y=qO#dm~}$~my<XjKQM#ToHPNEtW<jXo8I
> z5R5803~i2%G)`R@k&09I4L#sBag0y^q>mz1>c&n^M1zMYgyL^Mrb02u)JUmti
> o};;
> zkRhFys4z6kvA__&U`weAe?C%x0+s%oj42fsMF4JaJqq|VHFT@mu~4gI@KdU
> EE_CX2
> z?p>bd4#hS)qbza?X;f}%gtC4Z?orXCk`B@hK}>tOer;m*_MOAe57SEL4610<tf;
> k^
> zL&l^rI*@cy+h^*jnsG&=l5~WT$~mw}NHY}aJ}dt3cqG_Z#vB=aDnuZdR<xU%
> =L8Vb
> zT#rb!KT>h(zM+Y`hC9dceE<93=Wjo5DsL4EcGL=;g-
> T3NnjIZjWEpPhK}EKdicbqe
> z0SeS2Lh)!yrFRZD_*5t|>sCGG&QTuDLPMw1qsbh!-
> s&Z!sWh!P7Y#dl@Dv6+3&WDg
> z|MjCgE_5IdHSKgZ=6$kvj_xOyE_W-
> _)8%c{Pmx^hPwSojj9^AxS<cxt8FOUxskHpL
> zc9cmhB7GVU`w@xuM=H0jPE+?>#6SeB$X+^iVMnTwbBf0k6rx$lvB#AbhXZd
> k1^ZJf
> zMu^6AQV!8P#w^!tDHWK%RebyxXNOUsG5~ex7$Yi<MOXqn^*aX((G0p%j?
> 09BRZ{^P
> zrj@$UMgiMX80<_9o?WOP({uC=9m5gLUTG-n#Juf0hvkE)#p-
> podI+_NhE|r<riL}U
> zC@9Wr2Nj!6Ey_7skpojI_sBIJ?Q|mNuT2*@Hv3e%9krI@X#{|gylHiJsB}?Hdw
> S<E
> zP6SAM`dTqE4TWJLX=nVXgRvdCQYy|H4c7DMqT`S{%Qag{1y!|*IMK-
> Hpr)A`b&ja$
> zuXvn&w80~G98#-
> f^A=Rf6Q`S=4C;^;n8i#XjVexRJ<!A)V2pgwZ|~nZwQIV82xTwV
> zuT4zazH@Z->6=asY&Op=fW(81WfBd|;V5bRFvA0Y07SJ-Nlz+APd-
> Xl<iM25J#tOP
> zH-kLTp?O_1f{PrReJWM5K8-
> NDZa&RjTHPHguBdP5iJm5ip&~%q)7OfTX{aEYME0jQ
> zKu4~Wit|RJo>BelEZ1x)6;#zK(z#N*gPLY))H$M}zvAh>tLumG@yM!GvUv+C<
> >4$e
> zlu(O`4$Uo)LK+oAMZ@j~xWR}|(PQb;!X|J^YXL{mYzj=*zH=~wC$v(eu;?Tm5a
> P7}
> z2bM`RG>2)@G<dv8G*LhO=}-
> 9&;zXTTVjV)Iip<*MG*Q~f;GA7k!=`qhN|mfnBQWr^
> zK>Cz9t?mdGsoc6cP0eF{W<-
> FrCsH{#tj=BzPf1*<=%ZMQh=YJ`7S~Lv9Dp{Nn&~#I
> zvs{CvR3OJFg{kchs#BwGj;J`w;T=D+YL#r>g39qYxuz$BIuu(Vg)}NRqibS!n_Ijn
> zIJItn47Z|6YY#!}<z~?)rrUDou!0b{5Wr^OaSmrkZ4NAxXlM@8q$x=noU`*sU#U
> p-
> zrgUIR<sP}FY7Cp%8%g2(wdo?qW}ixxtQQUdRruBUoTCzH7F3N`Z+x287~;gNX-
> }F#
> zo!!~f>F8f)IX$QdmQvyANFq+EMhBHMc8n1f$2vS!V0vWng3^6jt7P*QRE|f*fj
> vDL
> zls|n(V*yi0qjEFGCKd}%{CVOl&cYtdwdKyiI895DLmv59hkIYh$yp}R&>W^oBgS
> Z#
> zGgrKGQd-S<OsNA?D)-1WxkfW|mUv=0XV-
> L*W3x}CN>U#rNUs!|UEjMqg(E=P6RF&~
> zI!(n$)5jnwL+p%H&POF;aK&(Hn2$Q7oNgA^OsP0~G&%>ljjFSp9#mvYsqi$FC_
> -9K
> z2bD8+j1d*bMm(MsDD^ZuhB`X3YL#r>f-3T;R@0L~;p0AKs1(wu=u;Rc-
> ZmDhm<v=J
> z?;I7$!n;FM%N!2r9yKDCNi;NvF=@KRM;BV;j8}?bFsrd19hg$NN3Q84R~RRk^N
> dXw
> zIX3%Ls-
> &jL)w0qegHDzRkoH8XxU^}HCfZ@Ru_;6Bj8x7?CE^r3IHAU<iqyyHi8yW+
> z*G#E6do(y#vAJwik!3if2Nl^;Dm+akijdaRLFJ4cV??E69idjyjw7p9$>uGn9E=l6
> z_nJEy^bxQ}2b~2>A&tt-IBJ?QXZ<;v1^uAfc;{e{6QjVa_k@;-vo(h?X}Xg}X8<^P
> znHXU_2}~HizlpR3m3!ox7MXu`6dTo)iyWJ(ReY*Fs-
> $XIWDt*>ZW^$#BNf#c89bkA
> z9(_u-
> f<zxhDt!uDB{EJuv0{aAE$SApM>mUWrc{g^4GLB8*eK01wPL{ZpdwpJl}f~b
> zY7kQM70U@jIAg~cQR&z^iH;{Wolvz(Hg7={VN|8g$zX(zN`t^oA&ts;K6(>W+w
> UBs
> zb|-pF-
> RKbIqP0w%tvQTI<1K+ni&SXU7rRsUrF*MUP`O90$u*kMsjQJ)E^=(DR`IF!
> zsFJ$sm^=1Fc{N~RM=GaDY-
> +v;P#eT6Nc2&p(x<RhA|q6);tdX*)stWr#LeQGDOJ>m
> zJ)EehYID{sJ0v)y2Nl^;s#GF^sX<7W!HB^bJI07g$HpWYn4TMs%9?QxYS_Xqs75
> e`
> z)HxZz7DZF3VW(_H<vbs~397w!j<Khe72oHj3r%&hPR(IV8n3&0&uKmjBz1F#iX
> &7i
> z_sBKfdUcAl*wGp5-GaEtvDv3mCG|8)k=*sm6-
> 9uwCsHxO$Vh7`Wn(AzV#*LZBbD<}
> ziHwu~(m-8oaMq7H$fhpS&ElFVl@50{g_<I1mZ=q^VX=-
> xn<*6>qC^a+1|gX&Ga`mg
> zI<-
> esI<O{8!A9qUhAr%Zs)m`K3{fr>nRd!%RP?zL160TEoFnT<b+S&)VV$%i0MoIK
> zP^sJ_*PKS~JGjWP*{3>1$q114M5_LhcX*}@u`^ORpHn1?{B9Q4OsQg!x(DPtU
> XDbY
> zDHR+rOHH!%sZKhzM^tX$S&%O5s98{*MN+7WDN-
> <_Dh58vBT$uhjxOaOpoW^-n!{$&
> z7_;eLFDFf-
> QgOP}sDp2Mn#R}8K2=j0xD_v*y09bFrd4lsE=crIq|&FbvGA=^cl_Nf
> zt~sT0{+DTvs7{w?({e^sF33Sh*1rooY8F%nNmyM)96U<FjEWJi!~oU0bFy5dX)
> G!$
> z<~)nq>Px4N@!8X-
> Lgdbik&hUWs<rsNPEFKE<px5Z4gzKDIK#)y;+j(`=YN^zh^i@3
> zQ<<qaZm}aO=XL}VV_mdqv!FUc($sK-XH?A~7jpwu`_37ytSRbfc-
> pTy+#0{>Uu%pY
> z5lpG#)5q$0Dpa-LTc099X^!eFOtnJH4hd)3>d%2{OsUlQV)mlyOI>KytdLICjeJI&
> zMl~AsSpA?n<IaJu)7MCtw7<w<>ObuS-
> X@LVA7h?Q6{pzI^Hiud=|6SeAryv8wQAN0
> zXW#12foe>t)cIoeqUuXsXw|HcX~7o`BTl0#20qFoP#wN=Mk_wjU*zye*n?viR
> bRj-
> zs#WuZpblI8IZ%x!s+BI`V)m2Ms#zgNj{lMPrqz+i4>1;0>&_XaEc8FQdJikOT*uO?
> zul3UEhP7IEj=Q+lozt)O#y2xtf}Q5OPOQF^ORJ?-
> UxB`7QCAOr=OF%w)2Q5$|L9Fn
> zt<O25l!gAHvV!mBIu=!5>!sDws;@xbv#6_wzH<slqk8m9#sPrp?#_ARjW-
> JR3qJyk
> zskNx4$}g>^647C4MJcAn(rPLZ9crzP-#Lg-
> yolipQoVTb!kzk$*aXb|o%7*`A3Eem
> zYy!saoJBRw!qRFg5gnFRlwxWut)>#u;mWo8;DZky@se><1LpqD!QW60S0jad6
> axTE
> zAg`T8mF8k;mCBNKF0E2o($1w-
> Dofh=RJ6iL|LC7~0ALr6+&Ol}uRoUpOM#`pQeY|Y
> Ka0)zo_WuC{9xg=y
> 
> literal 0
> HcmV?d00001
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/ComponentName.c
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/ComponentName.c
> new file mode 100644
> index 0000000000..6ac28ab90b
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/ComponentName.c
> @@ -0,0 +1,159 @@
> +/** @file
> 
> +  Virtual Keyboard driver name.
> 
> +
> 
> +  Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "VirtualKeyboard.h"
> 
> +
> 
> +//
> 
> +// EFI Component Name Protocol
> 
> +//
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED
> EFI_COMPONENT_NAME_PROTOCOL gVirtualKeyboardComponentName = {
> 
> +  VirtualKeyboardComponentNameGetDriverName,
> 
> +  VirtualKeyboardComponentNameGetControllerName,
> 
> +  "eng"
> 
> +};
> 
> +
> 
> +//
> 
> +// EFI Component Name 2 Protocol
> 
> +//
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED
> EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2
> = {
> 
> +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)
> VirtualKeyboardComponentNameGetDriverName,
> 
> +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)
> VirtualKeyboardComponentNameGetControllerName,
> 
> +  "en"
> 
> +};
> 
> +
> 
> +//
> 
> +// Table of driver names
> 
> +//
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> mVirtualKeyboardDriverNameTable[] = {
> 
> +  {
> 
> +    "eng;en",
> 
> +    L"UEFI Virtual Keyboard Driver"
> 
> +  },
> 
> +  {
> 
> +    NULL,
> 
> +    NULL
> 
> +  }
> 
> +};
> 
> +
> 
> +//
> 
> +// Controller name string table
> 
> +//
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> mVirtualKeyboardControllerNameStringTable[] = {
> 
> +  {
> 
> +    "eng",
> 
> +    L"UEFI Virtual Keyboard Driver"
> 
> +  },
> 
> +  {
> 
> +    NULL,
> 
> +    NULL
> 
> +  }
> 
> +};
> 
> +
> 
> +/**
> 
> +  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
> 
> +
> 
> +  @param[in]  This              A pointer to the
> EFI_COMPONENT_NAME_PROTOCOL instance.
> 
> +  @param[in]  Language          A pointer to a three-character ISO 639-2
> language identifier.
> 
> +                                This is the language of the driver name that that the caller
> 
> +                                is requesting, and it must match one of the languages
> specified
> 
> +                                in SupportedLanguages.  The number of languages
> supported by a
> 
> +                                driver is up to the driver writer.
> 
> +  @param[out] DriverName        A pointer to the Unicode string to return.
> This Unicode string
> 
> +                                is the name of the driver specified by This in the language
> 
> +                                specified by Language.
> 
> +
> 
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
> This
> 
> +                                and the language specified by Language was returned
> 
> +                                in DriverName.
> 
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> 
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> 
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support the
> 
> +                                language specified by Language.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VirtualKeyboardComponentNameGetDriverName (
> 
> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
> 
> +  IN  CHAR8                       *Language,
> 
> +  OUT CHAR16                      **DriverName
> 
> +  )
> 
> +{
> 
> +  return LookupUnicodeString2 (
> 
> +           Language,
> 
> +           This->SupportedLanguages,
> 
> +           mVirtualKeyboardDriverNameTable,
> 
> +           DriverName,
> 
> +           (BOOLEAN)(This == &gVirtualKeyboardComponentName)
> 
> +           );
> 
> +}
> 
> +
> 
> +/**
> 
> +  Retrieves a Unicode string that is the user readable name of the controller
> 
> +  that is being managed by an EFI Driver.
> 
> +
> 
> +  @param[in]  This              A pointer to the
> EFI_COMPONENT_NAME_PROTOCOL instance.
> 
> +  @param[in]  ControllerHandle  The handle of a controller that the driver
> specified by
> 
> +                                This is managing.  This handle specifies the controller
> 
> +                                whose name is to be returned.
> 
> +  @param[in]  ChildHandle       The handle of the child controller to retrieve
> the name
> 
> +                                of.  This is an optional parameter that may be NULL.  It
> 
> +                                will be NULL for device drivers.  It will also be NULL
> 
> +                                for a bus drivers that wish to retrieve the name of the
> 
> +                                bus controller.  It will not be NULL for a bus driver
> 
> +                                that wishes to retrieve the name of a child controller.
> 
> +  @param[in]  Language          A pointer to a three character ISO 639-2
> language
> 
> +                                identifier.  This is the language of the controller name
> 
> +                                that the caller is requesting, and it must match one
> 
> +                                of the languages specified in SupportedLanguages.  The
> 
> +                                number of languages supported by a driver is up to the
> 
> +                                driver writer.
> 
> +  @param[out] ControllerName    A pointer to the Unicode string to return.
> This Unicode
> 
> +                                string is the name of the controller specified by
> 
> +                                ControllerHandle and ChildHandle in the language specified
> 
> +                                by Language, from the point of view of the driver specified
> 
> +                                by This.
> 
> +
> 
> +  @retval EFI_SUCCESS           The Unicode string for the user-readable name
> in the
> 
> +                                language specified by Language for the driver
> 
> +                                specified by This was returned in DriverName.
> 
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> 
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid EFI_HANDLE.
> 
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> 
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> 
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
> managing
> 
> +                                the controller specified by ControllerHandle and
> 
> +                                ChildHandle.
> 
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support the
> 
> +                                language specified by Language.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VirtualKeyboardComponentNameGetControllerName (
> 
> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
> 
> +  IN  EFI_HANDLE                  ControllerHandle,
> 
> +  IN  EFI_HANDLE                  ChildHandle, OPTIONAL
> 
> +  IN  CHAR8                       *Language,
> 
> +  OUT CHAR16                      **ControllerName
> 
> +  )
> 
> +{
> 
> +  //
> 
> +  // ChildHandle must be NULL for a Device Driver
> 
> +  //
> 
> +  if (ChildHandle != NULL) {
> 
> +    return EFI_UNSUPPORTED;
> 
> +  }
> 
> +  return LookupUnicodeString2 (
> 
> +           Language,
> 
> +           This->SupportedLanguages,
> 
> +           mVirtualKeyboardControllerNameStringTable,
> 
> +           ControllerName,
> 
> +           (BOOLEAN)(This == &gVirtualKeyboardComponentName)
> 
> +           );
> 
> +}
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/ComponentName.h
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/ComponentName.h
> new file mode 100644
> index 0000000000..327ce9f9cb
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/ComponentName.h
> @@ -0,0 +1,95 @@
> +/** @file
> 
> +  Header file for Virtual Keyboard driver name.
> 
> +
> 
> +  Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#ifndef _VIRTUAL_KEYBOARD_COMPONENT_NAME_H_
> 
> +#define _VIRTUAL_KEYBOARD_COMPONENT_NAME_H_
> 
> +
> 
> +#include <Uefi.h>
> 
> +#include <Protocol/ComponentName.h>
> 
> +#include <Protocol/ComponentName2.h>
> 
> +
> 
> +/**
> 
> +  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
> 
> +
> 
> +  @param[in]  This              A pointer to the
> EFI_COMPONENT_NAME_PROTOCOL instance.
> 
> +  @param[in]  Language          A pointer to a three-character ISO 639-2
> language identifier.
> 
> +                                This is the language of the driver name that that the caller
> 
> +                                is requesting, and it must match one of the languages
> specified
> 
> +                                in SupportedLanguages.  The number of languages
> supported by a
> 
> +                                driver is up to the driver writer.
> 
> +  @param[out] DriverName        A pointer to the Unicode string to return.
> This Unicode string
> 
> +                                is the name of the driver specified by This in the language
> 
> +                                specified by Language.
> 
> +
> 
> +  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
> This
> 
> +                                and the language specified by Language was returned
> 
> +                                in DriverName.
> 
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> 
> +  @retval EFI_INVALID_PARAMETER DriverName is NULL.
> 
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support the
> 
> +                                language specified by Language.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VirtualKeyboardComponentNameGetDriverName (
> 
> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
> 
> +  IN  CHAR8                       *Language,
> 
> +  OUT CHAR16                      **DriverName
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Retrieves a Unicode string that is the user readable name of the controller
> 
> +  that is being managed by an EFI Driver.
> 
> +
> 
> +  @param[in]  This              A pointer to the
> EFI_COMPONENT_NAME_PROTOCOL instance.
> 
> +  @param[in]  ControllerHandle  The handle of a controller that the driver
> specified by
> 
> +                                This is managing.  This handle specifies the controller
> 
> +                                whose name is to be returned.
> 
> +  @param[in]  ChildHandle       The handle of the child controller to retrieve
> the name
> 
> +                                of.  This is an optional parameter that may be NULL.  It
> 
> +                                will be NULL for device drivers.  It will also be NULL
> 
> +                                for a bus drivers that wish to retrieve the name of the
> 
> +                                bus controller.  It will not be NULL for a bus driver
> 
> +                                that wishes to retrieve the name of a child controller.
> 
> +  @param[in]  Language          A pointer to a three character ISO 639-2
> language
> 
> +                                identifier.  This is the language of the controller name
> 
> +                                that the caller is requesting, and it must match one
> 
> +                                of the languages specified in SupportedLanguages.  The
> 
> +                                number of languages supported by a driver is up to the
> 
> +                                driver writer.
> 
> +  @param[out] ControllerName    A pointer to the Unicode string to return.
> This Unicode
> 
> +                                string is the name of the controller specified by
> 
> +                                ControllerHandle and ChildHandle in the language specified
> 
> +                                by Language, from the point of view of the driver specified
> 
> +                                by This.
> 
> +
> 
> +  @retval EFI_SUCCESS           The Unicode string for the user-readable name
> in the
> 
> +                                language specified by Language for the driver
> 
> +                                specified by This was returned in DriverName.
> 
> +  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
> 
> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a
> valid EFI_HANDLE.
> 
> +  @retval EFI_INVALID_PARAMETER Language is NULL.
> 
> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
> 
> +  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
> managing
> 
> +                                the controller specified by ControllerHandle and
> 
> +                                ChildHandle.
> 
> +  @retval EFI_UNSUPPORTED       The driver specified by This does not
> support the
> 
> +                                language specified by Language.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VirtualKeyboardComponentNameGetControllerName (
> 
> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
> 
> +  IN  EFI_HANDLE                  ControllerHandle,
> 
> +  IN  EFI_HANDLE                  ChildHandle, OPTIONAL
> 
> +  IN  CHAR8                       *Language,
> 
> +  OUT CHAR16                      **ControllerName
> 
> +  );
> 
> +#endif
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/DigitKeyboard.bmp
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/DigitKeyboard.bmp
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..b64d62034817e7407120ee218
> 1c935e07bef5a8c
> GIT binary patch
> literal 330454
> zcmeHwF|TDua^71RHeg2%9gwMIknzxwG@t_+B;Y`al<6mM04EB$7&vieOuT
> ^=P(MH>
> zASl=wEf~mvu!ICbgaASUK@Ok=L}3#x$i;9>e|#U`$C~Qy>N@B2x%b@r`eOI7
> x=(fW
> z*I!jvoj&)xH~;0oee&=A_04ymxA6b}g#Z7?-?+K?zxeNuZvF#)-
> rW4}@2}rBzW?$6
> z=4Uc68JG-A1||b1Vc_P5(>#0j>^H9KgB4i@53;~xqPi~6&($1-
> fn!GdM3s*Z$JN7!
> z5AAtnk&LlS$hS2IhVv*cNK=FzYJtZ@bwO^OP%nsqV@CT@REv^pRryCh`cc<
> wOHp+V
> z4p9)Q_uqfNy0m;J%g$}h83OH?Mp#*ohV7WBj>gi&a~%vEGujuS%BR(qW~S!
> A-HTA2
> zEIf#+wX{Y3Fg0t=$sA`UI%Z@UfK!|d3}fJ!(VjuID4WL0v*wVWS#yT%t7V2V@x
> ILB
> z)Se6+m4RbMdj?fpMiyP2HD}hGvu@B#yq^`|oP07cjDZ!={^-
> %87cX9X^UXKIKoo{D
> zs1{X~Sb5f*S#ydQJY`2F-
> cN~V&NUg>kAW4@{^ZG%Z@>Na(@#G=BdWNDEWJ8w&a656
> z1#`mkid~qndNC?X_v>}&C$rAQcrguhMYMnX@yDn+AAImZdXmM8T~uSEF6
> sR)s>SOZ
> zF@UIs5CT*49fA=)S!&~$k+pOctM!Kj@5LEOW}Vfn9(Lf;Xn*s~H^2JoD?C_x_u
> Y5*
> zTT~a-*Z@m<zl&-=LITS~HG~kDx_>oi2y-
> +NcqzVg%*cu{54<|i1s7y0nRN#8d=OJh
> zqx}RA*1${`)!5KVdcTTFNIv}VLmdC|pN~HJNMk9i3kjlfrq(rKYSx@})ZLC+=fF(7
> zueN*<12<59!9$Z-
> =OR3~2xK*n(n8gpe6UvL%c^pwvx+uA6=2IuSJg>+zlur*x7Qq*
> zDg_{Hfh4MO$ci4Anl)zyZ_9_csINwr)4Ag2a{jJiL~BD|v7@=PAlgg6zV_N{&!0bk
> z`SRuC$B)aa>w2mT2dJpOZm!m-
> r1z_+S~iFGw?Gorkm+FRBsFIUSQ@E@PtaNVa3Gkx
> zDTlB`<rJ>Fndj}AG+P_`x_yn+1<_vm_r3St!&}l{e);8t2M@}t>w2mT2dJozxd^6
> w
> zmbIcJCcR%pwQkibMzuf^)e3{<5SUt3b4p7m>#2rM&{_KMWKiuy4q=JPDO`8c
> GIM|A
> z)`q@rUt@Jaw3puJ<D-EO)-
> Xkt;Q$r&F>ux#QbDdtXRYXgsabPY@V0!2i~4T7JN+wb
> zF6ZwWM$DR1hOzVO9uL+qML92ex_i)J+t^Hczlusz@A`cXW@&*WD#6$yz|^
> ccTL?^#
> zbx~i9ET?nD%`|OSrP$igSL|pmEr@pK;5{C!VTvll0V?V{Y#W<N?^jW2>REF{#R-
> LK
> z_ynD$4+Zv(H*UWA>gL;TEC2iQ%NsmR4iqq|cnwj8D}qB<qH+q?-K-
> E)>nfk4AG4>1
> zz0#M=I@jm=Ale;GdP~~%Z){d64Ny^k<D_nQ()(3Z&eVR*7D%ERGA~SxIOn|
> a#vAw@
> zt}-9sx4PbW=N%w*k45q8#SXqzh`*n!hELF0`cP8`C1uu}fYR-
> k<bqfzBkGtv@hWt+
> zwV}83d2kEm9u#1aLqUIj!1ZrzYC0<fsHnDaQa3#5{VFPFYQJU+BvB2S7pBJ59Q
> <*l
> zDkwao{p_>PSbU(s@?yUubl)06|MSm3Z@npLqb4JlJ}g1L_S((!=ii-
> n%A?DB@7=t3
> z@!h4OO#Wcz$&()xXo@B42aV!%U!uya<!W>+Gl6`}3R9vAmS8WnHuTlFwY88
> S+ATl4
> zb=8fky|huT0t--4f8(TXc+&e-
> RL<0X%@#<a8Zs|T?O$_Bq_~?=Wbrg@OHiqAd#d3R
> zbe2A})+h%x2MQ`Xjhg!XBRJKo4?nzl`SQm7a)CowqH+q?-
> 7H;D?NN5e(O2>j1mLld
> zs^H7c)`q@rUt@Jav|E;Tda#BmstgCHsBf`tmy_PFqS`)t(n1R)Q6-
> JUYA|)~nq%uv
> z43<}`;S+S0J}hU6YYz1F6s|nL(Aviz-{=x+luA$)c8Mxj!u4G$T~O^&d0~#P>YSyM
> zcmywrp|zo}&%bU(L9|=yc6zXeDI6X)15{M7*tW|_?^jW6pFL@z1(K+eMq)LXI
> (f}u
> zWbr{9UyWS!`(M@Y2|7z3mXvgB4u(iawZ+=O<F#+Txw-
> xB>U&LhC~^o(R8HZ#o0hsj
> zR#K-
> BXrB1eI$*60eciss>VjyO<M?0=#k}=UU79O|D#HOP>aUn67?SjU6;)t%?4=e+
> zq8c(6Or5Icu)J`ys>m?VT3-ZJmsky-ptJO0X;$^b9ZsC4)NI+o38(tzn>wlN5SFN%
> z!gV(tv90F1)ZVf-uzww})`q@rUt@Jaw96?wy(LZiRfYpp)EBlPLel$HR6_t{jI=-!
> zRmMVB2c}L^bNHkdJ5|+&&@Skla|gKjwgHNd&NlX~0uFRhUyUrMbH&YWU{
> YaSYEK&9
> zqP7lLYeQeLqq(#o+T{iJB9Z!s2vvpyRMa0bwTvXaUqvM&dkZa)L^Wh~m>O4e
> +(y(f
> znT16!4LIP4wbmu4$!0Ztg3i*1rCA+d;&ToM^6Q%NEdjhbpvP<c{>NH#2uoB>;k
> uip
> z3+_WtYeQeRud%uy+U57*f7er%AygR-
> P*LAn*e)l%Uq!Wj_N0XtNTNy_iPd0gT+L}c
> zB4f>IUFDg&b+v?F4WFR1^kHdpQO#*7+p`UI>?1gbuten)uDe;f;6C)UHuQD-
> 8mkMU
> z{WN~BG8~|y{#a~D?^jWcMG{zRfh4M6VEz(J?O$^M2ZtFQd(gzAHv4k4dq)yA
> >Nvlj
> zQ{|H1;qXbCUTM=8IHdqh7xmT1aynPstg?FbovjUh#g69Ef@t5v>9~#k^{;<z-
> $kf0
> z9H659SZqn}S5b{c5?E`2B&uLw{t`@`q~-t-&og}fR-
> S5j7ShwX@(&egP1W!TI!hnQ
> zl!VsN<renMPk$=K?*u99+Z$eHzn-
> V@5uARL)FCWUIfd(PzC!4|X|y)<b^98t3!;4w
> z=g*q6n$=c_(u1qb+JP{2s+wb`-6AjDpk=&kc9sP^0sF1rYQ7mD9sOe-
> _}+#m8PyXR
> z#3emX<M~H*$-
> ypBIfd(Pim`hov^Mm0`x>hYqJ575m^EiLtE~{F2UnZ517Ygk*BtvO
> zOs5n}l8TJgRBf@E_)16b7Pzl;TwV!wq0_v|rX}tE$gK^1l`gi63Zi`v@6VdEn$=c_
> z&YEN6xhI$LUOI$d|D&W-YYz0?mo~AQuG%-
> *9Ly4xQ@HMC>4N*v)7sG2?Q5(qi1t1F
> zK5NcuR$C!@)S9DjV<eQ{+pH!-1D9^lGTvqCl!Aj@qH+q?-
> 8?1p$C<0Op|9K5SX~h9
> zdw6G5%>nW)@RSBi0WVawoL=Q>3yei$TOmqRi%hkYVQR#)wU+rk`dhwg^_
> M=}169|i
> zgIA(*3fJB2(sh*ztqpzMzQ*c;Xy3!p2dO!3X-V%_xpJnqH%p3Wvjvi<w$BR-
> Fg0t=
> z5GH#@TwbY0meaZ7W{<7wyx!W-
> SL|pmEr|9#JY6Q#D#HOP=?{dL^nMl9Ko~StQpEli
> zNTM171E%g@%~3#gg&`c%h?}b#Sx)DQn*)ixAXBXkeZ`LE(t>E;!+m8!tuh>-
> lKwz=
> zN$<B%4MYM{B}KH~0!dUuFu>HTISQ~s7{W1)INPnra%!_V8Mp!lP8{uz9zEjkg
> vQim
> zPz}rgt#s}{W>C2yE1F4)WSOXjumMxE=7`u63a5#z6E0{@H5q6!aN=lBCe#e7Az
> 7A2
> zX3ZfF2dFvCKpk`;6Ip|%T43gws1__>s!j&d44gRHXU(a4hW~I``4Sy_@E8B9qu5
> Cg
> z4ynK}wd$M`pgY>76UTdU`Nu?+1V7a#1B)0qakS5x)Adf0BH5t_XU!2Ip>X1O53
> &4k
> z@tCN7z&EAIz&Hj@9PP=3nn5)r%hJevwniR6`#k52+go`{nRw4zo0^k>BQtQ~X
> rDEw
> z8w^Q`WQQIcQh{g95v!*aPP_|GySO>qWZ)GBP8{vYgqlG$B+Jfoj-
> _$doLBb7=^B}M
> zKOLGm(_~;z22LF9v*vW2nWRW|=s{aLR?D;Ih}F{yC*FmpUEG{)GVlrm$Bgz2s
> @0jb
> z9C)bjb6#;zqCu|8MXl(8srh|Qg7V=inRp*Q=`=VQI12;EjP?ww6*;vvWY!!qb60c
> T
> ze*5jS1moV5VqJ`^LoM)_sP^{7w0}PtIA*jbQMC%livCQ^NuoM&APLoqRhL8V
> YR<D~
> z&rZCK(@ckTvF03VfyYF38js9b?i&NgjP{8tABW=V{rBH5YsjLWhYug#)g1g6hEdP
> *
> zKn|{nwTLQ}owG0Sn5Yi!$_ej688~LNPgMDED!JNHc35ys&0%7mKPLl|fyuyRU
> ^1{D
> z1Gn!G>}P&jo(xO|CIgd!$$%KRt2uZQl|OS`gl73{?Fg_Zs=OB_SCgwe19{Dhh^w
> bh
> zpDy~U<oL>15zEeP&4Cm09=jk-
> 1=pb#I8o(8XmT~V$}^DHTohM$<!s2O3s0!7ui&sG
> zvh2*?&*?_O4hpRII~d+%a-
> z!9H@Uh$T%q6$IYnd`yE_RCned24u)tY!GLbM^XJ)KC
> zqm!#WxO)El`OB9tA3uJaH@;f)(mgn9&cNa|YtHI@v~A#}@4{`XUp9JjmFFwZ)r
> TK`
> zh<~i>qmMqy8(*!NN40v26$6u~2BzB#NTM1z>CsGKf%BY`iG<NQ$#@?<ZO7h
> 3)gj1S
> zzI3keR~}!yc!7T%@~yYtGRxXUylAcl=Iji)<Z9rgM>B;5&YF{ngwZ<PU1-
> 0veDA&Y
> zkRCqx-~-
> zk%j@uVQLQt(anwbl(mx1%v=hbaufKk>$7>hu!GSqDvk}PEz)6p03JY9Y
> zb9P!v#x09<E;Qa9y(~N5eDlpa@4VwKWtvIGE|e>*?#YuUcv6J2oLuR4wG3B$e
> #L)p
> z{xn~nWKe1CCwsiM2$kUNEhJH8_E%CTvm&BO8oWd`EHF`X_FkD>fr%uK5|W
> WMYPzJI
> zE~=9A*Is)KH>P+P^5DUP@@m{O3RTk1ShX%!nhuAGPe1)s&0U2Is)N^@lRa
> MRa+Um&
> zeyl^gs5o7`vld;=;3uj@W-
> m(_3p_y0>2j9wRZAxsS*_ta^><NKIpN(rp3+pW2A#=O
> zbWtVkj8$8N3T5XwPqFy?iszi;pptjqeDlq(zWNG>=Xc+ISDkwZT@NN}PW5^6Y
> QSAo
> zv>a@!rI#{LiE63k3)05|XU)k(!f2gtyjO$hjW^yvl2~!nNy6`<O4=E#wg?sO-M{|&
> z>vc~cE$2vY@hTRficJl?x)c?^ZgO80S{?#f6`+g1iz-=j0x-NJNKU9C?4shR?xcBz
> zDh$_2RC${hr-=p5nq!>4#eoQOW2qx{<J}@*sp0K1ey;ddr-
> SD1au?N|;z|Fz2o;VN
> zpMU;2e(l5(xI*rFa}g@bmrIA;rXAarm!jgy84n~^P^2N-
> QGo<m+e4@#Oma04PZfsi
> zB&vav9?cXMIBSk^`WF9mvy_?VH@fj|k?7qgmYo&n9GloI3@3L{Iej!YW{c8b*
> ^@zK
> zpJMUbdQ0F6x$DggDy_xxzZ8s&WQ0YiV34;nEAC?KD!RbBs5VBC1yhx)2)n2_s
> %mgu
> zXBCF)B&v1xFJcrHIBSk^`WB~kvy_=<Q_WfNeU8=@gG}y1yO539!kTKy8C3i_e
> 05D0
> zKN4c105yY3E855sQFS3DQ8_Sryr#7;6|~Hj(B;ZOS_+`6Uj^1h#Zg`3d4(zr*GW`)
> zn-
> `~v1vYBVMJ&a+tJ+LP7RPQ`btWYUVHcG}!Z+5KP`4Bu*o;ATQ2{?J*pJ1zLKY!`
> zkU@pv%$-
> 9HIbEVKT@n@71;$p8<A%UUz!EQIP&qK$AFr)LW#80xkhE|c`HX+}Q)m8+
> zru*&JDpwX2*Cj9#GIQbO(ykiTQoh|!RGRDh1T1jY9J6J%csP?1G*va;brr%EB*E
> Ai
> zWET~HwbDZ{X>iFdxg}>%4F?9y+qu$;hL9HH;anN69GLBo*R;%*P(@|4yMv^F
> >89;j
> zbHvr92ndE*bIeZJ=r?Q~`!R;SSlxwIX(N)>aKN*(IJt`o`mg}w_#M?>{NfiYepAQ+
> za{#K%3@QP0_BS@Gc-WalMP-
> t<5e$Y0c=D)97#kn2twWWmISwjuW{&z!vx>0lL5qr`
> z9EP&#=CTU>Rc@WVt1w(AQCTBbCS!q%YtFyAxxw#;d|UkQf4<7if4x=s`sU`}n
> |_Uz
> z@^9YU{OacB#m&uszEdl8?ylVYcQff9px3#p+N?%aRTG`Cso!YVtm}l0*?rxl-
> BBA+
> zfg+|)u(a`uXF`qf&`n7X5?GgkMGCDrL4OhzEsVkz;NhhVs*-_?kJr|rve`Y!PmtZ+
> zqMT+GVU;V3ildz6vgzh>3gkBbS15?e8L2i|(A>jDG*#j_wcDpUI=a%$h0_|I_-
> RJl
> zkE`|-$Etk|YzbK4u$qG^WGl?@nnQ!Cb>Gz-
> e5%o8JFAgp6|78xbztWd>wd=Bw2Nxp
> zq}@>)QGqL_2N0#u?oJvg#CYhME>~0|uwbqgmuze}If-
> g4Hiw~XW>A$p?EROOs;Icv
> zkomBRr0?SFZr9~BOQO)zMa5CpY*lu1l{$;c4pEgx%ASEWhX_@^SaVdJ)K5Xh>
> eMyo
> z|Gdfpk1Hq$>K|Tnc*wD3?K=q7XtJHv$g&EO89U%rq`tbwWvw`yc2O;xEUmo}
> 6}V!0
> zAXoN&C=KBi#TXA=)8$I2UNJqQq1Y&e3@VKxY1<LWU`xoLDq%3YtiFk8fl+@I)
> %~eC
> zAUt1o$W`g1vd2BRD;26WL6yX2Ir_q#h}emIXtz0RYGBoV3B&bZfs4;M&V-t-
> CJe7R
> zKe>IdrkeKsyo&3VP>pw|O!8R89r0S;QX$T!EmTWqS*pJdm8A<aR>O8F66(izIB
> $z9
> zi)vI-cdM{dI5~q#Lq@@q!IqFg<<`iiDnRvW+}Q%7{wgZX2(=_X-4lgyI!z(5LKhX4
> zWwRx?xms#WGTn!4MAb54`v=w>F2O!G)9<0H!q}-
> PpTFj?Cg>b;Ni|22Sn|5MC(fqT
> zcn6Hubh_uTanVu^`q!ZnKSZc_-
> 2M<U#>07ATv=4fq!lnzy=13wat4)#jDjbFEg^%d
> zx>6=EIJ9~-?recke-+hzt2y8>Q+CKzOgOLZT64O_wVb6l=~&=^bB@0C-
> }Twrj^`Y1
> zj*Or4I&n6w?n1z*+PBBBjgS7;p;Gc7!dY{`L(7AfE6K;NIeNTSjlj55%WMf%u5=s4
> z=L_~{>)twfq5xW_Sp{}_RDhwgLF@0T5>-
> q%uXf9V=CXf&u=<dqJm=83b&8eww5@8t
> ziyRBwRCE5#%?)mh^u7My-
> rW4#yE!lKoO6eK%zxKq_v+k7t2x!Mts?Js#w;;aRC9yN
> zBBPSJ1MFt8%?v8(kAf$IEg^%-t#Ny^1xEc<RQI#yfD<kpM@siQs-
> %ltWt_5W&Cz|O
> zEj5zQQ*-
> RuhBfE=7s>9}V$H!N+pik6;$7+cd(Hu++Mq{xwsz;@0soyfXAz0Y;w_<?
> z-
> JSBH88gbxe%Y*|Vo2ji1N~%8cBhvBo6{^Ip{I+Aqk>s@$;}n$3x<ZMN5ayYqdFi#
> zr$pVW+Lr)SOr!?D#A9=d?kmf&de@|CKUh95VS#JTIVv61YD3eiIrevNST}4T`px
> w3
> z=iKX>)AeLhA<psDU8vnaAvsY}EylwcGpLeDD~U>KZtb?2K_&fB@MN$hWKd~
> !ql6Y1
> z^;c2d=b97z%SGfW<C@mvFBKEj1XT%`WqGkZ>a;Znog8j8=`wwRQ?=hkjs>o
> %Ir`m9
> z9aqYk^la^an1^qyQT7p>t2wevP5ea3`d@{GAF7t(x+PTOy{cTUVM|Y(O<Sn8%
> $OOw
> z4wa=VGfQ44#>07ATv=43lDb1~r*Luxm4=LhCxa~^gUYROd$R>b{Z&-
> =x#oZw=6;+a
> z#1aK^m2pb`+1j7~`Jd|)L_u%=&<pOW&Nc+uy2_e^67+X}_jfYeMUDk7t~q+D
> W=lso
> zlWGqB4guw|;9%5IYR;&vAR^*yTHS>RIt|}RScl4Pi?P6BJa!ja45d8WeOzWak$P
> Gl
> zl!6sT!Lv52au?MoBsL7HNNi^n)s~vmT?LaR@A#o?!AS0+qNZJGRkm|g71XJzA!
> wBC
> zgiKT#5(xR4gLepYCP8sf!GZC(=0L#?v}Yb&Le2Tz-
> ~HX^&!5wB0GOAsz*E$mE)J`p
> zn&u8s`#xLiMzMvMkz0|@5Ua*JE@dol(OHMeZi_9mmt$i*F;^DVaQ6|aox;g2
> 4>~nA
> zN5QKax1C*7qmWovS^!nKiptg;jIst>vhs9y71D$$D6dA90cPiFA!omZp;5LIGP#
> QF
> z@M^c_WQ<UUVBE8{{P0DZSYV^(SSAXSdIDyDLzA`Q5AKxhIp?k~_1{@@QZ%
> hoYVAL|
> zyP6wpBtTv_Z);SHCy%O|gjxXNez$hp%y1?BA@F1^5W1*_AaSGxczCIbDpPa#
> g|~8{
> z@^rb1mL{M=xr#7@3Ip9@(G2Et%J?S!v(G-$tIC4G?{jc4*!9_(0~0hapymL*-
> UiSY
> zFBF#69KMcV-!qVL{dy_M;!`+V<-
> Y5e8(Ts(vP$JLiaG1*pRGve)Gbu2r%Mi8hsx5G
> zoG7Ul<B7SlsD`_b`0W%<Zh6qDu{i`@)w1jCqDuNDsm8j|dhJ)(s;Kfchu;<GC!Uz
> W
> zvZGY5V@VAHpREao6EdhUq@*I4%PH&aFP2RLP{F}dsq(jUh|1ZiHe2ry*hgp8f
> n_I6
> zskWC21ADN*HRl{6aBr{u@V)-
> +<>WbsY8Y#uq_MoHn%PT!@h*<aW;L=(H5bBun&oX6
> zEN4+q3)S*@mW^14O0Xd;o3E!G<Ket5t}LqI?jvwJg_AR=G-L=oSqp?Ns-
> 8m@T(_yW
> zykEB<tEgCWY>AMpH=~Hgex<-l0^?OmOHEj?NUS^@Rh2u-k`@So-
> ;G#2l!>Zp%5@H`
> zInMH~O)PMI&54mEYfkl?1IxCc&6*Qa-MMOSw&EOL-
> Gy#jbS7JPImTmmp@ZR?)eN){
> zOGO>e9B}jJ=E|eez@_jwuLYDL3e$BxXl-
> tnx1V!t8kX#8j&L%|R?j)op&(5(<pn2H
> zxyn~U&1mORrxRQ;3{Hkb<%VBV6AMh#9Qf)`i*~USH>;6V4q2KNx`f0@qJ^q!
> c7=lC
> zy>)9PHd?5p0AU4yU`Wgo=gpuR>ppu2*}8+zpb~FO;W?LqK$(h#E~>y6t1rcnaJ
> 7pH
> zI!TH&S5iNqE`tiwt)`_MDDZ(mROQ&K>A?bL&AAPLd<Z9<4};yvDixB(7pd8EPC2
> 9P
> z$?U>KQ&*LdQ2C%8SHTkQEL(Y<*fOYwxKBjkhTA@Xw-
> iavppx=Bcot7^XRKKubWv43
> zvZeDc|MD-(FC{Fb3@Yd(DYBMV46(zzTv2%oIc}_-
> y(JTs8+c7kEbu~VPRm8z{$yk&
> z<F|DF7hil~|A}V%_%=wTEmWobfjwAbOjiq)9km^geQ*RwX!2=^oyE!-
> RIA;`<&@_N
> z_FEWE&Y;qejqoz(F3#0OwcUNr!k_%fpFDp2SSzgxT~rvAq{!M|F~knfpn|?z@
> 0O;W
> zy(JUXmRSxy77ILl&1pF&*`JK8Wc-
> %?{Q1v+jy;EdRU6*K<0kd<&p&U0Y@sUc5A4Aj
> zTX@*tLS;v7#KU`cJ+LQf@lAXN)oS-)IVgHO*w|%u<qRroWD9R{To-
> B=)fO1lvGibY
> zdj%4@sGyVdprv%h5Ia1B3i{Pmuj{n4w`8JPXa6EbVS%&e+<HG5zol1IYLK_w&
> coev
> z99iYn(*D36rLJ;b_GEV9Mm)S_*Do~lfKh#ER3I~`R=bbOapxRO9S9jzcK8<Fj(pC
> +
> zy7;|&>tzd&kl`xnK}+dIIfDvQY;l|$n*mHzZs0XFvA|h#ZX+QX@-63g)42<`R=l_D
> zuj>aYe!BO^gx5l4!LLKYQ2?Xt&gW@*O~{pNJ7WeFEN=nE>0W>Rb^Zwt+&;u
> dFX(4b
> z*;TB7cM;#`U|sr!lh!lR3|C1HT1q#{8B~~Jh2vU7GJuJyW#J0?vA|h#ZX+QX@-
> 3fZ
> zcqX8v(~9?&{bWC2*bk?B^ytxx7cY=U&;H&TurWUg39+61oFl(D#>%s+G+Q2&
> LQ=5)
> zlB~*1qR^kT)<u;Jq^_FIHqcb9ZWZb-
> Dy$A`>`n@WBo7(23@X^kpi1iGQ6&vtq8ezQ
> zHRm=Gk|E!6ay~0C?ppB<J6k@jpdNV6*#Zw^TL^>x7FWTLQJ275>ygo}sDgRp
> rFBuY
> z0@(F;y{w3Wrp`ID<~SN%Gxi;?(t~c`H8ruoS#xfEjjglAu}iaQH#cO$bGXh#m8b
> MV
> zxyl52CYW&&(_vK)NH;!P!@S*3-
> a%c>qz5yMC3U)xpg>efgO{j=1s<>FWIU7CNk$fe
> zeTxGzJP%2cwP?r*l#^VY0EwMqqOxqna+j-
> 2kSBv#&usAo5}#JV0pKpGcu_lDO`^&$
> zmek2Cgs74RFHsE(JWS2WIAn!RGO{+-oTb2$sFs@Ds6SEV37lNr6Rrm4^$cT-
> tAUdq
> z%@h`xt2r6Aj;WK(4YTIJeMzoP?C6OqPx$0&I9CI6b_N?gIB?RVnZg2ZYtGwmzn
> $UZ
> z;&iYs`mnpeQ`Ve3s#6j^QRUg5T-
> __KHYNvU{Vr*WtA`ICYSc9eSl3<6dG_pCmyb(S
> zz`9s-
> x(nPGR*T5VqgrHkqw++RCvb9guejQn98@&Aq$#eRK7FcD*Cb$FcQpt9#d1+)
> zyR2M_0@fl2s_X;{+!$6#T9%?pn%$^2QRNAoT-
> `&ikQ|150_w`RLVCWY(+<|cf@5k9
> z6Z8Bz8JG-
> A1||cOf&Cb`{XS<u^V9NVU@|Znm<&t?#K2w6!Qn1A`o)(pR`wv^p;oMa
> znyclrwbRTS&oWWP{Mf6LE6YYKPp)Eq?A43l>L6d~=z$nB{FcXke1QOVZfnkufB
> a+X
> zlNGYc4*a=d_)bF<ToYB7;mK8(A}LI+L`7GaTy-
> gug19<J!Qtx*Dm(AL|Nh1o8d!F2
> zYmOGZMPMP^VquT56IGto$<^d4&p=*t#??};Hm3IB!|A~xW?^d9oP0ct)1137
> &*kK5
> za+PNwuX*IS8j{@y8X;Fh48qi`Ir%6Zr+MUfAGgXemL^wu9w%4V!PSuLKF|o`Y
> KTFY
> znl&dMrQ<YbZpd>vxtd(%8OUoMIj)9e_kl*p)ewU)HET{jO2=s)Io`*ua*U<PRi4
> Mm
> z)pc++B)bnZ!nhh@5T?#rb2k2VZzjIxF3hk*oypbYD$hV(bH>$Du7+gyfkx=TAqH
> XU
> z+%;#*I?9q&`ZgKwrKv?d<-
> BoE5>;$u_|=IjPwC`pa+PNwugSRDk`?zDI}jC2ownxe
> z!G~<3N|e4$<_3(FofSekZ`_ka6&o3Tb)w2sdQDtq0=~Mrl5|}YSBq{%shnhqYU
> C>8
> zkyGjnL<Li`=G^-FP&H>oTz7|L0{@zFgIjNxA1b&}L315fNf=TK08}sKQDKTjNelYb
> z88e-ER2gfdbk?C-%9|xQgPf@Bs3XV&QNh%#Ik%CpC6o{pnP{>)al8+YvSh-
> DQCa+_
> zl!u^7`ZvF>JgVf>vD1fpa0{wDOVrGBwbb$!{dK7J=8dT0U^xBNfv8|=)|}h8-
> 4aR&
> zfu*q@$NTV@8lJJ1u6K)m%vEU_i`8c-
> lclv*PaYM(EQL|(!$=E>?LQ4FJ7Y%9qYA9a
> zr?C)NaF-ULDm}8I#{sA|iE4%MU55-r1yd)iId8uC=2u^R_3gLce)Q2t8HS!bc>?9`
> z=YtPEptb70>_*liR3Co$VHXb+zWnmbx88cI8dL0yQDHf6yz#~&uE@a0AAfA&y
> ?pud
> z@#Dw1RAr`w7o&pyBCZIj{0TesEa8<fT+dFZN>?I~+|)sHCsd&8wbx#I{`|T1Blg
> P~
> zJt#bg>IV-
> V0AWB&_0l4)V4;keYL9?fuJTS?gsKXl?9{duB%AB1<hV|vDlMP4XCNw=
> znl)!hB`gz_g3Ai0uQ~6%_uh*aFDwSh$<&V6-
> (we+dj%7nx8_uHmFP+)t(~}P1z6IF
> zJE5}vf<u!9P}y`5DvT;)rtE1EML%YoxCm7VpzI0mk%0&LA|w!qsx*Gyo`I-f>cBO}
> z(af}}dv|vg&FWSd8(F%K(LJAqQ3X(quNW0<Y9f1|WaqN7lt2CSQ`>I~(OGt(1tS
> @R
> z*c?{n$94u>fpD1B@-
> tjPpXutGZ@ziwop*%FCX91&B@8yYw7N{$3AiGq>rSe|K!)>i
> z&Pf-c!Vo#7C8*%IY#^MdJY6R)Le)ZI`{BL-52&+I-I9sQnuW~u#^D{`Nr4a>RJ1P|
> zan&Jr0IH~*PO=G8v*s*0=YUtmb?L+WUX0`2&JqV2{R~K7eDMXJdpOT45|Lux
> efQl~
> zq_aOp1)X&n%Rz#jv)3HncRFD5>{+<d?C!<^Amv1a+?HpyTRdnBbw1Abh$|6Q
> -GHyZ
> z{yLvbcAa>dXoveqUFMbnbP<({%;7ah5yfMnewMLEBvn)nWU>iUv*s+UIiOb
> O2N(7E
> zy%@(krqIU9)STGcLfgI5icxLJSQa7doVVs!Fiw8-
> =n)@Lo}Mdm;!a<JCnv_Y@B4Ys
> z0?5bt9yP}XkNBZLU~=NQxN@kJ;JddBTWXG*lwa+(vWHGMy7`iSt3w!9Zi;nHn
> 3^?b
> zdCdXYa*-
> `N`MntD2G}21a}@HpiD3?C{ftpz)S=EfV4G1tkSpCKchkdgu9zfRH=0Q&
> z4o7A43K25kTOm~KAB)PKxGX%#+<-
> Ppt9aNs7L`NdnoJj&qYhEI;hA%e8xqtU?H3gs
> zjwQ(IT~8I2n=#phsry%R5SaEO4^#_$KxA2VU^a+xdnt~0Ou8CX6|l0!X`aj|LF&
> vN
> z3-
> M!+7FS@Kiyg=ne58~XKZ<Ojl9z4ft2)JYc9(#~swioSQW%TMB7|%Y80FMK&sbE!
> zfsh-}GJi5ujw{#Hj!543x#44L4hgh3%bJcc=4uhH(t}dlBEZzWtT~pm?sm7zPFC6B
> z?ddUVj^h1f_wJf8E;YJ3YmNe`-
> 0loHQ5rjOY<73iZg)zM%gak+Q3YIa12U%~x<F<L
> zMm=LuIj+hk>qhK8U?VCwd~D4LjzFBKJZx7{IgrUFOwF3J>NjCTuyz0(b<CP0gs
> 1$D
> zf|FKXhQY>KbjRGv4PcvIu(?ovStkJ7iO+<@sWjO-
> Y^&zPH_9!plxXc4U<F0YN%1{`
> z=8`ZLm8dB1)DaR|U>D?AR9!NYF;7&^+Q6D4_NsR`+_ojLRa6dSvI$eO=4`7uVA
> >`O
> z?Xy^j;~h3f<xz!LcMAe=j0y_c(5=*H<Bl7pj9=JE?mu$aLbXTD(E{VtKAbCsP)Qdl
> zP2M=PxFVDIsRhD=AkclR`>L{F#778CM`01F>b$N~FdSXlHQhrFfDK0lkmQrMEj
> q^Y
> zZd90K>WIp%cX-XI-
> V9<=f^@8+zlzF%Og3R^)||~X2V^T}!~vzf7{@ydYWHNad&}Dl
> zRm6Vg%gf=ru(bqCbj+Hg`h5C~rTD?rrN;%V>&G~*z`U(Fibe@YnXOo2zmOm;
> #orCe
> zCWJ+(VgS0T6fVYWrq67{;i$l#^&^1kgFC+8|NY<RUlxh65tWunK^s{HC6v*^A*}
> ~!
> z+?B1G!>d4Re{~H8tEe2vWD};&QFBC?6UzE(*TE=ju?0=|+(tU(GP2ypQfhQy)Q
> nLH
> zA>*Q(6<Vk)a@bsfO8G#@DG<N4-
> ;ztNoTf6Cn?g;;m8~rz3N~%Oo1$#CP|1%gxDpr%
> zHe2w<6!!5c@vx_bO8Seq5+P5YJ_VVUM!PyB7}>81V^N75D+nt7tWp(2*|{Go
> TW1vQ
> z$znJhl`Vs|u#mA|{_>ZZ*YJtT5)OIRoHD3xdxrba5r6QSqm++?(T)0;D=ge*8fA1
> V
> z*tA5V1i-54HmKpWSGr?VP+gQqiHcbPSzO+Poke-
> 8g$f0MHkWc$B}$}OsIdPEL8j3{
> zC6z^7DP18~wGs?~$#_c`i%KrDg4pgBK!My36$44WgJ6@r091vss1#JyhuHd+As
> ~!-
> zBPvTcWQK(Hvb$Pst~=*24zKZ?vxqz~x_8Z4hf44u*vwH4b9Kh?4pVk#+bQz0H
> bL^}
> z1#B@YC@7ESxza+A3<w@}cB(l^RAR>FD#&FS2Vl9(31hi(EGdwPu$smk9yS-
> Ds#?ed
> z7*pU*s4@VcW1Yy`1f6*@H+@+9BCfiq<T3<dl~~<Mv=pod-E;$M4tZ-
> mE#fL>&AH>B
> ze6-
> ktR`p3p8CkkNreSUOWX8IKQ~56}>$biccj_!r=@JB(9))U1b{Do4H3w@U1_d&#
> z4M8P8F6Bz;${lGc9z9jf5u{cS$_23y#}&p}4^~Zy)hZk8RDMk!Di)y%=CzkpVRSEp
> zs{%ImOxSXY#lx}?+~4V_6O%@+tYydpYYwcDI?J1;<Hjs+zN)A+YLNg_=lDJ+<H
> K?t
> z7g2K<9o<{Nco$;rOY>++7kiY<PQME+B!)Ttj#M{mjwOdODJr)+uU6|r*%`+b^o
> P_O
> z1=U$j6d**krOYG@Eu0VI)D9{ZaaH=u^>jD>acWLb!FZ{>7b910$?KXhb(u8>cV
> p#-
> ztM-
> (U<?iH0Wp{W0mKpNLsX0K!ILf4lk}F54%~*>fjwI_YaMqlXJw=XtWr&*25v}GT
> z4_1x1-BIFX&kzp^z|y!<f-kvJJ?!3OE#j)hgZc%j_2(;+j1iU0QlRm&z&bVCw0C*7
> zA2N}YcQ>N0oT!S*nN2ofYSx?)?@E(z?ALDSai7KU4r>D|VG<I6#i*dLG&k5VBn
> +0m
> z<o=7fQg&R*mG)M7KW70`CWi9oaIWH2lmMzdi%?Z9h}Dt`+hfsI?byymsO&5)
> IX)BW
> zYWynCSXAARPHsb@atr6!vJ_Y~dPE@|)EvdXd%PArNUEZ;v*%@)I&jSa)ArjN
> O9^&{
> z4eCHHBg^e7yL&RsA-J5cGzyl_67K>~6$q(&^a6(^SB}^%HAj(-
> t<&A0cHRIL*Spk%
> zLZS^?<&B*diIoFXR9nFnQ;Usx0kcyF@*-
> 4KJ8pLffD@pWOrn@&5h^!PwW+C(bI!4k
> z`$}T<w_}s1FSly0H&b)mYcZ`M+<<%n$+?8Tx+&;EhiY9DrjA{6EQLS&+0XETJ9i{P
> zzI1H0r;K;EtCnUgx~u9;>$fTxb(W}fiNey1g{eRJ<dZTA@{lm^a8wQt!Jzv6(I5R0
> zJgY}-ZtboaprZYy9z1N#5in5XvZ>>w)eN}e5F1xjBW`y%52^{Z<QEi}Wf3Y(5eQ0|
> z<u+8n<5G2j>Ku-WH+R*jws#W(P!)*Et)0VdGL-
> B>Ma)p4<VTjPHp>TY)UTqFsYL=z
> z9k}LTDT*L*eD<0HR604>#2{~<<wQZENRC24>{a(c8S=w-
> p^!*mr2o@D{SzFz9Tm-9
> zP0hh_<TCJMkJG$S9{as`835?X*BsrucfTs!Bd)jy!IHf%Kkpt?9MX59*FsfiOQ>e|
> zYJI>g__&&*jmAI<YK{vwm<p7us5I9i0jADTb8gA1|7fjSe%r6+)B)Z0mZ(}$usx4
> 5
> z7<E6IN2Lu{4(aA9PMXgR<rL~Exl%|XpD9s6e>+z&h>zXtg5d;<O2-
> MOqo&=*ac*c`
> zMgIy9lBi%gT|W-=U;slzQRw<{AS%TY1m%RKc=n6-
> !0FwmY8I7U<`HCia0n8Zx{#W~
> z<zgTF>Q}$QAKgHv3AVevRK`2TTJkb`%VsQ%EmIfN?9_o=qH@YX@M?!uQMr
> w%yFh2Z
> z+T0HnNu$^FOs1Qw2y!^8(s81c!g*^Bxv~cyqUshL&^3^&%)StBapVs~rQJuN1
> gT9?
> zjd0t!2P)ckcYnz^=UAe0%RGB?AS#$TVa>4)hrETzfi-6f42;bqvCHqqJC!$Lv%~G|
> zEjfeA+FUB{$JJ6KdHpS1aV%DypRT3Zg5mlz9&|&>W($MuU*yURsv#^{gyp(iP
> X?8S
> zSj&Md{nY|d1yh{m(m+%&HEYf`CobB2io|5RZ-
> KS~SO(RJA%U^IQI#voP?tePcf(ri
> zQ%+s>V64KXE96lHrb-ND&u~;QSkAJgCs-
> gaE#fMPq&sO>fvA$xolI>YDwvuzXPe^|
> zZ9YX@GTyg9TLCPC>co)1SO%4d#j00-
> WF#XjLe(;uArs4K4KMpI7ZsM7VFOFfYnJ@j
> zo<&?`utCS#Undh)a=MeL4MYV~v*v7b+@h4AFigh#7HBJgB~fV=rxC6gRmQ)I
> {5XWG
> zW1>>9fso8c`YmA*SC}zFOKYxtKT&1oI;GA)R4{eEnv)5fKqu+OMUj=Xxm_)ZYD
> -vw
> zx}`XisFs@DsDH(%g7CJN@&pdyDid{!qH74MJPAq7MX0de3@yp212v+`%ymk
> gfv8~W
> zd^IN^e&D4=ku`AM*i;hLmatls6^J&8Dqh;~s}oh8(#h3MT+Nz;(AtuYH1^gGe&i
> h$
> zXwG;K$Z?k@SB{XNIk^hRahE1nj*y^vWUiE<4<eAOAz)x?o^yh*-
> 0jkl<9)Y9uQWWl
> z$`d!ax(=>}WcPta7*|6K!qlue`6wNyIdemv%gNQ`D$hV(^T=^EB)bnZLav4wgsI
> Ur
> z=k2%O&bxhYO@JX=6IGY$$yJvkDNL?JMOT<ybt#g9xO({T;gAGB#0bFbP;-
> 9#;~#6?
> z>jbg&?Afz*7WNngFl1|@>e4&8>QW?y$(5++3X`iYMN$w~PoF*=QZ9xV0T^b
> {_uqei
> zqd}Ih+j9;~ZYet|I7;y75s_yR06-3$sA3mPu3~=d)yb7*BbFyuF+cWd$rUpF*-
> twF
> zpn|i#?3nWsjm@8vfyuyRU@|Zn*qed7bI#uLO#738$-
> rb_GB6pqt2uZQWzTx&lFJ8T
> z=R#uVov17uu{^no`LS0gSC)-
> fo?ONJ*sG4KgM2%r$8@(f2N*5n^U5M@qUt(ga@D0s
> z3X>~Q(G@0FU5cb|aIOwgaQN~8%g$}h5q}2}c>FvF7{QpRL`7GaTy-
> gu!sJR+bcHM6
> z3V%i?`ImI;OJW>V{tOr+SJuc8WT2WgC-
> B;<m#!e*UtQ3St;toM+{x8F;c9rwM+pk3
> zV_XfNbfZC_T2ga1&Sr-
> PRN>Oxg)u+&>g39@5zCXSm>+v}a%I_w<s?@&0S=T~m4~PX
> zPBg?6P~~dQklCz}AwG<a48NL;tl{&<1{a}1cv>&C<aox+)kUZ>28ZZORCyXFR|C
> 09
> z?z`50jQeNJiTSy^8vAp`d(4l$x`?Y}>|6Wm<VC2~O|fFsM3pCPay5{v<i5Mhj*I_
> W
> zg-
> Q=DwzcyBpql5Ls=sQTSFj6L#6E_UpBg={^j!g0udHX!#^fr`?j>@C?Xz<pum79a
> z<ZAD!m)ZxaS##0>e~Iz#7B?jPVZ@m&n^(Y9xu~6bCRcf4FOjPun=Vf6RRYOXJ
> n-~a
> zfoj&As=sQTtK%I(x9C%wyxF%16<}<SG8k#1xx26k)!m@o|GN~`haZ0Ut@*rs`
> SS7O
> z$HP%BMKv5i)!=GWnE=a#&{$MeYoj`2u9BM$YWie2v^v#=5S3Lsf(%rNn)B$<
> qZcn;
> zn7vmQxg(Rys*<G6*oRPi^5jV!MA7@@mtVg1)?2c?Md+fk#!G~Geyp9Yya*
> M7+B)dH
> z_uivtzxn2yciwr&UJ7Iw8Hnoj*I$4B{JHZR@Vxu(yWLrqD&)BeVt!ym5q}buC2B
> Z^
> zlF1}04s^vC-i)I?6G9~<^dwPPt{7S|9!7h0#!P37%5Azg-gx7yufDPY|LLcnW@dp-
> zYgbl>6IE--
> x%z?X9@Lx%4<2L)uKLY(#*rn>H{X2I#gvV&;jy1YMR+d!&t7xN%51qB
> zUU`yS1qFxj#sW*Cf(JzxqevmQhmb@iNY-(ZThYF2%?Tj2@VNZ26kg1g-
> E<#+{ISS!
> z!UrFG(DkFksb+N`QAy_@0#JoDhcK0y97(R3^rx0y<%ykDA8H_kAgmlJ+z}>gj<
> rwO
> zA*`ZuI%o!AC2WYVays>tHiModDq67NkLl#ubDeX#eq>MqcKHc7X<f>2<!+Hb`
> sgEA
> z!|b5TdKUMl@|T3xym5a96)o6XWB_oS2u3W#V01Nus_Q-
> md>QRPu89^2T~x5#MOET)
> zj4g#1qk=WsFHeI?2qG$GL#8r-
> iOOl7y$Mu_n&V(9Q7tVp&Q8E?)rW4l62L|n&a7=Z
> zgjG~d2TcMiYn=cizVet$`>rR6ilbc2%9W?7IhI?>Ob;#x*vty9s@Rrh1uj3smCaZH
> z=6F-usCv-
> 3CfUrOqA8Fj099H_hJ&7%!!9a!p4S5+&M2H!55`jmyme8*GCWv%$Kolk
> zI+m8gi&4QE>}#*N?Qi?((_nU*a%j=44k4;i`Mf<qb+I)E%-
> JmN^41VuUF^q^CFP(0
> z{O9<lxeCDMGu%K|bzG;+wuB@q4tFuDcwdyjssZlcRZ+R6#Z8+eO0F^(93(WW
> sGORD
> z%6?}e-fTTAQ8`n|W(E~afibxZsjCDKQ|hk99ClIJU{-MkPR-&J)DIz^I^eB~N}jUQ
> zQMS}okEwPD?C=wS(WMv_?7*_(s;qbx7<>wSS#|<VS)7!sLx`$WuJ$0D27anju
> oI{*
> zx#nOI@+1fwUUr<r<H)kgEy`be?KOR0ULJ(1qpaDg9HX-
> QWMV2)e5wKNuvJl27uf2w
> zT$LFjgTX;Uvx>^9*?V{FeqOR0y^CrEur4YgBv<ljGK5+T$56YdbW?zsu`hgRI?I(S
> zkMY!6Zz*(9S!W4}1eL)u@k_@FNt`h%7_ql1WiVq#=hJfG>}jp8ij%19a$0gGGc3
> |+
> zO@w}+y6~EVMaW&l%Z~GW99dR5pj>E^3B#JL$}uWUmkgQxYEHmO>yp5iTv
> az&l^@#~
> za|KQN_JHo)-
> 9`^kVIeDkbx~;vB+A|vZ@JHkp>|PSV$BK4U^NJ1isYA=D;Vjz%oRgf
> zb^=W0aS~Nk-
> *zH1Kr@*il4{nzlQGxj*Bq=#X#kXL*@ccC=kPePtg^GCrVaV(?T$1h
> zShH0*My14%43<OH9Dy%UC6j?;EanQzi)v2QgDZe_QE3&7iWO0$aI!)SwTr6C6
> `*Pg
> z<<W9i##3v(rO-
> tM%K}gpgsQxeDfN>$V^lDrNN%04Tv5UhejEenEJ30N{Z122qN?hv
> z6Rx2e1a(s26Pc1Fg&!`tAxbi?-!?JbRn#1;X^*nw+!#leRkj>kS@90%xTg(P&C1qn
> zRgO{VEi66&aWSh%FO#~(;N)t6J8UH?XQbOyXoIUV@G}@3Bs5D@PRBY3C52
> ZlY2Ak;
> zD}Z%T38Y99&Q=bSW+22+yQmaea1f)5I60$2i&x!mf5lU4y`|7aWu2u=4-
> EKl#|c=H
> zx)MX#6QcqoA!%(i8&@_nV5~lzx9U*nv`|&`*-2Ue9zv-
> mNEQ#&xR&ZdXs~Kc_A%YH
> z)Etq)bq_i1I5)<TWtBy+1UZoK$|NdHCs?ypxr<8oqvd_M_FpxE91=CF0q(Gss5C
> q&
> zD6N9A5;=^x88giil^bOzWlq9kEnp=NplZcfh95g`7nPKS#1>?i5~R}=Vw@RN3N1
> !8
> ztF*<&{*tJ8YOS{vx~S+c1vUZbC*u6~e((4A>vN~9Il3cmZG1~wHQL2k)vdZ}86#I!
> zeRP5oDnMxIa64F{l*dY+(k7{H8ALxOy`q|f1!Yn~z=ykJ9SFG_@6vZj6!H{Wapz`
> d
> zQ#M;d1{G<su|wn9nun@6cK?yFYJj&03HrNS*_u;MZKEq-
> teOC}pwd_yAp#R1vHGPP
> z<Lq)pRIco}P%lG{Fyg7T-
> csnIf@S4J2Zqgm_=kVcuWVQ2$`Ms!D0^a5fONE)11g9a
> zf?Ka^61mEtYdU2S?)q&L^IliY!Q$lJ)q7D4x!{T;%PPZyQiA*dVZ|+}HCvT4sPsCP
> zD|bhzIr5h!%F2p&`GrE2jkvSRl`<%jCI0Pp3&Y8QE0-qJE-
> Ed`GGH@nCU@Gglw+KE
> zRDf63YS0y+il^3kOQDO(CU{`50dE<jHv=b%t_;)|m4#&SXbK4SKC2b*u!D~sB^
> muK
> zuB0OYYbRg`>TC%j4c?@egS<*sW3!n0>S|8Ldo6-pzjI?8SymZ#sx=4R$b`9tVa-
> <M
> zBr0VE3*h)Q$D*~gK(4Y8cXqi_afYX`$yPhDngd$cx~MeJF`#nY%4AO8HDi!@RF
> *Vl
> z9SE)52^jIzT5l<IQ7NPWprl0^lsJRv5?2|hF)CQ-dTL|Vs)8gcErbFV&VC5)Qme_-
> zfxEDO{^x(jsNhzDtj3lx`_<JPFlXZ~V5r5h`d!G!k!6)-L4wU*!CsWU1Z%b`=TR~6
> z?QM#PvYnc`B~%04VJlI!tZ6$cU@2r+a+7wOB`P<>elO01B#MYCPn5G9G`pxY)
> ^R9o
> ztw&f+-
> !)@DCQ<2R2!22geo@D!&wws1YLU=IrF*LuCsF|5)6^U+P}{#OgLH}|Efe_}
> zSCT8M$rvvCtxi?eCXKPtK7Lk>uoJUiNX-
> crQN5HTsXA7jZZ~w}UHY<M1$&Q`33iT^
> z&6bcyrTb9@j*?c88|)I2kN~wrRoY>XJeB7}rdph|`b$)$rtpX*O}9uWEw_5As8A
> 5f
> zPYGZPTG($vLVp#N(^o_x&44amCCF};b*7TdE-
> KC23TeeWFlTN^W0nYeJF0cbLGe%p
> zNmSCIfK{_Ut_*IJ!YtmTu*r`bZkw3>N^6cnuXST#X=urAA9N#2`YnSiP|0RX$fJS
> <
> z-Q;n%Y5%o0XmueiB(}dqRW*gqWH?uc+Zi)*iK-
> kWidr|yRU~C+X}Q%?MO7NC_6Y4F
> z57JaMQ3+%fm9A1yJY#nKDFPa|H}2I$<xC};T~vb9+W3ljWXBWK9FPn`<fc|oSy
> WZJ
> zs@_*;)s^H*IuckGa20|&1A*Xw`O9DO-
> #rOPqvhBv=Dqfsvtlobezy<0@h*K?aDp~O
> z9+hmigghz)rZNEmDAMzIu%Z?c+h3w`RH(V7=3qtq*r@}#L{%!=$7>spI#?s%l~
> cH$
> zDk||43vwtn`qEq#W2>S9^6weH{f~SHqSP<IiuNjv(syjc%@!(+(xk1B?xug?rvRK
> Z
> zj>RI~Y9cEHs4yIMw9(+EYR(p_mV!kEYoC1biR}@{5|vexj9G{of;y{$4q$*yZd=4+
> zIIQtgHN{TMd-$5e*bEj?z0?gojgsaaUq1webs*#*vYe)jJ3(^=ese>d<+7Pa<-
> #8+
> zN?Re1ryAWERBl~rDsL@KnX&+(1W@fsa%B_17E}P1p{t6@t}d2^wsmLU8XjY-
> q5`Xo
> zBHEPis#QhN9s{d-s@2&-
> C4I4h?Oe_7!W^R#X;?2GAtDkqixUD=q|4qKROc0{<W9sg
> zt!CAgM5To|0sK$_g1cm!1SbEwrqzV36zckI6O$%tj$5A+RqLE+X9#5HH`}y6v@v
> e2
> z0aev|&{1s$2Q3|_aZi*<1-x=;77}EO%3ZQe+$ewc*=Oz-uQ8pCI~y-
> {QKf7xSLGxs
> zj1`kyIM(>bfBeTw|DDikbeF(NROQmxquo|IqBW%KF9B40N>o)fbP5$hsB{*tR`
> Xd2
> zEJIfnRcWf#W1~HZil$<0Ra9U`Q3NAmsZ0en+Jij^BP|zH`&+1_Y}qL1wG}BDZ!`#
> E
> zHAN`|s6>}4Fe1viNf{NFl-*nIR=-WlRaX*~^h*KL;R7}NEU%)6bXn($-
> YR>y_P+a3
> zwZ=|Nm#aB4hN;Am#S%=?x>UMOJ=TYEnzN(uagilfh`GuQOkukO?&Xegfo4$
> &YANX9
> zjGfw{3Z{0;EbY6VBr1#&lgbBrMq8#;2SZI8-PlHsB4I00$$}G<w=7*wr`y!Lu~4FN
> z`dA%5qDYbN1eZ1fgfQr4am^~Kz+ibv`79q-FcJf+q5^V^5&-
> Q%kYlrfV=wlsV<T?1
> zP-zt4i4CB#$-
> $z{2Rsvn>{o>VmFRLAK=Gq=>Nph1fq<3L<5gD@RWKZvFe%j_I86a|
> z?jvC9ZViMHe$-P6m~LUsxik9Rf2-
> 4$lh_`vgAT8HkDb<sa+<XR*+!5>W#v|6$yd&%
> zYw};h5l)Lrou#0fW06=n!y9((=bwL$e}@P5VNh~8T@n=rS|%NPEutJDXfnE0D7
> db&
> z@|37bQ|xi3EK!uJ*qGI{8!Rn)nTkByOC>6M)lmd^0XF4~*1BxJo5eM&s5IQ=?~
> )(e
> zQ{_sgoKQ_v!d6AKh@!xK7Kvue2rX0^%ODRNM^s7oA;13m*T3dA)D)!<pt76J
> mKW<a
> z$%}3oz@gw(T}f1y>Z**{p(zYQgz7}>#9WD*LtT6KKwO#J=_Vgob6`34VQc>Z!
> @vB?
> zzm(6u98@%s>=C?gz4aEOEQl-
> @hPp*49hfH#ge#W=hGaKa9+eG$tj_Ms7FQ)F%;>m%
> z1T93!@`dzoft9FAQ|z%YO1jX~!ltqeJDQpWAA1))u#B;Kp9(!CDh;IID1zl`%C~pV
> zt##RcH;ZdlQE7M;K$R$Vst(Hn1Q(FZxLE9p`dm^Jc(CO=i_NhSH>+IPA%Yj6s#0
> Vj
> zNk)V-)a?|d9H0^&+I07N){jdI4h%9jFc7n}P-!iJU||fAgSo&}y5?9j^k+VO+Od*L
> zlGI~;=$xkE65M_QXE89uk%CTv3BTFRO$Fe=ue|;Ar#~eyi%L+d0<o3xrFjKD5H
> Os%
> z6H^d#b*?-
> r$E4*glN$&XSqc@KiJUbDs6b;kySG*<7qo&sz=kF8_Cd^$bJk}oQ=!Y1
> zqo{>>X}{oAg(@mdVZ*XTk?k*IOpewi9^hSka@Po96&0>lDJnt6dr+%`z!|a8z
> W(}a
> zdxIb(R%oHJIzm{YT6D9(;o5_C3MU7s1ja5I8^^jVh;TcqDs$`M4%$INlc=hr%1(=
> C
> zyIk5=4^XYDIWn+CC`nR}^<mX%Tjtfj9nE7BHzM}mU;M>i;E(^YiJ&O&Z!9W7tq
> NP<
> zX)NIV;upW*DGTsgv7bjZgh|w#zy9mL=Bib5Aapa9)-
> _ge%rK9#=I~eK;ZXUg%heEy
> z$^{BQRj8sWjjZk=CpO*MWURPyOjc0=|8R=P31)X8l;_H6jzY*<Eq>fAw%OteI-
> |g}
> zykBlT0VAr`z;pEj)yZoPf{RCcaZ?J`hhv?lJ7ZAJy+|-<!h0z22r+sCS8ciiNQ<h(
> zY<sr*vvv1h?#n!?Axzq3vgX*QZMs^b+RjPK0$|8f@+pv5nZQa^0!(2DMZigB1e
> jn1
> z(oI@LrLo%u@}R(mL3{FXVAQOl!qrg}ab2u_sE5DvJHPYA7hnALZ~r#_sjwi;w@
> ?Z8
> zK!my{wZ^M*fNCsVWiTMp%A7!uL{$zsZx2wNyyj>-R=sE0qCD1V*lh^y2M-
> >Ac<x1H
> z0y=@=Z_l~w-
> XQ?&AzlR@y*d!QMi9iiV|WOY)+Su}v!DG8Z(Em9U!oeqNy`XIG|x7}
> zzt3sS828&SgQojp&~ga5<O-
> d!{Y6)m*BSO~;`R!W&&}xYuvtZgOGBc_;s*xa>;2&$
> z{vrQu%2sj4>@8Gw38N6snq%EGN`?o|QFEB)ZJ0ROM%JhZB4_rT!@E6u|ED`+
> D%&q}
> zlJU-
> kjPj3CDa=~g(q*}_{iQsFNtxBx&*ei%=#;2NaRNJZ9G^P#m}<Xe60l4q)N&{c
> zp@=I*Ea?bM+0CV9$rUawr3=V|4;jP0gAQ{%AGKkkrEvudOR>fJ<N*|w{t`tJs$
> A)+
> zgdreBn#{I@0M!sA0fF#li#MVQ#-
> 8O8P=z%I91p}rk0Hi`vom$950g$)IK=vhBm2@C
> zz|dn{CZi1SU<3w{z4YA$niiF&s|uq?!$uTW2(Ie=UmjJ=j4(qj_;9_<Tgdu6U6dr0
> zsAPYmVDH-
> PhQkelzWyrlu%|@jG_mlF@H8Aa5nVW1P|(|tZbme_sLCPhdgL{mrCQ0p
> zg=!#0<cg^N{_p?(CqMbgkaG^m*$9&H&q&h-
> 3^;FbwH=AVskI`+SoNk4Qxlae97F)B
> zUd<8H8zIvUAAPh)(p=VuEwUXRjg9pgN4f#k@tM|mm5<k8&^;2ds5D(maPaa
> ?;D=3w
> z67S>PPn#_`bsiNgXFjbJsh>##dlACvYmRl9WMTuJYFQTYE?3|u<0;V?EAx26pTb
> ZI
> zT~y_e)jf(U5(R7uFt;mPsFD=L%;+k29Ht)leGbUk0up0IZ;;WY1EIy$MkHdXCB#*
> c
> zs9Iys)eltZnqxV(a?-sVa`u`7rjePDFGV?;I_l7ex_#eLb1X%xW%tMk-$a$S%R#)a
> zo;Mh1J*b)koPYYKe`-gSs6_ZifoT%84uQwVX!cGNNupH-
> 0k1@5F+*My%w2ti(_j77
> zU;WMB{7vaKJ8u`2Ro)_#F5FV#m1Oy@W$<LE2mr^_jlX@_TF93E?WmFwwQ
> f`3o+}`Y
> z9$aU6zfnLnqUM0t?uVYYQ6I#@@OTG2u?R=uHv#PLgd$P#Y=dWO|M-
> vph%d#N#*knC
> z?9cv8IESN><(2>d-
> PZ_CjH+65PzT%rqeLbCHwyM_gOmVg*{Km=`t_lb)e@D{v2haM
> z)Tpk0_mBfqT~wNGqd>Y;qTMSp&iKhtao+9O-QgeAL~;;gEt>&X-
> 3ST7ta~ZOMpRuR
> zCsqKe%{8axhiX4-PWgbyDF;4un(LaSuW;Lk;|+l+Z($$k7eX=7-l(c;0aV?%TUpAd
> zN2QY?@0ICOoA`I-
> $`!pbmf*G47du_9k{LqeFV)vTD|As=<t;L6jywhTNiNNv3{^RG
> z&~tiJ3~%khDz*SsGD21)e%#LJTYv!73d_3=0avH3IZPNl-
> B)>HXW+wNRQ^&mO}gRs
> zjBy%N4gi}rF<4p3dvm3UtiT6c{3@W#`q11J6{Co=SCavVa^Fr6{H~}hKa1p(p|ZP
> =
> z@~k--Pj$;q;K7}04kDZd2lb(~1ftrtfUGbMRHv;uEqYvk;6tamy4fu|I8?YDc>+}B
> za_n6@GJSc>KMN}2MBrCbKCYe-
> Rmq`xCMsL5%UBXo(}R`@%GIX~ycERM9yJG#m-TP9
> z!F~zVqFPZFb{zt)?rY6~TeSaN;^a-
> dD>%>(BCF;06ZB71d6FkrldC)fdCefM_NY0w
> zCIldf$|@g02CCbd^Y+_s2iQ-
> 131G<9X;7*1@L3IhRv*ip7*&$<i7H7H)FxMxt2_gF
> z%{Z>M*Bn>~J}sO=_3+`tBa|9q0GPX)^X%EP7WUKk0}N}<MAapKa@D0s3X>
> ~Q(G@0F
> zU5cb|aIT&{eR`al12A_r2mb|gD2*cWECK+?fhs!_Rn-
> @ht12zk&dF7kmTKqZs!B_>
> l^HR7%ra${>2LM=bOwD1ApFbx9lYz;=WMDF|9|Jcx{~rV^Pj3JK
> 
> literal 0
> HcmV?d00001
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/FullIcon.bmp
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/FullIcon.bmp
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..b940505c8bc74ad6550bc3226
> 29d7975c1e1c1fc
> GIT binary patch
> literal 5454
> zcmdUyTS!(}6o56!L@l#1k<1H~<*msK=EYIGfJHUFgo!=$AR-
> O~g3Ln$_Tv5C7@{FW
> zuaziT6L~3b87f|a5!5uTbW}2D5<@ff*ZKTcvp6&*5#z(Z`TxV--
> &uR@b@o|%t#u-Q
> zirH&rZa;AK<^LmpPyW_cZd|Rb+&<nn4?bRUiz^!H>wdS8R##V7QBl$K<d1cW
> YA;{D
> ztZVAFD3jL*2L~Hl`%J6LZf@c|8xF%GjEsyJ{RdKAU2P;=(N9lLXQANWU{&7M)&
> |ib
> zoyp0`=g*%vw)L&AuN^pWKyM*7F)?9hXD7tQ#s+ft?p+nwqR!Q;S6L`LJY4m6b
> #+0u
> zZ{MzDW@ct|bX06Ubm)+BvDx0<UI<el_wL<Ofi3EY%@Gk1s$XojwY3#uZEbD
> oHhXz_
> z>C>^R<KyGTHv*}xtyO_7>J%0hvQTJfsOs<N=zy@jN?yNyjc+ux_O7p)LPA3J?c
> 3++
> z>FMO;BsL#Bc+kVc!`<E8$Hxa!UtjO&=*XjOQDfb*vN9GrckZ04t1GKGI5_n5^g
> z75
> zz4!0mk1<@|ym`YJtZUwgb&HFO@87>)T3UMd?j1wg!omWC#w~`ctE&(Mwy
> 2?ed3l+I
> z(9eooA!}=E5V1`y85$b0#P}@x{Fk}?ZEkdDXJ>gplgWhtz!<)L`xf%y!v{{T5P2hW
> zb93B<z*kmQkfDzTuFPdf69FJ^mLXzvM9KX8JOoujm?BD8PG%vdO{TNY4Xu4
> ^rqvTC
> zPVC;jd#|}UJ39vk2J&_W1_pNR+U4Tnf+xqv$D_QmvU10c9Y_%gFI~C>NlHq>
> @sNRc
> zcW<~^OiawqojboXH;fq@8{?$x*|P_=etv!kG&D5G6vWP+JqzLViCT`^qeqV*i
> HV8G
> zh&^&eA4+&A%_;b~o=rNWMV^-
> |sqoaPQ>eOg=Z+Grg~Y|hDe3L)g%}S$PWa-*i*4Js
> zi40~VK%Jvg$RLo+%uFR>vr(<yqVuKr%q>nRhmN<P@@LMRK{@-
> ZBsn=5a^b=SC4GIQ
> z)OBN0;AK(Lu!kbUjv+t@(kW3<QIPEHY$Z)iO`oXMTbtw*WGupFBC|dY9X15tz
> @HUH
> zM@RGcw{PE8g3Cc-
> V`G(wZxHI0;2Zd}4kh?Mc<?|;SXdZJGBPrhJbd^Na{l~zCB_c^
> ztU2ZM>C+sL@6FBM-
> =9}Th`={|eSMD}J$m@?VL5SB9aK{g>XWpzG?ZVye3?E3{`Bcn
> zNJ2uwkt0Vq#Wcdgt5>f$-
> ~j;vsKsp%XlZF7Pca3tix)3K%FD}{&f+AF_V#v2YHBJn
> zVvk(Wh7v*tHK#?!XA7+P>zg-
> nI@L&PYb!N2hngXN$Qy*v=s<WW#8m`{MMOvlbrik_
> zflIXS?CeAsLNr5wCQ2ZUjg1V+&N%bq$BzjP{r&wA5{IZo6%hu)p=fSy7PXRb5X
> KA$
> zoHY0B*)!^AlWB#7qOQ(FtkNMJh%w5gq@+M{b8}UOyAX1R5<(?JhoWR^YD
> &q;lP3|V
> zsi{#S-zoUH5={L>3EwH-R`XxEas^eTrKPI;{{8!qpr9ZnQr?h2l^{Sy(4iz&W2}~%
> zKQb~>Wu)fU@V-
> fWMmgVBn|!By$>w9nj_Gn@Gx=A^SK4e$N&n+_%GcZc4g36Gn?JkH
> z)JPOL#tkth0ytY#RaK<|1W!moL4gwPLX1VrXZ?A4dRnJQF<|^OCWE8o`0?W^
> Be7bC
> zbT|?CbA8K3+_-V$2JTc+Qj(LC!;lK|w}0EUYu6y0N^a55&(G)JL-
> >fu%gckXmPC@9
> zH*Xdf7emNv;v1p^wPFv|JGT&^kmF+wC2USsRu+U4EuL`e)~%wVA_yD{kzt4
> )l+dAo
> p86F<C#GKOBxe+HVs7?Mk@$)bFIfd8L^U5+T;g?l#J@wbDe*hRVpnL!T
> 
> literal 0
> HcmV?d00001
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/Keyboard.c
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/Keyboard.c
> new file mode 100644
> index 0000000000..84c3a06f68
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/Keyboard.c
> @@ -0,0 +1,1411 @@
> +/** @file
> 
> +  Virtural Keyboard Control Engine
> 
> +
> 
> +  Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "VirtualKeyboard.h"
> 
> +
> 
> +/**
> 
> +  Notify all keyboards pressed specific key need to hidden Virtual
> 
> +  Keyboard.
> 
> +
> 
> +  @param[in] KeyData          Keyboard pressed specific key data
> 
> +
> 
> +  @retval EFI_SUCCESS         Success for the function.
> 
> +  @retval EFI_NOT_FOUND       Not found Virtual Keyboard protocol.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkNotifyKeyCallback (
> 
> +  IN EFI_KEY_DATA *KeyData
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS Status;
> 
> +  VK_CONTEXT *VkContext;
> 
> +  UINTN      MaxColumn;
> 
> +  UINTN      MaxRow;
> 
> +  UINT32     HorizontalPixel;
> 
> +  UINT32     VerticalPixel;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkNotifyKeyCallback
> Start\n"));
> 
> +
> 
> +  Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, (VOID **)
> &VkContext);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    return Status;
> 
> +  }
> 
> +
> 
> +  gST->ConOut->QueryMode (
> 
> +                 gST->ConOut,
> 
> +                 gST->ConOut->Mode->Mode,
> 
> +                 &MaxColumn,
> 
> +                 &MaxRow
> 
> +                 );
> 
> +  HorizontalPixel = VkContext->GraphicsOutput->Mode->Info-
> >HorizontalResolution;
> 
> +  VerticalPixel   = VkContext->GraphicsOutput->Mode->Info-
> >VerticalResolution;
> 
> +
> 
> +  //
> 
> +  // CursorRow and CursorColumn are started from 0, so need to add 2 not 1.
> 
> +  //
> 
> +  if (((UINTN)(gST->ConOut->Mode->CursorColumn * EFI_GLYPH_WIDTH) <
> VkContext->SimIconBackWidth) &&
> 
> +      ((UINTN)((gST->ConOut->Mode->CursorRow + 2) *
> EFI_GLYPH_HEIGHT) > (VerticalPixel - VkContext->SimIconBackHeight))) {
> 
> +    SaveVkIconBackgroundBltBuffer (VkContext,
> VkDisplayAttributeSimpleBottom);
> 
> +  } else if (((UINTN)((gST->ConOut->Mode->CursorColumn + 2) *
> EFI_GLYPH_WIDTH) > (HorizontalPixel - VkContext->FullIconBackWidth)) &&
> 
> +             ((UINTN)((gST->ConOut->Mode->CursorRow + 2) *
> EFI_GLYPH_HEIGHT) > (VerticalPixel - VkContext->FullIconBackHeight))){
> 
> +    SaveVkIconBackgroundBltBuffer (VkContext,
> VkDisplayAttributeFullBottom);
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Hide icon/keyboard to prevent screen scroll up.
> 
> +  //
> 
> +  if ((KeyData->Key.UnicodeChar         == CHAR_CARRIAGE_RETURN)    ||
> 
> +      (KeyData->Key.ScanCode            == SCAN_ESC)                ||
> 
> +      ((gST->ConOut->Mode->CursorColumn >= (INT32) (MaxColumn - 2)) &&
> 
> +       (gST->ConOut->Mode->CursorRow    == (INT32) (MaxRow - 1)))) {
> 
> +    HideVkBody (VkContext);
> 
> +    HideVkIcon (VkContext);
> 
> +    VkContext->IconReDrawCheck = 0;
> 
> +  }
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkNotifyKeyCallback
> End\n"));
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Judge whether is a registed key.
> 
> +
> 
> +  @param[in] RegsiteredData   A pointer to a buffer that is filled in with the
> keystroke
> 
> +                              state data for the key that was registered.
> 
> +  @param[in] InputData        A pointer to a buffer that is filled in with the
> keystroke
> 
> +                              state data for the key that was pressed.
> 
> +
> 
> +  @retval TRUE                Key be pressed matches a registered key.
> 
> +  @retval FLASE               Match failed.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +IsKeyRegistered (
> 
> +  IN EFI_KEY_DATA  *RegsiteredData,
> 
> +  IN EFI_KEY_DATA  *InputData
> 
> +  )
> 
> +{
> 
> +  ASSERT (RegsiteredData != NULL && InputData != NULL);
> 
> +
> 
> +  if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||
> 
> +      (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means
> these state could be ignored.
> 
> +  //
> 
> +  if (RegsiteredData->KeyState.KeyShiftState != 0 &&
> 
> +      RegsiteredData->KeyState.KeyShiftState != InputData-
> >KeyState.KeyShiftState) {
> 
> +    return FALSE;
> 
> +  }
> 
> +  if (RegsiteredData->KeyState.KeyToggleState != 0 &&
> 
> +      RegsiteredData->KeyState.KeyToggleState != InputData-
> >KeyState.KeyToggleState) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  return TRUE;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Pop the key from the keybuffer.
> 
> +
> 
> +  @param[in, out] VkContext    Address of an VK_CONTEXT structure.
> 
> +  @param[out]     KeyData      The EFI stand key infomation when code get
> the key will put
> 
> +                               correct mapping key.
> 
> +
> 
> +  @retval EFI_SUCCESS          The keystroke information was returned.
> 
> +  @retval EFI_NOT_READY        The keystroke data is empty.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +VkPopTheKey (
> 
> +  IN OUT VK_CONTEXT   *VkContext,
> 
> +     OUT EFI_KEY_DATA *KeyData OPTIONAL
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS Status;
> 
> +  UINT8      IndexSt;
> 
> +  UINT8      IndexEd;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPopTheKey Start\n"));
> 
> +  //
> 
> +  // KeyBuffer
> 
> +  // [         0          ]
> 
> +  // [         1          ]<-*IndexSt/IndexEd
> 
> +  // [         2          ]
> 
> +  // [        ...         ]
> 
> +  // [MAX_KEY_BUF_SIZE - 1]
> 
> +  //
> 
> +  Status  = EFI_SUCCESS;
> 
> +  IndexSt = VkContext->KeyStartIndex;
> 
> +  IndexEd = VkContext->KeyEndIndex;
> 
> +
> 
> +  if (IndexEd == IndexSt) {
> 
> +    DEBUG ((DEBUG_VK_KEYS, "ERROR - Keyboard buffer is empty.\n"));
> 
> +    Status = EFI_NOT_READY;
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkPopTheKey
> Unicode:    %08x\n", VkContext->Keybuffer[IndexSt].Key.UnicodeChar));
> 
> +  DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkPopTheKey
> ScanCode:   %08x\n", VkContext->Keybuffer[IndexSt].Key.ScanCode));
> 
> +  DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkPopTheKey
> ShiftState: %08x\n", VkContext-
> >Keybuffer[IndexSt].KeyState.KeyShiftState));
> 
> +  DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkPopTheKey
> ToggleState:%08x\n", VkContext-
> >Keybuffer[IndexSt].KeyState.KeyToggleState));
> 
> +
> 
> +  if (KeyData != NULL) {
> 
> +    *KeyData = VkContext->Keybuffer[IndexSt];
> 
> +  }
> 
> +  VkContext->KeyStartIndex = ++IndexSt % MAX_KEY_BUF_SIZE;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPopTheKey Success,
> Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPopTheKey Failed,
> Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPopTheKey End\n"));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Push the event mapping key index to the input key buffer.
> 
> +
> 
> +  @param[in, out] VkContext    Address of an VK_CONTEXT structure.
> 
> +  @param[in]      Unicode      The font's unicode number.
> 
> +
> 
> +  @retval EFI_SUCCESS          The maping key index did put the key buffer.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +VkPushTheKey (
> 
> +  IN OUT VK_CONTEXT *VkContext,
> 
> +  IN     UINT16     Unicode
> 
> +  )
> 
> +{
> 
> +  UINT8        IndexSt;
> 
> +  UINT8        IndexEd;
> 
> +  EFI_KEY_DATA KeyData;
> 
> +  EFI_STATUS   Status;
> 
> +  LIST_ENTRY   *Link;
> 
> +  VK_NOTIFY    *CurrentNotify;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPushTheKey Start\n"));
> 
> +  //
> 
> +  // KeyBuffer
> 
> +  // [         0          ]
> 
> +  // [         1          ]<-IndexSt/*IndexEd
> 
> +  // [         2          ]
> 
> +  // [        ...         ]
> 
> +  // [MAX_KEY_BUF_SIZE - 1]
> 
> +  //
> 
> +  IndexSt = VkContext->KeyStartIndex;
> 
> +  IndexEd = VkContext->KeyEndIndex;
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +
> 
> +  //
> 
> +  // Check Keyboard Buffer if is full that will pop the first key
> 
> +  //
> 
> +  if (VkContext->IsSupportPartialKey &&
> 
> +    ((VkContext->KeyEndIndex + 2) % MAX_KEY_BUF_SIZE) == IndexSt) {
> 
> +    VkPopTheKey (VkContext, NULL);
> 
> +  }
> 
> +
> 
> +  if (((VkContext->KeyEndIndex + 1) % MAX_KEY_BUF_SIZE) == IndexSt) {
> 
> +    VkPopTheKey (VkContext, NULL);
> 
> +  }
> 
> +
> 
> +  KeyData.Key.ScanCode             = SCAN_NULL;
> 
> +  KeyData.Key.UnicodeChar          = CHAR_NULL;
> 
> +  KeyData.KeyState.KeyShiftState   = EFI_SHIFT_STATE_VALID;
> 
> +  KeyData.KeyState.KeyToggleState  = VkContext->KeyToggleState;
> 
> +  KeyData.KeyState.KeyToggleState &= ~EFI_CAPS_LOCK_ACTIVE;
> 
> +  KeyData.KeyState.KeyToggleState |= VkContext->IsCapsLockFlag ?
> EFI_CAPS_LOCK_ACTIVE : 0;
> 
> +
> 
> +  switch (Unicode) {
> 
> +  case VkKeyShift:
> 
> +    VkContext->IsShiftKeyFlag = !VkContext->IsShiftKeyFlag;
> 
> +    if (VkContext->PageNumber >= VkPage2 && VkContext->PageNumber
> <= VkPage3) {
> 
> +      VkContext->IsShiftKeyFlag ? VkContext->PageNumber++ : VkContext-
> >PageNumber--;
> 
> +    }
> 
> +    VkContext->IsRedrawUpdateUI = TRUE;
> 
> +    break;
> 
> +
> 
> +  case VkKeyTwoPage:
> 
> +    switch (VkContext->PageNumber) {
> 
> +    case VkPage0:
> 
> +    case VkPage1:
> 
> +      VkContext->IsShiftKeyFlag = FALSE;
> 
> +      VkContext->PageNumber     = VkContext->IsShiftKeyFlag ? VkPage3 :
> VkPage2;
> 
> +      break;
> 
> +
> 
> +    case VkPage2:
> 
> +    case VkPage3:
> 
> +      VkContext->IsShiftKeyFlag = FALSE;
> 
> +      VkContext->PageNumber     = VkContext->IsCapsLockFlag ? VkPage1 :
> VkPage0;
> 
> +      break;
> 
> +
> 
> +    default:
> 
> +      break;
> 
> +    }
> 
> +    VkContext->IsRedrawUpdateUI = TRUE;
> 
> +    break;
> 
> +
> 
> +  case VkKeyCapslock:
> 
> +    VkContext->IsCapsLockFlag = !VkContext->IsCapsLockFlag;
> 
> +    if (VkContext->PageNumber >= VkPage0 && VkContext->PageNumber
> <= VkPage1) {
> 
> +      VkContext->IsCapsLockFlag ? VkContext->PageNumber++ : VkContext-
> >PageNumber--;
> 
> +    }
> 
> +    KeyData.KeyState.KeyToggleState &= ~EFI_CAPS_LOCK_ACTIVE;
> 
> +    KeyData.KeyState.KeyToggleState |= VkContext->IsCapsLockFlag ?
> EFI_CAPS_LOCK_ACTIVE : 0;
> 
> +    VkContext->IsRedrawUpdateUI      = TRUE;
> 
> +    break;
> 
> +
> 
> +  default:
> 
> +    if ((Unicode & VkKeyScanMask) != 0) {
> 
> +      KeyData.Key.ScanCode    = Unicode & ~VkKeyScanMask;
> 
> +    } else {
> 
> +      KeyData.Key.UnicodeChar = Unicode;
> 
> +    }
> 
> +    break;
> 
> +  }
> 
> +
> 
> +  if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar
> == CHAR_NULL) {
> 
> +    if (!VkContext->IsSupportPartialKey) {
> 
> +      goto End;
> 
> +    }
> 
> +  }
> 
> +
> 
> +  for (Link = GetFirstNode (&VkContext->NotifyList); !IsNull (&VkContext-
> >NotifyList, Link); Link = GetNextNode (&VkContext->NotifyList, Link)) {
> 
> +    CurrentNotify = CR (Link, VK_NOTIFY, NotifyEntry,
> VK_NOTIFY_SIGNATURE);
> 
> +    //
> 
> +    // The key notification function needs to run at TPL_CALLBACK
> 
> +    // while current TPL is TPL_NOTIFY. It will be invoked in
> 
> +    // VkKeyNotifyProcessHandler() which runs at TPL_CALLBACK.
> 
> +    //
> 
> +    if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
> 
> +      VkContext->Keybuffer[IndexEd] = KeyData;
> 
> +      VkContext->KeyEndIndex        = ++IndexEd % MAX_KEY_BUF_SIZE;
> 
> +      gBS->SignalEvent (VkContext->KeyNotifyProcessEvent);
> 
> +    }
> 
> +  }
> 
> +  VkContext->Keybuffer[IndexEd] = KeyData;
> 
> +  VkContext->KeyEndIndex        = ++IndexEd % MAX_KEY_BUF_SIZE;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkPushTheKey Success,
> Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +End:
> 
> +  DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkPushTheKey End\n"));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Process key notify.
> 
> +
> 
> +  @param[in] Event                 Indicates the event that invoke this function.
> 
> +  @param[in] Context               Indicates the calling context.
> 
> +
> 
> +**/
> 
> +VOID
> 
> +EFIAPI
> 
> +VkKeyNotifyProcessHandler (
> 
> +  IN  EFI_EVENT Event,
> 
> +  IN  VOID      *Context
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS   Status;
> 
> +  VK_CONTEXT   *VkContext;
> 
> +  EFI_KEY_DATA KeyData;
> 
> +  LIST_ENTRY   *Link;
> 
> +  LIST_ENTRY   *NotifyList;
> 
> +  VK_NOTIFY    *CurrentNotify;
> 
> +  EFI_TPL      OldTpl;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyNotifyProcessHandler
> Start\n"));
> 
> +  VkContext = (VK_CONTEXT *) Context;
> 
> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
> 
> +
> 
> +  //
> 
> +  // Invoke notification functions.
> 
> +  //
> 
> +  NotifyList = &VkContext->NotifyList;
> 
> +  Status = VkPopTheKey (VkContext, &KeyData);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link =
> GetNextNode (NotifyList, Link)) {
> 
> +    CurrentNotify = CR (Link, VK_NOTIFY, NotifyEntry,
> VK_NOTIFY_SIGNATURE);
> 
> +    if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
> 
> +      CurrentNotify->KeyNotificationFn (&KeyData);
> 
> +    }
> 
> +  }
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyNotifyProcessHandler
> Success, Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyNotifyProcessHandler
> Failed, Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  gBS->RestoreTPL (OldTpl);
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyNotifyProcessHandler
> End\n"));
> 
> +}
> 
> +
> 
> +/**
> 
> +  Push the event mapping key index to the input key buffer.
> 
> +
> 
> +  @param[in]  VkContext        Address of an VK_CONTEXT structure.
> 
> +  @param[out] KeyItem          Key Item.
> 
> +  @param[out] Index            Index of Key Item.
> 
> +  @param[in]  TouchX           X position of finger touch.
> 
> +  @param[in]  TouchY           Y position of finger touch.
> 
> +
> 
> +  @retval TRUE                 Touch on Virtual Keyboard.
> 
> +  @retval FALSE                Not touch on Virtual Keyboard.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +IsTouchVk (
> 
> +  IN  VK_CONTEXT *VkContext,
> 
> +  OUT VK_STRUCT  *KeyItem,
> 
> +  OUT UINT32     *Index,
> 
> +  IN  UINT32     TouchX,
> 
> +  IN  UINT32     TouchY
> 
> +  )
> 
> +{
> 
> +  for (*Index = 0; *Index < VkContext->NumOfKeysInfo; (*Index)++) {
> 
> +    if (VkContext->KeyboardBodyPtr[*Index].DisStartX < TouchX &&
> 
> +        VkContext->KeyboardBodyPtr[*Index].DisEndX   > TouchX &&
> 
> +        VkContext->KeyboardBodyPtr[*Index].DisStartY < TouchY &&
> 
> +        VkContext->KeyboardBodyPtr[*Index].DisEndY   > TouchY) {
> 
> +      break;
> 
> +    }
> 
> +  }
> 
> +  if (*Index != VkContext->NumOfKeysInfo) {
> 
> +    *KeyItem = VkContext->KeyboardBodyPtr[*Index];
> 
> +  }
> 
> +
> 
> +  return *Index != VkContext->NumOfKeysInfo;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Call back function when ready to boot into OS.
> 
> +
> 
> +  It will clear the Virtual Keyboard.
> 
> +
> 
> +  @param[in] Event    Event whose notification function is being invoked.
> 
> +  @param[in] Context  Pointer to the VkContext.
> 
> +
> 
> +**/
> 
> +VOID
> 
> +EFIAPI
> 
> +VkReadyToBootCallBack (
> 
> +  IN EFI_EVENT Event,
> 
> +  IN VOID      *Context
> 
> +  )
> 
> +{
> 
> +  VK_CONTEXT                    *VkContext;
> 
> +  VkContext = (VK_CONTEXT *)Context;
> 
> +
> 
> +  HideVkBody (VkContext);
> 
> +  VkContext->TargetKeyboardDisplay  = VkDisplayAttributeNone;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Timer event
> 
> +
> 
> +  This routine is called at TPL_VK_SYNC.
> 
> +
> 
> +  This routine polls for touch panel input.
> 
> +
> 
> +  @param[in] Event    Event whose notification function is being invoked.
> 
> +  @param[in] Context  Pointer to the notification function's context,
> 
> +                      which is implementation-dependent. Context corresponds
> 
> +                      to NotifyContext in CreateEventEx().
> 
> +
> 
> +**/
> 
> +VOID
> 
> +EFIAPI
> 
> +VkTimer (
> 
> +  IN EFI_EVENT Event,
> 
> +  IN VOID      *Context
> 
> +  )
> 
> +{
> 
> +  EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;
> 
> +  EFI_ABSOLUTE_POINTER_STATE    Point;
> 
> +  EFI_STATUS                    Status;
> 
> +  UINT32                        TouchX;
> 
> +  UINT32                        TouchY;
> 
> +  VK_CONTEXT                    *VkContext;
> 
> +  UINT32                        Index;
> 
> +  VK_STRUCT                     KeyItem;
> 
> +  UINT32                        Font;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkTimer Start\n"));
> 
> +  VkContext = (VK_CONTEXT *)Context;
> 
> +
> 
> +  //
> 
> +  // Update keyboard UI layout
> 
> +  //
> 
> +  CheckIconCleared (VkContext);
> 
> +  CheckScreenCleared (VkContext);
> 
> +  CheckBackgroundChanged (VkContext);
> 
> +  if (VkContext->IsRedrawUpdateUI) {
> 
> +    HideVkBody (VkContext);
> 
> +    DrawKeyboardLayout (VkContext);
> 
> +    VkContext->IsRedrawUpdateUI = FALSE;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Error handle for invalid information
> 
> +  //
> 
> +  AbsolutePointer = VkContext->AbsolutePointer;
> 
> +  Status = gBS->CheckEvent (AbsolutePointer->WaitForInput);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    if (Status != EFI_NOT_READY) {
> 
> +      DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_VK_POINTS, "ERROR
> - VkContext->AbsolutePointer->WaitForInput->CheckEvent failed!
> Status: %r\n", Status));
> 
> +    }
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  Status = AbsolutePointer->GetState (AbsolutePointer, &Point);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_VK_POINTS, "ERROR
> - GetState failed, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  if (VkContext->AbsolutePointer->Mode->AbsoluteMaxX <=
> Point.CurrentX) {
> 
> +    DEBUG ((
> 
> +      DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_VK_POINTS,
> 
> +      "ERROR - X value exceeds maximum: X: 0x%016Lx, MaxX: 0x%016Lx\n",
> 
> +      Point.CurrentX,
> 
> +      VkContext->AbsolutePointer->Mode->AbsoluteMaxX
> 
> +      ));
> 
> +    Status = EFI_PROTOCOL_ERROR;
> 
> +    goto Error;
> 
> +  }
> 
> +  if (VkContext->AbsolutePointer->Mode->AbsoluteMaxY <=
> Point.CurrentY) {
> 
> +    DEBUG ((
> 
> +      DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_VK_POINTS,
> 
> +      "ERROR - Y value exceeds maximum: Y: 0x%016Lx, MaxY: 0x%016Lx\n",
> 
> +      Point.CurrentY,
> 
> +      VkContext->AbsolutePointer->Mode->AbsoluteMaxY
> 
> +      ));
> 
> +    Status = EFI_PROTOCOL_ERROR;
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Update the touch active status
> 
> +  //
> 
> +  VkContext->TouchActive = ((Point.ActiveButtons &
> EFI_ABSP_TouchActive) != 0) ? TRUE : FALSE;
> 
> +  if (!VkContext->TouchActive) {
> 
> +    VkContext->KeyPressed = FALSE;
> 
> +  }
> 
> +  ConvertCoordinate (VkContext, Point, &TouchX, &TouchY);
> 
> +
> 
> +  if (!VkContext->KeyPressed &&
> 
> +      VkContext->TouchActive &&
> 
> +      IsTouchVk (VkContext, &KeyItem, &Index, TouchX, TouchY)) {
> 
> +    VkGetMappingFont (VkContext, KeyItem, &Font);
> 
> +    DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO,                   "VK
> Touch event is trigger!\n" ));
> 
> +    DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO |
> DEBUG_VK_POINTS, "TouchActive:            0x%04x  \n", VkContext-
> >TouchActive));
> 
> +    DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO |
> DEBUG_VK_POINTS, "CurrentKeyboardDisplay: 0x%04x  \n", VkContext-
> >CurrentKeyboardDisplay));
> 
> +    DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO |
> DEBUG_VK_POINTS, "X:                      0x%016Lx\n", Point.CurrentX));
> 
> +    DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO |
> DEBUG_VK_POINTS, "Y:                      0x%016Lx\n", Point.CurrentY));
> 
> +    DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO |
> DEBUG_VK_POINTS, "Z:                      0x%016Lx\n", Point.CurrentZ));
> 
> +    DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO |
> DEBUG_VK_POINTS, "Buttons:                0x%08x  \n", Point.ActiveButtons));
> 
> +    DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO |
> DEBUG_VK_POINTS, "MapKey Index:           0x%04x  \n", Index));
> 
> +    DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO |
> DEBUG_VK_POINTS, "Key Unicode:            0x%08x  \n", Font));
> 
> +
> 
> +    switch (Font) {
> 
> +    //
> 
> +    // Touch the small keyboard icon, show/hide the keyboard.
> 
> +    //
> 
> +    case VkKeyTypeMaximum:
> 
> +      KeyboardLayoutHandler (VkContext, Index);
> 
> +      break;
> 
> +
> 
> +    //
> 
> +    // Touch the key raw.
> 
> +    //
> 
> +    default:
> 
> +      if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeNone) {
> 
> +        break;
> 
> +      }
> 
> +      VkPushTheKey (VkContext, (UINT16) Font);
> 
> +    }
> 
> +    VkContext->KeyPressed = TRUE;
> 
> +  }
> 
> +
> 
> +  DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkTimer Success, Status: %r\n",
> Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkTimer Failed, Status: %r\n",
> Status));
> 
> +
> 
> +End:
> 
> +  DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkTimer End\n"));
> 
> +  return;
> 
> +}
> 
> +
> 
> +/**
> 
> +  VkTouchWaitForKey - SignalEvent when the keybuffer has keys.
> 
> +
> 
> +  @param[in] Event    Event whose notification function is being invoked.
> 
> +  @param[in] Context  Pointer to the notification function's context,
> 
> +                      which is implementation-dependent.  Context corresponds
> 
> +                      to NotifyContext in CreateEventEx().
> 
> +
> 
> +**/
> 
> +VOID
> 
> +EFIAPI
> 
> +VkTouchWaitForKey (
> 
> +  IN EFI_EVENT Event,
> 
> +  IN VOID      *Context
> 
> +  )
> 
> +{
> 
> +  VK_CONTEXT *VkContext;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkTouchWaitForKey
> Start\n"));
> 
> +  VkContext = (VK_CONTEXT*) Context;
> 
> +
> 
> +  if (VkContext->KeyStartIndex != VkContext->KeyEndIndex) {
> 
> +    DEBUG ((DEBUG_VK_KEYS, "Signal VkTouchWaitForKey\n"));
> 
> +    gBS->SignalEvent (Event);
> 
> +  }
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkTouchWaitForKey
> End\n"));
> 
> +}
> 
> +
> 
> +/**
> 
> +  Get image file data from BIOS image through specific ImageId.
> 
> +
> 
> +  @param[in] VkContext      Address of an VK_CONTEXT structure.
> 
> +  @param[in] ImageId        Guid to get specific image file used.
> 
> +
> 
> +  @retval EFI_IMAGE_INPUT   Image data on BIOS image.
> 
> +
> 
> +**/
> 
> +EFI_IMAGE_INPUT*
> 
> +VkGetImage (
> 
> +  IN VK_CONTEXT   *VkContext,
> 
> +  IN EFI_IMAGE_ID ImageId
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS      Status;
> 
> +  EFI_IMAGE_INPUT Image;
> 
> +  EFI_IMAGE_INPUT *VkImage;
> 
> +
> 
> +
> 
> +  Status = VkContext->HiiImageEx->GetImageEx (
> 
> +                                    VkContext->HiiImageEx,
> 
> +                                    VkContext->HiiHandle,
> 
> +                                    ImageId,
> 
> +                                    &Image
> 
> +                                    );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +  }
> 
> +
> 
> +  VkImage = AllocateCopyPool (sizeof (EFI_IMAGE_INPUT), &Image);
> 
> +  if (VkImage == NULL) {
> 
> +    ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);
> 
> +    return NULL;
> 
> +  }
> 
> +
> 
> +  return VkImage;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Dump partial debug message on VkContext.
> 
> +
> 
> +  @param[in] VkContext        Address of an VK_CONTEXT structure.
> 
> +
> 
> +**/
> 
> +VOID
> 
> +VkDumpContext (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  )
> 
> +{
> 
> +  DEBUG ((
> 
> +    DEBUG_VK_ROUTINE_ENTRY_EXIT,
> 
> +    "VkContext->Signature: 0x%016x\n",
> 
> +    VkContext->Signature
> 
> +    ));
> 
> +  DEBUG ((
> 
> +    DEBUG_VK_ROUTINE_ENTRY_EXIT,
> 
> +    "VkContext->Controller: 0x%016x\n",
> 
> +    VkContext->Controller
> 
> +    ));
> 
> +  DEBUG ((
> 
> +    DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_GRAPHICS_INFO,
> 
> +    "VkContext->GraphicsOutput->Mode->MaxMode: 0x%08x\n",
> 
> +    VkContext->GraphicsOutput->Mode->MaxMode
> 
> +    ));
> 
> +  DEBUG ((
> 
> +    DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_GRAPHICS_INFO,
> 
> +    "VkContext->GraphicsOutput->Mode->Mode: 0x%08x\n",
> 
> +    VkContext->GraphicsOutput->Mode->Mode
> 
> +    ));
> 
> +  DEBUG ((
> 
> +    DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_GRAPHICS_INFO,
> 
> +    "VkContext->GraphicsOutput->Mode->Info->HorizontalResolution:
> 0x%08x\n",
> 
> +    VkContext->GraphicsOutput->Mode->Info->HorizontalResolution
> 
> +    ));
> 
> +  DEBUG ((
> 
> +    DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_GRAPHICS_INFO,
> 
> +    "VkContext->GraphicsOutput->Mode->Info->VerticalResolution:
> 0x%08x\n",
> 
> +    VkContext->GraphicsOutput->Mode->Info->VerticalResolution
> 
> +    ));
> 
> +  DEBUG ((
> 
> +    DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_POINTS,
> 
> +    "VkContext->AbsolutePointer->Mode X: 0x%016Lx - 0x%016Lx\n",
> 
> +    VkContext->AbsolutePointer->Mode->AbsoluteMinX,
> 
> +    VkContext->AbsolutePointer->Mode->AbsoluteMaxX
> 
> +    ));
> 
> +  DEBUG ((
> 
> +    DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_POINTS,
> 
> +    "VkContext->AbsolutePointer->Mode Y: 0x%016Lx - 0x%016Lx\n",
> 
> +    VkContext->AbsolutePointer->Mode->AbsoluteMinY,
> 
> +    VkContext->AbsolutePointer->Mode->AbsoluteMaxY
> 
> +    ));
> 
> +  DEBUG ((
> 
> +    DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_POINTS,
> 
> +    "VkContext->AbsolutePointer->Mode Z: 0x%016Lx - 0x%016Lx\n",
> 
> +    VkContext->AbsolutePointer->Mode->AbsoluteMinZ,
> 
> +    VkContext->AbsolutePointer->Mode->AbsoluteMaxZ
> 
> +    ));
> 
> +  DEBUG ((
> 
> +    DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_POINTS,
> 
> +    "VkContext->AbsolutePointer->Mode->Attributes: 0x%08x\n",
> 
> +    VkContext->AbsolutePointer->Mode->Attributes
> 
> +    ));
> 
> +}
> 
> +
> 
> +/**
> 
> +  Start the virtual keyboard driver
> 
> +
> 
> +  This routine allocates the necessary resources for the driver.
> 
> +
> 
> +  This routine is called by VirtualKeyboardDriverStart to complete the driver
> 
> +  initialization.
> 
> +
> 
> +  @param[in, out] VkContext        Address of an VK_CONTEXT structure
> 
> +  @param[in]      Controller       Handle of device to work with.
> 
> +
> 
> +  @retval EFI_SUCCESS              Driver API properly initialized
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +VkApiStart (
> 
> +  IN OUT VK_CONTEXT *VkContext,
> 
> +  IN EFI_HANDLE     Controller
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                        Status;
> 
> +  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
> 
> +  EFI_KEY_DATA                      KeyData;
> 
> +  EFI_HANDLE                        NotifyHandle;
> 
> +  EFI_EVENT                         ReadyToBootEvent;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStart Start\n"));
> 
> +
> 
> +  Status = gBS->CreateEvent (
> 
> +                  EVT_NOTIFY_SIGNAL,
> 
> +                  TPL_CALLBACK,
> 
> +                  VkKeyNotifyProcessHandler,
> 
> +                  VkContext,
> 
> +                  &VkContext->KeyNotifyProcessEvent
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to create VkContext->KeyNotifyProcessEvent, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  Status = gBS->CreateEvent (
> 
> +                  EVT_NOTIFY_WAIT,
> 
> +                  TPL_NOTIFY,
> 
> +                  VkTouchWaitForKey,
> 
> +                  VkContext,
> 
> +                  &(VkContext->SimpleTextIn.WaitForKey)
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to create VkContext->SimpleTextIn.WaitForKey, Status: %r\n",
> Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  Status = gBS->CreateEvent (
> 
> +                  EVT_NOTIFY_WAIT,
> 
> +                  TPL_NOTIFY,
> 
> +                  VkTouchWaitForKey,
> 
> +                  VkContext,
> 
> +                  &(VkContext->SimpleTextInEx.WaitForKeyEx)
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to create VkContext->SimpleTextInEx.WaitForKeyEx, Status %r\n",
> Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  Status = gBS->CreateEvent (
> 
> +                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
> 
> +                  TPL_VK_SYNC,
> 
> +                  VkTimer,
> 
> +                  (VOID *)VkContext,
> 
> +                  &(VkContext->TimerEvent)
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to create the timer event, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  Status = gBS->SetTimer (
> 
> +                  VkContext->TimerEvent,
> 
> +                  TimerPeriodic,
> 
> +                  (UINT64) VK_POLL_INTERVAL
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to set the timer event, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Create event to clear keyboard before boot into OS.
> 
> +  //
> 
> +  Status = EfiCreateEventReadyToBootEx (
> 
> +             TPL_CALLBACK,
> 
> +             VkReadyToBootCallBack,
> 
> +             (VOID *)VkContext,
> 
> +             &ReadyToBootEvent
> 
> +             );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to create ReadyToBootEvent, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  Status = gBS->LocateProtocol (
> 
> +                  &gEfiHiiImageExProtocolGuid,
> 
> +                  NULL,
> 
> +                  (VOID **) &VkContext->HiiImageEx
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to open HiiImageEx protocol, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Initialize VkContext
> 
> +  //
> 
> +  VkContext->Signature                          = VK_SIGNATURE;
> 
> +  VkContext->Controller                         = Controller;
> 
> +  VkContext->SimpleTextIn.Reset                 = VkKeyboardReset;
> 
> +  VkContext->SimpleTextIn.ReadKeyStroke         =
> VkKeyboardReadKeyStroke;
> 
> +  VkContext->SimpleTextInEx.Reset               = VkKeyboardResetEx;
> 
> +  VkContext->SimpleTextInEx.ReadKeyStrokeEx     =
> VkKeyboardReadKeyStrokeEx;
> 
> +  VkContext->SimpleTextInEx.SetState            = VkKeyboardSetState;
> 
> +  VkContext->SimpleTextInEx.RegisterKeyNotify   =
> VkKeyboardRegisterKeyNotify;
> 
> +  VkContext->SimpleTextInEx.UnregisterKeyNotify =
> VkKeyboardUnregisterKeyNotify;
> 
> +  VkContext->IsIconShowed                       = FALSE;
> 
> +  VkContext->IsBackgroundChanged                = FALSE;
> 
> +  VkContext->PageNumber                         = 0;
> 
> +  VkContext->CurrentKeyboardDisplay             = VkDisplayAttributeNone;
> 
> +  VkContext->TargetKeyboardDisplay              = VkDisplayAttributeNone;
> 
> +  VkContext->VkBodyBackgroundBltBuffer          = NULL;
> 
> +  VkContext->VkBodyCompoundBltBuffer            = NULL;
> 
> +  VkContext->VkBodyBltSize                      = 0;
> 
> +  VkContext->VkBodyBltStartX                    = 0;
> 
> +  VkContext->VkBodyBltStartY                    = 0;
> 
> +  VkContext->VkBodyBltHeight                    = 0;
> 
> +  VkContext->VkBodyBltWidth                     = 0;
> 
> +  VkContext->IconBltBuffer                      = NULL;
> 
> +  VkContext->IconBltSize                        = 0;
> 
> +  VkContext->IconReDrawCheck                    = 0;
> 
> +  VkContext->FullIconUpdatedFlag                = FALSE;
> 
> +  VkContext->SimIconUpdatedFlag                 = FALSE;
> 
> +  VkContext->KeyStartIndex                      = 0;
> 
> +  VkContext->KeyEndIndex                        = 0;
> 
> +  VkContext->KeyToggleState                     = EFI_TOGGLE_STATE_VALID;
> 
> +  VkContext->SmallIcon                          = VkGetImage (VkContext,
> IMAGE_TOKEN (IMG_VK_SIMPLEICON));
> 
> +  VkContext->FullIcon                           = VkGetImage (VkContext,
> IMAGE_TOKEN (IMG_VK_FULLICON));
> 
> +  VkContext->SimKeyBody                         = VkGetImage (VkContext,
> IMAGE_TOKEN (IMG_VK_SIMPLEKEYBOARD));
> 
> +  VkContext->DigKeyBody                         = VkGetImage (VkContext,
> IMAGE_TOKEN (IMG_VK_DIGITKEYBOARD));
> 
> +  VkContext->CapLeKeyBody                       = VkGetImage (VkContext,
> IMAGE_TOKEN (IMG_VK_CAPITALLETTERKEYBOARD));
> 
> +
> 
> +  InitializeListHead (&VkContext->NotifyList);
> 
> +
> 
> +  Status = SetCharacterPosition (VkContext, 800, 600);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  Status = DrawKeyboardLayout (VkContext);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  Status = HideVkBody (VkContext);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  Status = HideVkIcon (VkContext);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  DEBUG_CODE (
> 
> +    VkDumpContext (VkContext);
> 
> +  );
> 
> +
> 
> +  Status = gBS->HandleProtocol (
> 
> +                  gST->ConsoleInHandle,
> 
> +                  &gEfiSimpleTextInputExProtocolGuid,
> 
> +                  (VOID **)&SimpleEx
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to found ConIn Protocol, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  KeyData.KeyState.KeyToggleState = 0;
> 
> +  KeyData.KeyState.KeyShiftState  = 0;
> 
> +  KeyData.Key.ScanCode            = SCAN_ESC;
> 
> +  KeyData.Key.UnicodeChar         = CHAR_NULL;
> 
> +  NotifyHandle                    = NULL;
> 
> +  Status = SimpleEx->RegisterKeyNotify (
> 
> +                       SimpleEx,
> 
> +                       &KeyData,
> 
> +                       VkNotifyKeyCallback,
> 
> +                       &NotifyHandle
> 
> +                       );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to register 'Esc', Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  KeyData.KeyState.KeyToggleState = 0;
> 
> +  KeyData.KeyState.KeyShiftState  = 0;
> 
> +  KeyData.Key.ScanCode            = SCAN_NULL;
> 
> +  KeyData.Key.UnicodeChar         = CHAR_CARRIAGE_RETURN;
> 
> +  Status = SimpleEx->RegisterKeyNotify (
> 
> +                       SimpleEx,
> 
> +                       &KeyData,
> 
> +                       VkNotifyKeyCallback,
> 
> +                       &NotifyHandle
> 
> +                       );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to register 'Enter', Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  for (KeyData.Key.UnicodeChar = L' '; KeyData.Key.UnicodeChar <= L'~';
> KeyData.Key.UnicodeChar++) {
> 
> +    Status = SimpleEx->RegisterKeyNotify (
> 
> +                         SimpleEx,
> 
> +                         &KeyData,
> 
> +                         VkNotifyKeyCallback,
> 
> +                         &NotifyHandle
> 
> +                         );
> 
> +    if (EFI_ERROR (Status)) {
> 
> +      DEBUG ((
> 
> +        DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR,
> 
> +        "ERROR - Failed to register '%c', Status: %r\n",
> 
> +        KeyData.Key.UnicodeChar,
> 
> +        Status
> 
> +        ));
> 
> +      break;
> 
> +    }
> 
> +  }
> 
> +  if (EFI_ERROR(Status)) {
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStart Success,
> Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  VkApiStop (VkContext);
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStart Failed,
> Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStart End\n"));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Stop the virtual keyboard driver
> 
> +
> 
> +  This routine releases the resources allocated by VKApiStart.
> 
> +
> 
> +  This routine is called by VirtualKeyboardDriverStop to initiate the driver
> 
> +  shutdown.
> 
> +
> 
> +  @param[in] VkContext        Address of an VK_CONTEXT structure
> 
> +
> 
> +**/
> 
> +VOID
> 
> +VkApiStop (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS Status;
> 
> +  VK_NOTIFY  *NotifyNode;
> 
> +  LIST_ENTRY *NotifyList;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStop Start\n"));
> 
> +
> 
> +  Status = gBS->SetTimer (VkContext->TimerEvent, TimerCancel, 0);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  if (VkContext->KeyNotifyProcessEvent != NULL) {
> 
> +    Status = gBS->CloseEvent (VkContext->KeyNotifyProcessEvent);
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +    VkContext->KeyNotifyProcessEvent = NULL;
> 
> +  }
> 
> +
> 
> +  if (VkContext->TimerEvent != NULL) {
> 
> +    Status = gBS->CloseEvent (VkContext->TimerEvent);
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +    VkContext->TimerEvent = NULL;
> 
> +  }
> 
> +
> 
> +  if (VkContext->SimpleTextIn.WaitForKey != NULL) {
> 
> +    Status = gBS->CloseEvent (VkContext->SimpleTextIn.WaitForKey);
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +    VkContext->SimpleTextIn.WaitForKey = NULL;
> 
> +  }
> 
> +
> 
> +  if (VkContext->SimpleTextInEx.WaitForKeyEx != NULL) {
> 
> +    Status = gBS->CloseEvent (VkContext->SimpleTextInEx.WaitForKeyEx);
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +    VkContext->SimpleTextInEx.WaitForKeyEx = NULL;
> 
> +  }
> 
> +
> 
> +  NotifyList = &VkContext->NotifyList;
> 
> +  if (NotifyList != NULL) {
> 
> +    while (!IsListEmpty (NotifyList)) {
> 
> +      NotifyNode = CR (NotifyList->ForwardLink, VK_NOTIFY, NotifyEntry,
> VK_NOTIFY_SIGNATURE);
> 
> +      RemoveEntryList (NotifyList->ForwardLink);
> 
> +      gBS->FreePool (NotifyNode);
> 
> +    }
> 
> +  }
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStop End\n"));
> 
> +}
> 
> +
> 
> +/**
> 
> +  Reset the input device and optionally run diagnostics
> 
> +
> 
> +  @param[in] This                 Protocol instance pointer.
> 
> +  @param[in] ExtendedVerification Driver may perform diagnostics on reset.
> 
> +
> 
> +  @retval EFI_SUCCESS             The device was reset.
> 
> +  @retval EFI_DEVICE_ERROR        The device is not functioning properly and
> could not be reset.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardReset (
> 
> +  IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
> 
> +  IN BOOLEAN                        ExtendedVerification
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS Status;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReset Start\n"));
> 
> +  Status = EFI_SUCCESS;
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReset End\n"));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Resets the input device hardware.
> 
> +
> 
> +  The Reset() function resets the input device hardware. As part
> 
> +  of initialization process, the firmware/device will make a quick
> 
> +  but reasonable attempt to verify that the device is functioning.
> 
> +  If the ExtendedVerification flag is TRUE the firmware may take
> 
> +  an extended amount of time to verify the device is operating on
> 
> +  reset. Otherwise the reset operation is to occur as quickly as
> 
> +  possible. The hardware verification process is not defined by
> 
> +  this specification and is left up to the platform firmware or
> 
> +  driver to implement.
> 
> +
> 
> +  @param[in] This                 A pointer to the
> EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
> 
> +
> 
> +  @param[in] ExtendedVerification Indicates that the driver may perform a
> more exhaustive
> 
> +                                  verification operation of the device during reset.
> 
> +
> 
> +  @retval EFI_SUCCESS             The device was reset.
> 
> +  @retval EFI_DEVICE_ERROR        The device is not functioning correctly and
> could not be reset.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardResetEx (
> 
> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
> 
> +  IN BOOLEAN                           ExtendedVerification
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS Status;
> 
> +  VK_CONTEXT *VkContext;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardResetEx
> Start\n"));
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +  if (This == NULL) {
> 
> +    Status = EFI_INVALID_PARAMETER;
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);
> 
> +
> 
> +  Status = VkContext->SimpleTextIn.Reset (&VkContext->SimpleTextIn,
> ExtendedVerification);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_KEYS, "ERROR - Failed to VK reset, Status: %r\n",
> Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardResetEx
> Success, Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardResetEx Failed,
> Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardResetEx
> End\n"));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Reads the next keystroke from the input device. The WaitForKey Event
> can
> 
> +  be used to test for existence of a keystroke via WaitForEvent () call.
> 
> +
> 
> +  @param[in]  This         Protocol instance pointer.
> 
> +  @param[out] Key          Driver may perform diagnostics on reset.
> 
> +
> 
> +  @retval EFI_SUCCESS      The keystroke information was returned.
> 
> +  @retval EFI_NOT_READY    There was no keystroke data available.
> 
> +  @retval EFI_DEVICE_ERROR The keystroke information was not returned
> due to
> 
> +                           hardware errors.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardReadKeyStroke (
> 
> +  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
> 
> +  OUT EFI_INPUT_KEY                  *Key
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS    Status;
> 
> +  VK_CONTEXT    *VkContext;
> 
> +  EFI_KEY_DATA  TmpKeyData;
> 
> +  EFI_TPL       OldTpl;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStroke
> Start\n"));
> 
> +
> 
> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
> 
> +  if (This == NULL || Key == NULL) {
> 
> +    Status = EFI_INVALID_PARAMETER;
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  VkContext = VK_CONTEXT_FROM_PROTOCOL (This);
> 
> +
> 
> +  Status = VkKeyboardReadKeyStrokeEx (&VkContext->SimpleTextInEx,
> &TmpKeyData);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    goto Error;
> 
> +  }
> 
> +  *Key = TmpKeyData.Key;
> 
> +
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStroke
> Success, Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStroke
> Failed, Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  gBS->RestoreTPL (OldTpl);
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStroke
> End\n"));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Reads the next keystroke from the input device.
> 
> +
> 
> +  @param[in]  This               Protocol instance pointer.
> 
> +  @param[out] KeyData            A pointer to a buffer that is filled in with the
> keystroke
> 
> +                                 state data for the key that was pressed.
> 
> +
> 
> +  @retval EFI_SUCCESS            The keystroke information was returned.
> 
> +  @retval EFI_NOT_READY          There was no keystroke data available.
> 
> +  @retval EFI_INVALID_PARAMETER  This or KeyData is NULL.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardReadKeyStrokeEx (
> 
> +  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
> 
> +  OUT EFI_KEY_DATA                      *KeyData
> 
> +  )
> 
> +{
> 
> +  VK_CONTEXT        *VkContext;
> 
> +  EFI_STATUS        Status;
> 
> +  EFI_TPL           OldTpl;
> 
> +  EFI_KEY_DATA      TmpKeyData;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VkKeyboardReadKeyStrokeEx Start\n"));
> 
> +
> 
> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
> 
> +  if (This == NULL || KeyData == NULL) {
> 
> +    Status = EFI_INVALID_PARAMETER;
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);
> 
> +
> 
> +  while (TRUE) {
> 
> +    Status = VkPopTheKey (VkContext, &TmpKeyData);
> 
> +    if (EFI_ERROR (Status)) {
> 
> +      DEBUG ((DEBUG_VK_KEYS, "ERROR - Failed to VkPopTheKey check
> whether keybuffer is empty, Status: %r\n", Status));
> 
> +      goto Error;
> 
> +    }
> 
> +    if (TmpKeyData.Key.ScanCode != SCAN_NULL ||
> TmpKeyData.Key.UnicodeChar != CHAR_NULL) {
> 
> +      break;
> 
> +    }
> 
> +  }
> 
> +  *KeyData = TmpKeyData;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VkKeyboardReadKeyStrokeEx Success, Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VkKeyboardReadKeyStrokeEx Failed, Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  gBS->RestoreTPL (OldTpl);
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VkKeyboardReadKeyStrokeEx End\n"));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Set certain state for the input device.
> 
> +
> 
> +  @param[in] This                 Protocol instance pointer.
> 
> +  @param[in] KeyToggleState       A pointer to the EFI_KEY_TOGGLE_STATE
> to set the
> 
> +                                  state for the input device.
> 
> +
> 
> +  @retval EFI_SUCCESS             The device state was set appropriately.
> 
> +  @retval EFI_INVALID_PARAMETER   This or KeyToggleState is NULL.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardSetState (
> 
> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
> 
> +  IN EFI_KEY_TOGGLE_STATE              *KeyToggleState
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS Status;
> 
> +  VK_CONTEXT *VkContext;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardSetState
> Start\n"));
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +  if (This == NULL || KeyToggleState == NULL) {
> 
> +    Status = EFI_INVALID_PARAMETER;
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);
> 
> +
> 
> +  VkContext->KeyToggleState      = *KeyToggleState;
> 
> +  VkContext->IsCapsLockFlag      = (*KeyToggleState &
> EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE;
> 
> +  VkContext->IsSupportPartialKey = (*KeyToggleState &
> EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED;
> 
> +
> 
> +  if (VkContext->PageNumber >= VkPage0 && VkContext->PageNumber <=
> VkPage1) {
> 
> +    VkContext->PageNumber = VkContext->IsCapsLockFlag ? VkPage1 :
> VkPage0;
> 
> +  }
> 
> +
> 
> +  HideVkBody (VkContext);
> 
> +  DrawKeyboardLayout (VkContext);
> 
> +
> 
> +  DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkContext-
> >KeyToggleState:      %02x\n", VkContext->KeyToggleState));
> 
> +  DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkContext-
> >IsCapsLockFlag:      %02x\n", VkContext->IsCapsLockFlag));
> 
> +  DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkContext-
> >IsSupportPartialKey: %02x\n", VkContext->IsSupportPartialKey));
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardSetState
> Success, Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardSetState Failed,
> Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardSetState
> End\n"));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Register a notification function for a particular keystroke for the input
> device.
> 
> +
> 
> +  @param[in]  This                        Protocol instance pointer.
> 
> +  @param[in]  KeyData                     A pointer to a buffer that is filled in with
> the keystroke
> 
> +                                          information data for the key that was pressed.
> 
> +  @param[in]  KeyNotificationFunction     Points to the function to be called
> when the key
> 
> +                                          sequence is typed specified by KeyData.
> 
> +  @param[out] NotifyHandle                Points to the unique handle assigned to
> the registered notification.
> 
> +
> 
> +  @retval EFI_SUCCESS                     The notification function was registered
> successfully.
> 
> +  @retval EFI_OUT_OF_RESOURCES            Unable to allocate resources for
> necessary data structures.
> 
> +  @retval EFI_INVALID_PARAMETER           KeyData or NotifyHandle or
> KeyNotificationFunction is NULL.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardRegisterKeyNotify (
> 
> +  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
> 
> +  IN  EFI_KEY_DATA                      *KeyData,
> 
> +  IN  EFI_KEY_NOTIFY_FUNCTION           KeyNotificationFunction,
> 
> +  OUT EFI_HANDLE                        *NotifyHandle
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS Status;
> 
> +  EFI_TPL    OldTpl;
> 
> +  VK_CONTEXT *VkContext;
> 
> +  LIST_ENTRY *Link;
> 
> +  VK_NOTIFY  *CurrentNotify;
> 
> +  VK_NOTIFY  *NewNotify;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VkKeyboardRegisterKeyNotify Start\n"));
> 
> +
> 
> +  //
> 
> +  // Enter critical section
> 
> +  //
> 
> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
> 
> +  Status = EFI_SUCCESS;
> 
> +  if (This == NULL || KeyData == NULL || NotifyHandle == NULL ||
> KeyNotificationFunction == NULL) {
> 
> +    Status = EFI_INVALID_PARAMETER;
> 
> +    goto Error;
> 
> +  }
> 
> +  VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);
> 
> +
> 
> +
> 
> +  //
> 
> +  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already
> registered.
> 
> +  //
> 
> +  for (Link = VkContext->NotifyList.ForwardLink; Link != &VkContext-
> >NotifyList; Link = Link->ForwardLink) {
> 
> +    CurrentNotify = CR (Link, VK_NOTIFY, NotifyEntry,
> VK_NOTIFY_SIGNATURE);
> 
> +    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
> 
> +      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
> 
> +        *NotifyHandle = CurrentNotify;
> 
> +        Status = EFI_SUCCESS;
> 
> +        goto End;
> 
> +      }
> 
> +    }
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Allocate resource to save the notification function
> 
> +  //
> 
> +  NewNotify = (VK_NOTIFY *) AllocateZeroPool (sizeof (VK_NOTIFY));
> 
> +  if (NewNotify == NULL) {
> 
> +    Status = EFI_OUT_OF_RESOURCES;
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  NewNotify->Signature         = VK_NOTIFY_SIGNATURE;
> 
> +  NewNotify->KeyNotificationFn = KeyNotificationFunction;
> 
> +  CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
> 
> +  InsertTailList (&VkContext->NotifyList, &NewNotify->NotifyEntry);
> 
> +
> 
> +  *NotifyHandle = NewNotify;
> 
> +  Status        = EFI_SUCCESS;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VkKeyboardRegisterKeyNotify Success, Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VkKeyboardRegisterKeyNotify Failed, Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  //
> 
> +  // Leave critical section and return
> 
> +  //
> 
> +  gBS->RestoreTPL (OldTpl);
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VkKeyboardRegisterKeyNotify End\n"));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Remove a registered notification function from a particular keystroke.
> 
> +
> 
> +  @param[in] This                Protocol instance pointer.
> 
> +  @param[in] NotificationHandle  The handle of the notification function
> being unregistered.
> 
> +
> 
> +  @retval EFI_SUCCESS            The notification function was unregistered
> successfully.
> 
> +  @retval EFI_INVALID_PARAMETER  The NotificationHandle is invalid
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardUnregisterKeyNotify (
> 
> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
> 
> +  IN EFI_HANDLE                        NotificationHandle
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS Status;
> 
> +  VK_CONTEXT *VkContext;
> 
> +  EFI_TPL    OldTpl;
> 
> +  LIST_ENTRY *Link;
> 
> +  VK_NOTIFY  *CurrentNotify;
> 
> +  BOOLEAN    IsFindNotifyHandle;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VkKeyboardUnregisterKeyNotify Start\n"));
> 
> +
> 
> +  //
> 
> +  // Enter critical section
> 
> +  //
> 
> +  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
> 
> +  Status = EFI_SUCCESS;
> 
> +  if (This == NULL || NotificationHandle == NULL) {
> 
> +    Status = EFI_INVALID_PARAMETER;
> 
> +    goto Error;
> 
> +  }
> 
> +  VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);
> 
> +
> 
> +  IsFindNotifyHandle = FALSE;
> 
> +  for (Link = VkContext->NotifyList.ForwardLink; Link != &VkContext-
> >NotifyList; Link = Link->ForwardLink) {
> 
> +    CurrentNotify = CR (Link, VK_NOTIFY, NotifyEntry,
> VK_NOTIFY_SIGNATURE);
> 
> +    if (CurrentNotify == NotificationHandle) {
> 
> +      //
> 
> +      // Remove the notification function from NotifyList and free resources
> 
> +      //
> 
> +      RemoveEntryList (&CurrentNotify->NotifyEntry);
> 
> +
> 
> +      gBS->FreePool (CurrentNotify);
> 
> +      IsFindNotifyHandle = TRUE;
> 
> +      break;
> 
> +    }
> 
> +  }
> 
> +
> 
> +  if (!IsFindNotifyHandle) {
> 
> +    Status = EFI_INVALID_PARAMETER;
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VkKeyboardUnregisterKeyNotify Success, Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VkKeyboardUnregisterKeyNotify Failed, Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  //
> 
> +  // Leave critical section and return
> 
> +  //
> 
> +  gBS->RestoreTPL (OldTpl);
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VkKeyboardUnregisterKeyNotify End\n"));
> 
> +  return Status;
> 
> +}
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/KeyboardLayout.c
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/KeyboardLayout.c
> new file mode 100644
> index 0000000000..744c4324d3
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/KeyboardLayout.c
> @@ -0,0 +1,1438 @@
> +/** @file
> 
> +  Virtural Keyboard Layout Engine
> 
> +
> 
> +  Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "VirtualKeyboard.h"
> 
> +
> 
> +//
> 
> +// 1.FullKeyboardBody
> 
> +// Follow below design
> 
> +//   (1).\KeyboardLayout\CapitalLetterKeyboard.bmp
> 
> +//   (2).\KeyboardLayout\DigitKeyboard.bmp
> 
> +// Based on keyboard's (startX, startY)
> 
> +//
> 
> +// Page0Font
> 
> +// +---+---+---+---+---+---+---+---+---+---+---+
> 
> +// | q | w | e | r | t | y | u | i | o | p |<X|| Line 0
> 
> +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> 
> +// | | a | s | d | f | g | h | j | k | l | F2| | Line 1
> 
> +// +-+---+---+---+---+---+---+---+---+---+---+-+
> 
> +// |Caps | z | x | c | v | b | n | m |aU |Enter| Line 2
> 
> +// +-----+---+---+---+---+---+---+---+---+---+-+
> 
> +// | Esc |12#|       Space       |aL |aD |aR | | Line 3
> 
> +// +-----+---+-------------------+---+---+---+-+
> 
> +//
> 
> +// Page1Font
> 
> +// +---+---+---+---+---+---+---+---+---+---+---+
> 
> +// | Q | W | E | R | T | Y | U | I | O | P |<X|| Line 0
> 
> +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> 
> +// | | A | S | D | F | G | H | J | K | L | F2| | Line 1
> 
> +// +-+---+---+---+---+---+---+---+---+---+---+-+
> 
> +// |Caps | Z | X | C | V | B | N | M |aU |Enter| Line 2
> 
> +// +-----+---+---+---+---+---+---+---+---+---+-+
> 
> +// | Esc |12#|       Space       |aL |aD |aR | | Line 3
> 
> +// +-----+---+-------------------+---+---+---+-+
> 
> +//
> 
> +// Page2Font
> 
> +// +---+---+---+---+---+---+---+---+---+---+---+
> 
> +// | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |<X|| Line 0
> 
> +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> 
> +// | |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10| | Line 1
> 
> +// +-+---+---+---+---+---+---+---+---+---+---+-+
> 
> +// |Shift| . | ; | ' | , | . | / |F11|F12|Enter| Line 2
> 
> +// +-----+---+---+---+---+---+---+---+---+---+-+
> 
> +// | Esc |12#|       Space       | \ | - | = | | Line 3
> 
> +// +-----+---+-------------------+---+---+---+-+
> 
> +//
> 
> +// Page3Font
> 
> +// +---+---+---+---+---+---+---+---+---+---+---+
> 
> +// | ! | @ | # | $ | % | ^ | & | * | ( | ) |<X|| Line 0
> 
> +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> 
> +// | |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10| | Line 1
> 
> +// +-+---+---+---+---+---+---+---+---+---+---+-+
> 
> +// |Shift| ~ | : | " | < | > | ? |F11|F12|Enter| Line 2
> 
> +// +-----+---+---+---+---+---+---+---+---+---+-+
> 
> +// | Esc |12#|       Space       | | | _ | + | | Line 3
> 
> +// +-----+---+-------------------+---+---+---+-+
> 
> +//
> 
> +// 2.Screen Corner
> 
> +// Follow below design
> 
> +//   (1).\KeyboardLayout\SimpleIcon.bmp # Screen Corner A/B
> 
> +//   (2).\KeyboardLayout\FullIcon.bmp   # Screen Corner C/D
> 
> +// +-+------------------------------------+-+
> 
> +// |A|                                    |C|
> 
> +// +-+                                    +-+
> 
> +// |                                        |
> 
> +// |                                        |
> 
> +// |                                        |
> 
> +// |                                        |
> 
> +// |                                        |
> 
> +// |                                        |
> 
> +// +-+                                    +-+
> 
> +// |B|                                    |D|
> 
> +// +-+------------------------------------+-+
> 
> +//
> 
> +VK_STRUCT mFullKeyboardBody[] = {
> 
> +  // StartX  StartY  EndX    EndY     Page0Font            Page1Font            Page2Font
> Page3Font
> 
> +  // Line 0
> 
> +  {  0x0000, 0x0000, 0x0032, 0x0032, {L'q',                L'Q',                L'1',
> L'!'            }},
> 
> +  {  0x0032, 0x0000, 0x0064, 0x0032, {L'w',                L'W',                L'2',
> L'@'            }},
> 
> +  {  0x0064, 0x0000, 0x0096, 0x0032, {L'e',                L'E',                L'3',
> L'#'            }},
> 
> +  {  0x0096, 0x0000, 0x00C8, 0x0032, {L'r',                L'R',                L'4',
> L'$'            }},
> 
> +  {  0x00C8, 0x0000, 0x00FA, 0x0032, {L't',                L'T',                L'5',
> L'%'            }},
> 
> +  {  0x00FA, 0x0000, 0x012C, 0x0032, {L'y',                L'Y',                L'6',
> L'^'            }},
> 
> +  {  0x012C, 0x0000, 0x015E, 0x0032, {L'u',                L'U',                L'7',
> L'&'            }},
> 
> +  {  0x015E, 0x0000, 0x0190, 0x0032, {L'i',                L'I',                L'8',
> L'*'            }},
> 
> +  {  0x0190, 0x0000, 0x01C2, 0x0032, {L'o',                L'O',                L'9',
> L'('            }},
> 
> +  {  0x01C2, 0x0000, 0x01F4, 0x0032, {L'p',                L'P',                L'0',
> L')'            }},
> 
> +  {  0x01F4, 0x0000, 0x0226, 0x0032, {VkKeyBackspace,      VkKeyBackspace,
> VkKeyBackspace,      VkKeyBackspace  }},
> 
> +  // Line 1
> 
> +  {  0x0000, 0x0032, 0x0019, 0x0064, {VkKeyNull,           VkKeyNull,
> VkKeyNull,           VkKeyNull       }},
> 
> +  {  0x0019, 0x0032, 0x004B, 0x0064, {L'a',                L'A',                VkKeyF1,
> VkKeyF1         }},
> 
> +  {  0x004B, 0x0032, 0x007D, 0x0064, {L's',                L'S',                VkKeyF2,
> VkKeyF2         }},
> 
> +  {  0x007D, 0x0032, 0x00AF, 0x0064, {L'd',                L'D',                VkKeyF3,
> VkKeyF3         }},
> 
> +  {  0x00AF, 0x0032, 0x00E1, 0x0064, {L'f',                L'F',                VkKeyF4,
> VkKeyF4         }},
> 
> +  {  0x00E1, 0x0032, 0x0113, 0x0064, {L'g',                L'G',                VkKeyF5,
> VkKeyF5         }},
> 
> +  {  0x0113, 0x0032, 0x0145, 0x0064, {L'h',                L'H',                VkKeyF6,
> VkKeyF6         }},
> 
> +  {  0x0145, 0x0032, 0x0177, 0x0064, {L'j',                L'J',                VkKeyF7,
> VkKeyF7         }},
> 
> +  {  0x0177, 0x0032, 0x01A9, 0x0064, {L'k',                L'K',                VkKeyF8,
> VkKeyF8         }},
> 
> +  {  0x01A9, 0x0032, 0x01DB, 0x0064, {L'l',                L'L',                VkKeyF9,
> VkKeyF9         }},
> 
> +  {  0x01DB, 0x0032, 0x020D, 0x0064, {VkKeyF2,             VkKeyF2,
> VkKeyF10,            VkKeyF10        }},
> 
> +  // Line 2
> 
> +  {  0x0000, 0x0064, 0x004B, 0x0096, {VkKeyCapslock,       VkKeyCapslock,
> VkKeyShift,          VkKeyShift      }},
> 
> +  {  0x004B, 0x0064, 0x007D, 0x0096, {L'z',                L'Z',                L'`',
> L'~'            }},
> 
> +  {  0x007D, 0x0064, 0x00AF, 0x0096, {L'x',                L'X',                L';',
> L':'            }},
> 
> +  {  0x00AF, 0x0064, 0x00E1, 0x0096, {L'c',                L'C',                L'\'',
> L'"'            }},
> 
> +  {  0x00E1, 0x0064, 0x0113, 0x0096, {L'v',                L'V',                L',',
> L'<'            }},
> 
> +  {  0x0113, 0x0064, 0x0145, 0x0096, {L'b',                L'B',                L'.',
> L'>'            }},
> 
> +  {  0x0145, 0x0064, 0x0177, 0x0096, {L'n',                L'N',                L'/',
> L'?'            }},
> 
> +  {  0x0177, 0x0064, 0x01A9, 0x0096, {L'm',                L'M',                VkKeyF11,
> VkKeyF11        }},
> 
> +  {  0x01A9, 0x0064, 0x01DB, 0x0096, {VkKeyUp,             VkKeyUp,
> VkKeyF12,            VkKeyF12        }},
> 
> +  {  0x01DB, 0x0064, 0x0226, 0x0096, {VkKeyEnter,          VkKeyEnter,
> VkKeyEnter,          VkKeyEnter      }},
> 
> +  // Line 3
> 
> +  {  0x0000, 0x0096, 0x004B, 0x00C8, {VkKeyEsc,            VkKeyEsc,
> VkKeyEsc,            VkKeyEsc        }},
> 
> +  {  0x004B, 0x0096, 0x007D, 0x00C8, {VkKeyTwoPage,        VkKeyTwoPage,
> VkKeyTwoPage,        VkKeyTwoPage    }},
> 
> +  {  0x007D, 0x0096, 0x0177, 0x00C8, {L' ',                L' ',                L' ',                L'
> '            }},
> 
> +  {  0x0177, 0x0096, 0x01A9, 0x00C8, {VkKeyLeft,           VkKeyLeft,           L'\\',
> L'|'            }},
> 
> +  {  0x01A9, 0x0096, 0x01DB, 0x00C8, {VkKeyDown,           VkKeyDown,           L'-
> ',                L'_'            }},
> 
> +  {  0x01DB, 0x0096, 0x020D, 0x00C8, {VkKeyRight,          VkKeyRight,          L'=',
> L'+'            }},
> 
> +  // Screen Corner A
> 
> +  {  0x0000, 0x0000, 0x001E, 0x001E, {VkKeyTypeMaximum,
> VkKeyTypeMaximum,    VkKeyTypeMaximum,    VkKeyTypeMaximum}},
> 
> +  // Screen Corner B
> 
> +  {  0x0000, 0x023A, 0x001E, 0x0258, {VkKeyTypeMaximum,
> VkKeyTypeMaximum,    VkKeyTypeMaximum,    VkKeyTypeMaximum}},
> 
> +  // Screen Corner C
> 
> +  {  0x02E4, 0x0000, 0x0320, 0x001E, {VkKeyTypeMaximum,
> VkKeyTypeMaximum,    VkKeyTypeMaximum,    VkKeyTypeMaximum}},
> 
> +  // Screen Corner D
> 
> +  {  0x02E4, 0x023A, 0x0320, 0x0258, {VkKeyTypeMaximum,
> VkKeyTypeMaximum,    VkKeyTypeMaximum,    VkKeyTypeMaximum}}
> 
> +};
> 
> +
> 
> +//
> 
> +// 1.SimpleKeyboardBody
> 
> +// Follow below design
> 
> +//   (1).\KeyboardLayout\SimpleKeyboard.bmp
> 
> +// Based on keyboard's (startX, startY)
> 
> +// +-----+-----+
> 
> +// | Esc |Enter| Line 0
> 
> +// +-----+-----+
> 
> +// | Up  | Down| Line 1
> 
> +// +-----+-----+
> 
> +//
> 
> +// 2.Screen Corner
> 
> +// Follow below design
> 
> +//   (1).\KeyboardLayout\SimpleIcon.bmp # Screen Corner A/B
> 
> +//   (2).\KeyboardLayout\FullIcon.bmp   # Screen Corner C/D
> 
> +// +-+------------------------------------+-+
> 
> +// |A|                                    |C|
> 
> +// +-+                                    +-+
> 
> +// |                                        |
> 
> +// |                                        |
> 
> +// |                                        |
> 
> +// |                                        |
> 
> +// |                                        |
> 
> +// |                                        |
> 
> +// +-+                                    +-+
> 
> +// |B|                                    |D|
> 
> +// +-+------------------------------------+-+
> 
> +//
> 
> +VK_STRUCT mSimpleKeyboardBody[] = {
> 
> +  // StartX  StartY  EndX    EndY     Page0Font            Page1Font            Page2Font
> Page3Font
> 
> +  // Line 0
> 
> +  {  0x0000, 0x0000, 0x0032, 0x0032, {VkKeyEsc,            VkKeyEsc,
> VkKeyEsc,            VkKeyEsc        }},
> 
> +  {  0x0032, 0x0000, 0x0064, 0x0032, {VkKeyEnter,          VkKeyEnter,
> VkKeyEnter,          VkKeyEnter      }},
> 
> +  // Line 1
> 
> +  {  0x0000, 0x0032, 0x0032, 0x0064, {VkKeyUp,             VkKeyUp,
> VkKeyUp,             VkKeyUp         }},
> 
> +  {  0x0032, 0x0032, 0x0064, 0x0064, {VkKeyDown,           VkKeyDown,
> VkKeyDown,           VkKeyDown       }},
> 
> +  // Screen Corner A
> 
> +  {  0x0000, 0x0000, 0x001E, 0x001E, {VkKeyTypeMaximum,
> VkKeyTypeMaximum,    VkKeyTypeMaximum,    VkKeyTypeMaximum}},
> 
> +  // Screen Corner B
> 
> +  {  0x0000, 0x023A, 0x001E, 0x0258, {VkKeyTypeMaximum,
> VkKeyTypeMaximum,    VkKeyTypeMaximum,    VkKeyTypeMaximum}},
> 
> +  // Screen Corner C
> 
> +  {  0x02E4, 0x0000, 0x0320, 0x001E, {VkKeyTypeMaximum,
> VkKeyTypeMaximum,    VkKeyTypeMaximum,    VkKeyTypeMaximum}},
> 
> +  // Screen Corner D
> 
> +  {  0x02E4, 0x023A, 0x0320, 0x0258, {VkKeyTypeMaximum,
> VkKeyTypeMaximum,    VkKeyTypeMaximum,    VkKeyTypeMaximum}}
> 
> +};
> 
> +
> 
> +/**
> 
> +  Modify the color of key if Shift or CapsLock is pressed.
> 
> +
> 
> +  @param[in]       VkContext   Address of an VK_CONTEXT structure.
> 
> +  @param[in, out]  BltBuffer   Address of a blt buffer.
> 
> +
> 
> +  @retval EFI_SUCCESS          Success for the function.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +ModifyShiftKeyColor (
> 
> +  IN     VK_CONTEXT                    *VkContext,
> 
> +  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltBuffer
> 
> +  )
> 
> +{
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TempBltBuffer;
> 
> +  UINTN                         BltSize;
> 
> +  BOOLEAN                       IsPressed;
> 
> +
> 
> +  TempBltBuffer = *BltBuffer;
> 
> +  BltSize       = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth;
> 
> +  IsPressed     = VkContext->PageNumber <= VkPage1 ?
> 
> +                  VkContext->IsCapsLockFlag :
> 
> +                  VkContext->IsShiftKeyFlag;
> 
> +
> 
> +  while (BltSize-- != 0) {
> 
> +    //
> 
> +    // Color gradient issue
> 
> +    //
> 
> +    if (((TempBltBuffer->Red - TempBltBuffer->Green) > 0x20) &&
> 
> +        ((TempBltBuffer->Red - TempBltBuffer->Blue)  > 0x20)) {
> 
> +      if (IsPressed) {
> 
> +        TempBltBuffer->Red   = 0;
> 
> +        TempBltBuffer->Green = 255;
> 
> +        TempBltBuffer->Blue  = 255;
> 
> +      } else {
> 
> +        TempBltBuffer->Red   = 255;
> 
> +        TempBltBuffer->Green = 255;
> 
> +        TempBltBuffer->Blue  = 255;
> 
> +      }
> 
> +    }
> 
> +    TempBltBuffer++;
> 
> +  }
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Make the keyboard transparent.
> 
> +
> 
> +  @param[in]      VkContext      Address of an VK_CONTEXT structure.
> 
> +  @param[in]      IsTransparent  TRUE for set keyboard transparent.
> 
> +  @param[in]      BltIn          Address of keyboard blt buffer.
> 
> +  @param[in, out] BltOut         Address of output blt buffer.
> 
> +                                 NULL will allocate it.
> 
> +
> 
> +  @retval EFI_SUCCESS            Success for the function.
> 
> +  @retval EFI_OUT_OF_RESOURCES   Allocate memory failed.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +MakeKeyboardTransparent (
> 
> +  IN     VK_CONTEXT                    *VkContext,
> 
> +  IN     BOOLEAN                       IsTransparent,
> 
> +  IN     EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltIn,
> 
> +  IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltOut
> 
> +  )
> 
> +{
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Keyboard;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background;
> 
> +  UINTN                         BltSize;
> 
> +
> 
> +  if (*BltOut == NULL) {
> 
> +    *BltOut = AllocateZeroPool (VkContext->VkBodyBltSize);
> 
> +    if (*BltOut == NULL) {
> 
> +      return EFI_OUT_OF_RESOURCES;
> 
> +    }
> 
> +  }
> 
> +  Compound   = *BltOut;
> 
> +  Keyboard   = BltIn;
> 
> +  Background = VkContext->VkBodyBackgroundBltBuffer;
> 
> +  BltSize    = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth;
> 
> +  while (BltSize-- != 0) {
> 
> +    if (IsTransparent) {
> 
> +      Compound->Red   = (Keyboard->Red * TRANSPARENCY_WEIGHT) / 100
> + (Background->Red * (100 - TRANSPARENCY_WEIGHT)) / 100;
> 
> +      Compound->Green = (Keyboard->Green * TRANSPARENCY_WEIGHT) /
> 100 + (Background->Green * (100 - TRANSPARENCY_WEIGHT)) / 100;
> 
> +      Compound->Blue  = (Keyboard->Blue * TRANSPARENCY_WEIGHT) / 100
> + (Background->Blue * (100 - TRANSPARENCY_WEIGHT)) / 100;
> 
> +    } else {
> 
> +      *Compound = *Keyboard;
> 
> +    }
> 
> +    Compound++;
> 
> +    Keyboard++;
> 
> +    Background++;
> 
> +  }
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Save the background blt buffer.
> 
> +
> 
> +  @param[in] VkContext           Address of an VK_CONTEXT structure.
> 
> +  @param[in] BltSize             Size of blt.
> 
> +
> 
> +  @retval EFI_SUCCESS            Success for the function.
> 
> +  @retval EFI_OUT_OF_RESOURCES   Allocate memory failed.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +SaveVkBodyBackgroundBltBuffer (
> 
> +  IN VK_CONTEXT *VkContext,
> 
> +  IN UINTN      BltSize
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                    Status;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *CurrentBltBuffer;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *CurrentBltBufferSave;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *OldBltBuffer;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *OldBltBufferSave;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background;
> 
> +  UINTN                         Size;
> 
> +
> 
> +  CurrentBltBufferSave = NULL;
> 
> +  OldBltBufferSave     = NULL;
> 
> +
> 
> +  //
> 
> +  // Save original blt buffer first.
> 
> +  //
> 
> +  OldBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
> 
> +  if (OldBltBuffer == NULL) {
> 
> +    return EFI_OUT_OF_RESOURCES;
> 
> +  }
> 
> +  if (VkContext->VkBodyBackgroundBltBuffer != NULL) {
> 
> +    CopyMem (OldBltBuffer, VkContext->VkBodyBackgroundBltBuffer,
> VkContext->VkBodyBltSize);
> 
> +  }
> 
> +
> 
> +  if (VkContext->VkBodyBackgroundBltBuffer == NULL) {
> 
> +    VkContext->VkBodyBltSize = BltSize;
> 
> +    VkContext->VkBodyBackgroundBltBuffer = AllocateZeroPool (VkContext-
> >VkBodyBltSize);
> 
> +    ASSERT (VkContext->VkBodyBackgroundBltBuffer != NULL);
> 
> +    if (VkContext->VkBodyBackgroundBltBuffer == NULL) {
> 
> +      return EFI_OUT_OF_RESOURCES;
> 
> +    }
> 
> +  } else if (BltSize > VkContext->VkBodyBltSize) {
> 
> +    VkContext->VkBodyBltSize = BltSize;
> 
> +    FreePool (VkContext->VkBodyBackgroundBltBuffer);
> 
> +    VkContext->VkBodyBackgroundBltBuffer = NULL;
> 
> +    VkContext->VkBodyBackgroundBltBuffer = AllocateZeroPool (VkContext-
> >VkBodyBltSize);
> 
> +    ASSERT (VkContext->VkBodyBackgroundBltBuffer != NULL);
> 
> +    if (VkContext->VkBodyBackgroundBltBuffer == NULL) {
> 
> +      return EFI_OUT_OF_RESOURCES;
> 
> +    }
> 
> +  } else {
> 
> +    ZeroMem (VkContext->VkBodyBackgroundBltBuffer, VkContext-
> >VkBodyBltSize);
> 
> +  }
> 
> +
> 
> +  CurrentBltBuffer = NULL;
> 
> +  if (VkContext->IsBackgroundChanged == TRUE) {
> 
> +    //
> 
> +    // Background changed, merge current visioning blt buffer with old
> background blt buffer.
> 
> +    //
> 
> +    Compound   = VkContext->VkBodyCompoundBltBuffer;
> 
> +    Background = VkContext->VkBodyBackgroundBltBuffer;
> 
> +    CurrentBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
> 
> +    ASSERT (CurrentBltBuffer != NULL);
> 
> +    if (CurrentBltBuffer == NULL) {
> 
> +      return EFI_OUT_OF_RESOURCES;
> 
> +    }
> 
> +    Status = VkContext->GraphicsOutput->Blt (
> 
> +                                          VkContext->GraphicsOutput,
> 
> +                                          CurrentBltBuffer,
> 
> +                                          EfiBltVideoToBltBuffer,
> 
> +                                          VkContext->VkBodyBltStartX,
> 
> +                                          VkContext->VkBodyBltStartY,
> 
> +                                          0,
> 
> +                                          0,
> 
> +                                          VkContext->VkBodyBltWidth,
> 
> +                                          VkContext->VkBodyBltHeight,
> 
> +                                          VkContext->VkBodyBltWidth * sizeof
> (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
> 
> +                                          );
> 
> +    CurrentBltBufferSave = CurrentBltBuffer;
> 
> +    OldBltBufferSave = OldBltBuffer;
> 
> +    Size = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth;
> 
> +    while (Size-- != 0) {
> 
> +      if ((Compound->Red   != CurrentBltBuffer->Red) ||
> 
> +          (Compound->Green != CurrentBltBuffer->Green) ||
> 
> +          (Compound->Blue  != CurrentBltBuffer->Blue)) {
> 
> +        *Background = *CurrentBltBuffer;
> 
> +      } else {
> 
> +        *Background = *OldBltBuffer;
> 
> +      }
> 
> +      Compound++;
> 
> +      Background++;
> 
> +      CurrentBltBuffer++;
> 
> +      OldBltBuffer++;
> 
> +    }
> 
> +  } else {
> 
> +    //
> 
> +    // Background NOT changed, save it to VkBodyBackgroundBltBuffer
> directly.
> 
> +    //
> 
> +    Status = VkContext->GraphicsOutput->Blt (
> 
> +                                          VkContext->GraphicsOutput,
> 
> +                                          VkContext->VkBodyBackgroundBltBuffer,
> 
> +                                          EfiBltVideoToBltBuffer,
> 
> +                                          VkContext->VkBodyBltStartX,
> 
> +                                          VkContext->VkBodyBltStartY,
> 
> +                                          0,
> 
> +                                          0,
> 
> +                                          VkContext->VkBodyBltWidth,
> 
> +                                          VkContext->VkBodyBltHeight,
> 
> +                                          VkContext->VkBodyBltWidth * sizeof
> (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
> 
> +                                          );
> 
> +  }
> 
> +
> 
> +  if (CurrentBltBufferSave != NULL) {
> 
> +    FreePool (CurrentBltBufferSave);
> 
> +  }
> 
> +  if (OldBltBufferSave != NULL) {
> 
> +    FreePool (OldBltBufferSave);
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Restore the background blt buffer.
> 
> +
> 
> +  @param[in] VkContext           Address of an VK_CONTEXT structure.
> 
> +
> 
> +  @retval EFI_SUCCESS            Success for the function.
> 
> +  @retval EFI_UNSUPPORTED        Input blt buffer is NULL.
> 
> +  @retval Others                 An unexpected error occurred.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +RestoreVkBodyBackgroundBltBuffer (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS Status;
> 
> +
> 
> +  if (VkContext->VkBodyBackgroundBltBuffer == NULL) {
> 
> +    return EFI_UNSUPPORTED;
> 
> +  }
> 
> +
> 
> +  Status = VkContext->GraphicsOutput->Blt (
> 
> +                                        VkContext->GraphicsOutput,
> 
> +                                        VkContext->VkBodyBackgroundBltBuffer,
> 
> +                                        EfiBltBufferToVideo,
> 
> +                                        0,
> 
> +                                        0,
> 
> +                                        VkContext->VkBodyBltStartX,
> 
> +                                        VkContext->VkBodyBltStartY,
> 
> +                                        VkContext->VkBodyBltWidth,
> 
> +                                        VkContext->VkBodyBltHeight,
> 
> +                                        VkContext->VkBodyBltWidth * sizeof
> (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
> 
> +                                        );
> 
> +
> 
> +  FreePool (VkContext->VkBodyBackgroundBltBuffer);
> 
> +  VkContext->VkBodyBackgroundBltBuffer = NULL;
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Set the position of character.
> 
> +
> 
> +  @param[in] VkContext      Address of an VK_CONTEXT structure.
> 
> +  @param[in] DestX          X position.
> 
> +  @param[in] DestY          Y position.
> 
> +
> 
> +  @retval EFI_SUCCESS       Success for the function.
> 
> +  @retval Others            An unexpected error occurred.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +SetCharacterPosition (
> 
> +  IN VK_CONTEXT *VkContext,
> 
> +  IN UINT32     DestX,
> 
> +  IN UINT32     DestY
> 
> +  )
> 
> +{
> 
> +  UINTN     Index;
> 
> +  VK_STRUCT *KeyArryPtr;
> 
> +  UINT32    KeyArrySize;
> 
> +
> 
> +  switch (VkContext->TargetKeyboardDisplay) {
> 
> +  case VkDisplayAttributeSimpleTop:
> 
> +  case VkDisplayAttributeSimpleBottom:
> 
> +    KeyArryPtr  = mSimpleKeyboardBody;
> 
> +    KeyArrySize = DIM (mSimpleKeyboardBody);
> 
> +    break;
> 
> +
> 
> +  case VkDisplayAttributeFullBottom:
> 
> +  case VkDisplayAttributeFullTop:
> 
> +    KeyArryPtr = mFullKeyboardBody;
> 
> +    KeyArrySize = DIM (mFullKeyboardBody);
> 
> +    break;
> 
> +
> 
> +  case VkDisplayAttributeNone:
> 
> +    KeyArryPtr = mFullKeyboardBody;
> 
> +    KeyArrySize = DIM (mFullKeyboardBody);
> 
> +    break;
> 
> +
> 
> +  default:
> 
> +    return EFI_UNSUPPORTED;
> 
> +  }
> 
> +
> 
> +  for (Index = 0; Index < KeyArrySize; Index++) {
> 
> +    VkContext->KeyboardBodyPtr[Index] = KeyArryPtr[Index];
> 
> +  }
> 
> +  VkContext->NumOfKeysInfo = KeyArrySize;
> 
> +
> 
> +  for (Index = 0; Index < (VkContext->NumOfKeysInfo - 4); Index++) {
> 
> +    VkContext->KeyboardBodyPtr[Index].DisStartX += (UINT16)DestX;
> 
> +    VkContext->KeyboardBodyPtr[Index].DisStartY += (UINT16)DestY;
> 
> +    VkContext->KeyboardBodyPtr[Index].DisEndX   += (UINT16)DestX;
> 
> +    VkContext->KeyboardBodyPtr[Index].DisEndY   += (UINT16)DestY;
> 
> +  }
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Save the icon background blt buffer.
> 
> +
> 
> +  @param[in] VkContext      Address of an VK_CONTEXT structure.
> 
> +  @param[in] IconType       The icon type.
> 
> +
> 
> +  @retval EFI_SUCCESS            Success for the function.
> 
> +  @retval EFI_OUT_OF_RESOURCES   Allocate memory failed.
> 
> +  @retval Others                 An unexpected error occurred.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +SaveVkIconBackgroundBltBuffer (
> 
> +  IN VK_CONTEXT           *VkContext,
> 
> +  IN VK_DISPLAY_ATTRIBUTE IconType
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                    Status;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GraphicBlt;
> 
> +  UINTN                         BltSize;
> 
> +  UINTN                         Height;
> 
> +  UINTN                         Width;
> 
> +  INTN                          StartX;
> 
> +  INTN                          StartY;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TempIconBackBuffer;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *IconBackBuffer;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound;
> 
> +  UINTN                         Size;
> 
> +  BOOLEAN                       SaveCursor;
> 
> +
> 
> +  Status             = EFI_SUCCESS;
> 
> +  StartX             = 0;
> 
> +  StartY             = 0;
> 
> +  TempIconBackBuffer = NULL;
> 
> +  IconBackBuffer     = NULL;
> 
> +  Compound           = NULL;
> 
> +
> 
> +  if ((IconType == VkDisplayAttributeFullTop) ||
> 
> +      (IconType == VkDisplayAttributeSimpleTop)) {
> 
> +    return EFI_SUCCESS;
> 
> +  }
> 
> +
> 
> +  SaveCursor = gST->ConOut->Mode->CursorVisible;
> 
> +  gST->ConOut->EnableCursor (gST->ConOut, FALSE);
> 
> +
> 
> +  if (IconType == VkDisplayAttributeFullBottom) {
> 
> +    GraphicBlt = VkContext->FullIcon->Bitmap;
> 
> +    BltSize    = VkContext->FullIcon->Height * VkContext->FullIcon->Width *
> sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
> 
> +    Height     = VkContext->FullIcon->Height;
> 
> +    Width      = VkContext->FullIcon->Width;
> 
> +    StartX     = VkContext->FullIconBackStartX;
> 
> +    StartY     = VkContext->FullIconBackStartY;
> 
> +  } else if (IconType == VkDisplayAttributeSimpleBottom) {
> 
> +    GraphicBlt = VkContext->SmallIcon->Bitmap;
> 
> +    BltSize    = VkContext->SmallIcon->Height * VkContext->SmallIcon-
> >Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
> 
> +    Height     = VkContext->SmallIcon->Height;
> 
> +    Width      = VkContext->SmallIcon->Width;
> 
> +    StartX     = VkContext->SimIconBackStartX;
> 
> +    StartY     = VkContext->SimIconBackStartY;
> 
> +  } else {
> 
> +    gST->ConOut->EnableCursor (gST->ConOut, SaveCursor);
> 
> +    return EFI_UNSUPPORTED;
> 
> +  }
> 
> +
> 
> +  IconBackBuffer = AllocateZeroPool (BltSize);
> 
> +  if (IconBackBuffer == NULL) {
> 
> +    gST->ConOut->EnableCursor (gST->ConOut, SaveCursor);
> 
> +    return EFI_OUT_OF_RESOURCES;
> 
> +  }
> 
> +  TempIconBackBuffer = IconBackBuffer;
> 
> +  Status = VkContext->GraphicsOutput->Blt (
> 
> +                                        VkContext->GraphicsOutput,
> 
> +                                        IconBackBuffer,
> 
> +                                        EfiBltVideoToBltBuffer,
> 
> +                                        StartX,
> 
> +                                        StartY,
> 
> +                                        0,
> 
> +                                        0,
> 
> +                                        Width,
> 
> +                                        Height,
> 
> +                                        Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
> 
> +                                        );
> 
> +
> 
> +  if (IconType == VkDisplayAttributeFullBottom) {
> 
> +    //
> 
> +    // Store full icon background framebuffer
> 
> +    //
> 
> +    VkContext->FullIconBackHeight = Height;
> 
> +    VkContext->FullIconBackWidth  = Width;
> 
> +    if (VkContext->FullIconUpdatedFlag == FALSE) {
> 
> +      //
> 
> +      // No icon draw, save the buffer directly.
> 
> +      //
> 
> +      if (VkContext->FullIconBackBuffer == NULL) {
> 
> +        VkContext->FullIconBackBuffer = AllocateZeroPool (BltSize);
> 
> +        VkContext->FullIconBackSize = BltSize;
> 
> +      }
> 
> +      CopyMem (VkContext->FullIconBackBuffer, IconBackBuffer, BltSize);
> 
> +      VkContext->FullIconUpdatedFlag = TRUE;
> 
> +    } else {
> 
> +      if (CompareMem (VkContext->FullIconBackBuffer, IconBackBuffer,
> BltSize) != 0) {
> 
> +        Compound = VkContext->FullIconBackBuffer;
> 
> +        Size = Height * Width;
> 
> +        while (Size-- != 0) {
> 
> +          if ((GraphicBlt->Red   != IconBackBuffer->Red) ||
> 
> +              (GraphicBlt->Green != IconBackBuffer->Green) ||
> 
> +              (GraphicBlt->Blue  != IconBackBuffer->Blue)) {
> 
> +            *Compound = *IconBackBuffer;
> 
> +          }
> 
> +          Compound++;
> 
> +          GraphicBlt++;
> 
> +          IconBackBuffer++;
> 
> +        }
> 
> +      }
> 
> +    }
> 
> +  } else if (IconType == VkDisplayAttributeSimpleBottom) {
> 
> +    //
> 
> +    // Store simple icon background framebuffer
> 
> +    //
> 
> +    VkContext->SimIconBackHeight = Height;
> 
> +    VkContext->SimIconBackWidth  = Width;
> 
> +    if (VkContext->SimIconUpdatedFlag == FALSE) {
> 
> +      //
> 
> +      // No icon draw, save the buffer directly.
> 
> +      //
> 
> +      if (VkContext->SimIconBackBuffer == NULL) {
> 
> +        VkContext->SimIconBackBuffer = AllocateZeroPool (BltSize);
> 
> +        VkContext->SimIconBackSize = BltSize;
> 
> +      }
> 
> +      CopyMem (VkContext->SimIconBackBuffer, IconBackBuffer, BltSize);
> 
> +      VkContext->SimIconUpdatedFlag = TRUE;
> 
> +    } else {
> 
> +      if (CompareMem (VkContext->SimIconBackBuffer, IconBackBuffer,
> BltSize) != 0) {
> 
> +        Compound = VkContext->SimIconBackBuffer;
> 
> +        Size = Height * Width;
> 
> +        while (Size-- != 0) {
> 
> +          if ((GraphicBlt->Red   != IconBackBuffer->Red) ||
> 
> +              (GraphicBlt->Green != IconBackBuffer->Green) ||
> 
> +              (GraphicBlt->Blue  != IconBackBuffer->Blue)) {
> 
> +            *Compound = *IconBackBuffer;
> 
> +          }
> 
> +          Compound++;
> 
> +          GraphicBlt++;
> 
> +          IconBackBuffer++;
> 
> +        }
> 
> +      }
> 
> +    }
> 
> +  }
> 
> +
> 
> +  if (TempIconBackBuffer != NULL)  FreePool (TempIconBackBuffer);
> 
> +
> 
> +  gST->ConOut->EnableCursor (gST->ConOut, SaveCursor);
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Use to draw the keyboard icon.
> 
> +
> 
> +  @param[in] VkContext  Pointer to virtual keyboard's context
> 
> +  @param[in] VkImage    Image of keyboard to display on the screen.
> 
> +  @param[in] Attribute  Attribute of keyboard to display on the screen.
> 
> +
> 
> +  @retval EFI_SUCCESS           ConsoleControl has been flipped to graphics
> and keyboard icon displayed.
> 
> +  @retval EFI_UNSUPPORTED       KeyboardFile not found
> 
> +  @retval EFI_INVALID_PARAMETER Attribute is unknown.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +DrawVkIcon (
> 
> +  IN VK_CONTEXT                    *VkContext,
> 
> +  IN EFI_IMAGE_INPUT               *VkImage,
> 
> +  IN VK_DISPLAY_ATTRIBUTE          Attribute
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                    Status;
> 
> +  UINT32                        SizeOfX;
> 
> +  UINT32                        SizeOfY;
> 
> +  INTN                          DestX;
> 
> +  INTN                          DestY;
> 
> +  UINTN                         CoordinateX;
> 
> +  UINTN                         CoordinateY;
> 
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
> 
> +  UINTN                         BltSize;
> 
> +  UINTN                         Height;
> 
> +  UINTN                         Width;
> 
> +
> 
> +  Status         = EFI_SUCCESS;
> 
> +  GraphicsOutput = VkContext->GraphicsOutput;
> 
> +  SizeOfX        = GraphicsOutput->Mode->Info->HorizontalResolution;
> 
> +  SizeOfY        = GraphicsOutput->Mode->Info->VerticalResolution;
> 
> +  CoordinateX    = 0;
> 
> +  CoordinateY    = 0;
> 
> +  Height         = VkImage->Height;
> 
> +  Width          = VkImage->Width;
> 
> +  Blt            = VkImage->Bitmap;
> 
> +  BltSize        = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (UINT32)(Width
> * Height);
> 
> +
> 
> +  //
> 
> +  // Calculate the display position according to Attribute.
> 
> +  //
> 
> +  switch (Attribute) {
> 
> +  case VkDisplayAttributeSimpleTop:
> 
> +    DestX = CoordinateX;
> 
> +    DestY = CoordinateY;
> 
> +    break;
> 
> +
> 
> +  case VkDisplayAttributeFullTop:
> 
> +    DestX = (SizeOfX - Width - CoordinateX);
> 
> +    DestY = CoordinateY;;
> 
> +    break;
> 
> +
> 
> +  case VkDisplayAttributeFullBottom:
> 
> +    DestX                         = (SizeOfX - Width - CoordinateX);
> 
> +    DestY                         = (SizeOfY - Height - CoordinateY);
> 
> +    VkContext->FullIconBackStartX = DestX;
> 
> +    VkContext->FullIconBackStartY = DestY;
> 
> +    break;
> 
> +
> 
> +  case VkDisplayAttributeSimpleBottom:
> 
> +    DestX = CoordinateX;
> 
> +    DestY = (SizeOfY - Height - CoordinateY);
> 
> +
> 
> +    //
> 
> +    // Save to check icon/screen cleared
> 
> +    //
> 
> +    if (VkContext->IconBltBuffer == NULL) {
> 
> +      VkContext->IconBltSize   = BltSize;
> 
> +      VkContext->IconBltWidth  = Width;
> 
> +      VkContext->IconBltHeight = Height;
> 
> +      VkContext->IconBltBuffer = AllocateZeroPool (BltSize);
> 
> +    }
> 
> +    CopyMem (VkContext->IconBltBuffer, Blt, VkContext->IconBltSize);
> 
> +
> 
> +    VkContext->SimIconBackStartX = DestX;
> 
> +    VkContext->SimIconBackStartY = DestY;
> 
> +    break;
> 
> +
> 
> +  case VkDisplayAttributeNone:
> 
> +    return EFI_SUCCESS;
> 
> +
> 
> +  default:
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +
> 
> +  if ((DestX >= 0) && (DestY >= 0)) {
> 
> +    //
> 
> +    // Store icon background framebuffer
> 
> +    //
> 
> +    SaveVkIconBackgroundBltBuffer (VkContext, Attribute);
> 
> +    Status = GraphicsOutput->Blt (
> 
> +                               GraphicsOutput,
> 
> +                               Blt,
> 
> +                               EfiBltBufferToVideo,
> 
> +                               0,
> 
> +                               0,
> 
> +                               (UINTN) DestX,
> 
> +                               (UINTN) DestY,
> 
> +                               Width,
> 
> +                               Height,
> 
> +                               Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
> 
> +                               );
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Use to draw the keyboard.
> 
> +
> 
> +  @param[in] VkContext  Pointer to virtual keyboard's context
> 
> +  @param[in] VkImage    Image of keyboard to display on the screen.
> 
> +  @param[in] Attribute  Attribute of keyboard to display on the screen.
> 
> +
> 
> +  @retval EFI_SUCCESS           ConsoleControl has been flipped to graphics
> and keyboard displayed.
> 
> +  @retval EFI_UNSUPPORTED       KeyboardFile not found
> 
> +  @retval EFI_INVALID_PARAMETER Attribute is unknown.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +DrawVkBody (
> 
> +  IN VK_CONTEXT                    *VkContext,
> 
> +  IN EFI_IMAGE_INPUT               *VkImage,
> 
> +  IN VK_DISPLAY_ATTRIBUTE          Attribute
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                    Status;
> 
> +  UINT32                        SizeOfX;
> 
> +  UINT32                        SizeOfY;
> 
> +  INTN                          DestX;
> 
> +  INTN                          DestY;
> 
> +  UINTN                         BltSize;
> 
> +  UINTN                         Height;
> 
> +  UINTN                         Width;
> 
> +  UINTN                         CoordinateY;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltIn;
> 
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;
> 
> +
> 
> +  Status         = EFI_SUCCESS;
> 
> +  GraphicsOutput = VkContext->GraphicsOutput;
> 
> +  SizeOfX        = GraphicsOutput->Mode->Info->HorizontalResolution;
> 
> +  SizeOfY        = GraphicsOutput->Mode->Info->VerticalResolution;
> 
> +  CoordinateY    = 0;
> 
> +  Height         = VkImage->Height;
> 
> +  Width          = VkImage->Width;
> 
> +  BltSize        = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (UINT32)(Width
> * Height);
> 
> +  BltIn          = AllocateCopyPool (BltSize, VkImage->Bitmap);
> 
> +
> 
> +  if (BltIn == NULL) {
> 
> +    return EFI_OUT_OF_RESOURCES;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Calculate the display position according to Attribute.
> 
> +  //
> 
> +  switch (Attribute) {
> 
> +  case VkDisplayAttributeSimpleTop:
> 
> +    DestX = ((SizeOfX / 2) - Width) / 4;
> 
> +    DestY = CoordinateY;
> 
> +    VkContext->CurrentKeyboardDisplay = VkDisplayAttributeSimpleTop;
> 
> +    break;
> 
> +
> 
> +  case VkDisplayAttributeSimpleBottom:
> 
> +    DestX = ((SizeOfX / 2) - Width) / 4;
> 
> +    DestY = (SizeOfY - Height - CoordinateY);
> 
> +    VkContext->CurrentKeyboardDisplay = VkDisplayAttributeSimpleBottom;
> 
> +    break;
> 
> +
> 
> +  case VkDisplayAttributeFullTop:
> 
> +    DestX = (SizeOfX - Width) / 2;
> 
> +    DestY = CoordinateY;
> 
> +    VkContext->CurrentKeyboardDisplay = VkDisplayAttributeFullTop;
> 
> +    break;
> 
> +
> 
> +  case VkDisplayAttributeFullBottom:
> 
> +    DestX = (SizeOfX - Width) / 2;
> 
> +    DestY = (SizeOfY - Height - CoordinateY);
> 
> +    VkContext->CurrentKeyboardDisplay = VkDisplayAttributeFullBottom;
> 
> +    break;
> 
> +
> 
> +  case VkDisplayAttributeNone:
> 
> +    VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
> 
> +    goto DVKBODY_Exit;
> 
> +
> 
> +  default:
> 
> +    VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
> 
> +    Status = EFI_INVALID_PARAMETER;
> 
> +    goto DVKBODY_Exit;
> 
> +  }
> 
> +  if ((DestX >= 0) && (DestY >= 0)) {
> 
> +    SetCharacterPosition (VkContext, (UINT32)DestX, (UINT32)DestY);
> 
> +
> 
> +    //
> 
> +    // Store current framebuffer
> 
> +    //
> 
> +    VkContext->VkBodyBltStartX = DestX;
> 
> +    VkContext->VkBodyBltStartY = DestY;
> 
> +    VkContext->VkBodyBltHeight = Height;
> 
> +    VkContext->VkBodyBltWidth  = Width;
> 
> +    SaveVkBodyBackgroundBltBuffer (VkContext, BltSize);
> 
> +
> 
> +    //
> 
> +    // Free compound buffer first.
> 
> +    //
> 
> +    if (VkContext->VkBodyCompoundBltBuffer != NULL) {
> 
> +      FreePool (VkContext->VkBodyCompoundBltBuffer);
> 
> +    }
> 
> +    VkContext->VkBodyCompoundBltBuffer = NULL;
> 
> +    ModifyShiftKeyColor (VkContext, &BltIn);
> 
> +    MakeKeyboardTransparent (VkContext, TRUE, BltIn, &(VkContext-
> >VkBodyCompoundBltBuffer));
> 
> +
> 
> +    //
> 
> +    // Draw keyboard body
> 
> +    //
> 
> +    Status = GraphicsOutput->Blt (
> 
> +                               GraphicsOutput,
> 
> +                               VkContext->VkBodyCompoundBltBuffer,
> 
> +                               EfiBltBufferToVideo,
> 
> +                               0,
> 
> +                               0,
> 
> +                               (UINTN) DestX,
> 
> +                               (UINTN) DestY,
> 
> +                               Width,
> 
> +                               Height,
> 
> +                               Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
> 
> +                               );
> 
> +  }
> 
> +
> 
> +
> 
> +DVKBODY_Exit:
> 
> +  if (BltIn != NULL) {
> 
> +    FreePool (BltIn);
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Clear the keyboard body
> 
> +
> 
> +  @param  VkContext             Code context.
> 
> +
> 
> +  @retval EFI_SUCCESS           Clear rectangle is done.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +HideVkBody (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  )
> 
> +{
> 
> +  RestoreVkBodyBackgroundBltBuffer (VkContext);
> 
> +  VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  Clear the keyboard icon
> 
> +
> 
> +  @param  VkContext             Code context.
> 
> +
> 
> +  @retval EFI_SUCCESS           Clear rectangle is done.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +HideVkIcon (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                    Status;
> 
> +
> 
> +  if ((VkContext->FullIconBackBuffer == NULL) || (VkContext-
> >SimIconBackBuffer == NULL)) {
> 
> +    return EFI_UNSUPPORTED;
> 
> +  }
> 
> +
> 
> +  if ((VkContext->FullIconUpdatedFlag == FALSE) || (VkContext-
> >SimIconUpdatedFlag == FALSE)) {
> 
> +    return EFI_UNSUPPORTED;
> 
> +  }
> 
> +  Status = VkContext->GraphicsOutput->Blt (
> 
> +                                        VkContext->GraphicsOutput,
> 
> +                                        VkContext->FullIconBackBuffer,
> 
> +                                        EfiBltBufferToVideo,
> 
> +                                        0,
> 
> +                                        0,
> 
> +                                        VkContext->FullIconBackStartX,
> 
> +                                        VkContext->FullIconBackStartY,
> 
> +                                        VkContext->FullIconBackWidth,
> 
> +                                        VkContext->FullIconBackHeight,
> 
> +                                        VkContext->FullIconBackWidth * sizeof
> (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
> 
> +                                        );
> 
> +
> 
> +  ZeroMem (VkContext->FullIconBackBuffer, VkContext->FullIconBackSize);
> 
> +  VkContext->FullIconUpdatedFlag = FALSE;
> 
> +
> 
> +
> 
> +  Status = VkContext->GraphicsOutput->Blt (
> 
> +                                        VkContext->GraphicsOutput,
> 
> +                                        VkContext->SimIconBackBuffer,
> 
> +                                        EfiBltBufferToVideo,
> 
> +                                        0,
> 
> +                                        0,
> 
> +                                        VkContext->SimIconBackStartX,
> 
> +                                        VkContext->SimIconBackStartY,
> 
> +                                        VkContext->SimIconBackWidth,
> 
> +                                        VkContext->SimIconBackHeight,
> 
> +                                        VkContext->SimIconBackWidth * sizeof
> (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
> 
> +                                        );
> 
> +  if (!EFI_ERROR (Status)) {
> 
> +    if (VkContext->ScreenCheckBuffer == NULL) {
> 
> +      VkContext->ScreenCheckBufferSize = VkContext->SimIconBackHeight *
> 
> +                                         VkContext->SimIconBackWidth *
> 
> +                                         sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
> 
> +      VkContext->ScreenCheckBuffer = AllocateZeroPool (VkContext-
> >ScreenCheckBufferSize);
> 
> +    }
> 
> +
> 
> +    CopyMem (
> 
> +      VkContext->ScreenCheckBuffer,
> 
> +      VkContext->SimIconBackBuffer,
> 
> +      (VkContext->SimIconBackHeight * VkContext->SimIconBackWidth *
> sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))
> 
> +      );
> 
> +  }
> 
> +  ZeroMem (VkContext->SimIconBackBuffer, VkContext->SimIconBackSize);
> 
> +  VkContext->SimIconUpdatedFlag = FALSE;
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Draw key board on the display
> 
> +
> 
> +  @param[in] VkContext          Graphic Protocol for draw the alphabet.
> 
> +
> 
> +  @retval EFI_SUCCESS           Draw keyboard was done.
> 
> +  @retval EFI_UNSUPPORTED       Did not get key mapping table.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +DrawKeyboardLayout (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS Status;
> 
> +  if (!VkContext->IsIconShowed) {
> 
> +    Status = DrawVkIcon (VkContext, VkContext->SmallIcon,
> VkDisplayAttributeSimpleTop);
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +    Status = DrawVkIcon (VkContext, VkContext->SmallIcon,
> VkDisplayAttributeSimpleBottom);
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +    Status = DrawVkIcon (VkContext, VkContext->FullIcon,
> VkDisplayAttributeFullTop);
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +    Status = DrawVkIcon (VkContext, VkContext->FullIcon,
> VkDisplayAttributeFullBottom);
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +    VkContext->IsIconShowed = TRUE;
> 
> +  }
> 
> +
> 
> +  if (VkContext->TargetKeyboardDisplay != VkContext-
> >CurrentKeyboardDisplay) {
> 
> +    switch (VkContext->TargetKeyboardDisplay) {
> 
> +    case VkDisplayAttributeSimpleTop:
> 
> +    case VkDisplayAttributeSimpleBottom:
> 
> +      DrawVkBody (VkContext, VkContext->SimKeyBody, VkContext-
> >TargetKeyboardDisplay);
> 
> +      break;
> 
> +
> 
> +    case VkDisplayAttributeFullTop:
> 
> +    case VkDisplayAttributeFullBottom:
> 
> +      if (VkContext->PageNumber <= VkPage1) {
> 
> +        DrawVkBody (VkContext, VkContext->CapLeKeyBody, VkContext-
> >TargetKeyboardDisplay);
> 
> +      } else {
> 
> +        DrawVkBody (VkContext, VkContext->DigKeyBody, VkContext-
> >TargetKeyboardDisplay);
> 
> +      }
> 
> +
> 
> +    case VkDisplayAttributeNone:
> 
> +      break;
> 
> +
> 
> +    default:
> 
> +      break;
> 
> +    }
> 
> +  }
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Set the keyboard layout.
> 
> +
> 
> +  @param[in] VkContext          Graphic Protocol for draw the alphabet.
> 
> +  @param[in] Index              The layout selected.
> 
> +
> 
> +  @retval EFI_SUCCESS           Draw keyboard was done.
> 
> +  @retval Others                An unexpected error occurred.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +KeyboardLayoutHandler (
> 
> +  IN VK_CONTEXT *VkContext,
> 
> +  IN UINT32     Index
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS Status;
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +
> 
> +  if (Index == (VkContext->NumOfKeysInfo - 4)) {
> 
> +    //
> 
> +    // Touch the LeftTop icon
> 
> +    //
> 
> +    if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeSimpleTop)
> {
> 
> +      VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
> 
> +    } else {
> 
> +      VkContext->TargetKeyboardDisplay = VkDisplayAttributeSimpleTop;
> 
> +    }
> 
> +  } else if (Index == (VkContext->NumOfKeysInfo - 3)) {
> 
> +    //
> 
> +    // Touch the LeftBottom icon
> 
> +    //
> 
> +    if (VkContext->CurrentKeyboardDisplay ==
> VkDisplayAttributeSimpleBottom) {
> 
> +      VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
> 
> +    } else {
> 
> +      VkContext->TargetKeyboardDisplay = VkDisplayAttributeSimpleBottom;
> 
> +    }
> 
> +  } else if (Index == (VkContext->NumOfKeysInfo - 2)) {
> 
> +    //
> 
> +    // Touch the RightTop icon
> 
> +    //
> 
> +    if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeFullTop) {
> 
> +      VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
> 
> +    } else {
> 
> +      VkContext->TargetKeyboardDisplay = VkDisplayAttributeFullTop;
> 
> +    }
> 
> +  } else {
> 
> +    //
> 
> +    // Touch the RightBottom icon
> 
> +    //
> 
> +    if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeFullBottom)
> {
> 
> +      VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
> 
> +    } else {
> 
> +      VkContext->TargetKeyboardDisplay = VkDisplayAttributeFullBottom;
> 
> +    }
> 
> +  }
> 
> +
> 
> +  if (VkContext->TargetKeyboardDisplay == VkDisplayAttributeNone) {
> 
> +    //
> 
> +    // Just hide the current keyboard
> 
> +    //
> 
> +    HideVkBody (VkContext);
> 
> +    VkContext->KeyTouchedTimeOut = VK_REPEAT_TIMEOUT;
> 
> +
> 
> +  } else {
> 
> +    //
> 
> +    // If current keyboard status is NOT none,
> 
> +    // hide current keyboard first and then draw the target keyboard
> 
> +    //
> 
> +    if (VkContext->CurrentKeyboardDisplay != VkDisplayAttributeNone) {
> 
> +      HideVkBody (VkContext);
> 
> +    }
> 
> +    Status = DrawKeyboardLayout (VkContext);
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  This routine is used to check if icon has been cleared.
> 
> +
> 
> +  @param[in] VkContext  Pointer to virtual keyboard's context
> 
> +
> 
> +  @retval EFI_SUCCESS   Function completed.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +CheckIconCleared (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                    Status;
> 
> +  UINT32                        VerticalResolution;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +  BltBuffer = NULL;
> 
> +  VkContext->IconReDrawCheck++;
> 
> +  if (VkContext->IconReDrawCheck <= 10) {
> 
> +    //
> 
> +    // Check it every 10 * 100ms.
> 
> +    //
> 
> +    return Status;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Check if right-bottomed region is black, if yes, clean screen happened,
> need to re-draw keyboard.
> 
> +  //
> 
> +  VerticalResolution    = VkContext->GraphicsOutput->Mode->Info-
> >VerticalResolution;
> 
> +  BltBuffer             = AllocateZeroPool (VkContext->IconBltSize);
> 
> +  if (BltBuffer == NULL) {
> 
> +    return EFI_OUT_OF_RESOURCES;
> 
> +  }
> 
> +  Status = VkContext->GraphicsOutput->Blt (
> 
> +                                        VkContext->GraphicsOutput,
> 
> +                                        BltBuffer,
> 
> +                                        EfiBltVideoToBltBuffer,
> 
> +                                        0,
> 
> +                                        (VerticalResolution - VkContext->IconBltHeight),
> 
> +                                        0,
> 
> +                                        0,
> 
> +                                        VkContext->IconBltWidth,
> 
> +                                        VkContext->IconBltHeight,
> 
> +                                        VkContext->IconBltWidth * sizeof
> (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
> 
> +                                        );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    FreePool (BltBuffer);
> 
> +    return Status;
> 
> +  }
> 
> +  VkContext->IsIconShowed = TRUE;
> 
> +  if (VkContext->IconBltBuffer == NULL) {
> 
> +    //
> 
> +    // No icon has been drawn.
> 
> +    //
> 
> +    VkContext->IsIconShowed = FALSE;
> 
> +  } else {
> 
> +    if (CompareMem (BltBuffer, VkContext->IconBltBuffer, VkContext-
> >IconBltSize) != 0) {
> 
> +      //
> 
> +      // Icon has been overridden, need to re-draw.
> 
> +      //
> 
> +      VkContext->IsIconShowed = FALSE;
> 
> +    }
> 
> +  }
> 
> +
> 
> +  if (VkContext->IsIconShowed == FALSE) {
> 
> +    if (VkContext->ScreenCheckBuffer != NULL) {
> 
> +      if (CompareMem (BltBuffer, VkContext->ScreenCheckBuffer,
> VkContext->IconBltSize) == 0) {
> 
> +        //
> 
> +        // Icon has been overridden, force to re-draw the keyboard.
> 
> +        //
> 
> +        Status = DrawKeyboardLayout (VkContext);
> 
> +      } else {
> 
> +        //
> 
> +        // Save blt buffer of icon position and use it to check if icon is
> overridden.
> 
> +        //
> 
> +        CopyMem (VkContext->ScreenCheckBuffer, BltBuffer, VkContext-
> >IconBltSize);
> 
> +      }
> 
> +    } else {
> 
> +      //
> 
> +      // Draw the keyboard.
> 
> +      //
> 
> +      Status = DrawKeyboardLayout (VkContext);
> 
> +    }
> 
> +  }
> 
> +
> 
> +  if (BltBuffer != NULL) {
> 
> +    FreePool (BltBuffer);
> 
> +  }
> 
> +
> 
> +  VkContext->IconReDrawCheck = 0;
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  ConvertCoordinate - Convert the touch panel's coordinate to display's
> coordinate.
> 
> +
> 
> +  @param[in]  VkContext             Virtual Keyboard context.
> 
> +  @param[in]  Point                 The coordinate reported from touch panel.
> 
> +  @param[out] TouchX                The coordinate X converted to display panel.
> 
> +  @param[out] TouchY                The coordinate Y converted to display panel..
> 
> +
> 
> +  @retval EFI_SUCCESS               Convert success.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +ConvertCoordinate (
> 
> +  IN  VK_CONTEXT                 *VkContext,
> 
> +  IN  EFI_ABSOLUTE_POINTER_STATE Point,
> 
> +  OUT UINT32                     *TouchX,
> 
> +  OUT UINT32                     *TouchY
> 
> +  )
> 
> +{
> 
> +  UINT64 AbsoluteMaxX;
> 
> +  UINT64 AbsoluteMaxY;
> 
> +  UINT32 HorizontalResolution;
> 
> +  UINT32 VerticalResolution;
> 
> +
> 
> +  AbsoluteMaxX         = VkContext->AbsolutePointer->Mode-
> >AbsoluteMaxX;
> 
> +  AbsoluteMaxY         = VkContext->AbsolutePointer->Mode-
> >AbsoluteMaxY;
> 
> +  HorizontalResolution = VkContext->GraphicsOutput->Mode->Info-
> >HorizontalResolution;
> 
> +  VerticalResolution   = VkContext->GraphicsOutput->Mode->Info-
> >VerticalResolution;
> 
> +  *TouchX              = (UINT32) MultU64x32 (Point.CurrentX,
> HorizontalResolution) / (UINT32) AbsoluteMaxX;
> 
> +  *TouchY              = (UINT32) MultU64x32 (Point.CurrentY, VerticalResolution)
> / (UINT32) AbsoluteMaxY;
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  This routine is used to check if screen has been cleared.
> 
> +
> 
> +  @param[in] VkContext  Pointer to virtual keyboard's context
> 
> +
> 
> +  @retval EFI_SUCCESS   Function completed.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +CheckScreenCleared (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                    Status;
> 
> +  UINT32                        HorizontalResolution;
> 
> +  UINT32                        VerticalResolution;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBufferIndex;
> 
> +  UINTN                         BltSize;
> 
> +  BOOLEAN                       IsScreenCleared;
> 
> +
> 
> +  //
> 
> +  // Check left-bottom side.
> 
> +  // If IconBltBuffer is null, checking is meaningless.
> 
> +  //
> 
> +  if (VkContext->IconBltBuffer == NULL) {
> 
> +    return EFI_SUCCESS;
> 
> +  }
> 
> +
> 
> +  IsScreenCleared = FALSE;
> 
> +  Status          = EFI_SUCCESS;
> 
> +  if ((gST->ConOut->Mode->CursorColumn == 0) && (gST->ConOut->Mode-
> >CursorRow == 0)) {
> 
> +    //
> 
> +    // System may call gST->ConOut->ClearScreen
> 
> +    //
> 
> +    HorizontalResolution  = VkContext->GraphicsOutput->Mode->Info-
> >HorizontalResolution;
> 
> +    VerticalResolution    = VkContext->GraphicsOutput->Mode->Info-
> >VerticalResolution;
> 
> +    BltBuffer             = AllocateZeroPool (VkContext->IconBltSize);
> 
> +    if (BltBuffer == NULL) {
> 
> +      return EFI_OUT_OF_RESOURCES;
> 
> +    }
> 
> +
> 
> +    BltBufferIndex = BltBuffer;
> 
> +    Status = VkContext->GraphicsOutput->Blt (
> 
> +                                          VkContext->GraphicsOutput,
> 
> +                                          BltBuffer,
> 
> +                                          EfiBltVideoToBltBuffer,
> 
> +                                          (HorizontalResolution - VkContext->IconBltWidth),
> 
> +                                          (VerticalResolution - VkContext->IconBltHeight),
> 
> +                                          0,
> 
> +                                          0,
> 
> +                                          VkContext->IconBltWidth,
> 
> +                                          VkContext->IconBltHeight,
> 
> +                                          VkContext->IconBltWidth * sizeof
> (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
> 
> +                                          );
> 
> +    if (EFI_ERROR (Status)) {
> 
> +      FreePool (BltBuffer);
> 
> +      return Status;
> 
> +    }
> 
> +    BltSize = VkContext->IconBltHeight * VkContext->IconBltWidth;
> 
> +    IsScreenCleared = TRUE;
> 
> +    while (BltSize-- != 0) {
> 
> +      if ((BltBufferIndex->Red != 0) || (BltBufferIndex->Green != 0) ||
> (BltBufferIndex->Blue != 0)) {
> 
> +        IsScreenCleared = FALSE;
> 
> +        break;
> 
> +      }
> 
> +      BltBufferIndex++;
> 
> +    }
> 
> +    FreePool (BltBuffer);
> 
> +  }
> 
> +
> 
> +  if (IsScreenCleared) {
> 
> +    VkContext->IsIconShowed   = FALSE;
> 
> +    VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
> 
> +
> 
> +    if (VkContext->VkBodyBackgroundBltBuffer != NULL) {
> 
> +      FreePool (VkContext->VkBodyBackgroundBltBuffer);
> 
> +      VkContext->VkBodyBackgroundBltBuffer = NULL;
> 
> +    }
> 
> +
> 
> +    if (VkContext->VkBodyCompoundBltBuffer != NULL) {
> 
> +      FreePool (VkContext->VkBodyCompoundBltBuffer);
> 
> +      VkContext->VkBodyCompoundBltBuffer = NULL;
> 
> +    }
> 
> +
> 
> +    if (VkContext->IconBltBuffer != NULL) {
> 
> +      FreePool (VkContext->IconBltBuffer);
> 
> +      VkContext->IconBltBuffer = NULL;
> 
> +    }
> 
> +
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  This routine is used to check if background beneath virtual keyboard has
> been cleared.
> 
> +
> 
> +  @param[in] VkContext  Pointer to virtual keyboard's context
> 
> +
> 
> +  @retval EFI_SUCCESS   Function completed.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +CheckBackgroundChanged (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                    Status;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
> 
> +
> 
> +  Status                         = EFI_SUCCESS;
> 
> +  VkContext->IsBackgroundChanged = FALSE;
> 
> +
> 
> +  if ((VkContext->CurrentKeyboardDisplay == VkDisplayAttributeNone) ||
> (VkContext->VkBodyCompoundBltBuffer == NULL)) {
> 
> +    return EFI_SUCCESS;
> 
> +  }
> 
> +
> 
> +  BltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
> 
> +  if (BltBuffer == NULL) {
> 
> +    return EFI_OUT_OF_RESOURCES;
> 
> +  }
> 
> +  Status = VkContext->GraphicsOutput->Blt (
> 
> +                                        VkContext->GraphicsOutput,
> 
> +                                        BltBuffer,
> 
> +                                        EfiBltVideoToBltBuffer,
> 
> +                                        VkContext->VkBodyBltStartX,
> 
> +                                        VkContext->VkBodyBltStartY,
> 
> +                                        0,
> 
> +                                        0,
> 
> +                                        VkContext->VkBodyBltWidth,
> 
> +                                        VkContext->VkBodyBltHeight,
> 
> +                                        VkContext->VkBodyBltWidth * sizeof
> (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
> 
> +                                        );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    FreePool (BltBuffer);
> 
> +    return Status;
> 
> +  }
> 
> +  if (CompareMem (BltBuffer, VkContext->VkBodyCompoundBltBuffer,
> VkContext->VkBodyBltSize) != 0) {
> 
> +    VkContext->IsBackgroundChanged = TRUE;
> 
> +    VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
> 
> +    DrawKeyboardLayout (VkContext);
> 
> +  }
> 
> +
> 
> +  if (BltBuffer != NULL) {
> 
> +    FreePool (BltBuffer);
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Get unicode by VkContext->PageNumber and VkContext-
> >KeyboardBodyPtr.
> 
> +
> 
> +  @param[in]  VkContext            Address of an VK_CONTEXT structure.
> 
> +  @param[in]  KeyItem              Key Item.
> 
> +  @param[out] FontPtr              Follow VkContext->PageNumber to translate
> 
> +                                   font unicode.
> 
> +
> 
> +  @retval EFI_SUCCESS              Finish translating FontPtr.
> 
> +  @retval EFI_INVALID_PARAMETER    VkContext or FontPtr is NULL.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +VkGetMappingFont (
> 
> +  IN  VK_CONTEXT *VkContext,
> 
> +  IN  VK_STRUCT  KeyItem,
> 
> +  OUT UINT32     *FontPtr
> 
> +  )
> 
> +{
> 
> +  if ((VkContext == NULL) || (FontPtr == NULL) || (VkContext-
> >PageNumber>=VkPageMaximum)) {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +  *FontPtr = (UINT32) KeyItem.PageFont[VkContext->PageNumber];
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/KeyboardLayout.idf
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/KeyboardLayout.idf
> new file mode 100644
> index 0000000000..995bd0d859
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/KeyboardLayout.idf
> @@ -0,0 +1,12 @@
> +// /** @file
> 
> +// Virtual Keyboard Layout
> 
> +//
> 
> +// Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +//
> 
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +//
> 
> +#image IMG_VK_CAPITALLETTERKEYBOARD TRANSPARENT
> CapitalLetterKeyboard.bmp
> 
> +#image IMG_VK_DIGITKEYBOARD         TRANSPARENT DigitKeyboard.bmp
> 
> +#image IMG_VK_FULLICON              TRANSPARENT FullIcon.bmp
> 
> +#image IMG_VK_SIMPLEICON            TRANSPARENT SimpleIcon.bmp
> 
> +#image IMG_VK_SIMPLEKEYBOARD        TRANSPARENT
> SimpleKeyboard.bmp
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/SimpleIcon.bmp
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/SimpleIcon.bmp
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..16816f031eb98bf8169c7119b9
> 5ea3ed1371f41d
> GIT binary patch
> literal 2814
> zcmeHDu?>JQ41<*mn3%bM1K9bStAMDgEvtknP%#v#jj<EA^|~EHm%hdJ+18
> X--;Igi
> zvz~tHZ083bZvKJwS=AedIaS~0$e`HvNI;OvAp=5}kZlld1O%z<Y2HkwWx^;3ew
> ~S4
> zE{O5qpp83T)f<O7RWIkrpxE|EK#<BI145UOZ4hn*1gY$4-
> b|%s!YByBnW#Y!<5EEz
> Lcf5u-&Un3EdmJn}
> 
> literal 0
> HcmV?d00001
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/SimpleKeyboard.bmp
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/SimpleKeyboard.bmp
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..3004a534f026fe4906e64480f2
> 239b7b7923640b
> GIT binary patch
> literal 30054
> zcmeI4u}<Vj5QcZfOI*MMoQN*rh)6CYxVKncNOmv4BfvB82Bbvfq#z*?AOZqJ
> ghT*n
> z_unb@zyGS-
> J?$BL#!R;*ta5dA_1~YXjc085>+gU5{W9DB#Qt~ueEazM`sKHo|BsLM
> z*}=!|d)xXGP=M>Qqv~}j(Q%zBZCbCb!q%%qN2e-vPQf-
> |Q&6HB3RQjm|E3w{+S+w%
> zYin*i0t!_jQj?oqlAkf?LVK=JsLDy2n^ps~Z)2roqTN_UCMnMvSsfl8o}ZtmguxG
> O
> znO4`d{2JWZ*?D<+u{>{YZwChlZiscU0;t#5R|q>jJ#~_JSRpIUod!YKNlf8ttQ@Ee
> zuF6?;f=c14nU!8VjgQ;A#aJz?xu9Zo)yc|%dU|?#cz7^4@9*zdS65nKtgZ@KIZ%
> &}
> zkNf-k_xJZ?b#!!ec6LTwpa&0rY1YOng4*5P-QM1ItU%`S^3vfNn-
> %Y2%uuPTzZX>|
> z;DCw(C<s$OtEdx~n@;A?IA;Q^3H-
> Ua;OVf^GnHZm@vJUo=qA;9xG}606lR)X#ilx0
> zIZ%04Y^{*h-
> QAu2QqzUQ;=#h{WP*Usj+(^TpM4G5Rn$!ihjUq_F26AqJ&hGn%r!QH
> zRjjU7SMk(yDZ$Xz&&W#W0(;bF6OEM;h_;>!ZEba>G|ZkLD+t49ndj%{_~>EoX
> B>8{
> zWDOcCJg<p&$az-
> QYQ1V>g?kKsmbX=qVa1C^wX7Vj6f1&4e9f#BS0^h4RUs>^IQKZ|
> z=H`aiF#sVGIQbnBoc!oo&-
> Kc#P7znEt4>hpUK=Y++2Ojqz18;_uCK3WCH8a2iZad>
> zvWmC}M-
> 2z6&bqQ9an+@iVnx+lS9x5qq8cj@h}D$>h2T1`S5_ysKR!Oz1<1$W8e?{2
> z1rEfO0fn%}%4!C<@}O4C%2Z|cIB~XRVqB9gALopRzY_P(k5t-
> sW#5a&DL4;RIe+G`
> zvC6=4O^dPON$G10URQ29qaIF>l}W;W)QR^^PF2$prjjPB%86`;jlfU@`Yz!y;^S
> P#
> z7^QDcr>bxF@#0n3c%$^qOjUh5jva5p#vY|_{-
> &y&SYy>#l@lnBY<1OGl@lnBY<1OG
> zl@lnB{B(6y_^nPkf$~Vl3QCsW%11{ehtpmuRTi(2YU81j9xiF~t2yTBRK?a3gOjC
> E
> z(u*;jy*gDP61{BC?lkb{f%p#tJS;a-2{)CMy=`)FaZ!$lk@c{`i(Y&!htuz648n>U
> zY(==ez6lv4Q_sKLJ8Z~_Vt`s~IzhJvwMipgHVrGcHDT<9l}M*k^;7gO*^z+aA}jq
> n
> zVhxCI;ie*yYHx3kl3+Mh+C+JH?~8w>Yw>tSxxjXEa>8CZklCwY1^xEopADJ<g|
> G!!
> z;a47C`Z7?1?3ZViT2O?bOyJ}TAuKI@_s_i?g44PHEBmK9gYeNLW3!6+c^M%q78
> O10
> zHCy!mEqwEve#WR_YY?YT=QxzD14Y}ZGUXP=>s7w4Tuv4hGPB<DsdP}w=2Y
> nr#tNQ@
> z3&Sn85w#8!ZKq0Q=O^e==_<3FT0)k}tv+VZLCxt@F%kw@!FISbtlUPzRkGp|<
> Dl-g
> za3od^S2-Vz9F`Rc(9oLcTy!c1Heou37PfF*S$9^K8?^9nm8{4ib6LX;jB!@ToXe7|
> zkjHSLdYQA_SPLuOotjQ4Cq4dVG-
> C845*Qb_XNV|}6W7D&pX(Wxl};@Vt!t2rG&0GA
> z4Z;e-;(uv~YMsYQnzCK1JG3x5bvf7t83B1#=*wluLCtU-
> Q@Dm=#aWaat7ipmZk2%*
> zZgn~}JFp1T6J%Wsb!T@3clsA|u7%ZNQmt2GRZee{Sh=f^9d_O+mGjZaUaYj^
> ^0s|Z
> z%n9Zbx+{aq=Cz%v)M%{gWW`V13)Gbn%kT4Pd$sBbvW~9Wdu8htY-
> _Nyi#5&tUNlcB
> zPOWn+b@olTVXR7~-
> z!Ghu8frq>g)mQsuzcnV3pcf<%wljSw{_6f!*qA8OT$p_Nc$9
> zicC_T#wtZ7`WvgrB;{$WQe>jPv5HJmp2jLg#`z5t_RhcFL#mpNFqJe}RZe6(>?H6
> 5
> D{aYn_
> 
> literal 0
> HcmV?d00001
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/VirtualKeyboard.h
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/VirtualKeyboard.h
> new file mode 100644
> index 0000000000..14a50fa5af
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/VirtualKeyboard.h
> @@ -0,0 +1,829 @@
> +/** @file
> 
> +  Header file for Virtual Keyboard driver.
> 
> +
> 
> +  Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#ifndef _VIRTUAL_KEYBOARD_H_
> 
> +#define _VIRTUAL_KEYBOARD_H_
> 
> +
> 
> +#include <Uefi.h>
> 
> +#include <Library/BaseMemoryLib.h>
> 
> +#include <Library/DebugLib.h>
> 
> +#include <Library/MemoryAllocationLib.h>
> 
> +#include <Library/UefiBootServicesTableLib.h>
> 
> +#include <Library/UefiDriverEntryPoint.h>
> 
> +#include <Library/UefiLib.h>
> 
> +#include <Library/BaseLib.h>
> 
> +#include <Library/PcdLib.h>
> 
> +#include <Library/HiiLib.h>
> 
> +#include <Protocol/AbsolutePointer.h>
> 
> +#include <Protocol/GraphicsOutput.h>
> 
> +#include <Protocol/SimpleTextIn.h>
> 
> +#include <Protocol/SimpleTextInEx.h>
> 
> +#include <Protocol/SimpleTextOut.h>
> 
> +#include <Protocol/HiiDatabase.h>
> 
> +#include <Protocol/HiiImageEx.h>
> 
> +#include <Protocol/HiiPackageList.h>
> 
> +#include <Guid/ConsoleInDevice.h>
> 
> +#include "ComponentName.h"
> 
> +
> 
> +//
> 
> +// Global Variables
> 
> +//
> 
> +extern EFI_DRIVER_BINDING_PROTOCOL   gVirtualKeyboardDriverBinding;
> 
> +extern EFI_COMPONENT_NAME_PROTOCOL
> gVirtualKeyboardComponentName;
> 
> +extern EFI_COMPONENT_NAME2_PROTOCOL
> gVirtualKeyboardComponentName2;
> 
> +
> 
> +///
> 
> +/// Debug raw data points
> 
> +///
> 
> +#define DEBUG_VK_POINTS               DEBUG_INFO
> 
> +
> 
> +///
> 
> +/// Debug data point scaling
> 
> +///
> 
> +#define DEBUG_VK_POINT_SCALING        DEBUG_INFO
> 
> +
> 
> +///
> 
> +/// Debug key press
> 
> +///
> 
> +#define DEBUG_VK_KEYS                 DEBUG_INFO
> 
> +
> 
> +///
> 
> +/// Debug routine entry and exit
> 
> +///
> 
> +#define DEBUG_VK_ROUTINE_ENTRY_EXIT   DEBUG_VERBOSE
> 
> +
> 
> +///
> 
> +/// Display the graphics info
> 
> +///
> 
> +#define DEBUG_VK_GRAPHICS_INFO        DEBUG_INFO
> 
> +
> 
> +///
> 
> +/// Display the timer entry and exit
> 
> +///
> 
> +#define DEBUG_VK_TIMER_ENTRY_EXIT     DEBUG_VERBOSE
> 
> +
> 
> +///
> 
> +/// Signature
> 
> +///
> 
> +#define VK_SIGNATURE                  SIGNATURE_32 ('V', 'K', 'e', 'y')
> 
> +#define VK_NOTIFY_SIGNATURE           SIGNATURE_32 ('V', 'K', 'n', 's')
> 
> +
> 
> +///
> 
> +/// Poll interval
> 
> +///
> 
> +#define VK_POLL_INTERVAL              (1000 * 1000)
> 
> +
> 
> +///
> 
> +/// Define the touch timeout in poll intervals
> 
> +///
> 
> +#define VK_REPEAT_TIMEOUT             5
> 
> +
> 
> +///
> 
> +/// TPL used to synchronize add/remove from list
> 
> +///
> 
> +#define TPL_VK_SYNC                   TPL_NOTIFY
> 
> +
> 
> +///
> 
> +/// Dimension of an array ( number of elements )
> 
> +///
> 
> +#define DIM(x)      ( sizeof ( x ) / sizeof ( x [ 0 ]))
> 
> +
> 
> +///
> 
> +/// Define Key buffer
> 
> +///
> 
> +#define MAX_KEY_BUF_SIZE 64
> 
> +
> 
> +///
> 
> +/// Define Transparent Weight
> 
> +///
> 
> +#define TRANSPARENCY_WEIGHT 50
> 
> +
> 
> +typedef struct _VK_CONTEXT VK_CONTEXT;
> 
> +
> 
> +typedef enum _VK_KEY_TYPE {
> 
> +  VkKeyNull         = 0x0000 | CHAR_NULL,
> 
> +  VkKeyBackspace    = 0x0000 | CHAR_BACKSPACE,
> 
> +  VkKeyTab          = 0x0000 | CHAR_TAB,
> 
> +  VkKeyEnter        = 0x0000 | CHAR_CARRIAGE_RETURN,
> 
> +  VkKeyScanMask     = 0x1000,
> 
> +  VkKeyEsc          = 0x1000 | SCAN_ESC,
> 
> +  VkKeyLeft         = 0x1000 | SCAN_LEFT,
> 
> +  VkKeyRight        = 0x1000 | SCAN_RIGHT,
> 
> +  VkKeyUp           = 0x1000 | SCAN_UP,
> 
> +  VkKeyDown         = 0x1000 | SCAN_DOWN,
> 
> +  VkKeyF1           = 0x1000 | SCAN_F1,
> 
> +  VkKeyF2           = 0x1000 | SCAN_F2,
> 
> +  VkKeyF3           = 0x1000 | SCAN_F3,
> 
> +  VkKeyF4           = 0x1000 | SCAN_F4,
> 
> +  VkKeyF5           = 0x1000 | SCAN_F5,
> 
> +  VkKeyF6           = 0x1000 | SCAN_F6,
> 
> +  VkKeyF7           = 0x1000 | SCAN_F7,
> 
> +  VkKeyF8           = 0x1000 | SCAN_F8,
> 
> +  VkKeyF9           = 0x1000 | SCAN_F9,
> 
> +  VkKeyF10          = 0x1000 | SCAN_F10,
> 
> +  VkKeyF11          = 0x1000 | SCAN_F11,
> 
> +  VkKeyF12          = 0x1000 | SCAN_F12,
> 
> +  VkKeySpecificMask = 0x2000,
> 
> +  VkKeyShift        = 0x2000 | 0x0000,
> 
> +  VkKeyCapslock     = 0x2000 | 0x0001,
> 
> +  VkKeyTwoPage      = 0x2000 | 0x0002,
> 
> +  VkKeyTypeMaximum  = 0xFFFF
> 
> +} VK_KEY_TYPE;
> 
> +
> 
> +typedef enum _VK_PAGE_TYPE {
> 
> +  //
> 
> +  // +---+---+---+---+---+---+---+---+---+---+---+
> 
> +  // | q | w | e | r | t | y | u | i | o | p |<X|| Line 0
> 
> +  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> 
> +  // | | a | s | d | f | g | h | j | k | l | F2| | Line 1
> 
> +  // +-+---+---+---+---+---+---+---+---+---+---+-+
> 
> +  // |Caps | z | x | c | v | b | n | m |aU |Enter| Line 2
> 
> +  // +-----+---+---+---+---+---+---+---+---+---+-+
> 
> +  // | Esc |12#|       Space       |aL |aD |aR | | Line 3
> 
> +  // +-----+---+-------------------+---+---+---+-+
> 
> +  //
> 
> +  VkPage0,
> 
> +
> 
> +  //
> 
> +  // +---+---+---+---+---+---+---+---+---+---+---+
> 
> +  // | Q | W | E | R | T | Y | U | I | O | P |<X|| Line 0
> 
> +  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> 
> +  // | | A | S | D | F | G | H | J | K | L | F2| | Line 1
> 
> +  // +-+---+---+---+---+---+---+---+---+---+---+-+
> 
> +  // |Caps | Z | X | C | V | B | N | M |aU |Enter| Line 2
> 
> +  // +-----+---+---+---+---+---+---+---+---+---+-+
> 
> +  // | Esc |12#|       Space       |aL |aD |aR | | Line 3
> 
> +  // +-----+---+-------------------+---+---+---+-+
> 
> +  //
> 
> +  VkPage1,
> 
> +
> 
> +  //
> 
> +  // +---+---+---+---+---+---+---+---+---+---+---+
> 
> +  // | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |<X|| Line 0
> 
> +  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> 
> +  // | |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10| | Line 1
> 
> +  // +-+---+---+---+---+---+---+---+---+---+---+-+
> 
> +  // |Shift| . | ; | ' | , | . | / |F11|F12|Enter| Line 2
> 
> +  // +-----+---+---+---+---+---+---+---+---+---+-+
> 
> +  // | Esc |12#|       Space       | \ | - | = | | Line 3
> 
> +  // +-----+---+-------------------+---+---+---+-+
> 
> +  //
> 
> +  VkPage2,
> 
> +
> 
> +  //
> 
> +  // +---+---+---+---+---+---+---+---+---+---+---+
> 
> +  // | ! | @ | # | $ | % | ^ | & | * | ( | ) |<X|| Line 0
> 
> +  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> 
> +  // | |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10| | Line 1
> 
> +  // +-+---+---+---+---+---+---+---+---+---+---+-+
> 
> +  // |Shift| ~ | : | " | < | > | ? |F11|F12|Enter| Line 2
> 
> +  // +-----+---+---+---+---+---+---+---+---+---+-+
> 
> +  // | Esc |12#|       Space       | | | _ | + | | Line 3
> 
> +  // +-----+---+-------------------+---+---+---+-+
> 
> +  //
> 
> +  VkPage3,
> 
> +  VkPageMaximum
> 
> +} VK_PAGE_TYPE;
> 
> +
> 
> +typedef enum VK_DISPLAY_ATTRIBUTE {
> 
> +  VkDisplayAttributeNone,         /// No keyboard displayed
> 
> +  VkDisplayAttributeFullTop,      /// Full keyboard display at top
> 
> +  VkDisplayAttributeFullBottom,   /// Full keyboard display at bottom
> 
> +  VkDisplayAttributeSimpleTop,    /// Simple keyboard display at top
> 
> +  VkDisplayAttributeSimpleBottom, /// Simple keyboard display at bottom
> 
> +  VkDisplayAttributeMaximum
> 
> +} VK_DISPLAY_ATTRIBUTE;
> 
> +
> 
> +typedef struct _VK_STRUCT {
> 
> +  UINT16      DisStartX;
> 
> +  UINT16      DisStartY;
> 
> +  UINT16      DisEndX;
> 
> +  UINT16      DisEndY;
> 
> +  VK_KEY_TYPE PageFont[VkPageMaximum];
> 
> +} VK_STRUCT;
> 
> +
> 
> +typedef struct _VK_NOTIFY {
> 
> +  UINTN                               Signature;
> 
> +  EFI_KEY_DATA                        KeyData;
> 
> +  EFI_KEY_NOTIFY_FUNCTION             KeyNotificationFn;
> 
> +  LIST_ENTRY                          NotifyEntry;
> 
> +} VK_NOTIFY;
> 
> +
> 
> +///
> 
> +/// Virtual Keyboard context
> 
> +///
> 
> +struct _VK_CONTEXT {
> 
> +  ///
> 
> +  /// Structure identification
> 
> +  ///
> 
> +  UINTN                             Signature;
> 
> +
> 
> +  ///
> 
> +  /// Controller Handle
> 
> +  ///
> 
> +  EFI_HANDLE                        Controller;
> 
> +
> 
> +  ///
> 
> +  /// Upper level API
> 
> +  ///
> 
> +  EFI_SIMPLE_TEXT_INPUT_PROTOCOL    SimpleTextIn;
> 
> +
> 
> +  ///
> 
> +  /// Simple Text In EX
> 
> +  ///
> 
> +  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleTextInEx;
> 
> +
> 
> +  ///
> 
> +  /// Lower level APIs
> 
> +  ///
> 
> +  EFI_ABSOLUTE_POINTER_PROTOCOL     *AbsolutePointer;
> 
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL      *GraphicsOutput;
> 
> +
> 
> +  ///
> 
> +  /// Flag when the last poll indicated a touch event
> 
> +  ///
> 
> +  BOOLEAN                           TouchActive;
> 
> +
> 
> +  ///
> 
> +  /// Time to poll for touch input
> 
> +  ///
> 
> +  EFI_EVENT                         TimerEvent;
> 
> +
> 
> +  ///
> 
> +  /// HII handle to get image data used
> 
> +  ///
> 
> +  EFI_HII_HANDLE                    HiiHandle;
> 
> +  EFI_HII_IMAGE_EX_PROTOCOL         *HiiImageEx;
> 
> +
> 
> +  ///
> 
> +  /// Keyboard body background buffer information
> 
> +  ///
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     *VkBodyBackgroundBltBuffer;
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     *VkBodyCompoundBltBuffer;
> 
> +  UINTN                             VkBodyBltSize;
> 
> +  UINTN                             VkBodyBltStartX;
> 
> +  UINTN                             VkBodyBltStartY;
> 
> +  UINTN                             VkBodyBltHeight;
> 
> +  UINTN                             VkBodyBltWidth;
> 
> +  BOOLEAN                           IsBackgroundChanged;
> 
> +
> 
> +  ///
> 
> +  /// Icon buffer information
> 
> +  ///
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     *IconBltBuffer;
> 
> +  UINTN                             IconBltSize;
> 
> +  UINTN                             IconBltHeight;
> 
> +  UINTN                             IconBltWidth;
> 
> +
> 
> +  ///
> 
> +  /// Full icon background buffer information
> 
> +  ///
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     *FullIconBackBuffer;
> 
> +  UINTN                             FullIconBackStartX;
> 
> +  UINTN                             FullIconBackStartY;
> 
> +  UINTN                             FullIconBackHeight;
> 
> +  UINTN                             FullIconBackWidth;
> 
> +  UINTN                             FullIconBackSize;
> 
> +  BOOLEAN                           FullIconUpdatedFlag;
> 
> +
> 
> +  ///
> 
> +  /// Simple icon background buffer information
> 
> +  ///
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     *SimIconBackBuffer;
> 
> +  UINTN                             SimIconBackStartX;
> 
> +  UINTN                             SimIconBackStartY;
> 
> +  UINTN                             SimIconBackHeight;
> 
> +  UINTN                             SimIconBackWidth;
> 
> +  UINTN                             SimIconBackSize;
> 
> +  BOOLEAN                           SimIconUpdatedFlag;
> 
> +
> 
> +  ///
> 
> +  /// Small Icon
> 
> +  ///
> 
> +  EFI_IMAGE_INPUT                   *SmallIcon;
> 
> +
> 
> +  ///
> 
> +  /// Full Icon
> 
> +  ///
> 
> +  EFI_IMAGE_INPUT                   *FullIcon;
> 
> +
> 
> +  ///
> 
> +  /// Simple Key body
> 
> +  ///
> 
> +  EFI_IMAGE_INPUT                   *SimKeyBody;
> 
> +
> 
> +  ///
> 
> +  /// Digital key body
> 
> +  ///
> 
> +  EFI_IMAGE_INPUT                   *DigKeyBody;
> 
> +
> 
> +  ///
> 
> +  /// Capital Letter Key board
> 
> +  ///
> 
> +  EFI_IMAGE_INPUT                   *CapLeKeyBody;
> 
> +
> 
> +  ///
> 
> +  /// Screen check buffer.
> 
> +  /// This is used to check if screen is kept scrolling up.
> 
> +  ///
> 
> +  EFI_GRAPHICS_OUTPUT_BLT_PIXEL     *ScreenCheckBuffer;
> 
> +  UINTN                             ScreenCheckBufferSize;
> 
> +
> 
> +  ///
> 
> +  /// Key state
> 
> +  ///
> 
> +  BOOLEAN                           KeyPressed;
> 
> +
> 
> +  ///
> 
> +  /// Keyboard display status
> 
> +  ///
> 
> +  VK_DISPLAY_ATTRIBUTE              CurrentKeyboardDisplay;
> 
> +  VK_DISPLAY_ATTRIBUTE              TargetKeyboardDisplay;
> 
> +
> 
> +  ///
> 
> +  /// Keyboard icon display status
> 
> +  ///
> 
> +  BOOLEAN                           IsIconShowed;
> 
> +  UINT8                             IconReDrawCheck;
> 
> +
> 
> +  ///
> 
> +  /// Keyboard body Image address
> 
> +  /// Size of KeyboardBodyPtr must larger than mFullKeyboardBody
> 
> +  ///
> 
> +  UINT32                            NumOfKeysInfo;
> 
> +  VK_STRUCT                         KeyboardBodyPtr[50];
> 
> +
> 
> +  ///
> 
> +  /// KeyBuffer
> 
> +  ///
> 
> +  EFI_EVENT                         KeyNotifyProcessEvent;
> 
> +  EFI_KEY_TOGGLE_STATE              KeyToggleState;
> 
> +  EFI_KEY_DATA                      Keybuffer[MAX_KEY_BUF_SIZE];
> 
> +  UINT8                             KeyStartIndex;
> 
> +  UINT8                             KeyEndIndex;
> 
> +  UINT16                            KeyTouchedTimeOut;
> 
> +  BOOLEAN                           IsShiftKeyFlag;
> 
> +  BOOLEAN                           IsCapsLockFlag;
> 
> +  BOOLEAN                           IsSupportPartialKey;
> 
> +  BOOLEAN                           IsRedrawUpdateUI;
> 
> +  VK_PAGE_TYPE                      PageNumber;
> 
> +  LIST_ENTRY                        NotifyList;
> 
> +};
> 
> +
> 
> +///
> 
> +/// Locate VK_CONTEXT from protocol
> 
> +///
> 
> +#define VK_CONTEXT_FROM_PROTOCOL(a)                CR (a, VK_CONTEXT,
> SimpleTextIn, VK_SIGNATURE)
> 
> +#define VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL(a) CR (a,
> VK_CONTEXT, SimpleTextInEx, VK_SIGNATURE)
> 
> +#define VK_CONTEXT_FROM_VKBD_PROTOCOL(a)           CR (a,
> VK_CONTEXT, VkbdProtocol, VK_SIGNATURE)
> 
> +
> 
> +/**
> 
> +  Start the virtual keyboard driver
> 
> +
> 
> +  This routine allocates the necessary resources for the driver.
> 
> +
> 
> +  This routine is called by VirtualKeyboardDriverStart to complete the driver
> 
> +  initialization.
> 
> +
> 
> +  @param[in, out] VkContext        Address of an VK_CONTEXT structure
> 
> +  @param[in] Controller            Handle of device to work with.
> 
> +
> 
> +  @retval EFI_SUCCESS              Driver API properly initialized
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +VkApiStart (
> 
> +  IN OUT VK_CONTEXT *VkContext,
> 
> +  IN EFI_HANDLE Controller
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Stop the virtual keyboard driver
> 
> +
> 
> +  This routine releases the resources allocated by VKApiStart.
> 
> +
> 
> +  This routine is called by VirtualKeyboardDriverStop to initiate the driver
> 
> +  shutdown.
> 
> +
> 
> +  @param[in] VkContext        Address of an VK_CONTEXT structure
> 
> +
> 
> +**/
> 
> +VOID
> 
> +VkApiStop (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Resets the input device hardware.
> 
> +
> 
> +  The Reset() function resets the input device hardware. As part
> 
> +  of initialization process, the firmware/device will make a quick
> 
> +  but reasonable attempt to verify that the device is functioning.
> 
> +  If the ExtendedVerification flag is TRUE the firmware may take
> 
> +  an extended amount of time to verify the device is operating on
> 
> +  reset. Otherwise the reset operation is to occur as quickly as
> 
> +  possible. The hardware verification process is not defined by
> 
> +  this specification and is left up to the platform firmware or
> 
> +  driver to implement.
> 
> +
> 
> +  @param[in] This                 A pointer to the
> EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
> 
> +
> 
> +  @param[in] ExtendedVerification Indicates that the driver may perform a
> more exhaustive
> 
> +                                  verification operation of the device during reset.
> 
> +
> 
> +  @retval EFI_SUCCESS             The device was reset.
> 
> +  @retval EFI_DEVICE_ERROR        The device is not functioning correctly and
> could not be reset.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardReset (
> 
> +  IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
> 
> +  IN BOOLEAN                        ExtendedVerification
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Reads the next keystroke from the input device. The WaitForKey Event
> can
> 
> +  be used to test for existence of a keystroke via WaitForEvent () call.
> 
> +
> 
> +  @param[in]  This         Protocol instance pointer.
> 
> +  @param[out] Key          Driver may perform diagnostics on reset.
> 
> +
> 
> +  @retval EFI_SUCCESS      The keystroke information was returned.
> 
> +  @retval EFI_NOT_READY    There was no keystroke data available.
> 
> +  @retval EFI_DEVICE_ERROR The keystroke information was not returned
> due to
> 
> +                           hardware errors.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardReadKeyStroke (
> 
> +  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
> 
> +  OUT EFI_INPUT_KEY                  *Key
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Resets the input device hardware.
> 
> +
> 
> +  The Reset() function resets the input device hardware. As part
> 
> +  of initialization process, the firmware/device will make a quick
> 
> +  but reasonable attempt to verify that the device is functioning.
> 
> +  If the ExtendedVerification flag is TRUE the firmware may take
> 
> +  an extended amount of time to verify the device is operating on
> 
> +  reset. Otherwise the reset operation is to occur as quickly as
> 
> +  possible. The hardware verification process is not defined by
> 
> +  this specification and is left up to the platform firmware or
> 
> +  driver to implement.
> 
> +
> 
> +  @param[in] This                 A pointer to the
> EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
> 
> +
> 
> +  @param[in] ExtendedVerification Indicates that the driver may perform a
> more exhaustive
> 
> +                                  verification operation of the device during reset.
> 
> +
> 
> +  @retval EFI_SUCCESS             The device was reset.
> 
> +  @retval EFI_DEVICE_ERROR        The device is not functioning correctly and
> could not be reset.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardResetEx (
> 
> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
> 
> +  IN BOOLEAN                           ExtendedVerification
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Reads the next keystroke from the input device.
> 
> +
> 
> +  @param[in]  This               Protocol instance pointer.
> 
> +  @param[out] KeyData            A pointer to a buffer that is filled in with the
> keystroke
> 
> +                                 state data for the key that was pressed.
> 
> +
> 
> +  @retval EFI_SUCCESS            The keystroke information was returned.
> 
> +  @retval EFI_NOT_READY          There was no keystroke data available.
> 
> +  @retval EFI_INVALID_PARAMETER  This or KeyData is NULL.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardReadKeyStrokeEx (
> 
> +  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
> 
> +  OUT EFI_KEY_DATA                      *KeyData
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Set certain state for the input device.
> 
> +
> 
> +  @param[in] This                 Protocol instance pointer.
> 
> +  @param[in] KeyToggleState       A pointer to the EFI_KEY_TOGGLE_STATE
> to set the
> 
> +                                  state for the input device.
> 
> +
> 
> +  @retval EFI_SUCCESS             The device state was set appropriately.
> 
> +  @retval EFI_INVALID_PARAMETER   This or KeyToggleState is NULL.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardSetState (
> 
> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
> 
> +  IN EFI_KEY_TOGGLE_STATE              *KeyToggleState
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Register a notification function for a particular keystroke for the input
> device.
> 
> +
> 
> +  @param[in]  This                        Protocol instance pointer.
> 
> +  @param[in]  KeyData                     A pointer to a buffer that is filled in with
> the keystroke
> 
> +                                          information data for the key that was pressed.
> 
> +  @param[in]  KeyNotificationFunction     Points to the function to be called
> when the key
> 
> +                                          sequence is typed specified by KeyData.
> 
> +  @param[out] NotifyHandle                Points to the unique handle assigned to
> the registered notification.
> 
> +
> 
> +  @retval EFI_SUCCESS                     The notification function was registered
> successfully.
> 
> +  @retval EFI_OUT_OF_RESOURCES            Unable to allocate resources for
> necessary data structures.
> 
> +  @retval EFI_INVALID_PARAMETER           KeyData or NotifyHandle or
> KeyNotificationFunction is NULL.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardRegisterKeyNotify (
> 
> +  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
> 
> +  IN  EFI_KEY_DATA                      *KeyData,
> 
> +  IN  EFI_KEY_NOTIFY_FUNCTION           KeyNotificationFunction,
> 
> +  OUT EFI_HANDLE                        *NotifyHandle
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Remove a registered notification function from a particular keystroke.
> 
> +
> 
> +  @param[in] This                Protocol instance pointer.
> 
> +  @param[in] NotificationHandle  The handle of the notification function
> being unregistered.
> 
> +
> 
> +  @retval EFI_SUCCESS            The notification function was unregistered
> successfully.
> 
> +  @retval EFI_INVALID_PARAMETER  The NotificationHandle is invalid
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VkKeyboardUnregisterKeyNotify (
> 
> +  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
> 
> +  IN EFI_HANDLE                        NotificationHandle
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Draw key board on the display
> 
> +
> 
> +  @param[in] VkContext          Graphic Protocol for draw the alphabet.
> 
> +
> 
> +  @retval EFI_SUCCESS           Draw keyboard was done.
> 
> +  @retval EFI_UNSUPPORTED       Did not get key mapping table.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +DrawKeyboardLayout (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Clear the keyboard body
> 
> +
> 
> +  @param[in] VkContext          Code context.
> 
> +
> 
> +  @retval EFI_SUCCESS           Clear rectangle is done.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +HideVkBody (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Clear the keyboard icon
> 
> +
> 
> +  @param[in] VkContext          Code context.
> 
> +
> 
> +  @retval EFI_SUCCESS           Clear rectangle is done.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +HideVkIcon (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Use to draw the keyboard icon.
> 
> +
> 
> +  @param[in] VkContext  Pointer to virtual keyboard's context
> 
> +  @param[in] VkImage    Image of keyboard to display on the screen.
> 
> +  @param[in] Attribute  Attribute of keyboard to display on the screen.
> 
> +
> 
> +  @retval EFI_SUCCESS           ConsoleControl has been flipped to graphics
> and keyboard icon displayed.
> 
> +  @retval EFI_UNSUPPORTED       KeyboardFile not found
> 
> +  @retval EFI_INVALID_PARAMETER Attribute is unknown.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +DrawVkIcon (
> 
> +  IN VK_CONTEXT                    *VkContext,
> 
> +  IN EFI_IMAGE_INPUT               *VkImage,
> 
> +  IN VK_DISPLAY_ATTRIBUTE          Attribute
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Use to draw the keyboard.
> 
> +
> 
> +  @param[in] VkContext  Pointer to virtual keyboard's context
> 
> +  @param[in] VkImage    Image of keyboard to display on the screen.
> 
> +  @param[in] Attribute  Attribute of keyboard to display on the screen.
> 
> +
> 
> +  @retval EFI_SUCCESS           ConsoleControl has been flipped to graphics
> and keyboard displayed.
> 
> +  @retval EFI_UNSUPPORTED       KeyboardFile not found
> 
> +  @retval EFI_INVALID_PARAMETER Attribute is unknown.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +DrawVkBody (
> 
> +  IN VK_CONTEXT                    *VkContext,
> 
> +  IN EFI_IMAGE_INPUT               *VkImage,
> 
> +  IN VK_DISPLAY_ATTRIBUTE          Attribute
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Get unicode by VkContext->PageNumber and VkContext-
> >KeyboardBodyPtr.
> 
> +
> 
> +  @param[in]  VkContext            Address of an VK_CONTEXT structure.
> 
> +  @param[in]  KeyItem              Key Item.
> 
> +  @param[out] FontPtr              Follow VkContext->PageNumber to translate
> 
> +                                   font unicode.
> 
> +
> 
> +  @retval EFI_SUCCESS              Finish translating FontPtr.
> 
> +  @retval EFI_INVALID_PARAMETER    VkContext or FontPtr is NULL.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +VkGetMappingFont (
> 
> +  IN  VK_CONTEXT *VkContext,
> 
> +  IN  VK_STRUCT  KeyItem,
> 
> +  OUT UINT32     *FontPtr
> 
> +  );
> 
> +
> 
> +/**
> 
> +  This routine is used to check if icon has been cleared.
> 
> +
> 
> +  @param[in] VkContext  Pointer to virtual keyboard's context
> 
> +
> 
> +  @retval EFI_SUCCESS   Function completed.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +CheckIconCleared (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  );
> 
> +
> 
> +/**
> 
> +  ConvertCoordinate - Convert the touch panel's coordinate to display's
> coordinate.
> 
> +
> 
> +  @param[in]  VkContext             Virtual Keyboard context.
> 
> +  @param[in]  Point                 The coordinate reported from touch panel.
> 
> +  @param[out] TouchX                The coordinate X converted to display panel.
> 
> +  @param[out] TouchY                The coordinate Y converted to display panel..
> 
> +
> 
> +  @retval EFI_SUCCESS               Convert success.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +ConvertCoordinate (
> 
> +  IN  VK_CONTEXT                 *VkContext,
> 
> +  IN  EFI_ABSOLUTE_POINTER_STATE Point,
> 
> +  OUT UINT32                     *TouchX,
> 
> +  OUT UINT32                     *TouchY
> 
> +  );
> 
> +
> 
> +/**
> 
> +  This routine is used to check if screen has been cleared.
> 
> +
> 
> +  @param[in] VkContext  Pointer to virtual keyboard's context
> 
> +
> 
> +  @retval EFI_SUCCESS   Function completed.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +CheckScreenCleared (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  );
> 
> +
> 
> +/**
> 
> +  This routine is used to check if background beneath virtual keyboard has
> been cleared.
> 
> +
> 
> +  @param[in] VkContext  Pointer to virtual keyboard's context
> 
> +
> 
> +  @retval EFI_SUCCESS   Function completed.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +CheckBackgroundChanged (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  );
> 
> +
> 
> +/**
> 
> +  To prevent screen keyboard layout occur scroll up
> 
> +
> 
> +  @param[in, out]  VkContext            Address of an VK_CONTEXT structure.
> 
> +
> 
> +**/
> 
> +VOID
> 
> +PreventScreenScrollUp (
> 
> +  IN OUT VK_CONTEXT *VkContext
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Set the position of character.
> 
> +
> 
> +  @param[in] VkContext      Address of an VK_CONTEXT structure.
> 
> +  @param[in] DestX          X position.
> 
> +  @param[in] DestY          Y position.
> 
> +
> 
> +  @retval EFI_SUCCESS       Success for the function.
> 
> +  @retval Others            An unexpected error occurred.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +SetCharacterPosition (
> 
> +  IN VK_CONTEXT *VkContext,
> 
> +  IN UINT32     DestX,
> 
> +  IN UINT32     DestY
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Set the keyboard layout.
> 
> +
> 
> +  @param[in] VkContext          Graphic Protocol for draw the alphabet.
> 
> +  @param[in] Index              The layout selected.
> 
> +
> 
> +  @retval EFI_SUCCESS           Draw keyboard was done.
> 
> +  @retval Others                An unexpected error occurred.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +KeyboardLayoutHandler (
> 
> +  IN VK_CONTEXT *VkContext,
> 
> +  IN UINT32     Index
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Save the background blt buffer.
> 
> +
> 
> +  @param[in] VkContext           Address of an VK_CONTEXT structure.
> 
> +  @param[in] BltSize             Size of blt.
> 
> +
> 
> +  @retval EFI_SUCCESS            Success for the function.
> 
> +  @retval EFI_OUT_OF_RESOURCES   Allocate memory failed.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +SaveVkBodyBackgroundBltBuffer (
> 
> +  IN VK_CONTEXT *VkContext,
> 
> +  IN UINTN      BltSize
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Restore the background blt buffer.
> 
> +
> 
> +  @param[in] VkContext           Address of an VK_CONTEXT structure.
> 
> +
> 
> +  @retval EFI_SUCCESS            Success for the function.
> 
> +  @retval EFI_UNSUPPORTED        Input blt buffer is NULL.
> 
> +  @retval Others                 An unexpected error occurred.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +RestoreVkBodyBackgroundBltBuffer (
> 
> +  IN VK_CONTEXT *VkContext
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Save the icon background blt buffer.
> 
> +
> 
> +  @param[in] VkContext      Address of an VK_CONTEXT structure.
> 
> +  @param[in] IconType       The icon type.
> 
> +
> 
> +  @retval EFI_SUCCESS            Success for the function.
> 
> +  @retval EFI_OUT_OF_RESOURCES   Allocate memory failed.
> 
> +  @retval Others                 An unexpected error occurred.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +SaveVkIconBackgroundBltBuffer (
> 
> +  IN VK_CONTEXT           *VkContext,
> 
> +  IN VK_DISPLAY_ATTRIBUTE IconType
> 
> +  );
> 
> +#endif
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/VirtualKeyboardDriver.c
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/VirtualKeyboardDriver.c
> new file mode 100644
> index 0000000000..523c662b29
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/VirtualKeyboardDriver.c
> @@ -0,0 +1,515 @@
> +/** @file
> 
> +  Virtual Keyboard driver.
> 
> +
> 
> +  Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "VirtualKeyboard.h"
> 
> +
> 
> +UINT32         mOrigConOutRow      = 0;
> 
> +UINT32         mOrigSetupConOutRow = 0;
> 
> +EFI_HII_HANDLE mHiiHandle          = NULL;
> 
> +/**
> 
> +  Verify the controller type
> 
> +
> 
> +  This routine determines if the pointer and GOP are available.
> 
> +
> 
> +  This routine is called by the UEFI driver framework during connect
> 
> +  processing.
> 
> +
> 
> +  @param[in] This                 Protocol instance pointer.
> 
> +  @param[in] Controller           Handle of device to test.
> 
> +  @param[in] RemainingDevicePath  Not used.
> 
> +
> 
> +  @retval EFI_SUCCESS             This driver supports this device.
> 
> +  @retval other                   This driver does not support this device.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VirtualKeyboardDriverSupported (
> 
> +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> 
> +  IN EFI_HANDLE                  Controller,
> 
> +  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
> 
> +  )
> 
> +{
> 
> +  EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;
> 
> +  EFI_STATUS                    Status;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VirtualKeyboardDriverSupported Start\n"));
> 
> +
> 
> +  //
> 
> +  // Verify that the driver is not already started
> 
> +  //
> 
> +  Status = gBS->OpenProtocol (
> 
> +                  Controller,
> 
> +                  &gEfiCallerIdGuid,
> 
> +                  NULL,
> 
> +                  This->DriverBindingHandle,
> 
> +                  Controller,
> 
> +                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
> 
> +                  );
> 
> +  if (!EFI_ERROR (Status)) {
> 
> +    Status = EFI_ALREADY_STARTED;
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - VK has already
> initialized\n"));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Determine if the pointer protocol is available.
> 
> +  // This should be installed in touch driver.
> 
> +  //
> 
> +  Status = gBS->OpenProtocol (
> 
> +                  Controller,
> 
> +                  &gEfiAbsolutePointerProtocolGuid,
> 
> +                  NULL,
> 
> +                  This->DriverBindingHandle,
> 
> +                  Controller,
> 
> +                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - VK Absolute
> pointer protocol not found\n"));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  Status = gBS->OpenProtocol (
> 
> +                  Controller,
> 
> +                  &gEdkiiTouchPanelGuid,
> 
> +                  NULL,
> 
> +                  This->DriverBindingHandle,
> 
> +                  Controller,
> 
> +                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - VK Touch Panel
> Guid not found\n"));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Determine if the graphics output protocol is available
> 
> +  //
> 
> +  Status = gBS->HandleProtocol (
> 
> +                  gST->ConsoleOutHandle,
> 
> +                  &gEfiGraphicsOutputProtocolGuid,
> 
> +                  (VOID **)&GraphicsOutput
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - VK Graphics
> output protocol not found\n"));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_INFO,
> "VirtualKeyboardDriverSupported Success, Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VirtualKeyboardDriverSupported Failed, Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VirtualKeyboardDriverSupported End\n"));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Connect to the controller
> 
> +
> 
> +  This routine initializes an instance of the virutal keyboard driver for this
> 
> +  controller.
> 
> +
> 
> +  This routine is called by the UEFI driver framework during connect
> 
> +  processing if the controller passes the tests in I2cBusDriverSupported.
> 
> +
> 
> +  @param[in] This                 Protocol instance pointer.
> 
> +  @param[in] Controller           Handle of device to work with.
> 
> +  @param[in] RemainingDevicePath  Not used, always produce all possible
> children.
> 
> +
> 
> +  @retval EFI_SUCCESS             This driver is added to Controller.
> 
> +  @retval other                   This driver does not support this device.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VirtualKeyboardDriverStart (
> 
> +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> 
> +  IN EFI_HANDLE                  Controller,
> 
> +  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
> 
> +  )
> 
> +{
> 
> +  VK_CONTEXT *VkContext;
> 
> +  EFI_STATUS Status;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_INFO,
> "VirtualKeyboardDriverStart Start\n"));
> 
> +
> 
> +  VkContext = AllocateZeroPool (sizeof (VK_CONTEXT));
> 
> +  if (VkContext == NULL) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> No memory for virtual keyboard driver\n"));
> 
> +    Status = EFI_OUT_OF_RESOURCES;
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  Status = gBS->OpenProtocol (
> 
> +                  Controller,
> 
> +                  &gEfiAbsolutePointerProtocolGuid,
> 
> +                  (VOID**) &VkContext->AbsolutePointer,
> 
> +                  This->DriverBindingHandle,
> 
> +                  Controller,
> 
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to open absolute pointer protocol, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  Status = gBS->OpenProtocol (
> 
> +                  Controller,
> 
> +                  &gEdkiiTouchPanelGuid,
> 
> +                  NULL,
> 
> +                  This->DriverBindingHandle,
> 
> +                  Controller,
> 
> +                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> TouchPanel GUID not found, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  Status = gBS->HandleProtocol (
> 
> +                  gST->ConsoleOutHandle,
> 
> +                  &gEfiGraphicsOutputProtocolGuid,
> 
> +                  (VOID**) &VkContext->GraphicsOutput
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Graphics output protocol not available, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  VkContext->HiiHandle = mHiiHandle;
> 
> +  Status = VkApiStart (VkContext, Controller);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to VkApiStart, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> 
> +                  &Controller,
> 
> +                  &gEfiCallerIdGuid,
> 
> +                  VkContext,
> 
> +                  &gEfiSimpleTextInProtocolGuid,
> 
> +                  &VkContext->SimpleTextIn,
> 
> +                  &gEfiSimpleTextInputExProtocolGuid,
> 
> +                  &VkContext->SimpleTextInEx,
> 
> +                  &gEfiConsoleInDeviceGuid,
> 
> +                  NULL,
> 
> +                  NULL
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR -
> Failed to install VK protocols, Status: %r\n", Status));
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_INFO,
> "VirtualKeyboardDriverStart Success, Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  if (VkContext != NULL) {
> 
> +    FreePool (VkContext);
> 
> +  }
> 
> +
> 
> +  gBS->CloseProtocol (
> 
> +         Controller,
> 
> +         &gEfiAbsolutePointerProtocolGuid,
> 
> +         This->DriverBindingHandle,
> 
> +         Controller
> 
> +         );
> 
> +
> 
> +  //
> 
> +  // Restore setting if connect device fail.
> 
> +  //
> 
> +  PcdSet32S (PcdConOutRow, mOrigConOutRow);
> 
> +  PcdSet32S (PcdSetupConOutRow, mOrigSetupConOutRow);
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStart
> Failed, Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStart
> End\n"));
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Disconnect from the controller.
> 
> +
> 
> +  This routine disconnects from the controller.
> 
> +
> 
> +  This routine is called by DriverUnload when the I2C bus driver
> 
> +  is being unloaded.
> 
> +
> 
> +  @param[in] This                 Protocol instance pointer.
> 
> +  @param[in] Controller           Handle of device to stop driver on.
> 
> +  @param[in] NumberOfChildren     How many children need to be stopped.
> 
> +  @param[in] ChildHandleBuffer    Not used.
> 
> +
> 
> +  @retval EFI_SUCCESS             This driver is removed Controller.
> 
> +  @retval EFI_DEVICE_ERROR        The device could not be stopped due to a
> device error.
> 
> +  @retval other                   This driver was not removed from this device.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VirtualKeyboardDriverStop (
> 
> +  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
> 
> +  IN  EFI_HANDLE                  Controller,
> 
> +  IN  UINTN                       NumberOfChildren,
> 
> +  IN  EFI_HANDLE                  *ChildHandleBuffer
> 
> +  )
> 
> +{
> 
> +  VK_CONTEXT                          *VkContext;
> 
> +  EFI_STATUS                          Status;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStop
> Start\n"));
> 
> +
> 
> +  Status = gBS->OpenProtocol (
> 
> +                  Controller,
> 
> +                  &gEfiCallerIdGuid,
> 
> +                  (VOID**)&VkContext,
> 
> +                  This->DriverBindingHandle,
> 
> +                  Controller,
> 
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER |
> EFI_OPEN_PROTOCOL_EXCLUSIVE
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    Status = EFI_SUCCESS;
> 
> +    goto Success;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Done with the driver protocol
> 
> +  //
> 
> +  Status = gBS->CloseProtocol (
> 
> +                  Controller,
> 
> +                  &gEfiCallerIdGuid,
> 
> +                  This->DriverBindingHandle,
> 
> +                  Controller
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to close the
> VK protocol, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Remove ConsoleIn protocols first to close the link in ConSplitter
> 
> +  //
> 
> +  Status = gBS->OpenProtocol (
> 
> +                  Controller,
> 
> +                  &gEfiConsoleInDeviceGuid,
> 
> +                  NULL,
> 
> +                  This->DriverBindingHandle,
> 
> +                  Controller,
> 
> +                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to uninstall
> the protocols, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Remove the remaining protocols
> 
> +  //
> 
> +  Status = gBS->UninstallMultipleProtocolInterfaces (
> 
> +                  Controller,
> 
> +                  &gEfiCallerIdGuid,
> 
> +                  VkContext,
> 
> +                  &gEfiSimpleTextInProtocolGuid,
> 
> +                  &VkContext->SimpleTextIn,
> 
> +                  &gEfiSimpleTextInputExProtocolGuid,
> 
> +                  &VkContext->SimpleTextInEx,
> 
> +                  &gEfiConsoleInDeviceGuid,
> 
> +                  NULL,
> 
> +                  NULL
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to uninstall
> the protocols, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Stop the driver
> 
> +  //
> 
> +  VkApiStop (VkContext);
> 
> +
> 
> +  //
> 
> +  // Release the pointer protocol upon failure
> 
> +  //
> 
> +  Status = gBS->CloseProtocol (
> 
> +                  Controller,
> 
> +                  &gEfiAbsolutePointerProtocolGuid,
> 
> +                  This->DriverBindingHandle,
> 
> +                  Controller
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to close
> absolute pointer protocol, Status: %r\n", Status));
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Release VkContext
> 
> +  //
> 
> +  if (VkContext != NULL) {
> 
> +    FreePool (VkContext);
> 
> +  }
> 
> +
> 
> +Success:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStop
> Success, Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStop
> Failed, Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStop
> End\n"));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Unloads an image.
> 
> +
> 
> +  @param[in] ImageHandle        Handle that identifies the image to be
> unloaded.
> 
> +
> 
> +  @retval EFI_SUCCESS           The image has been unloaded.
> 
> +  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image
> handle.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VirtualKeyboardDriverUnload (
> 
> +  IN EFI_HANDLE ImageHandle
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                 Status;
> 
> +  EFI_HANDLE                 *HandleBuffer;
> 
> +  UINTN                      HandleCount;
> 
> +  UINTN                      Index;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VirtualKeyboardDriverUnload Start\n"));
> 
> +
> 
> +  //
> 
> +  // Retrieve array of all handles in the handle database
> 
> +  //
> 
> +  Status = gBS->LocateHandleBuffer (
> 
> +                  AllHandles,
> 
> +                  NULL,
> 
> +                  NULL,
> 
> +                  &HandleCount,
> 
> +                  &HandleBuffer
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to locate
> handle buffer, Status: %r\n", Status));
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Disconnect the current driver from handles in the handle database
> 
> +  //
> 
> +  for (Index = 0; Index < HandleCount; Index++) {
> 
> +    gBS->DisconnectController (HandleBuffer[Index], ImageHandle, NULL);
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Free the array of handles
> 
> +  //
> 
> +  if (HandleBuffer != NULL) {
> 
> +    FreePool (HandleBuffer);
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Uninstall protocols installed in the driver entry point
> 
> +  //
> 
> +  Status = gBS->UninstallMultipleProtocolInterfaces (
> 
> +                  ImageHandle,
> 
> +                  &gEfiDriverBindingProtocolGuid,
> 
> +                  &gVirtualKeyboardDriverBinding,
> 
> +                  &gEfiComponentNameProtocolGuid,
> 
> +                  &gVirtualKeyboardComponentName,
> 
> +                  &gEfiComponentName2ProtocolGuid,
> 
> +                  &gVirtualKeyboardComponentName2,
> 
> +                  NULL
> 
> +                  );
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    ASSERT_EFI_ERROR (Status);
> 
> +    goto Error;
> 
> +  }
> 
> +
> 
> +  HiiRemovePackages (mHiiHandle);
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VirtualKeyboardDriverUnload Success, Status: %r\n", Status));
> 
> +  goto End;
> 
> +
> 
> +Error:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VirtualKeyboardDriverUnload Failed, Status: %r\n", Status));
> 
> +
> 
> +End:
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VirtualKeyboardDriverUnload End\n"));
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +EFI_DRIVER_BINDING_PROTOCOL gVirtualKeyboardDriverBinding = {
> 
> +  VirtualKeyboardDriverSupported,
> 
> +  VirtualKeyboardDriverStart,
> 
> +  VirtualKeyboardDriverStop,
> 
> +  0x10,
> 
> +  NULL,
> 
> +  NULL
> 
> +};
> 
> +
> 
> +/**
> 
> +  This is the declaration of an EFI image entry point. This entry point is
> 
> +  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
> 
> +  both device drivers and bus drivers.
> 
> +
> 
> +  @param  ImageHandle           The firmware allocated handle for the UEFI
> image.
> 
> +  @param  SystemTable           A pointer to the EFI System Table.
> 
> +
> 
> +  @retval EFI_SUCCESS           The operation completed successfully.
> 
> +  @retval Others                An unexpected error occurred.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VirtualKeyboardDriverEntryPoint (
> 
> +  IN EFI_HANDLE       ImageHandle,
> 
> +  IN EFI_SYSTEM_TABLE *SystemTable
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                     Status;
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VirtualKeyboardDriverEntryPoint Start\n"));
> 
> +  //
> 
> +  // Install UEFI Driver Model protocol(s).
> 
> +  //
> 
> +  Status = EfiLibInstallDriverBindingComponentName2 (
> 
> +             ImageHandle,
> 
> +             SystemTable,
> 
> +             &gVirtualKeyboardDriverBinding,
> 
> +             ImageHandle,
> 
> +             &gVirtualKeyboardComponentName,
> 
> +             &gVirtualKeyboardComponentName2
> 
> +             );
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
> +  mHiiHandle = HiiAddPackages (
> 
> +                 &gEfiCallerIdGuid,
> 
> +                 NULL,
> 
> +                 VirtualKeyboardDxeImages,
> 
> +                 NULL
> 
> +                 );
> 
> +  ASSERT (mHiiHandle != NULL);
> 
> +
> 
> +  mOrigConOutRow      = PcdGet32 (PcdConOutRow);
> 
> +  mOrigSetupConOutRow = PcdGet32 (PcdSetupConOutRow);
> 
> +
> 
> +  DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT,
> "VirtualKeyboardDriverEntryPoint End\n"));
> 
> +  return Status;
> 
> +}
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/VirtualKeyboardDxe.inf
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/VirtualKeyboardDxe.inf
> new file mode 100644
> index 0000000000..38843443e1
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dDxe/VirtualKeyboardDxe.inf
> @@ -0,0 +1,78 @@
> +## @file
> 
> +# Instance of virtual keyboard driver binding protocol.
> 
> +#
> 
> +# Compliant with efi driver model, 1. VirtualKeyboardDriverSupported
> 
> +# determines if the pointer and GOP are available. 2.
> 
> +# VirtualKeyboardDriverStart initializes an instance of the virtual
> 
> +# keyboard driver for a particular controller. 3.
> 
> +# VirtualKeyboardDriverStop is called by DriverUnload when the I2C bus
> 
> +# driver is being unload.
> 
> +#
> 
> +# Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +#
> 
> +##
> 
> +
> 
> +[Defines]
> 
> +  INF_VERSION                    = 0x00010017
> 
> +  BASE_NAME                      = VirtualKeyboardDxe
> 
> +  FILE_GUID                      = E4735AAC-9C27-493f-86EA-9EFF43D7ADCD
> 
> +  VERSION_STRING                 = 2.0
> 
> +  MODULE_TYPE                    = UEFI_DRIVER
> 
> +  ENTRY_POINT                    = VirtualKeyboardDriverEntryPoint
> 
> +  UNLOAD_IMAGE                   = VirtualKeyboardDriverUnload
> 
> +
> 
> +#
> 
> +#  VALID_ARCHITECTURES           = IA32 X64
> 
> +#  DRIVER_BINDING                = gVirtualKeyboardDriverBinding;
> 
> +#  COMPONENT_NAME                = gVirtualKeyboardComponentName;
> 
> +#  COMPONENT_NAME2               = gVirtualKeyboardComponentName2;
> 
> +#
> 
> +
> 
> +[LibraryClasses]
> 
> +  BaseMemoryLib
> 
> +  DebugLib
> 
> +  MemoryAllocationLib
> 
> +  UefiBootServicesTableLib
> 
> +  UefiDriverEntryPoint
> 
> +  UefiLib
> 
> +  PcdLib
> 
> +  HiiLib
> 
> +
> 
> +[Packages]
> 
> +  MdePkg/MdePkg.dec
> 
> +  MdeModulePkg/MdeModulePkg.dec
> 
> +  VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dec
> 
> +
> 
> +[Pcd]
> 
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow
> 
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow
> 
> +
> 
> +[Sources]
> 
> +  CapitalLetterKeyboard.bmp
> 
> +  DigitKeyboard.bmp
> 
> +  FullIcon.bmp
> 
> +  SimpleIcon.bmp
> 
> +  SimpleKeyboard.bmp
> 
> +  KeyboardLayout.idf
> 
> +  KeyboardLayout.c
> 
> +  ComponentName.c
> 
> +  ComponentName.h
> 
> +  Keyboard.c
> 
> +  VirtualKeyboard.h
> 
> +  VirtualKeyboardDriver.c
> 
> +
> 
> +[Protocols]
> 
> +  gEfiAbsolutePointerProtocolGuid               ## TO_START
> 
> +  gEfiDriverBindingProtocolGuid                 ## PRODUCES
> 
> +  gEfiGraphicsOutputProtocolGuid                ## TO_START
> 
> +  gEfiSimpleTextInProtocolGuid                  ## BY_START
> 
> +  gEfiSimpleTextInputExProtocolGuid             ## BY_START
> 
> +  gEfiHiiImageExProtocolGuid                    ## TO_START
> 
> +
> 
> +[Guids]
> 
> +  gEfiConsoleInDeviceGuid                       ## SOMETIMES_PRODUCES
> 
> +  gEdkiiTouchPanelGuid                          ## TO_START
> 
> +
> 
> +[Depex]
> 
> +  gEfiHiiDatabaseProtocolGuid
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dFeaturePkg.dec
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dFeaturePkg.dec
> new file mode 100644
> index 0000000000..c26db01f09
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dFeaturePkg.dec
> @@ -0,0 +1,26 @@
> +## @file
> 
> +# This package provides advanced feature functionality for User
> Authentication support.
> 
> +# This package should only depend on EDK II Core packages, IntelSiliconPkg,
> and MinPlatformPkg.
> 
> +#
> 
> +# The DEC files are used by the utilities that parse DSC and
> 
> +# INF files to generate AutoGen.c and AutoGen.h files
> 
> +# for the build infrastructure.
> 
> +#
> 
> +# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#
> 
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +#
> 
> +##
> 
> +
> 
> +[Defines]
> 
> +  DEC_SPECIFICATION = 0x00010017
> 
> +  PACKAGE_NAME      = VirtualKeyboardFeaturePkg
> 
> +  PACKAGE_GUID      = A40DFD69-3552-40E8-8D3D-89741B03B9E1
> 
> +  PACKAGE_VERSION   = 0.1
> 
> +
> 
> +[Includes]
> 
> +  Include
> 
> +
> 
> +[Guids]
> 
> +  ## GUID used for VirtualKeyboardDriver to open TouchPanel protocol.
> 
> +  gEdkiiTouchPanelGuid                             = { 0x91b1d27b, 0xe126, 0x48d1,
> { 0x82, 0x34, 0xd2, 0x8b, 0x81, 0xc8, 0x83, 0x62 }}
> 
> diff --git
> a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dFeaturePkg.dsc
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dFeaturePkg.dsc
> new file mode 100644
> index 0000000000..ea2005c6d2
> --- /dev/null
> +++
> b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboar
> dFeaturePkg.dsc
> @@ -0,0 +1,30 @@
> +## @file
> 
> +# This is a build description file for the Virtual Keyboard advanced feature.
> 
> +# This package should only depend on EDK II Core packages, IntelSiliconPkg,
> and MinPlatformPkg.
> 
> +#
> 
> +# The DEC files are used by the utilities that parse DSC and
> 
> +# INF files to generate AutoGen.c and AutoGen.h files
> 
> +# for the build infrastructure.
> 
> +#
> 
> +# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#
> 
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +#
> 
> +##
> 
> +
> 
> +[Defines]
> 
> +  PLATFORM_NAME                  = VirtualKeyboardFeaturePkg
> 
> +  PLATFORM_GUID                  = 6D396683-C82B-41D5-84E7-BB6E13B7C2BF
> 
> +  PLATFORM_VERSION               = 0.1
> 
> +  DSC_SPECIFICATION              = 0x00010005
> 
> +  OUTPUT_DIRECTORY               = Build/$(PLATFORM_NAME)
> 
> +  SUPPORTED_ARCHITECTURES        = IA32|X64
> 
> +  BUILD_TARGETS                  = DEBUG|RELEASE|NOOPT
> 
> +  SKUID_IDENTIFIER               = DEFAULT
> 
> +  PEI_ARCH                       = IA32
> 
> +  DXE_ARCH                       = X64
> 
> +
> 
> +#
> 
> +# This package always builds the feature.
> 
> +#
> 
> +!include Include/VirtualKeyboardFeature.dsc
> 
> --
> 2.24.0.windows.2
> 
> 
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> 
> View/Reply Online (#58821): https://edk2.groups.io/g/devel/message/58821
> Mute This Topic: https://groups.io/mt/74063917/1768733
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub  [eric.dong@intel.com]
> -=-=-=-=-=-=


      reply	other threads:[~2020-05-08  5:30 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-08  0:50 [PATCH v3] Features/Intel/UserInterface: Add VirtualKeyboardFeaturePkg Tan, Ming
2020-05-08  5:30 ` Dong, Eric [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DM6PR11MB32746B0CD6B7E80C6E769C0EFEA20@DM6PR11MB3274.namprd11.prod.outlook.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox