• 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 - 2016, 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 stopping 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_SIO_PROTOCOL                           *Sio;
125   EFI_DEVICE_PATH_PROTOCOL                   *DevicePath;
126   ACPI_HID_DEVICE_PATH                       *Acpi;
127 
128   //
129   // Check whether the controller is keyboard.
130   //
131   Status = gBS->OpenProtocol (
132                   Controller,
133                   &gEfiDevicePathProtocolGuid,
134                   (VOID **) &DevicePath,
135                   This->DriverBindingHandle,
136                   Controller,
137                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
138                   );
139   if (EFI_ERROR (Status)) {
140     return Status;
141   }
142 
143   do {
144     Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
145     DevicePath = NextDevicePathNode (DevicePath);
146   } while (!IsDevicePathEnd (DevicePath));
147 
148   if (DevicePathType (Acpi) != ACPI_DEVICE_PATH ||
149       (DevicePathSubType (Acpi) != ACPI_DP && DevicePathSubType (Acpi) != ACPI_EXTENDED_DP)) {
150     return EFI_UNSUPPORTED;
151   }
152 
153   if (Acpi->HID != EISA_PNP_ID (0x303) || Acpi->UID != 0) {
154     return EFI_UNSUPPORTED;
155   }
156 
157   //
158   // Open the IO Abstraction(s) needed to perform the supported test
159   //
160   Status = gBS->OpenProtocol (
161                   Controller,
162                   &gEfiSioProtocolGuid,
163                   (VOID **) &Sio,
164                   This->DriverBindingHandle,
165                   Controller,
166                   EFI_OPEN_PROTOCOL_BY_DRIVER
167                   );
168   if (EFI_ERROR (Status)) {
169     return Status;
170   }
171 
172   //
173   // Close the I/O Abstraction(s) used to perform the supported test
174   //
175   gBS->CloseProtocol (
176          Controller,
177          &gEfiSioProtocolGuid,
178          This->DriverBindingHandle,
179          Controller
180          );
181 
182   return Status;
183 }
184 
185 /**
186   Create KEYBOARD_CONSOLE_IN_DEV instance on controller.
187 
188   @param This         Pointer of EFI_DRIVER_BINDING_PROTOCOL
189   @param Controller   driver controller handle
190   @param RemainingDevicePath Children's device path
191 
192   @retval whether success to create floppy control instance.
193 **/
194 EFI_STATUS
195 EFIAPI
KbdControllerDriverStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)196 KbdControllerDriverStart (
197   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
198   IN EFI_HANDLE                     Controller,
199   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
200   )
201 {
202   EFI_STATUS                                Status;
203   EFI_STATUS                                Status1;
204   EFI_SIO_PROTOCOL                          *Sio;
205   KEYBOARD_CONSOLE_IN_DEV                   *ConsoleIn;
206   UINT8                                     Data;
207   EFI_STATUS_CODE_VALUE                     StatusCode;
208   EFI_DEVICE_PATH_PROTOCOL                  *DevicePath;
209 
210   StatusCode = 0;
211 
212   Status = gBS->OpenProtocol (
213                   Controller,
214                   &gEfiDevicePathProtocolGuid,
215                   (VOID **) &DevicePath,
216                   This->DriverBindingHandle,
217                   Controller,
218                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
219                   );
220   if (EFI_ERROR (Status)) {
221     return Status;
222   }
223   //
224   // Report that the keyboard is being enabled
225   //
226   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
227     EFI_PROGRESS_CODE,
228     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE,
229     DevicePath
230     );
231 
232   //
233   // Get the ISA I/O Protocol on Controller's handle
234   //
235   Status = gBS->OpenProtocol (
236                   Controller,
237                   &gEfiSioProtocolGuid,
238                   (VOID **) &Sio,
239                   This->DriverBindingHandle,
240                   Controller,
241                   EFI_OPEN_PROTOCOL_BY_DRIVER
242                   );
243   if (EFI_ERROR (Status)) {
244     return Status;
245   }
246   //
247   // Allocate private data
248   //
249   ConsoleIn = AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV));
250   if (ConsoleIn == NULL) {
251     Status      = EFI_OUT_OF_RESOURCES;
252     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
253     goto ErrorExit;
254   }
255   //
256   // Setup the device instance
257   //
258   ConsoleIn->Signature              = KEYBOARD_CONSOLE_IN_DEV_SIGNATURE;
259   ConsoleIn->Handle                 = Controller;
260   (ConsoleIn->ConIn).Reset          = KeyboardEfiReset;
261   (ConsoleIn->ConIn).ReadKeyStroke  = KeyboardReadKeyStroke;
262   ConsoleIn->DataRegisterAddress    = KEYBOARD_8042_DATA_REGISTER;
263   ConsoleIn->StatusRegisterAddress  = KEYBOARD_8042_STATUS_REGISTER;
264   ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;
265   ConsoleIn->DevicePath             = DevicePath;
266 
267   ConsoleIn->ConInEx.Reset               = KeyboardEfiResetEx;
268   ConsoleIn->ConInEx.ReadKeyStrokeEx     = KeyboardReadKeyStrokeEx;
269   ConsoleIn->ConInEx.SetState            = KeyboardSetState;
270   ConsoleIn->ConInEx.RegisterKeyNotify   = KeyboardRegisterKeyNotify;
271   ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify;
272 
273   InitializeListHead (&ConsoleIn->NotifyList);
274 
275   //
276   // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS.
277   // When KBC decode (IO port 0x60/0x64 decode) is not enabled,
278   // KeyboardRead will read back as 0xFF and return status is EFI_SUCCESS.
279   // So instead we read status register to detect after read if KBC decode is enabled.
280   //
281 
282   //
283   // Return code is ignored on purpose.
284   //
285   if (!PcdGetBool (PcdFastPS2Detection)) {
286     KeyboardRead (ConsoleIn, &Data);
287     if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) {
288       //
289       // If nobody decodes KBC I/O port, it will read back as 0xFF.
290       // Check the Time-Out and Parity bit to see if it has an active KBC in system
291       //
292       Status      = EFI_DEVICE_ERROR;
293       StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
294       goto ErrorExit;
295     }
296   }
297 
298   //
299   // Setup the WaitForKey event
300   //
301   Status = gBS->CreateEvent (
302                   EVT_NOTIFY_WAIT,
303                   TPL_NOTIFY,
304                   KeyboardWaitForKey,
305                   ConsoleIn,
306                   &((ConsoleIn->ConIn).WaitForKey)
307                   );
308   if (EFI_ERROR (Status)) {
309     Status      = EFI_OUT_OF_RESOURCES;
310     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
311     goto ErrorExit;
312   }
313   //
314   // Setup the WaitForKeyEx event
315   //
316   Status = gBS->CreateEvent (
317                   EVT_NOTIFY_WAIT,
318                   TPL_NOTIFY,
319                   KeyboardWaitForKeyEx,
320                   ConsoleIn,
321                   &(ConsoleIn->ConInEx.WaitForKeyEx)
322                   );
323   if (EFI_ERROR (Status)) {
324     Status      = EFI_OUT_OF_RESOURCES;
325     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
326     goto ErrorExit;
327   }
328   // Setup a periodic timer, used for reading keystrokes at a fixed interval
329   //
330   Status = gBS->CreateEvent (
331                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
332                   TPL_NOTIFY,
333                   KeyboardTimerHandler,
334                   ConsoleIn,
335                   &ConsoleIn->TimerEvent
336                   );
337   if (EFI_ERROR (Status)) {
338     Status      = EFI_OUT_OF_RESOURCES;
339     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
340     goto ErrorExit;
341   }
342 
343   Status = gBS->SetTimer (
344                   ConsoleIn->TimerEvent,
345                   TimerPeriodic,
346                   KEYBOARD_TIMER_INTERVAL
347                   );
348   if (EFI_ERROR (Status)) {
349     Status      = EFI_OUT_OF_RESOURCES;
350     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
351     goto ErrorExit;
352   }
353 
354   Status = gBS->CreateEvent (
355                   EVT_NOTIFY_SIGNAL,
356                   TPL_CALLBACK,
357                   KeyNotifyProcessHandler,
358                   ConsoleIn,
359                   &ConsoleIn->KeyNotifyProcessEvent
360                   );
361   if (EFI_ERROR (Status)) {
362     Status      = EFI_OUT_OF_RESOURCES;
363     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
364     goto ErrorExit;
365   }
366 
367   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
368     EFI_PROGRESS_CODE,
369     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,
370     DevicePath
371     );
372 
373   //
374   // Reset the keyboard device
375   //
376   Status = ConsoleIn->ConInEx.Reset (&ConsoleIn->ConInEx, FeaturePcdGet (PcdPs2KbdExtendedVerification));
377   if (EFI_ERROR (Status)) {
378     Status      = EFI_DEVICE_ERROR;
379     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
380     goto ErrorExit;
381   }
382 
383   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
384     EFI_PROGRESS_CODE,
385     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED,
386     DevicePath
387     );
388 
389   ConsoleIn->ControllerNameTable = NULL;
390   AddUnicodeString2 (
391     "eng",
392     gPs2KeyboardComponentName.SupportedLanguages,
393     &ConsoleIn->ControllerNameTable,
394     L"PS/2 Keyboard Device",
395     TRUE
396     );
397   AddUnicodeString2 (
398     "en",
399     gPs2KeyboardComponentName2.SupportedLanguages,
400     &ConsoleIn->ControllerNameTable,
401     L"PS/2 Keyboard Device",
402     FALSE
403     );
404 
405 
406   //
407   // Install protocol interfaces for the keyboard device.
408   //
409   Status = gBS->InstallMultipleProtocolInterfaces (
410                   &Controller,
411                   &gEfiSimpleTextInProtocolGuid,
412                   &ConsoleIn->ConIn,
413                   &gEfiSimpleTextInputExProtocolGuid,
414                   &ConsoleIn->ConInEx,
415                   NULL
416                   );
417   if (EFI_ERROR (Status)) {
418     StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
419     goto ErrorExit;
420   }
421 
422   return Status;
423 
424 ErrorExit:
425   //
426   // Report error code
427   //
428   if (StatusCode != 0) {
429     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
430       EFI_ERROR_CODE | EFI_ERROR_MINOR,
431       StatusCode,
432       DevicePath
433       );
434   }
435 
436   if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) {
437     gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey);
438   }
439 
440   if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) {
441     gBS->CloseEvent (ConsoleIn->TimerEvent);
442   }
443   if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) {
444     gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
445   }
446   if ((ConsoleIn != NULL) && (ConsoleIn->KeyNotifyProcessEvent != NULL)) {
447     gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);
448   }
449   KbdFreeNotifyList (&ConsoleIn->NotifyList);
450   if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) {
451     FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
452   }
453   //
454   // Since there will be no timer handler for keyboard input any more,
455   // exhaust input data just in case there is still keyboard data left
456   //
457   if (ConsoleIn != NULL) {
458     Status1 = EFI_SUCCESS;
459     while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) {
460       Status1 = KeyboardRead (ConsoleIn, &Data);;
461     }
462   }
463 
464   if (ConsoleIn != NULL) {
465     gBS->FreePool (ConsoleIn);
466   }
467 
468   gBS->CloseProtocol (
469          Controller,
470          &gEfiSioProtocolGuid,
471          This->DriverBindingHandle,
472          Controller
473          );
474 
475   return Status;
476 }
477 
478 /**
479   Stop this driver on ControllerHandle. Support stopping any child handles
480   created by this driver.
481 
482   @param  This              Protocol instance pointer.
483   @param  ControllerHandle  Handle of device to stop driver on
484   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
485                             children is zero stop the entire bus driver.
486   @param  ChildHandleBuffer List of Child Handles to Stop.
487 
488   @retval EFI_SUCCESS       This driver is removed ControllerHandle
489   @retval other             This driver was not removed from this device
490 
491 **/
492 EFI_STATUS
493 EFIAPI
KbdControllerDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)494 KbdControllerDriverStop (
495   IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
496   IN  EFI_HANDLE                     Controller,
497   IN  UINTN                          NumberOfChildren,
498   IN  EFI_HANDLE                     *ChildHandleBuffer
499   )
500 {
501   EFI_STATUS                     Status;
502   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
503   KEYBOARD_CONSOLE_IN_DEV        *ConsoleIn;
504   UINT8                          Data;
505 
506   //
507   // Disable Keyboard
508   //
509   Status = gBS->OpenProtocol (
510                   Controller,
511                   &gEfiSimpleTextInProtocolGuid,
512                   (VOID **) &ConIn,
513                   This->DriverBindingHandle,
514                   Controller,
515                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
516                   );
517   if (EFI_ERROR (Status)) {
518     return Status;
519   }
520   Status = gBS->OpenProtocol (
521                   Controller,
522                   &gEfiSimpleTextInputExProtocolGuid,
523                   NULL,
524                   This->DriverBindingHandle,
525                   Controller,
526                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
527                   );
528   if (EFI_ERROR (Status)) {
529     return Status;
530   }
531 
532   ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn);
533 
534   //
535   // Report that the keyboard is being disabled
536   //
537   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
538     EFI_PROGRESS_CODE,
539     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE,
540     ConsoleIn->DevicePath
541     );
542 
543   if (ConsoleIn->TimerEvent != NULL) {
544     gBS->CloseEvent (ConsoleIn->TimerEvent);
545     ConsoleIn->TimerEvent = NULL;
546   }
547 
548   //
549   // Since there will be no timer handler for keyboard input any more,
550   // exhaust input data just in case there is still keyboard data left
551   //
552   Status = EFI_SUCCESS;
553   while (!EFI_ERROR (Status)) {
554     Status = KeyboardRead (ConsoleIn, &Data);;
555   }
556   //
557   // Uninstall the SimpleTextIn and SimpleTextInEx protocols
558   //
559   Status = gBS->UninstallMultipleProtocolInterfaces (
560                   Controller,
561                   &gEfiSimpleTextInProtocolGuid,
562                   &ConsoleIn->ConIn,
563                   &gEfiSimpleTextInputExProtocolGuid,
564                   &ConsoleIn->ConInEx,
565                   NULL
566                   );
567   if (EFI_ERROR (Status)) {
568     return Status;
569   }
570 
571   gBS->CloseProtocol (
572          Controller,
573          &gEfiSioProtocolGuid,
574          This->DriverBindingHandle,
575          Controller
576          );
577 
578   //
579   // Free other resources
580   //
581   if ((ConsoleIn->ConIn).WaitForKey != NULL) {
582     gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey);
583     (ConsoleIn->ConIn).WaitForKey = NULL;
584   }
585   if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) {
586     gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
587     ConsoleIn->ConInEx.WaitForKeyEx = NULL;
588   }
589   if (ConsoleIn->KeyNotifyProcessEvent != NULL) {
590     gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);
591     ConsoleIn->KeyNotifyProcessEvent = NULL;
592   }
593   KbdFreeNotifyList (&ConsoleIn->NotifyList);
594   FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
595   gBS->FreePool (ConsoleIn);
596 
597   return EFI_SUCCESS;
598 }
599 
600 /**
601   Free the waiting key notify list.
602 
603   @param ListHead  Pointer to list head
604 
605   @retval EFI_INVALID_PARAMETER  ListHead is NULL
606   @retval EFI_SUCCESS            Sucess to free NotifyList
607 **/
608 EFI_STATUS
KbdFreeNotifyList(IN OUT LIST_ENTRY * ListHead)609 KbdFreeNotifyList (
610   IN OUT LIST_ENTRY           *ListHead
611   )
612 {
613   KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
614 
615   if (ListHead == NULL) {
616     return EFI_INVALID_PARAMETER;
617   }
618   while (!IsListEmpty (ListHead)) {
619     NotifyNode = CR (
620                    ListHead->ForwardLink,
621                    KEYBOARD_CONSOLE_IN_EX_NOTIFY,
622                    NotifyEntry,
623                    KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
624                    );
625     RemoveEntryList (ListHead->ForwardLink);
626     gBS->FreePool (NotifyNode);
627   }
628 
629   return EFI_SUCCESS;
630 }
631 
632 /**
633   The module Entry Point for module Ps2Keyboard.
634 
635   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
636   @param[in] SystemTable    A pointer to the EFI System Table.
637 
638   @retval EFI_SUCCESS       The entry point is executed successfully.
639   @retval other             Some error occurs when executing this entry point.
640 
641 **/
642 EFI_STATUS
643 EFIAPI
InitializePs2Keyboard(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)644 InitializePs2Keyboard(
645   IN EFI_HANDLE           ImageHandle,
646   IN EFI_SYSTEM_TABLE     *SystemTable
647   )
648 {
649   EFI_STATUS              Status;
650 
651   //
652   // Install driver model protocol(s).
653   //
654   Status = EfiLibInstallDriverBindingComponentName2 (
655              ImageHandle,
656              SystemTable,
657              &gKeyboardControllerDriver,
658              ImageHandle,
659              &gPs2KeyboardComponentName,
660              &gPs2KeyboardComponentName2
661              );
662   ASSERT_EFI_ERROR (Status);
663 
664 
665   return Status;
666 }
667 
668