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