• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 
3   PS/2 Keyboard driver. Routines that interacts with callers,
4   conforming to EFI driver model
5 
6 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution.  The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11 
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 
15 **/
16 
17 #include "Ps2Keyboard.h"
18 
19 //
20 // Function prototypes
21 //
22 /**
23   Test controller is a keyboard Controller.
24 
25   @param This                 Pointer of EFI_DRIVER_BINDING_PROTOCOL
26   @param Controller           driver's controller
27   @param RemainingDevicePath  children device path
28 
29   @retval EFI_UNSUPPORTED controller is not floppy disk
30   @retval EFI_SUCCESS     controller is floppy disk
31 **/
32 EFI_STATUS
33 EFIAPI
34 KbdControllerDriverSupported (
35   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
36   IN EFI_HANDLE                     Controller,
37   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
38   );
39 
40 /**
41   Create KEYBOARD_CONSOLE_IN_DEV instance on controller.
42 
43   @param This         Pointer of EFI_DRIVER_BINDING_PROTOCOL
44   @param Controller   driver controller handle
45   @param RemainingDevicePath Children's device path
46 
47   @retval whether success to create floppy control instance.
48 **/
49 EFI_STATUS
50 EFIAPI
51 KbdControllerDriverStart (
52   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
53   IN EFI_HANDLE                     Controller,
54   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
55   );
56 
57 /**
58   Stop this driver on ControllerHandle. Support stoping any child handles
59   created by this driver.
60 
61   @param  This              Protocol instance pointer.
62   @param  ControllerHandle  Handle of device to stop driver on
63   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
64                             children is zero stop the entire bus driver.
65   @param  ChildHandleBuffer List of Child Handles to Stop.
66 
67   @retval EFI_SUCCESS       This driver is removed ControllerHandle
68   @retval other             This driver was not removed from this device
69 
70 **/
71 EFI_STATUS
72 EFIAPI
73 KbdControllerDriverStop (
74   IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
75   IN  EFI_HANDLE                     Controller,
76   IN  UINTN                          NumberOfChildren,
77   IN  EFI_HANDLE                     *ChildHandleBuffer
78   );
79 
80 /**
81   Free the waiting key notify list.
82 
83   @param ListHead  Pointer to list head
84 
85   @retval EFI_INVALID_PARAMETER  ListHead is NULL
86   @retval EFI_SUCCESS            Sucess to free NotifyList
87 **/
88 EFI_STATUS
89 KbdFreeNotifyList (
90   IN OUT LIST_ENTRY           *ListHead
91   );
92 
93 //
94 // DriverBinding Protocol Instance
95 //
96 EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver = {
97   KbdControllerDriverSupported,
98   KbdControllerDriverStart,
99   KbdControllerDriverStop,
100   0xa,
101   NULL,
102   NULL
103 };
104 
105 /**
106   Test controller is a keyboard Controller.
107 
108   @param This                 Pointer of EFI_DRIVER_BINDING_PROTOCOL
109   @param Controller           driver's controller
110   @param RemainingDevicePath  children device path
111 
112   @retval EFI_UNSUPPORTED controller is not floppy disk
113   @retval EFI_SUCCESS     controller is floppy disk
114 **/
115 EFI_STATUS
116 EFIAPI
KbdControllerDriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)117 KbdControllerDriverSupported (
118   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
119   IN EFI_HANDLE                     Controller,
120   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
121   )
122 {
123   EFI_STATUS                          Status;
124   EFI_ISA_IO_PROTOCOL                 *IsaIo;
125 
126   //
127   // Open the IO Abstraction(s) needed to perform the supported test
128   //
129   Status = gBS->OpenProtocol (
130                   Controller,
131                   &gEfiIsaIoProtocolGuid,
132                   (VOID **) &IsaIo,
133                   This->DriverBindingHandle,
134                   Controller,
135                   EFI_OPEN_PROTOCOL_BY_DRIVER
136                   );
137   if (EFI_ERROR (Status)) {
138     return Status;
139   }
140   //
141   // Use the ISA I/O Protocol to see if Controller is the Keyboard controller
142   //
143   if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) {
144     Status = EFI_UNSUPPORTED;
145   }
146   //
147   // Close the I/O Abstraction(s) used to perform the supported test
148   //
149   gBS->CloseProtocol (
150          Controller,
151          &gEfiIsaIoProtocolGuid,
152          This->DriverBindingHandle,
153          Controller
154          );
155 
156   return Status;
157 }
158 
159 /**
160   Create KEYBOARD_CONSOLE_IN_DEV instance on controller.
161 
162   @param This         Pointer of EFI_DRIVER_BINDING_PROTOCOL
163   @param Controller   driver controller handle
164   @param RemainingDevicePath Children's device path
165 
166   @retval whether success to create floppy control instance.
167 **/
168 EFI_STATUS
169 EFIAPI
KbdControllerDriverStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)170 KbdControllerDriverStart (
171   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
172   IN EFI_HANDLE                     Controller,
173   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
174   )
175 {
176   EFI_STATUS                                Status;
177   EFI_STATUS                                Status1;
178   EFI_ISA_IO_PROTOCOL                       *IsaIo;
179   KEYBOARD_CONSOLE_IN_DEV                   *ConsoleIn;
180   UINT8                                     Data;
181   EFI_STATUS_CODE_VALUE                     StatusCode;
182   EFI_DEVICE_PATH_PROTOCOL                  *ParentDevicePath;
183 
184   StatusCode = 0;
185 
186   Status = gBS->OpenProtocol (
187                   Controller,
188                   &gEfiDevicePathProtocolGuid,
189                   (VOID **) &ParentDevicePath,
190                   This->DriverBindingHandle,
191                   Controller,
192                   EFI_OPEN_PROTOCOL_BY_DRIVER
193                   );
194   if (EFI_ERROR (Status)) {
195     return Status;
196   }
197   //
198   // Report that the keyboard is being enabled
199   //
200   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
201     EFI_PROGRESS_CODE,
202     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE,
203     ParentDevicePath
204     );
205 
206   //
207   // Get the ISA I/O Protocol on Controller's handle
208   //
209   Status = gBS->OpenProtocol (
210                   Controller,
211                   &gEfiIsaIoProtocolGuid,
212                   (VOID **) &IsaIo,
213                   This->DriverBindingHandle,
214                   Controller,
215                   EFI_OPEN_PROTOCOL_BY_DRIVER
216                   );
217   if (EFI_ERROR (Status)) {
218     gBS->CloseProtocol (
219            Controller,
220            &gEfiDevicePathProtocolGuid,
221            This->DriverBindingHandle,
222            Controller
223            );
224     return EFI_INVALID_PARAMETER;
225   }
226   //
227   // Allocate private data
228   //
229   ConsoleIn = AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV));
230   if (ConsoleIn == NULL) {
231     Status      = EFI_OUT_OF_RESOURCES;
232     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
233     goto ErrorExit;
234   }
235   //
236   // Setup the device instance
237   //
238   ConsoleIn->Signature              = KEYBOARD_CONSOLE_IN_DEV_SIGNATURE;
239   ConsoleIn->Handle                 = Controller;
240   (ConsoleIn->ConIn).Reset          = KeyboardEfiReset;
241   (ConsoleIn->ConIn).ReadKeyStroke  = KeyboardReadKeyStroke;
242   ConsoleIn->DataRegisterAddress    = KEYBOARD_8042_DATA_REGISTER;
243   ConsoleIn->StatusRegisterAddress  = KEYBOARD_8042_STATUS_REGISTER;
244   ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;
245   ConsoleIn->IsaIo                  = IsaIo;
246   ConsoleIn->DevicePath             = ParentDevicePath;
247 
248   ConsoleIn->ConInEx.Reset               = KeyboardEfiResetEx;
249   ConsoleIn->ConInEx.ReadKeyStrokeEx     = KeyboardReadKeyStrokeEx;
250   ConsoleIn->ConInEx.SetState            = KeyboardSetState;
251   ConsoleIn->ConInEx.RegisterKeyNotify   = KeyboardRegisterKeyNotify;
252   ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify;
253 
254   InitializeListHead (&ConsoleIn->NotifyList);
255 
256   //
257   // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS.
258   // When KBC decode (IO port 0x60/0x64 decode) is not enabled,
259   // KeyboardRead will read back as 0xFF and return status is EFI_SUCCESS.
260   // So instead we read status register to detect after read if KBC decode is enabled.
261   //
262 
263   //
264   // Return code is ignored on purpose.
265   //
266   if (!PcdGetBool (PcdFastPS2Detection)) {
267     KeyboardRead (ConsoleIn, &Data);
268     if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) {
269       //
270       // If nobody decodes KBC I/O port, it will read back as 0xFF.
271       // Check the Time-Out and Parity bit to see if it has an active KBC in system
272       //
273       Status      = EFI_DEVICE_ERROR;
274       StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
275       goto ErrorExit;
276     }
277   }
278 
279   //
280   // Setup the WaitForKey event
281   //
282   Status = gBS->CreateEvent (
283                   EVT_NOTIFY_WAIT,
284                   TPL_NOTIFY,
285                   KeyboardWaitForKey,
286                   ConsoleIn,
287                   &((ConsoleIn->ConIn).WaitForKey)
288                   );
289   if (EFI_ERROR (Status)) {
290     Status      = EFI_OUT_OF_RESOURCES;
291     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
292     goto ErrorExit;
293   }
294   //
295   // Setup the WaitForKeyEx event
296   //
297   Status = gBS->CreateEvent (
298                   EVT_NOTIFY_WAIT,
299                   TPL_NOTIFY,
300                   KeyboardWaitForKeyEx,
301                   ConsoleIn,
302                   &(ConsoleIn->ConInEx.WaitForKeyEx)
303                   );
304   if (EFI_ERROR (Status)) {
305     Status      = EFI_OUT_OF_RESOURCES;
306     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
307     goto ErrorExit;
308   }
309   // Setup a periodic timer, used for reading keystrokes at a fixed interval
310   //
311   Status = gBS->CreateEvent (
312                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
313                   TPL_NOTIFY,
314                   KeyboardTimerHandler,
315                   ConsoleIn,
316                   &ConsoleIn->TimerEvent
317                   );
318   if (EFI_ERROR (Status)) {
319     Status      = EFI_OUT_OF_RESOURCES;
320     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
321     goto ErrorExit;
322   }
323 
324   Status = gBS->SetTimer (
325                   ConsoleIn->TimerEvent,
326                   TimerPeriodic,
327                   KEYBOARD_TIMER_INTERVAL
328                   );
329   if (EFI_ERROR (Status)) {
330     Status      = EFI_OUT_OF_RESOURCES;
331     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
332     goto ErrorExit;
333   }
334 
335   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
336     EFI_PROGRESS_CODE,
337     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,
338     ParentDevicePath
339     );
340 
341   //
342   // Reset the keyboard device
343   //
344   Status = ConsoleIn->ConInEx.Reset (&ConsoleIn->ConInEx, FeaturePcdGet (PcdPs2KbdExtendedVerification));
345   if (EFI_ERROR (Status)) {
346     Status      = EFI_DEVICE_ERROR;
347     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
348     goto ErrorExit;
349   }
350 
351   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
352     EFI_PROGRESS_CODE,
353     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED,
354     ParentDevicePath
355     );
356 
357   ConsoleIn->ControllerNameTable = NULL;
358   AddUnicodeString2 (
359     "eng",
360     gPs2KeyboardComponentName.SupportedLanguages,
361     &ConsoleIn->ControllerNameTable,
362     L"PS/2 Keyboard Device",
363     TRUE
364     );
365   AddUnicodeString2 (
366     "en",
367     gPs2KeyboardComponentName2.SupportedLanguages,
368     &ConsoleIn->ControllerNameTable,
369     L"PS/2 Keyboard Device",
370     FALSE
371     );
372 
373 
374   //
375   // Install protocol interfaces for the keyboard device.
376   //
377   Status = gBS->InstallMultipleProtocolInterfaces (
378                   &Controller,
379                   &gEfiSimpleTextInProtocolGuid,
380                   &ConsoleIn->ConIn,
381                   &gEfiSimpleTextInputExProtocolGuid,
382                   &ConsoleIn->ConInEx,
383                   NULL
384                   );
385   if (EFI_ERROR (Status)) {
386     StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
387     goto ErrorExit;
388   }
389 
390   return Status;
391 
392 ErrorExit:
393   //
394   // Report error code
395   //
396   if (StatusCode != 0) {
397     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
398       EFI_ERROR_CODE | EFI_ERROR_MINOR,
399       StatusCode,
400       ParentDevicePath
401       );
402   }
403 
404   if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) {
405     gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey);
406   }
407 
408   if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) {
409     gBS->CloseEvent (ConsoleIn->TimerEvent);
410   }
411   if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) {
412     gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
413   }
414   KbdFreeNotifyList (&ConsoleIn->NotifyList);
415   if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) {
416     FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
417   }
418   //
419   // Since there will be no timer handler for keyboard input any more,
420   // exhaust input data just in case there is still keyboard data left
421   //
422   if (ConsoleIn != NULL) {
423     Status1 = EFI_SUCCESS;
424     while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) {
425       Status1 = KeyboardRead (ConsoleIn, &Data);;
426     }
427   }
428 
429   if (ConsoleIn != NULL) {
430     gBS->FreePool (ConsoleIn);
431   }
432 
433   gBS->CloseProtocol (
434          Controller,
435          &gEfiDevicePathProtocolGuid,
436          This->DriverBindingHandle,
437          Controller
438          );
439 
440   gBS->CloseProtocol (
441          Controller,
442          &gEfiIsaIoProtocolGuid,
443          This->DriverBindingHandle,
444          Controller
445          );
446 
447   return Status;
448 }
449 
450 /**
451   Stop this driver on ControllerHandle. Support stoping any child handles
452   created by this driver.
453 
454   @param  This              Protocol instance pointer.
455   @param  ControllerHandle  Handle of device to stop driver on
456   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
457                             children is zero stop the entire bus driver.
458   @param  ChildHandleBuffer List of Child Handles to Stop.
459 
460   @retval EFI_SUCCESS       This driver is removed ControllerHandle
461   @retval other             This driver was not removed from this device
462 
463 **/
464 EFI_STATUS
465 EFIAPI
KbdControllerDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)466 KbdControllerDriverStop (
467   IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
468   IN  EFI_HANDLE                     Controller,
469   IN  UINTN                          NumberOfChildren,
470   IN  EFI_HANDLE                     *ChildHandleBuffer
471   )
472 {
473   EFI_STATUS                     Status;
474   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
475   KEYBOARD_CONSOLE_IN_DEV        *ConsoleIn;
476   UINT8                          Data;
477 
478   //
479   // Disable Keyboard
480   //
481   Status = gBS->OpenProtocol (
482                   Controller,
483                   &gEfiSimpleTextInProtocolGuid,
484                   (VOID **) &ConIn,
485                   This->DriverBindingHandle,
486                   Controller,
487                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
488                   );
489   if (EFI_ERROR (Status)) {
490     return Status;
491   }
492   Status = gBS->OpenProtocol (
493                   Controller,
494                   &gEfiSimpleTextInputExProtocolGuid,
495                   NULL,
496                   This->DriverBindingHandle,
497                   Controller,
498                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
499                   );
500   if (EFI_ERROR (Status)) {
501     return Status;
502   }
503 
504   ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn);
505 
506   //
507   // Report that the keyboard is being disabled
508   //
509   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
510     EFI_PROGRESS_CODE,
511     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE,
512     ConsoleIn->DevicePath
513     );
514 
515   if (ConsoleIn->TimerEvent != NULL) {
516     gBS->CloseEvent (ConsoleIn->TimerEvent);
517     ConsoleIn->TimerEvent = NULL;
518   }
519 
520   //
521   // Since there will be no timer handler for keyboard input any more,
522   // exhaust input data just in case there is still keyboard data left
523   //
524   Status = EFI_SUCCESS;
525   while (!EFI_ERROR (Status)) {
526     Status = KeyboardRead (ConsoleIn, &Data);;
527   }
528   //
529   // Uninstall the SimpleTextIn and SimpleTextInEx protocols
530   //
531   Status = gBS->UninstallMultipleProtocolInterfaces (
532                   Controller,
533                   &gEfiSimpleTextInProtocolGuid,
534                   &ConsoleIn->ConIn,
535                   &gEfiSimpleTextInputExProtocolGuid,
536                   &ConsoleIn->ConInEx,
537                   NULL
538                   );
539   if (EFI_ERROR (Status)) {
540     return Status;
541   }
542 
543   gBS->CloseProtocol (
544          Controller,
545          &gEfiDevicePathProtocolGuid,
546          This->DriverBindingHandle,
547          Controller
548          );
549 
550   gBS->CloseProtocol (
551          Controller,
552          &gEfiIsaIoProtocolGuid,
553          This->DriverBindingHandle,
554          Controller
555          );
556 
557   //
558   // Free other resources
559   //
560   if ((ConsoleIn->ConIn).WaitForKey != NULL) {
561     gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey);
562     (ConsoleIn->ConIn).WaitForKey = NULL;
563   }
564   if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) {
565     gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
566     ConsoleIn->ConInEx.WaitForKeyEx = NULL;
567   }
568   KbdFreeNotifyList (&ConsoleIn->NotifyList);
569   FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
570   gBS->FreePool (ConsoleIn);
571 
572   return EFI_SUCCESS;
573 }
574 
575 /**
576   Free the waiting key notify list.
577 
578   @param ListHead  Pointer to list head
579 
580   @retval EFI_INVALID_PARAMETER  ListHead is NULL
581   @retval EFI_SUCCESS            Sucess to free NotifyList
582 **/
583 EFI_STATUS
KbdFreeNotifyList(IN OUT LIST_ENTRY * ListHead)584 KbdFreeNotifyList (
585   IN OUT LIST_ENTRY           *ListHead
586   )
587 {
588   KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
589 
590   if (ListHead == NULL) {
591     return EFI_INVALID_PARAMETER;
592   }
593   while (!IsListEmpty (ListHead)) {
594     NotifyNode = CR (
595                    ListHead->ForwardLink,
596                    KEYBOARD_CONSOLE_IN_EX_NOTIFY,
597                    NotifyEntry,
598                    KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
599                    );
600     RemoveEntryList (ListHead->ForwardLink);
601     gBS->FreePool (NotifyNode);
602   }
603 
604   return EFI_SUCCESS;
605 }
606 
607 /**
608   The module Entry Point for module Ps2Keyboard.
609 
610   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
611   @param[in] SystemTable    A pointer to the EFI System Table.
612 
613   @retval EFI_SUCCESS       The entry point is executed successfully.
614   @retval other             Some error occurs when executing this entry point.
615 
616 **/
617 EFI_STATUS
618 EFIAPI
InitializePs2Keyboard(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)619 InitializePs2Keyboard(
620   IN EFI_HANDLE           ImageHandle,
621   IN EFI_SYSTEM_TABLE     *SystemTable
622   )
623 {
624   EFI_STATUS              Status;
625 
626   //
627   // Install driver model protocol(s).
628   //
629   Status = EfiLibInstallDriverBindingComponentName2 (
630              ImageHandle,
631              SystemTable,
632              &gKeyboardControllerDriver,
633              ImageHandle,
634              &gPs2KeyboardComponentName,
635              &gPs2KeyboardComponentName2
636              );
637   ASSERT_EFI_ERROR (Status);
638 
639 
640   return Status;
641 }
642 
643