2 Implementation for PlatformBootManagerLib library class interfaces.
4 Copyright (C) 2015-2016, Red Hat, Inc.
5 Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
6 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <IndustryStandard/Pci22.h>
13 #include <IndustryStandard/Virtio095.h>
14 #include <Library/BootLogoLib.h>
15 #include <Library/DevicePathLib.h>
16 #include <Library/PcdLib.h>
17 #include <Library/PlatformBmPrintScLib.h>
18 #include <Library/QemuBootOrderLib.h>
19 #include <Library/UefiBootManagerLib.h>
20 #include <Protocol/DevicePath.h>
21 #include <Protocol/FirmwareVolume2.h>
22 #include <Protocol/GraphicsOutput.h>
23 #include <Protocol/LoadedImage.h>
24 #include <Protocol/PciIo.h>
25 #include <Protocol/PciRootBridgeIo.h>
26 #include <Protocol/VirtioDevice.h>
27 #include <Guid/EventGroup.h>
28 #include <Guid/RootBridgesConnectedEventGroup.h>
29 #include <Guid/SerialPortLibVendor.h>
31 #include "PlatformBm.h"
33 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
38 VENDOR_DEVICE_PATH SerialDxe
;
39 UART_DEVICE_PATH Uart
;
40 VENDOR_DEFINED_DEVICE_PATH TermType
;
41 EFI_DEVICE_PATH_PROTOCOL End
;
42 } PLATFORM_SERIAL_CONSOLE
;
45 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole
= {
47 // VENDOR_DEVICE_PATH SerialDxe
50 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, DP_NODE_LEN (VENDOR_DEVICE_PATH
) },
51 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
55 // UART_DEVICE_PATH Uart
58 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, DP_NODE_LEN (UART_DEVICE_PATH
) },
60 FixedPcdGet64 (PcdUartDefaultBaudRate
), // BaudRate
61 FixedPcdGet8 (PcdUartDefaultDataBits
), // DataBits
62 FixedPcdGet8 (PcdUartDefaultParity
), // Parity
63 FixedPcdGet8 (PcdUartDefaultStopBits
) // StopBits
67 // VENDOR_DEFINED_DEVICE_PATH TermType
71 MESSAGING_DEVICE_PATH
, MSG_VENDOR_DP
,
72 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH
)
75 // Guid to be filled in dynamically
80 // EFI_DEVICE_PATH_PROTOCOL End
83 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
84 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
91 USB_CLASS_DEVICE_PATH Keyboard
;
92 EFI_DEVICE_PATH_PROTOCOL End
;
93 } PLATFORM_USB_KEYBOARD
;
96 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard
= {
98 // USB_CLASS_DEVICE_PATH Keyboard
102 MESSAGING_DEVICE_PATH
, MSG_USB_CLASS_DP
,
103 DP_NODE_LEN (USB_CLASS_DEVICE_PATH
)
105 0xFFFF, // VendorId: any
106 0xFFFF, // ProductId: any
107 3, // DeviceClass: HID
108 1, // DeviceSubClass: boot
109 1 // DeviceProtocol: keyboard
113 // EFI_DEVICE_PATH_PROTOCOL End
116 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
117 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
123 Check if the handle satisfies a particular condition.
125 @param[in] Handle The handle to check.
126 @param[in] ReportText A caller-allocated string passed in for reporting
127 purposes. It must never be NULL.
129 @retval TRUE The condition is satisfied.
130 @retval FALSE Otherwise. This includes the case when the condition could not
131 be fully evaluated due to an error.
135 (EFIAPI
*FILTER_FUNCTION
) (
136 IN EFI_HANDLE Handle
,
137 IN CONST CHAR16
*ReportText
144 @param[in] Handle The handle to process.
145 @param[in] ReportText A caller-allocated string passed in for reporting
146 purposes. It must never be NULL.
150 (EFIAPI
*CALLBACK_FUNCTION
) (
151 IN EFI_HANDLE Handle
,
152 IN CONST CHAR16
*ReportText
156 Locate all handles that carry the specified protocol, filter them with a
157 callback function, and pass each handle that passes the filter to another
160 @param[in] ProtocolGuid The protocol to look for.
162 @param[in] Filter The filter function to pass each handle to. If this
163 parameter is NULL, then all handles are processed.
165 @param[in] Process The callback function to pass each handle to that
171 IN EFI_GUID
*ProtocolGuid
,
172 IN FILTER_FUNCTION Filter OPTIONAL
,
173 IN CALLBACK_FUNCTION Process
181 Status
= gBS
->LocateHandleBuffer (ByProtocol
, ProtocolGuid
,
182 NULL
/* SearchKey */, &NoHandles
, &Handles
);
183 if (EFI_ERROR (Status
)) {
185 // This is not an error, just an informative condition.
187 DEBUG ((EFI_D_VERBOSE
, "%a: %g: %r\n", __FUNCTION__
, ProtocolGuid
,
192 ASSERT (NoHandles
> 0);
193 for (Idx
= 0; Idx
< NoHandles
; ++Idx
) {
194 CHAR16
*DevicePathText
;
195 STATIC CHAR16 Fallback
[] = L
"<device path unavailable>";
198 // The ConvertDevicePathToText() function handles NULL input transparently.
200 DevicePathText
= ConvertDevicePathToText (
201 DevicePathFromHandle (Handles
[Idx
]),
202 FALSE
, // DisplayOnly
203 FALSE
// AllowShortcuts
205 if (DevicePathText
== NULL
) {
206 DevicePathText
= Fallback
;
209 if (Filter
== NULL
|| Filter (Handles
[Idx
], DevicePathText
)) {
210 Process (Handles
[Idx
], DevicePathText
);
213 if (DevicePathText
!= Fallback
) {
214 FreePool (DevicePathText
);
217 gBS
->FreePool (Handles
);
222 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
228 IN EFI_HANDLE Handle
,
229 IN CONST CHAR16
*ReportText
233 EFI_PCI_IO_PROTOCOL
*PciIo
;
236 Status
= gBS
->HandleProtocol (Handle
, &gEfiPciIoProtocolGuid
,
238 if (EFI_ERROR (Status
)) {
240 // This is not an error worth reporting.
245 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, 0 /* Offset */,
246 sizeof Pci
/ sizeof (UINT32
), &Pci
);
247 if (EFI_ERROR (Status
)) {
248 DEBUG ((EFI_D_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
252 return IS_PCI_DISPLAY (&Pci
);
257 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
258 the VIRTIO_DEVICE_PROTOCOL level.
264 IN EFI_HANDLE Handle
,
265 IN CONST CHAR16
*ReportText
269 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
271 Status
= gBS
->HandleProtocol (Handle
, &gVirtioDeviceProtocolGuid
,
273 if (EFI_ERROR (Status
)) {
276 return (BOOLEAN
)(VirtIo
->SubSystemDeviceId
==
277 VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
);
282 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
283 the EFI_PCI_IO_PROTOCOL level.
289 IN EFI_HANDLE Handle
,
290 IN CONST CHAR16
*ReportText
294 EFI_PCI_IO_PROTOCOL
*PciIo
;
301 Status
= gBS
->HandleProtocol (Handle
, &gEfiPciIoProtocolGuid
,
303 if (EFI_ERROR (Status
)) {
308 // Read and check VendorId.
310 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_VENDOR_ID_OFFSET
,
312 if (EFI_ERROR (Status
)) {
315 if (VendorId
!= VIRTIO_VENDOR_ID
) {
320 // Read DeviceId and RevisionId.
322 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_DEVICE_ID_OFFSET
,
324 if (EFI_ERROR (Status
)) {
327 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, PCI_REVISION_ID_OFFSET
,
329 if (EFI_ERROR (Status
)) {
334 // From DeviceId and RevisionId, determine whether the device is a
335 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
336 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
337 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
338 // only be sanity-checked, and SubsystemId will decide.
340 if (DeviceId
== 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
&&
341 RevisionId
>= 0x01) {
343 } else if (DeviceId
>= 0x1000 && DeviceId
<= 0x103F && RevisionId
== 0x00) {
350 // Read and check SubsystemId as dictated by Virtio10.
352 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
,
353 PCI_SUBSYSTEM_ID_OFFSET
, 1, &SubsystemId
);
354 if (EFI_ERROR (Status
)) {
357 if (Virtio10
&& SubsystemId
>= 0x40) {
360 if (!Virtio10
&& SubsystemId
== VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
) {
366 DEBUG ((DEBUG_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
372 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
373 the matching driver to produce all first-level child handles.
379 IN EFI_HANDLE Handle
,
380 IN CONST CHAR16
*ReportText
385 Status
= gBS
->ConnectController (
386 Handle
, // ControllerHandle
387 NULL
, // DriverImageHandle
388 NULL
, // RemainingDevicePath -- produce all children
391 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
, "%a: %s: %r\n",
392 __FUNCTION__
, ReportText
, Status
));
397 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
398 handle, and adds it to ConOut and ErrOut.
404 IN EFI_HANDLE Handle
,
405 IN CONST CHAR16
*ReportText
409 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
411 DevicePath
= DevicePathFromHandle (Handle
);
412 if (DevicePath
== NULL
) {
413 DEBUG ((EFI_D_ERROR
, "%a: %s: handle %p: device path not found\n",
414 __FUNCTION__
, ReportText
, Handle
));
418 Status
= EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
419 if (EFI_ERROR (Status
)) {
420 DEBUG ((EFI_D_ERROR
, "%a: %s: adding to ConOut: %r\n", __FUNCTION__
,
421 ReportText
, Status
));
425 Status
= EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
426 if (EFI_ERROR (Status
)) {
427 DEBUG ((EFI_D_ERROR
, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__
,
428 ReportText
, Status
));
432 DEBUG ((EFI_D_VERBOSE
, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__
,
438 PlatformRegisterFvBootOption (
446 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
447 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
448 UINTN BootOptionCount
;
449 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
450 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
451 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
453 Status
= gBS
->HandleProtocol (
455 &gEfiLoadedImageProtocolGuid
,
456 (VOID
**) &LoadedImage
458 ASSERT_EFI_ERROR (Status
);
460 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
461 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
462 ASSERT (DevicePath
!= NULL
);
463 DevicePath
= AppendDevicePathNode (
465 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
467 ASSERT (DevicePath
!= NULL
);
469 Status
= EfiBootManagerInitializeLoadOption (
471 LoadOptionNumberUnassigned
,
479 ASSERT_EFI_ERROR (Status
);
480 FreePool (DevicePath
);
482 BootOptions
= EfiBootManagerGetLoadOptions (
483 &BootOptionCount
, LoadOptionTypeBoot
486 OptionIndex
= EfiBootManagerFindLoadOption (
487 &NewOption
, BootOptions
, BootOptionCount
490 if (OptionIndex
== -1) {
491 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
492 ASSERT_EFI_ERROR (Status
);
494 EfiBootManagerFreeLoadOption (&NewOption
);
495 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
500 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
501 whose device paths do not resolve exactly to an FvFile in the system.
503 This removes any boot options that point to binaries built into the firmware
504 and have become stale due to any of the following:
505 - FvMain's base address or size changed (historical),
506 - FvMain's FvNameGuid changed,
507 - the FILE_GUID of the pointed-to binary changed,
508 - the referenced binary is no longer built into the firmware.
510 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
511 avoids exact duplicates.
515 RemoveStaleFvFileOptions (
519 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
520 UINTN BootOptionCount
;
523 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
,
526 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
527 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
532 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
533 // then keep the boot option.
535 Node1
= BootOptions
[Index
].FilePath
;
536 if (!(DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
&&
537 DevicePathSubType (Node1
) == HW_MEMMAP_DP
) &&
538 !(DevicePathType (Node1
) == MEDIA_DEVICE_PATH
&&
539 DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)) {
544 // If the second device path node is not FvFile(...), then keep the boot
547 Node2
= NextDevicePathNode (Node1
);
548 if (DevicePathType (Node2
) != MEDIA_DEVICE_PATH
||
549 DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
) {
554 // Locate the Firmware Volume2 protocol instance that is denoted by the
555 // boot option. If this lookup fails (i.e., the boot option references a
556 // firmware volume that doesn't exist), then we'll proceed to delete the
560 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
,
561 &SearchNode
, &FvHandle
);
563 if (!EFI_ERROR (Status
)) {
565 // The firmware volume was found; now let's see if it contains the FvFile
566 // identified by GUID.
568 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
569 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
571 EFI_FV_FILETYPE FoundType
;
572 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
573 UINT32 AuthenticationStatus
;
575 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiFirmwareVolume2ProtocolGuid
,
576 (VOID
**)&FvProtocol
);
577 ASSERT_EFI_ERROR (Status
);
579 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
581 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
584 Status
= FvProtocol
->ReadFile (
586 &FvFileNode
->FvFileName
, // NameGuid
591 &AuthenticationStatus
593 if (!EFI_ERROR (Status
)) {
595 // The FvFile was found. Keep the boot option.
602 // Delete the boot option.
604 Status
= EfiBootManagerDeleteLoadOptionVariable (
605 BootOptions
[Index
].OptionNumber
, LoadOptionTypeBoot
);
607 CHAR16
*DevicePathString
;
609 DevicePathString
= ConvertDevicePathToText(BootOptions
[Index
].FilePath
,
612 EFI_ERROR (Status
) ? EFI_D_WARN
: EFI_D_VERBOSE
,
613 "%a: removing stale Boot#%04x %s: %r\n",
615 (UINT32
)BootOptions
[Index
].OptionNumber
,
616 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
619 if (DevicePathString
!= NULL
) {
620 FreePool (DevicePathString
);
625 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
631 PlatformRegisterOptionsAndKeys (
639 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
642 // Register ENTER as CONTINUE key
644 Enter
.ScanCode
= SCAN_NULL
;
645 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
646 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
647 ASSERT_EFI_ERROR (Status
);
650 // Map F2 and ESC to Boot Manager Menu
652 F2
.ScanCode
= SCAN_F2
;
653 F2
.UnicodeChar
= CHAR_NULL
;
654 Esc
.ScanCode
= SCAN_ESC
;
655 Esc
.UnicodeChar
= CHAR_NULL
;
656 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
657 ASSERT_EFI_ERROR (Status
);
658 Status
= EfiBootManagerAddKeyOptionVariable (
659 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
661 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
662 Status
= EfiBootManagerAddKeyOptionVariable (
663 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
665 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
670 // BDS Platform Functions
673 Do the platform init, can be customized by OEM/IBV
674 Possible things that can be done in PlatformBootManagerBeforeConsole:
675 > Update console variable: 1. include hot-plug devices;
676 > 2. Clear ConIn and add SOL for AMT
677 > Register new Driver#### or Boot####
678 > Register new Key####: e.g.: F12
679 > Signal ReadyToLock event
680 > Authentication action: 1. connect Auth devices;
681 > 2. Identify auto logon user.
685 PlatformBootManagerBeforeConsole (
689 RETURN_STATUS PcdStatus
;
692 // Signal EndOfDxe PI Event
694 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
697 // Dispatch deferred images after EndOfDxe event.
699 EfiBootManagerDispatchDeferredImages ();
702 // Locate the PCI root bridges and make the PCI bus driver connect each,
703 // non-recursively. This will produce a number of child handles with PciIo on
706 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid
, NULL
, Connect
);
709 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
711 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
714 // Find all display class PCI devices (using the handles from the previous
715 // step), and connect them non-recursively. This should produce a number of
716 // child handles with GOPs on them.
718 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsPciDisplay
, Connect
);
721 // Now add the device path of all handles with GOP on them to ConOut and
724 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid
, NULL
, AddOutput
);
727 // Add the hardcoded short-form USB keyboard device path to ConIn.
729 EfiBootManagerUpdateConsoleVariable (ConIn
,
730 (EFI_DEVICE_PATH_PROTOCOL
*)&mUsbKeyboard
, NULL
);
733 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
735 CopyGuid (&mSerialConsole
.TermType
.Guid
,
736 PcdGetPtr (PcdTerminalTypeGuidBuffer
));
737 EfiBootManagerUpdateConsoleVariable (ConIn
,
738 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
739 EfiBootManagerUpdateConsoleVariable (ConOut
,
740 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
741 EfiBootManagerUpdateConsoleVariable (ErrOut
,
742 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
745 // Set the front page timeout from the QEMU configuration.
747 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
,
748 GetFrontPageTimeoutFromQemu ());
749 ASSERT_RETURN_ERROR (PcdStatus
);
752 // Register platform-specific boot options and keyboard shortcuts.
754 PlatformRegisterOptionsAndKeys ();
757 // At this point, VIRTIO_DEVICE_PROTOCOL instances exist only for Virtio MMIO
758 // transports. Install EFI_RNG_PROTOCOL instances on Virtio MMIO RNG devices.
760 FilterAndProcess (&gVirtioDeviceProtocolGuid
, IsVirtioRng
, Connect
);
763 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
764 // instances on Virtio PCI RNG devices.
766 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsVirtioPciRng
, Connect
);
770 Do the platform specific action after the console is ready
771 Possible things that can be done in PlatformBootManagerAfterConsole:
772 > Console post action:
773 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
774 > Signal console ready platform customized event
775 > Run diagnostics like memory testing
776 > Connect certain devices
777 > Dispatch additional option roms
778 > Special boot: e.g.: USB boot, enter UI
782 PlatformBootManagerAfterConsole (
786 RETURN_STATUS Status
;
789 // Show the splash screen.
791 BootLogoEnableLogo ();
794 // Process QEMU's -kernel command line option. The kernel booted this way
795 // will receive ACPI tables: in PlatformBootManagerBeforeConsole(), we
796 // connected any and all PCI root bridges, and then signaled the ACPI
799 TryRunningQemuKernel ();
802 // Connect the purported boot devices.
804 Status
= ConnectDevicesFromQemu ();
805 if (RETURN_ERROR (Status
)) {
807 // Connect the rest of the devices.
809 EfiBootManagerConnectAll ();
813 // Enumerate all possible boot options, then filter and reorder them based on
814 // the QEMU configuration.
816 EfiBootManagerRefreshAllBootOption ();
819 // Register UEFI Shell
821 PlatformRegisterFvBootOption (
822 &gUefiShellFileGuid
, L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
825 RemoveStaleFvFileOptions ();
826 SetBootOrderFromQemu ();
828 PlatformBmPrintScRegisterHandler ();
832 This function is called each second during the boot manager waits the
835 @param TimeoutRemain The remaining timeout.
839 PlatformBootManagerWaitCallback (
843 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
844 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
845 UINT16 TimeoutInitial
;
847 TimeoutInitial
= PcdGet16 (PcdPlatformBootTimeOut
);
850 // If PcdPlatformBootTimeOut is set to zero, then we consider
851 // that no progress update should be enacted.
853 if (TimeoutInitial
== 0) {
857 Black
.Raw
= 0x00000000;
858 White
.Raw
= 0x00FFFFFF;
860 BootLogoUpdateProgress (
863 L
"Start boot option",
865 (TimeoutInitial
- TimeoutRemain
) * 100 / TimeoutInitial
,
871 The function is called when no boot option could be launched,
872 including platform recovery options and options pointing to applications
873 built into firmware volumes.
875 If this function returns, BDS attempts to enter an infinite loop.
879 PlatformBootManagerUnableToBoot (
885 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
889 // BootManagerMenu doesn't contain the correct information when return status
892 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
893 if (EFI_ERROR (Status
)) {
897 // Normally BdsDxe does not print anything to the system console, but this is
898 // a last resort -- the end-user will likely not see any DEBUG messages
899 // logged in this situation.
901 // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
902 // here to see if it makes sense to request and wait for a keypress.
904 if (gST
->ConIn
!= NULL
) {
906 "%a: No bootable option or device was found.\n"
907 "%a: Press any key to enter the Boot Manager Menu.\n",
911 Status
= gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
912 ASSERT_EFI_ERROR (Status
);
916 // Drain any queued keys.
918 while (!EFI_ERROR (gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
))) {
920 // just throw away Key
926 EfiBootManagerBoot (&BootManagerMenu
);