1 /** @file 2 Platform BDS customizations. 3 4 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "BdsPlatform.h" 16 #include <Library/QemuBootOrderLib.h> 17 18 19 // 20 // Global data 21 // 22 23 VOID *mEfiDevPathNotifyReg; 24 EFI_EVENT mEfiDevPathEvent; 25 VOID *mEmuVariableEventReg; 26 EFI_EVENT mEmuVariableEvent; 27 BOOLEAN mDetectVgaOnly; 28 UINT16 mHostBridgeDevId; 29 30 // 31 // Table of host IRQs matching PCI IRQs A-D 32 // (for configuring PCI Interrupt Line register) 33 // 34 CONST UINT8 PciHostIrqs[] = { 35 0x0a, 0x0a, 0x0b, 0x0b 36 }; 37 38 // 39 // Array Size macro 40 // 41 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) 42 43 // 44 // Type definitions 45 // 46 47 typedef 48 EFI_STATUS 49 (EFIAPI *PROTOCOL_INSTANCE_CALLBACK)( 50 IN EFI_HANDLE Handle, 51 IN VOID *Instance, 52 IN VOID *Context 53 ); 54 55 /** 56 @param[in] Handle - Handle of PCI device instance 57 @param[in] PciIo - PCI IO protocol instance 58 @param[in] Pci - PCI Header register block 59 **/ 60 typedef 61 EFI_STATUS 62 (EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)( 63 IN EFI_HANDLE Handle, 64 IN EFI_PCI_IO_PROTOCOL *PciIo, 65 IN PCI_TYPE00 *Pci 66 ); 67 68 69 // 70 // Function prototypes 71 // 72 73 EFI_STATUS 74 VisitAllInstancesOfProtocol ( 75 IN EFI_GUID *Id, 76 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction, 77 IN VOID *Context 78 ); 79 80 EFI_STATUS 81 VisitAllPciInstancesOfProtocol ( 82 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction 83 ); 84 85 VOID 86 InstallDevicePathCallback ( 87 VOID 88 ); 89 90 // 91 // BDS Platform Functions 92 // 93 VOID 94 EFIAPI 95 PlatformBdsInit ( 96 VOID 97 ) 98 /*++ 99 100 Routine Description: 101 102 Platform Bds init. Incude the platform firmware vendor, revision 103 and so crc check. 104 105 Arguments: 106 107 Returns: 108 109 None. 110 111 --*/ 112 { 113 DEBUG ((EFI_D_INFO, "PlatformBdsInit\n")); 114 InstallDevicePathCallback (); 115 } 116 117 118 EFI_STATUS 119 EFIAPI 120 ConnectRootBridge ( 121 IN EFI_HANDLE RootBridgeHandle, 122 IN VOID *Instance, 123 IN VOID *Context 124 ) 125 { 126 EFI_STATUS Status; 127 128 // 129 // Make the PCI bus driver connect the root bridge, non-recursively. This 130 // will produce a number of child handles with PciIo on them. 131 // 132 Status = gBS->ConnectController ( 133 RootBridgeHandle, // ControllerHandle 134 NULL, // DriverImageHandle 135 NULL, // RemainingDevicePath -- produce all 136 // children 137 FALSE // Recursive 138 ); 139 return Status; 140 } 141 142 143 EFI_STATUS 144 PrepareLpcBridgeDevicePath ( 145 IN EFI_HANDLE DeviceHandle 146 ) 147 /*++ 148 149 Routine Description: 150 151 Add IsaKeyboard to ConIn, 152 add IsaSerial to ConOut, ConIn, ErrOut. 153 LPC Bridge: 06 01 00 154 155 Arguments: 156 157 DeviceHandle - Handle of PCIIO protocol. 158 159 Returns: 160 161 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut. 162 EFI_STATUS - No LPC bridge is added. 163 164 --*/ 165 { 166 EFI_STATUS Status; 167 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 168 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; 169 CHAR16 *DevPathStr; 170 171 DevicePath = NULL; 172 Status = gBS->HandleProtocol ( 173 DeviceHandle, 174 &gEfiDevicePathProtocolGuid, 175 (VOID*)&DevicePath 176 ); 177 if (EFI_ERROR (Status)) { 178 return Status; 179 } 180 TempDevicePath = DevicePath; 181 182 // 183 // Register Keyboard 184 // 185 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode); 186 187 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); 188 189 // 190 // Register COM1 191 // 192 DevicePath = TempDevicePath; 193 gPnp16550ComPortDeviceNode.UID = 0; 194 195 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode); 196 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); 197 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); 198 199 // 200 // Print Device Path 201 // 202 DevPathStr = DevicePathToStr(DevicePath); 203 if (DevPathStr != NULL) { 204 DEBUG(( 205 EFI_D_INFO, 206 "BdsPlatform.c+%d: COM%d DevPath: %s\n", 207 __LINE__, 208 gPnp16550ComPortDeviceNode.UID + 1, 209 DevPathStr 210 )); 211 FreePool(DevPathStr); 212 } 213 214 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); 215 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); 216 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL); 217 218 // 219 // Register COM2 220 // 221 DevicePath = TempDevicePath; 222 gPnp16550ComPortDeviceNode.UID = 1; 223 224 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode); 225 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); 226 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); 227 228 // 229 // Print Device Path 230 // 231 DevPathStr = DevicePathToStr(DevicePath); 232 if (DevPathStr != NULL) { 233 DEBUG(( 234 EFI_D_INFO, 235 "BdsPlatform.c+%d: COM%d DevPath: %s\n", 236 __LINE__, 237 gPnp16550ComPortDeviceNode.UID + 1, 238 DevPathStr 239 )); 240 FreePool(DevPathStr); 241 } 242 243 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); 244 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); 245 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL); 246 247 return EFI_SUCCESS; 248 } 249 250 EFI_STATUS 251 GetGopDevicePath ( 252 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath, 253 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath 254 ) 255 { 256 UINTN Index; 257 EFI_STATUS Status; 258 EFI_HANDLE PciDeviceHandle; 259 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; 260 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath; 261 UINTN GopHandleCount; 262 EFI_HANDLE *GopHandleBuffer; 263 264 if (PciDevicePath == NULL || GopDevicePath == NULL) { 265 return EFI_INVALID_PARAMETER; 266 } 267 268 // 269 // Initialize the GopDevicePath to be PciDevicePath 270 // 271 *GopDevicePath = PciDevicePath; 272 TempPciDevicePath = PciDevicePath; 273 274 Status = gBS->LocateDevicePath ( 275 &gEfiDevicePathProtocolGuid, 276 &TempPciDevicePath, 277 &PciDeviceHandle 278 ); 279 if (EFI_ERROR (Status)) { 280 return Status; 281 } 282 283 // 284 // Try to connect this handle, so that GOP dirver could start on this 285 // device and create child handles with GraphicsOutput Protocol installed 286 // on them, then we get device paths of these child handles and select 287 // them as possible console device. 288 // 289 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE); 290 291 Status = gBS->LocateHandleBuffer ( 292 ByProtocol, 293 &gEfiGraphicsOutputProtocolGuid, 294 NULL, 295 &GopHandleCount, 296 &GopHandleBuffer 297 ); 298 if (!EFI_ERROR (Status)) { 299 // 300 // Add all the child handles as possible Console Device 301 // 302 for (Index = 0; Index < GopHandleCount; Index++) { 303 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath); 304 if (EFI_ERROR (Status)) { 305 continue; 306 } 307 if (CompareMem ( 308 PciDevicePath, 309 TempDevicePath, 310 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH 311 ) == 0) { 312 // 313 // In current implementation, we only enable one of the child handles 314 // as console device, i.e. sotre one of the child handle's device 315 // path to variable "ConOut" 316 // In futhure, we could select all child handles to be console device 317 // 318 319 *GopDevicePath = TempDevicePath; 320 321 // 322 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath() 323 // Add the integrity GOP device path. 324 // 325 BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath); 326 BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL); 327 } 328 } 329 gBS->FreePool (GopHandleBuffer); 330 } 331 332 return EFI_SUCCESS; 333 } 334 335 EFI_STATUS 336 PreparePciVgaDevicePath ( 337 IN EFI_HANDLE DeviceHandle 338 ) 339 /*++ 340 341 Routine Description: 342 343 Add PCI VGA to ConOut. 344 PCI VGA: 03 00 00 345 346 Arguments: 347 348 DeviceHandle - Handle of PCIIO protocol. 349 350 Returns: 351 352 EFI_SUCCESS - PCI VGA is added to ConOut. 353 EFI_STATUS - No PCI VGA device is added. 354 355 --*/ 356 { 357 EFI_STATUS Status; 358 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 359 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; 360 361 DevicePath = NULL; 362 GopDevicePath = NULL; 363 Status = gBS->HandleProtocol ( 364 DeviceHandle, 365 &gEfiDevicePathProtocolGuid, 366 (VOID*)&DevicePath 367 ); 368 if (EFI_ERROR (Status)) { 369 return Status; 370 } 371 372 GetGopDevicePath (DevicePath, &GopDevicePath); 373 DevicePath = GopDevicePath; 374 375 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); 376 377 return EFI_SUCCESS; 378 } 379 380 EFI_STATUS 381 PreparePciSerialDevicePath ( 382 IN EFI_HANDLE DeviceHandle 383 ) 384 /*++ 385 386 Routine Description: 387 388 Add PCI Serial to ConOut, ConIn, ErrOut. 389 PCI Serial: 07 00 02 390 391 Arguments: 392 393 DeviceHandle - Handle of PCIIO protocol. 394 395 Returns: 396 397 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut. 398 EFI_STATUS - No PCI Serial device is added. 399 400 --*/ 401 { 402 EFI_STATUS Status; 403 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 404 405 DevicePath = NULL; 406 Status = gBS->HandleProtocol ( 407 DeviceHandle, 408 &gEfiDevicePathProtocolGuid, 409 (VOID*)&DevicePath 410 ); 411 if (EFI_ERROR (Status)) { 412 return Status; 413 } 414 415 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); 416 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); 417 418 BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); 419 BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); 420 BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL); 421 422 return EFI_SUCCESS; 423 } 424 425 EFI_STATUS 426 VisitAllInstancesOfProtocol ( 427 IN EFI_GUID *Id, 428 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction, 429 IN VOID *Context 430 ) 431 { 432 EFI_STATUS Status; 433 UINTN HandleCount; 434 EFI_HANDLE *HandleBuffer; 435 UINTN Index; 436 VOID *Instance; 437 438 // 439 // Start to check all the PciIo to find all possible device 440 // 441 HandleCount = 0; 442 HandleBuffer = NULL; 443 Status = gBS->LocateHandleBuffer ( 444 ByProtocol, 445 Id, 446 NULL, 447 &HandleCount, 448 &HandleBuffer 449 ); 450 if (EFI_ERROR (Status)) { 451 return Status; 452 } 453 454 for (Index = 0; Index < HandleCount; Index++) { 455 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance); 456 if (EFI_ERROR (Status)) { 457 continue; 458 } 459 460 Status = (*CallBackFunction) ( 461 HandleBuffer[Index], 462 Instance, 463 Context 464 ); 465 } 466 467 gBS->FreePool (HandleBuffer); 468 469 return EFI_SUCCESS; 470 } 471 472 473 EFI_STATUS 474 EFIAPI 475 VisitingAPciInstance ( 476 IN EFI_HANDLE Handle, 477 IN VOID *Instance, 478 IN VOID *Context 479 ) 480 { 481 EFI_STATUS Status; 482 EFI_PCI_IO_PROTOCOL *PciIo; 483 PCI_TYPE00 Pci; 484 485 PciIo = (EFI_PCI_IO_PROTOCOL*) Instance; 486 487 // 488 // Check for all PCI device 489 // 490 Status = PciIo->Pci.Read ( 491 PciIo, 492 EfiPciIoWidthUint32, 493 0, 494 sizeof (Pci) / sizeof (UINT32), 495 &Pci 496 ); 497 if (EFI_ERROR (Status)) { 498 return Status; 499 } 500 501 return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) ( 502 Handle, 503 PciIo, 504 &Pci 505 ); 506 507 } 508 509 510 511 EFI_STATUS 512 VisitAllPciInstances ( 513 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction 514 ) 515 { 516 return VisitAllInstancesOfProtocol ( 517 &gEfiPciIoProtocolGuid, 518 VisitingAPciInstance, 519 (VOID*)(UINTN) CallBackFunction 520 ); 521 } 522 523 524 /** 525 Do platform specific PCI Device check and add them to 526 ConOut, ConIn, ErrOut. 527 528 @param[in] Handle - Handle of PCI device instance 529 @param[in] PciIo - PCI IO protocol instance 530 @param[in] Pci - PCI Header register block 531 532 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully. 533 @retval EFI_STATUS - PCI Device check or Console variable update fail. 534 535 **/ 536 EFI_STATUS 537 EFIAPI 538 DetectAndPreparePlatformPciDevicePath ( 539 IN EFI_HANDLE Handle, 540 IN EFI_PCI_IO_PROTOCOL *PciIo, 541 IN PCI_TYPE00 *Pci 542 ) 543 { 544 EFI_STATUS Status; 545 546 Status = PciIo->Attributes ( 547 PciIo, 548 EfiPciIoAttributeOperationEnable, 549 EFI_PCI_DEVICE_ENABLE, 550 NULL 551 ); 552 ASSERT_EFI_ERROR (Status); 553 554 if (!mDetectVgaOnly) { 555 // 556 // Here we decide whether it is LPC Bridge 557 // 558 if ((IS_PCI_LPC (Pci)) || 559 ((IS_PCI_ISA_PDECODE (Pci)) && 560 (Pci->Hdr.VendorId == 0x8086) && 561 (Pci->Hdr.DeviceId == 0x7000) 562 ) 563 ) { 564 // 565 // Add IsaKeyboard to ConIn, 566 // add IsaSerial to ConOut, ConIn, ErrOut 567 // 568 DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n")); 569 PrepareLpcBridgeDevicePath (Handle); 570 return EFI_SUCCESS; 571 } 572 // 573 // Here we decide which Serial device to enable in PCI bus 574 // 575 if (IS_PCI_16550SERIAL (Pci)) { 576 // 577 // Add them to ConOut, ConIn, ErrOut. 578 // 579 DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n")); 580 PreparePciSerialDevicePath (Handle); 581 return EFI_SUCCESS; 582 } 583 } 584 585 // 586 // Here we decide which VGA device to enable in PCI bus 587 // 588 if (IS_PCI_VGA (Pci)) { 589 // 590 // Add them to ConOut. 591 // 592 DEBUG ((EFI_D_INFO, "Found PCI VGA device\n")); 593 PreparePciVgaDevicePath (Handle); 594 return EFI_SUCCESS; 595 } 596 597 return Status; 598 } 599 600 601 /** 602 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut 603 604 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE. 605 606 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully. 607 @retval EFI_STATUS - PCI Device check or Console variable update fail. 608 609 **/ 610 EFI_STATUS 611 DetectAndPreparePlatformPciDevicePaths ( 612 BOOLEAN DetectVgaOnly 613 ) 614 { 615 mDetectVgaOnly = DetectVgaOnly; 616 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath); 617 } 618 619 620 EFI_STATUS 621 PlatformBdsConnectConsole ( 622 IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole 623 ) 624 /*++ 625 626 Routine Description: 627 628 Connect the predefined platform default console device. Always try to find 629 and enable the vga device if have. 630 631 Arguments: 632 633 PlatformConsole - Predfined platform default console device array. 634 635 Returns: 636 637 EFI_SUCCESS - Success connect at least one ConIn and ConOut 638 device, there must have one ConOut device is 639 active vga device. 640 641 EFI_STATUS - Return the status of 642 BdsLibConnectAllDefaultConsoles () 643 644 --*/ 645 { 646 EFI_STATUS Status; 647 UINTN Index; 648 EFI_DEVICE_PATH_PROTOCOL *VarConout; 649 EFI_DEVICE_PATH_PROTOCOL *VarConin; 650 UINTN DevicePathSize; 651 652 // 653 // Connect RootBridge 654 // 655 VarConout = BdsLibGetVariableAndSize ( 656 VarConsoleOut, 657 &gEfiGlobalVariableGuid, 658 &DevicePathSize 659 ); 660 VarConin = BdsLibGetVariableAndSize ( 661 VarConsoleInp, 662 &gEfiGlobalVariableGuid, 663 &DevicePathSize 664 ); 665 666 if (VarConout == NULL || VarConin == NULL) { 667 // 668 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut 669 // 670 DetectAndPreparePlatformPciDevicePaths (FALSE); 671 672 // 673 // Have chance to connect the platform default console, 674 // the platform default console is the minimue device group 675 // the platform should support 676 // 677 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) { 678 // 679 // Update the console variable with the connect type 680 // 681 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { 682 BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL); 683 } 684 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { 685 BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL); 686 } 687 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { 688 BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL); 689 } 690 } 691 } else { 692 // 693 // Only detect VGA device and add them to ConOut 694 // 695 DetectAndPreparePlatformPciDevicePaths (TRUE); 696 } 697 698 // 699 // Connect the all the default console with current cosole variable 700 // 701 Status = BdsLibConnectAllDefaultConsoles (); 702 if (EFI_ERROR (Status)) { 703 return Status; 704 } 705 706 return EFI_SUCCESS; 707 } 708 709 710 /** 711 Configure PCI Interrupt Line register for applicable devices 712 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq() 713 714 @param[in] Handle - Handle of PCI device instance 715 @param[in] PciIo - PCI IO protocol instance 716 @param[in] PciHdr - PCI Header register block 717 718 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully. 719 720 **/ 721 EFI_STATUS 722 EFIAPI 723 SetPciIntLine ( 724 IN EFI_HANDLE Handle, 725 IN EFI_PCI_IO_PROTOCOL *PciIo, 726 IN PCI_TYPE00 *PciHdr 727 ) 728 { 729 EFI_DEVICE_PATH_PROTOCOL *DevPathNode; 730 EFI_DEVICE_PATH_PROTOCOL *DevPath; 731 UINTN RootSlot; 732 UINTN Idx; 733 UINT8 IrqLine; 734 EFI_STATUS Status; 735 UINT32 RootBusNumber; 736 737 Status = EFI_SUCCESS; 738 739 if (PciHdr->Device.InterruptPin != 0) { 740 741 DevPathNode = DevicePathFromHandle (Handle); 742 ASSERT (DevPathNode != NULL); 743 DevPath = DevPathNode; 744 745 RootBusNumber = 0; 746 if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH && 747 DevicePathSubType (DevPathNode) == ACPI_DP && 748 ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) { 749 RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID; 750 } 751 752 // 753 // Compute index into PciHostIrqs[] table by walking 754 // the device path and adding up all device numbers 755 // 756 Status = EFI_NOT_FOUND; 757 RootSlot = 0; 758 Idx = PciHdr->Device.InterruptPin - 1; 759 while (!IsDevicePathEnd (DevPathNode)) { 760 if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH && 761 DevicePathSubType (DevPathNode) == HW_PCI_DP) { 762 763 Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device; 764 765 // 766 // Unlike SeaBIOS, which starts climbing from the leaf device 767 // up toward the root, we traverse the device path starting at 768 // the root moving toward the leaf node. 769 // The slot number of the top-level parent bridge is needed for 770 // Q35 cases with more than 24 slots on the root bus. 771 // 772 if (Status != EFI_SUCCESS) { 773 Status = EFI_SUCCESS; 774 RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device; 775 } 776 } 777 778 DevPathNode = NextDevicePathNode (DevPathNode); 779 } 780 if (EFI_ERROR (Status)) { 781 return Status; 782 } 783 if (RootBusNumber == 0 && RootSlot == 0) { 784 DEBUG(( 785 EFI_D_ERROR, 786 "%a: PCI host bridge (00:00.0) should have no interrupts!\n", 787 __FUNCTION__ 788 )); 789 ASSERT (FALSE); 790 } 791 792 // 793 // Final PciHostIrqs[] index calculation depends on the platform 794 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq() 795 // 796 switch (mHostBridgeDevId) { 797 case INTEL_82441_DEVICE_ID: 798 Idx -= 1; 799 break; 800 case INTEL_Q35_MCH_DEVICE_ID: 801 // 802 // SeaBIOS contains the following comment: 803 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but 804 // with a different starting index - see q35-acpi-dsdt.dsl. 805 // 806 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)" 807 // 808 if (RootSlot > 24) { 809 // 810 // in this case, subtract back out RootSlot from Idx 811 // (SeaBIOS never adds it to begin with, but that would make our 812 // device path traversal loop above too awkward) 813 // 814 Idx -= RootSlot; 815 } 816 break; 817 default: 818 ASSERT (FALSE); // should never get here 819 } 820 Idx %= ARRAY_SIZE (PciHostIrqs); 821 IrqLine = PciHostIrqs[Idx]; 822 823 DEBUG_CODE_BEGIN (); 824 { 825 CHAR16 *DevPathString; 826 STATIC CHAR16 Fallback[] = L"<failed to convert>"; 827 UINTN Segment, Bus, Device, Function; 828 829 DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE); 830 if (DevPathString == NULL) { 831 DevPathString = Fallback; 832 } 833 Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); 834 ASSERT_EFI_ERROR (Status); 835 836 DEBUG ((EFI_D_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__, 837 (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString, 838 IrqLine)); 839 840 if (DevPathString != Fallback) { 841 FreePool (DevPathString); 842 } 843 } 844 DEBUG_CODE_END (); 845 846 // 847 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx] 848 // 849 Status = PciIo->Pci.Write ( 850 PciIo, 851 EfiPciIoWidthUint8, 852 PCI_INT_LINE_OFFSET, 853 1, 854 &IrqLine 855 ); 856 } 857 858 return Status; 859 } 860 861 862 VOID 863 PciAcpiInitialization ( 864 ) 865 { 866 UINTN Pmba; 867 868 // 869 // Query Host Bridge DID to determine platform type 870 // 871 mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId); 872 switch (mHostBridgeDevId) { 873 case INTEL_82441_DEVICE_ID: 874 Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA); 875 // 876 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets 877 // 878 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A 879 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B 880 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C 881 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D 882 break; 883 case INTEL_Q35_MCH_DEVICE_ID: 884 Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE); 885 // 886 // 00:1f.0 LPC Bridge (Q35) LNK routing targets 887 // 888 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A 889 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B 890 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C 891 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D 892 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E 893 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F 894 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G 895 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H 896 break; 897 default: 898 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n", 899 __FUNCTION__, mHostBridgeDevId)); 900 ASSERT (FALSE); 901 return; 902 } 903 904 // 905 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices 906 // 907 VisitAllPciInstances (SetPciIntLine); 908 909 // 910 // Set ACPI SCI_EN bit in PMCNTRL 911 // 912 IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0); 913 } 914 915 916 EFI_STATUS 917 EFIAPI 918 ConnectRecursivelyIfPciMassStorage ( 919 IN EFI_HANDLE Handle, 920 IN EFI_PCI_IO_PROTOCOL *Instance, 921 IN PCI_TYPE00 *PciHeader 922 ) 923 { 924 EFI_STATUS Status; 925 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 926 CHAR16 *DevPathStr; 927 928 if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) { 929 DevicePath = NULL; 930 Status = gBS->HandleProtocol ( 931 Handle, 932 &gEfiDevicePathProtocolGuid, 933 (VOID*)&DevicePath 934 ); 935 if (EFI_ERROR (Status)) { 936 return Status; 937 } 938 939 // 940 // Print Device Path 941 // 942 DevPathStr = DevicePathToStr (DevicePath); 943 if (DevPathStr != NULL) { 944 DEBUG(( 945 EFI_D_INFO, 946 "Found Mass Storage device: %s\n", 947 DevPathStr 948 )); 949 FreePool(DevPathStr); 950 } 951 952 Status = gBS->ConnectController (Handle, NULL, NULL, TRUE); 953 if (EFI_ERROR (Status)) { 954 return Status; 955 } 956 957 } 958 959 return EFI_SUCCESS; 960 } 961 962 963 /** 964 This notification function is invoked when the 965 EMU Variable FVB has been changed. 966 967 @param Event The event that occured 968 @param Context For EFI compatiblity. Not used. 969 970 **/ 971 VOID 972 EFIAPI 973 EmuVariablesUpdatedCallback ( 974 IN EFI_EVENT Event, 975 IN VOID *Context 976 ) 977 { 978 DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n")); 979 UpdateNvVarsOnFileSystem (); 980 } 981 982 983 EFI_STATUS 984 EFIAPI 985 VisitingFileSystemInstance ( 986 IN EFI_HANDLE Handle, 987 IN VOID *Instance, 988 IN VOID *Context 989 ) 990 { 991 EFI_STATUS Status; 992 STATIC BOOLEAN ConnectedToFileSystem = FALSE; 993 994 if (ConnectedToFileSystem) { 995 return EFI_ALREADY_STARTED; 996 } 997 998 Status = ConnectNvVarsToFileSystem (Handle); 999 if (EFI_ERROR (Status)) { 1000 return Status; 1001 } 1002 1003 ConnectedToFileSystem = TRUE; 1004 mEmuVariableEvent = 1005 EfiCreateProtocolNotifyEvent ( 1006 &gEfiDevicePathProtocolGuid, 1007 TPL_CALLBACK, 1008 EmuVariablesUpdatedCallback, 1009 NULL, 1010 &mEmuVariableEventReg 1011 ); 1012 PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent); 1013 1014 return EFI_SUCCESS; 1015 } 1016 1017 1018 VOID 1019 PlatformBdsRestoreNvVarsFromHardDisk ( 1020 ) 1021 { 1022 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage); 1023 VisitAllInstancesOfProtocol ( 1024 &gEfiSimpleFileSystemProtocolGuid, 1025 VisitingFileSystemInstance, 1026 NULL 1027 ); 1028 1029 } 1030 1031 1032 VOID 1033 PlatformBdsConnectSequence ( 1034 VOID 1035 ) 1036 /*++ 1037 1038 Routine Description: 1039 1040 Connect with predeined platform connect sequence, 1041 the OEM/IBV can customize with their own connect sequence. 1042 1043 Arguments: 1044 1045 None. 1046 1047 Returns: 1048 1049 None. 1050 1051 --*/ 1052 { 1053 UINTN Index; 1054 1055 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n")); 1056 1057 Index = 0; 1058 1059 // 1060 // Here we can get the customized platform connect sequence 1061 // Notes: we can connect with new variable which record the 1062 // last time boots connect device path sequence 1063 // 1064 while (gPlatformConnectSequence[Index] != NULL) { 1065 // 1066 // Build the platform boot option 1067 // 1068 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]); 1069 Index++; 1070 } 1071 1072 // 1073 // Just use the simple policy to connect all devices 1074 // 1075 BdsLibConnectAll (); 1076 1077 PciAcpiInitialization (); 1078 1079 // 1080 // Clear the logo after all devices are connected. 1081 // 1082 gST->ConOut->ClearScreen (gST->ConOut); 1083 } 1084 1085 VOID 1086 PlatformBdsGetDriverOption ( 1087 IN OUT LIST_ENTRY *BdsDriverLists 1088 ) 1089 /*++ 1090 1091 Routine Description: 1092 1093 Load the predefined driver option, OEM/IBV can customize this 1094 to load their own drivers 1095 1096 Arguments: 1097 1098 BdsDriverLists - The header of the driver option link list. 1099 1100 Returns: 1101 1102 None. 1103 1104 --*/ 1105 { 1106 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n")); 1107 return; 1108 } 1109 1110 VOID 1111 PlatformBdsDiagnostics ( 1112 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel, 1113 IN BOOLEAN QuietBoot, 1114 IN BASEM_MEMORY_TEST BaseMemoryTest 1115 ) 1116 /*++ 1117 1118 Routine Description: 1119 1120 Perform the platform diagnostic, such like test memory. OEM/IBV also 1121 can customize this fuction to support specific platform diagnostic. 1122 1123 Arguments: 1124 1125 MemoryTestLevel - The memory test intensive level 1126 1127 QuietBoot - Indicate if need to enable the quiet boot 1128 1129 BaseMemoryTest - A pointer to BaseMemoryTest() 1130 1131 Returns: 1132 1133 None. 1134 1135 --*/ 1136 { 1137 EFI_STATUS Status; 1138 1139 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n")); 1140 1141 // 1142 // Here we can decide if we need to show 1143 // the diagnostics screen 1144 // Notes: this quiet boot code should be remove 1145 // from the graphic lib 1146 // 1147 if (QuietBoot) { 1148 EnableQuietBoot (PcdGetPtr(PcdLogoFile)); 1149 // 1150 // Perform system diagnostic 1151 // 1152 Status = BaseMemoryTest (MemoryTestLevel); 1153 if (EFI_ERROR (Status)) { 1154 DisableQuietBoot (); 1155 } 1156 1157 return ; 1158 } 1159 // 1160 // Perform system diagnostic 1161 // 1162 Status = BaseMemoryTest (MemoryTestLevel); 1163 } 1164 1165 1166 /** 1167 Empty callback function executed when the EndOfDxe event group is signaled. 1168 1169 We only need this function because we'd like to signal EndOfDxe, and for that 1170 we need to create an event, with a callback function. 1171 1172 @param[in] Event Event whose notification function is being invoked. 1173 @param[in] Context The pointer to the notification function's context, which 1174 is implementation-dependent. 1175 **/ 1176 STATIC 1177 VOID 1178 EFIAPI 1179 OnEndOfDxe ( 1180 IN EFI_EVENT Event, 1181 IN VOID *Context 1182 ) 1183 { 1184 } 1185 1186 1187 /** 1188 Save the S3 boot script. 1189 1190 Note that we trigger DxeSmmReadyToLock here -- otherwise the script wouldn't 1191 be saved actually. Triggering this protocol installation event in turn locks 1192 down SMM, so no further changes to LockBoxes or SMRAM are possible 1193 afterwards. 1194 **/ 1195 STATIC 1196 VOID 1197 SaveS3BootScript ( 1198 VOID 1199 ) 1200 { 1201 EFI_STATUS Status; 1202 EFI_S3_SAVE_STATE_PROTOCOL *BootScript; 1203 EFI_HANDLE Handle; 1204 STATIC CONST UINT8 Info[] = { 0xDE, 0xAD, 0xBE, 0xEF }; 1205 1206 Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL, 1207 (VOID **) &BootScript); 1208 ASSERT_EFI_ERROR (Status); 1209 1210 // 1211 // Despite the opcode documentation in the PI spec, the protocol 1212 // implementation embeds a deep copy of the info in the boot script, rather 1213 // than storing just a pointer to runtime or NVS storage. 1214 // 1215 Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE, 1216 (UINT32) sizeof Info, 1217 (EFI_PHYSICAL_ADDRESS)(UINTN) &Info); 1218 ASSERT_EFI_ERROR (Status); 1219 1220 Handle = NULL; 1221 Status = gBS->InstallProtocolInterface (&Handle, 1222 &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE, 1223 NULL); 1224 ASSERT_EFI_ERROR (Status); 1225 } 1226 1227 1228 VOID 1229 EFIAPI 1230 PlatformBdsPolicyBehavior ( 1231 IN OUT LIST_ENTRY *DriverOptionList, 1232 IN OUT LIST_ENTRY *BootOptionList, 1233 IN PROCESS_CAPSULES ProcessCapsules, 1234 IN BASEM_MEMORY_TEST BaseMemoryTest 1235 ) 1236 /*++ 1237 1238 Routine Description: 1239 1240 The function will excute with as the platform policy, current policy 1241 is driven by boot mode. IBV/OEM can customize this code for their specific 1242 policy action. 1243 1244 Arguments: 1245 1246 DriverOptionList - The header of the driver option link list 1247 1248 BootOptionList - The header of the boot option link list 1249 1250 ProcessCapsules - A pointer to ProcessCapsules() 1251 1252 BaseMemoryTest - A pointer to BaseMemoryTest() 1253 1254 Returns: 1255 1256 None. 1257 1258 --*/ 1259 { 1260 EFI_STATUS Status; 1261 EFI_BOOT_MODE BootMode; 1262 EFI_EVENT EndOfDxeEvent; 1263 1264 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n")); 1265 1266 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid, 1267 ConnectRootBridge, NULL); 1268 1269 // 1270 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers 1271 // the preparation of S3 system information. That logic has a hard dependency 1272 // on the presence of the FACS ACPI table. Since our ACPI tables are only 1273 // installed after PCI enumeration completes, we must not trigger the S3 save 1274 // earlier, hence we can't signal End-of-Dxe earlier. 1275 // 1276 Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, OnEndOfDxe, 1277 NULL /* NotifyContext */, &gEfiEndOfDxeEventGroupGuid, 1278 &EndOfDxeEvent); 1279 if (!EFI_ERROR (Status)) { 1280 gBS->SignalEvent (EndOfDxeEvent); 1281 gBS->CloseEvent (EndOfDxeEvent); 1282 } 1283 1284 if (QemuFwCfgS3Enabled ()) { 1285 // 1286 // Save the boot script too. Note that this requires/includes emitting the 1287 // DxeSmmReadyToLock event, which in turn locks down SMM. 1288 // 1289 SaveS3BootScript (); 1290 } 1291 1292 if (PcdGetBool (PcdOvmfFlashVariablesEnable)) { 1293 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars " 1294 "from disk since flash variables appear to be supported.\n")); 1295 } else { 1296 // 1297 // Try to restore variables from the hard disk early so 1298 // they can be used for the other BDS connect operations. 1299 // 1300 PlatformBdsRestoreNvVarsFromHardDisk (); 1301 } 1302 1303 // 1304 // Load the driver option as the driver option list 1305 // 1306 PlatformBdsGetDriverOption (DriverOptionList); 1307 1308 // 1309 // Get current Boot Mode 1310 // 1311 Status = BdsLibGetBootMode (&BootMode); 1312 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode)); 1313 1314 // 1315 // Go the different platform policy with different boot mode 1316 // Notes: this part code can be change with the table policy 1317 // 1318 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION); 1319 // 1320 // Connect platform console 1321 // 1322 Status = PlatformBdsConnectConsole (gPlatformConsole); 1323 if (EFI_ERROR (Status)) { 1324 // 1325 // Here OEM/IBV can customize with defined action 1326 // 1327 PlatformBdsNoConsoleAction (); 1328 } 1329 1330 // 1331 // Memory test and Logo show 1332 // 1333 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest); 1334 1335 // 1336 // Perform some platform specific connect sequence 1337 // 1338 PlatformBdsConnectSequence (); 1339 1340 // 1341 // Process QEMU's -kernel command line option 1342 // 1343 TryRunningQemuKernel (); 1344 1345 DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n")); 1346 BdsLibConnectAll (); 1347 BdsLibEnumerateAllBootOption (BootOptionList); 1348 1349 SetBootOrderFromQemu (BootOptionList); 1350 // 1351 // The BootOrder variable may have changed, reload the in-memory list with 1352 // it. 1353 // 1354 BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); 1355 1356 PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE); 1357 } 1358 1359 VOID 1360 EFIAPI 1361 PlatformBdsBootSuccess ( 1362 IN BDS_COMMON_OPTION *Option 1363 ) 1364 /*++ 1365 1366 Routine Description: 1367 1368 Hook point after a boot attempt succeeds. We don't expect a boot option to 1369 return, so the EFI 1.0 specification defines that you will default to an 1370 interactive mode and stop processing the BootOrder list in this case. This 1371 is alos a platform implementation and can be customized by IBV/OEM. 1372 1373 Arguments: 1374 1375 Option - Pointer to Boot Option that succeeded to boot. 1376 1377 Returns: 1378 1379 None. 1380 1381 --*/ 1382 { 1383 CHAR16 *TmpStr; 1384 1385 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n")); 1386 // 1387 // If Boot returned with EFI_SUCCESS and there is not in the boot device 1388 // select loop then we need to pop up a UI and wait for user input. 1389 // 1390 TmpStr = Option->StatusString; 1391 if (TmpStr != NULL) { 1392 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); 1393 FreePool (TmpStr); 1394 } 1395 } 1396 1397 VOID 1398 EFIAPI 1399 PlatformBdsBootFail ( 1400 IN BDS_COMMON_OPTION *Option, 1401 IN EFI_STATUS Status, 1402 IN CHAR16 *ExitData, 1403 IN UINTN ExitDataSize 1404 ) 1405 /*++ 1406 1407 Routine Description: 1408 1409 Hook point after a boot attempt fails. 1410 1411 Arguments: 1412 1413 Option - Pointer to Boot Option that failed to boot. 1414 1415 Status - Status returned from failed boot. 1416 1417 ExitData - Exit data returned from failed boot. 1418 1419 ExitDataSize - Exit data size returned from failed boot. 1420 1421 Returns: 1422 1423 None. 1424 1425 --*/ 1426 { 1427 CHAR16 *TmpStr; 1428 1429 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n")); 1430 1431 // 1432 // If Boot returned with failed status then we need to pop up a UI and wait 1433 // for user input. 1434 // 1435 TmpStr = Option->StatusString; 1436 if (TmpStr != NULL) { 1437 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); 1438 FreePool (TmpStr); 1439 } 1440 } 1441 1442 EFI_STATUS 1443 PlatformBdsNoConsoleAction ( 1444 VOID 1445 ) 1446 /*++ 1447 1448 Routine Description: 1449 1450 This function is remained for IBV/OEM to do some platform action, 1451 if there no console device can be connected. 1452 1453 Arguments: 1454 1455 None. 1456 1457 Returns: 1458 1459 EFI_SUCCESS - Direct return success now. 1460 1461 --*/ 1462 { 1463 DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n")); 1464 return EFI_SUCCESS; 1465 } 1466 1467 VOID 1468 EFIAPI 1469 PlatformBdsLockNonUpdatableFlash ( 1470 VOID 1471 ) 1472 { 1473 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n")); 1474 return; 1475 } 1476 1477 1478 /** 1479 This notification function is invoked when an instance of the 1480 EFI_DEVICE_PATH_PROTOCOL is produced. 1481 1482 @param Event The event that occured 1483 @param Context For EFI compatiblity. Not used. 1484 1485 **/ 1486 VOID 1487 EFIAPI 1488 NotifyDevPath ( 1489 IN EFI_EVENT Event, 1490 IN VOID *Context 1491 ) 1492 { 1493 EFI_HANDLE Handle; 1494 EFI_STATUS Status; 1495 UINTN BufferSize; 1496 EFI_DEVICE_PATH_PROTOCOL *DevPathNode; 1497 ATAPI_DEVICE_PATH *Atapi; 1498 1499 // 1500 // Examine all new handles 1501 // 1502 for (;;) { 1503 // 1504 // Get the next handle 1505 // 1506 BufferSize = sizeof (Handle); 1507 Status = gBS->LocateHandle ( 1508 ByRegisterNotify, 1509 NULL, 1510 mEfiDevPathNotifyReg, 1511 &BufferSize, 1512 &Handle 1513 ); 1514 1515 // 1516 // If not found, we're done 1517 // 1518 if (EFI_NOT_FOUND == Status) { 1519 break; 1520 } 1521 1522 if (EFI_ERROR (Status)) { 1523 continue; 1524 } 1525 1526 // 1527 // Get the DevicePath protocol on that handle 1528 // 1529 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode); 1530 ASSERT_EFI_ERROR (Status); 1531 1532 while (!IsDevicePathEnd (DevPathNode)) { 1533 // 1534 // Find the handler to dump this device path node 1535 // 1536 if ( 1537 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) && 1538 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP) 1539 ) { 1540 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode; 1541 PciOr16 ( 1542 PCI_LIB_ADDRESS ( 1543 0, 1544 1, 1545 1, 1546 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40 1547 ), 1548 BIT15 1549 ); 1550 } 1551 1552 // 1553 // Next device path node 1554 // 1555 DevPathNode = NextDevicePathNode (DevPathNode); 1556 } 1557 } 1558 1559 return; 1560 } 1561 1562 1563 VOID 1564 InstallDevicePathCallback ( 1565 VOID 1566 ) 1567 { 1568 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n")); 1569 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent ( 1570 &gEfiDevicePathProtocolGuid, 1571 TPL_CALLBACK, 1572 NotifyDevPath, 1573 NULL, 1574 &mEfiDevPathNotifyReg 1575 ); 1576 } 1577 1578 /** 1579 Lock the ConsoleIn device in system table. All key 1580 presses will be ignored until the Password is typed in. The only way to 1581 disable the password is to type it in to a ConIn device. 1582 1583 @param Password Password used to lock ConIn device. 1584 1585 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully. 1586 @retval EFI_UNSUPPORTED Password not found 1587 1588 **/ 1589 EFI_STATUS 1590 EFIAPI 1591 LockKeyboards ( 1592 IN CHAR16 *Password 1593 ) 1594 { 1595 return EFI_UNSUPPORTED; 1596 } 1597 1598