1 /** @file 2 Implementation for PlatformBootManagerLib library class interfaces. 3 4 Copyright (C) 2015-2016, Red Hat, Inc. 5 Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> 6 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR> 7 8 This program and the accompanying materials are licensed and made available 9 under the terms and conditions of the BSD License which accompanies this 10 distribution. The full text of the license may be found at 11 http://opensource.org/licenses/bsd-license.php 12 13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT 14 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 15 16 **/ 17 18 #include <IndustryStandard/Pci22.h> 19 #include <Library/BootLogoLib.h> 20 #include <Library/DevicePathLib.h> 21 #include <Library/PcdLib.h> 22 #include <Library/QemuBootOrderLib.h> 23 #include <Library/UefiBootManagerLib.h> 24 #include <Protocol/DevicePath.h> 25 #include <Protocol/FirmwareVolume2.h> 26 #include <Protocol/GraphicsOutput.h> 27 #include <Protocol/LoadedImage.h> 28 #include <Protocol/PciIo.h> 29 #include <Protocol/PciRootBridgeIo.h> 30 #include <Guid/EventGroup.h> 31 #include <Guid/RootBridgesConnectedEventGroup.h> 32 33 #include "PlatformBm.h" 34 35 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) } 36 37 38 #pragma pack (1) 39 typedef struct { 40 VENDOR_DEVICE_PATH SerialDxe; 41 UART_DEVICE_PATH Uart; 42 VENDOR_DEFINED_DEVICE_PATH TermType; 43 EFI_DEVICE_PATH_PROTOCOL End; 44 } PLATFORM_SERIAL_CONSOLE; 45 #pragma pack () 46 47 #define SERIAL_DXE_FILE_GUID { \ 48 0xD3987D4B, 0x971A, 0x435F, \ 49 { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \ 50 } 51 52 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = { 53 // 54 // VENDOR_DEVICE_PATH SerialDxe 55 // 56 { 57 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, 58 SERIAL_DXE_FILE_GUID 59 }, 60 61 // 62 // UART_DEVICE_PATH Uart 63 // 64 { 65 { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) }, 66 0, // Reserved 67 FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate 68 FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits 69 FixedPcdGet8 (PcdUartDefaultParity), // Parity 70 FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits 71 }, 72 73 // 74 // VENDOR_DEFINED_DEVICE_PATH TermType 75 // 76 { 77 { 78 MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, 79 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH) 80 } 81 // 82 // Guid to be filled in dynamically 83 // 84 }, 85 86 // 87 // EFI_DEVICE_PATH_PROTOCOL End 88 // 89 { 90 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, 91 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) 92 } 93 }; 94 95 96 #pragma pack (1) 97 typedef struct { 98 USB_CLASS_DEVICE_PATH Keyboard; 99 EFI_DEVICE_PATH_PROTOCOL End; 100 } PLATFORM_USB_KEYBOARD; 101 #pragma pack () 102 103 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = { 104 // 105 // USB_CLASS_DEVICE_PATH Keyboard 106 // 107 { 108 { 109 MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP, 110 DP_NODE_LEN (USB_CLASS_DEVICE_PATH) 111 }, 112 0xFFFF, // VendorId: any 113 0xFFFF, // ProductId: any 114 3, // DeviceClass: HID 115 1, // DeviceSubClass: boot 116 1 // DeviceProtocol: keyboard 117 }, 118 119 // 120 // EFI_DEVICE_PATH_PROTOCOL End 121 // 122 { 123 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, 124 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) 125 } 126 }; 127 128 129 /** 130 Check if the handle satisfies a particular condition. 131 132 @param[in] Handle The handle to check. 133 @param[in] ReportText A caller-allocated string passed in for reporting 134 purposes. It must never be NULL. 135 136 @retval TRUE The condition is satisfied. 137 @retval FALSE Otherwise. This includes the case when the condition could not 138 be fully evaluated due to an error. 139 **/ 140 typedef 141 BOOLEAN 142 (EFIAPI *FILTER_FUNCTION) ( 143 IN EFI_HANDLE Handle, 144 IN CONST CHAR16 *ReportText 145 ); 146 147 148 /** 149 Process a handle. 150 151 @param[in] Handle The handle to process. 152 @param[in] ReportText A caller-allocated string passed in for reporting 153 purposes. It must never be NULL. 154 **/ 155 typedef 156 VOID 157 (EFIAPI *CALLBACK_FUNCTION) ( 158 IN EFI_HANDLE Handle, 159 IN CONST CHAR16 *ReportText 160 ); 161 162 /** 163 Locate all handles that carry the specified protocol, filter them with a 164 callback function, and pass each handle that passes the filter to another 165 callback. 166 167 @param[in] ProtocolGuid The protocol to look for. 168 169 @param[in] Filter The filter function to pass each handle to. If this 170 parameter is NULL, then all handles are processed. 171 172 @param[in] Process The callback function to pass each handle to that 173 clears the filter. 174 **/ 175 STATIC 176 VOID 177 FilterAndProcess ( 178 IN EFI_GUID *ProtocolGuid, 179 IN FILTER_FUNCTION Filter OPTIONAL, 180 IN CALLBACK_FUNCTION Process 181 ) 182 { 183 EFI_STATUS Status; 184 EFI_HANDLE *Handles; 185 UINTN NoHandles; 186 UINTN Idx; 187 188 Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid, 189 NULL /* SearchKey */, &NoHandles, &Handles); 190 if (EFI_ERROR (Status)) { 191 // 192 // This is not an error, just an informative condition. 193 // 194 DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid, 195 Status)); 196 return; 197 } 198 199 ASSERT (NoHandles > 0); 200 for (Idx = 0; Idx < NoHandles; ++Idx) { 201 CHAR16 *DevicePathText; 202 STATIC CHAR16 Fallback[] = L"<device path unavailable>"; 203 204 // 205 // The ConvertDevicePathToText() function handles NULL input transparently. 206 // 207 DevicePathText = ConvertDevicePathToText ( 208 DevicePathFromHandle (Handles[Idx]), 209 FALSE, // DisplayOnly 210 FALSE // AllowShortcuts 211 ); 212 if (DevicePathText == NULL) { 213 DevicePathText = Fallback; 214 } 215 216 if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) { 217 Process (Handles[Idx], DevicePathText); 218 } 219 220 if (DevicePathText != Fallback) { 221 FreePool (DevicePathText); 222 } 223 } 224 gBS->FreePool (Handles); 225 } 226 227 228 /** 229 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device. 230 **/ 231 STATIC 232 BOOLEAN 233 EFIAPI 234 IsPciDisplay ( 235 IN EFI_HANDLE Handle, 236 IN CONST CHAR16 *ReportText 237 ) 238 { 239 EFI_STATUS Status; 240 EFI_PCI_IO_PROTOCOL *PciIo; 241 PCI_TYPE00 Pci; 242 243 Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid, 244 (VOID**)&PciIo); 245 if (EFI_ERROR (Status)) { 246 // 247 // This is not an error worth reporting. 248 // 249 return FALSE; 250 } 251 252 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */, 253 sizeof Pci / sizeof (UINT32), &Pci); 254 if (EFI_ERROR (Status)) { 255 DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status)); 256 return FALSE; 257 } 258 259 return IS_PCI_DISPLAY (&Pci); 260 } 261 262 263 /** 264 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking 265 the matching driver to produce all first-level child handles. 266 **/ 267 STATIC 268 VOID 269 EFIAPI 270 Connect ( 271 IN EFI_HANDLE Handle, 272 IN CONST CHAR16 *ReportText 273 ) 274 { 275 EFI_STATUS Status; 276 277 Status = gBS->ConnectController ( 278 Handle, // ControllerHandle 279 NULL, // DriverImageHandle 280 NULL, // RemainingDevicePath -- produce all children 281 FALSE // Recursive 282 ); 283 DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n", 284 __FUNCTION__, ReportText, Status)); 285 } 286 287 288 /** 289 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the 290 handle, and adds it to ConOut and ErrOut. 291 **/ 292 STATIC 293 VOID 294 EFIAPI 295 AddOutput ( 296 IN EFI_HANDLE Handle, 297 IN CONST CHAR16 *ReportText 298 ) 299 { 300 EFI_STATUS Status; 301 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 302 303 DevicePath = DevicePathFromHandle (Handle); 304 if (DevicePath == NULL) { 305 DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n", 306 __FUNCTION__, ReportText, Handle)); 307 return; 308 } 309 310 Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); 311 if (EFI_ERROR (Status)) { 312 DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__, 313 ReportText, Status)); 314 return; 315 } 316 317 Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); 318 if (EFI_ERROR (Status)) { 319 DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__, 320 ReportText, Status)); 321 return; 322 } 323 324 DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__, 325 ReportText)); 326 } 327 328 STATIC 329 VOID 330 PlatformRegisterFvBootOption ( 331 EFI_GUID *FileGuid, 332 CHAR16 *Description, 333 UINT32 Attributes 334 ) 335 { 336 EFI_STATUS Status; 337 INTN OptionIndex; 338 EFI_BOOT_MANAGER_LOAD_OPTION NewOption; 339 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; 340 UINTN BootOptionCount; 341 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; 342 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; 343 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 344 345 Status = gBS->HandleProtocol ( 346 gImageHandle, 347 &gEfiLoadedImageProtocolGuid, 348 (VOID **) &LoadedImage 349 ); 350 ASSERT_EFI_ERROR (Status); 351 352 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); 353 DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle); 354 ASSERT (DevicePath != NULL); 355 DevicePath = AppendDevicePathNode ( 356 DevicePath, 357 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode 358 ); 359 ASSERT (DevicePath != NULL); 360 361 Status = EfiBootManagerInitializeLoadOption ( 362 &NewOption, 363 LoadOptionNumberUnassigned, 364 LoadOptionTypeBoot, 365 Attributes, 366 Description, 367 DevicePath, 368 NULL, 369 0 370 ); 371 ASSERT_EFI_ERROR (Status); 372 FreePool (DevicePath); 373 374 BootOptions = EfiBootManagerGetLoadOptions ( 375 &BootOptionCount, LoadOptionTypeBoot 376 ); 377 378 OptionIndex = EfiBootManagerFindLoadOption ( 379 &NewOption, BootOptions, BootOptionCount 380 ); 381 382 if (OptionIndex == -1) { 383 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN); 384 ASSERT_EFI_ERROR (Status); 385 } 386 EfiBootManagerFreeLoadOption (&NewOption); 387 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); 388 } 389 390 391 /** 392 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options 393 whose device paths do not resolve exactly to an FvFile in the system. 394 395 This removes any boot options that point to binaries built into the firmware 396 and have become stale due to any of the following: 397 - FvMain's base address or size changed (historical), 398 - FvMain's FvNameGuid changed, 399 - the FILE_GUID of the pointed-to binary changed, 400 - the referenced binary is no longer built into the firmware. 401 402 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only 403 avoids exact duplicates. 404 **/ 405 STATIC 406 VOID 407 RemoveStaleFvFileOptions ( 408 VOID 409 ) 410 { 411 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; 412 UINTN BootOptionCount; 413 UINTN Index; 414 415 BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, 416 LoadOptionTypeBoot); 417 418 for (Index = 0; Index < BootOptionCount; ++Index) { 419 EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode; 420 EFI_STATUS Status; 421 EFI_HANDLE FvHandle; 422 423 // 424 // If the device path starts with neither MemoryMapped(...) nor Fv(...), 425 // then keep the boot option. 426 // 427 Node1 = BootOptions[Index].FilePath; 428 if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH && 429 DevicePathSubType (Node1) == HW_MEMMAP_DP) && 430 !(DevicePathType (Node1) == MEDIA_DEVICE_PATH && 431 DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) { 432 continue; 433 } 434 435 // 436 // If the second device path node is not FvFile(...), then keep the boot 437 // option. 438 // 439 Node2 = NextDevicePathNode (Node1); 440 if (DevicePathType (Node2) != MEDIA_DEVICE_PATH || 441 DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) { 442 continue; 443 } 444 445 // 446 // Locate the Firmware Volume2 protocol instance that is denoted by the 447 // boot option. If this lookup fails (i.e., the boot option references a 448 // firmware volume that doesn't exist), then we'll proceed to delete the 449 // boot option. 450 // 451 SearchNode = Node1; 452 Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, 453 &SearchNode, &FvHandle); 454 455 if (!EFI_ERROR (Status)) { 456 // 457 // The firmware volume was found; now let's see if it contains the FvFile 458 // identified by GUID. 459 // 460 EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol; 461 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode; 462 UINTN BufferSize; 463 EFI_FV_FILETYPE FoundType; 464 EFI_FV_FILE_ATTRIBUTES FileAttributes; 465 UINT32 AuthenticationStatus; 466 467 Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, 468 (VOID **)&FvProtocol); 469 ASSERT_EFI_ERROR (Status); 470 471 FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2; 472 // 473 // Buffer==NULL means we request metadata only: BufferSize, FoundType, 474 // FileAttributes. 475 // 476 Status = FvProtocol->ReadFile ( 477 FvProtocol, 478 &FvFileNode->FvFileName, // NameGuid 479 NULL, // Buffer 480 &BufferSize, 481 &FoundType, 482 &FileAttributes, 483 &AuthenticationStatus 484 ); 485 if (!EFI_ERROR (Status)) { 486 // 487 // The FvFile was found. Keep the boot option. 488 // 489 continue; 490 } 491 } 492 493 // 494 // Delete the boot option. 495 // 496 Status = EfiBootManagerDeleteLoadOptionVariable ( 497 BootOptions[Index].OptionNumber, LoadOptionTypeBoot); 498 DEBUG_CODE ( 499 CHAR16 *DevicePathString; 500 501 DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath, 502 FALSE, FALSE); 503 DEBUG (( 504 EFI_ERROR (Status) ? EFI_D_WARN : EFI_D_VERBOSE, 505 "%a: removing stale Boot#%04x %s: %r\n", 506 __FUNCTION__, 507 (UINT32)BootOptions[Index].OptionNumber, 508 DevicePathString == NULL ? L"<unavailable>" : DevicePathString, 509 Status 510 )); 511 if (DevicePathString != NULL) { 512 FreePool (DevicePathString); 513 } 514 ); 515 } 516 517 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); 518 } 519 520 521 STATIC 522 VOID 523 PlatformRegisterOptionsAndKeys ( 524 VOID 525 ) 526 { 527 EFI_STATUS Status; 528 EFI_INPUT_KEY Enter; 529 EFI_INPUT_KEY F2; 530 EFI_INPUT_KEY Esc; 531 EFI_BOOT_MANAGER_LOAD_OPTION BootOption; 532 533 // 534 // Register ENTER as CONTINUE key 535 // 536 Enter.ScanCode = SCAN_NULL; 537 Enter.UnicodeChar = CHAR_CARRIAGE_RETURN; 538 Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); 539 ASSERT_EFI_ERROR (Status); 540 541 // 542 // Map F2 and ESC to Boot Manager Menu 543 // 544 F2.ScanCode = SCAN_F2; 545 F2.UnicodeChar = CHAR_NULL; 546 Esc.ScanCode = SCAN_ESC; 547 Esc.UnicodeChar = CHAR_NULL; 548 Status = EfiBootManagerGetBootManagerMenu (&BootOption); 549 ASSERT_EFI_ERROR (Status); 550 Status = EfiBootManagerAddKeyOptionVariable ( 551 NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL 552 ); 553 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); 554 Status = EfiBootManagerAddKeyOptionVariable ( 555 NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL 556 ); 557 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); 558 } 559 560 561 // 562 // BDS Platform Functions 563 // 564 /** 565 Do the platform init, can be customized by OEM/IBV 566 Possible things that can be done in PlatformBootManagerBeforeConsole: 567 > Update console variable: 1. include hot-plug devices; 568 > 2. Clear ConIn and add SOL for AMT 569 > Register new Driver#### or Boot#### 570 > Register new Key####: e.g.: F12 571 > Signal ReadyToLock event 572 > Authentication action: 1. connect Auth devices; 573 > 2. Identify auto logon user. 574 **/ 575 VOID 576 EFIAPI 577 PlatformBootManagerBeforeConsole ( 578 VOID 579 ) 580 { 581 RETURN_STATUS PcdStatus; 582 583 // 584 // Signal EndOfDxe PI Event 585 // 586 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); 587 588 // 589 // Dispatch deferred images after EndOfDxe event. 590 // 591 EfiBootManagerDispatchDeferredImages (); 592 593 // 594 // Locate the PCI root bridges and make the PCI bus driver connect each, 595 // non-recursively. This will produce a number of child handles with PciIo on 596 // them. 597 // 598 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect); 599 600 // 601 // Signal the ACPI platform driver that it can download QEMU ACPI tables. 602 // 603 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid); 604 605 // 606 // Find all display class PCI devices (using the handles from the previous 607 // step), and connect them non-recursively. This should produce a number of 608 // child handles with GOPs on them. 609 // 610 FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect); 611 612 // 613 // Now add the device path of all handles with GOP on them to ConOut and 614 // ErrOut. 615 // 616 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput); 617 618 // 619 // Add the hardcoded short-form USB keyboard device path to ConIn. 620 // 621 EfiBootManagerUpdateConsoleVariable (ConIn, 622 (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL); 623 624 // 625 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut. 626 // 627 CopyGuid (&mSerialConsole.TermType.Guid, 628 PcdGetPtr (PcdTerminalTypeGuidBuffer)); 629 EfiBootManagerUpdateConsoleVariable (ConIn, 630 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); 631 EfiBootManagerUpdateConsoleVariable (ConOut, 632 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); 633 EfiBootManagerUpdateConsoleVariable (ErrOut, 634 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); 635 636 // 637 // Set the front page timeout from the QEMU configuration. 638 // 639 PcdStatus = PcdSet16S (PcdPlatformBootTimeOut, 640 GetFrontPageTimeoutFromQemu ()); 641 ASSERT_RETURN_ERROR (PcdStatus); 642 643 // 644 // Register platform-specific boot options and keyboard shortcuts. 645 // 646 PlatformRegisterOptionsAndKeys (); 647 } 648 649 /** 650 Do the platform specific action after the console is ready 651 Possible things that can be done in PlatformBootManagerAfterConsole: 652 > Console post action: 653 > Dynamically switch output mode from 100x31 to 80x25 for certain senarino 654 > Signal console ready platform customized event 655 > Run diagnostics like memory testing 656 > Connect certain devices 657 > Dispatch aditional option roms 658 > Special boot: e.g.: USB boot, enter UI 659 **/ 660 VOID 661 EFIAPI 662 PlatformBootManagerAfterConsole ( 663 VOID 664 ) 665 { 666 // 667 // Show the splash screen. 668 // 669 BootLogoEnableLogo (); 670 671 // 672 // Connect the rest of the devices. 673 // 674 EfiBootManagerConnectAll (); 675 676 // 677 // Process QEMU's -kernel command line option. Note that the kernel booted 678 // this way should receive ACPI tables, which is why we connect all devices 679 // first (see above) -- PCI enumeration blocks ACPI table installation, if 680 // there is a PCI host. 681 // 682 TryRunningQemuKernel (); 683 684 // 685 // Enumerate all possible boot options, then filter and reorder them based on 686 // the QEMU configuration. 687 // 688 EfiBootManagerRefreshAllBootOption (); 689 690 // 691 // Register UEFI Shell 692 // 693 PlatformRegisterFvBootOption ( 694 PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE 695 ); 696 697 RemoveStaleFvFileOptions (); 698 SetBootOrderFromQemu (); 699 } 700 701 /** 702 This function is called each second during the boot manager waits the 703 timeout. 704 705 @param TimeoutRemain The remaining timeout. 706 **/ 707 VOID 708 EFIAPI 709 PlatformBootManagerWaitCallback ( 710 UINT16 TimeoutRemain 711 ) 712 { 713 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black; 714 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White; 715 UINT16 Timeout; 716 717 Timeout = PcdGet16 (PcdPlatformBootTimeOut); 718 719 Black.Raw = 0x00000000; 720 White.Raw = 0x00FFFFFF; 721 722 BootLogoUpdateProgress ( 723 White.Pixel, 724 Black.Pixel, 725 L"Start boot option", 726 White.Pixel, 727 (Timeout - TimeoutRemain) * 100 / Timeout, 728 0 729 ); 730 } 731