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 668