MdeModulePkg: Update comments in SimpleTextInEx according to UEFI 2.7
[mirror_edk2.git] / MdeModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2Keyboard.c
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
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
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
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
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
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