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 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
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.
18 #include <IndustryStandard/Pci22.h>
19 #include <IndustryStandard/Virtio095.h>
20 #include <Library/BootLogoLib.h>
21 #include <Library/DevicePathLib.h>
22 #include <Library/PcdLib.h>
23 #include <Library/PlatformBmPrintScLib.h>
24 #include <Library/QemuBootOrderLib.h>
25 #include <Library/UefiBootManagerLib.h>
26 #include <Protocol/DevicePath.h>
27 #include <Protocol/FirmwareVolume2.h>
28 #include <Protocol/GraphicsOutput.h>
29 #include <Protocol/LoadedImage.h>
30 #include <Protocol/PciIo.h>
31 #include <Protocol/PciRootBridgeIo.h>
32 #include <Protocol/VirtioDevice.h>
33 #include <Guid/EventGroup.h>
34 #include <Guid/RootBridgesConnectedEventGroup.h>
36 #include "PlatformBm.h"
38 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
43 VENDOR_DEVICE_PATH SerialDxe
;
44 UART_DEVICE_PATH Uart
;
45 VENDOR_DEFINED_DEVICE_PATH TermType
;
46 EFI_DEVICE_PATH_PROTOCOL End
;
47 } PLATFORM_SERIAL_CONSOLE
;
50 #define SERIAL_DXE_FILE_GUID { \
51 0xD3987D4B, 0x971A, 0x435F, \
52 { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \
55 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole
= {
57 // VENDOR_DEVICE_PATH SerialDxe
60 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, DP_NODE_LEN (VENDOR_DEVICE_PATH
) },
65 // UART_DEVICE_PATH Uart
68 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, DP_NODE_LEN (UART_DEVICE_PATH
) },
70 FixedPcdGet64 (PcdUartDefaultBaudRate
), // BaudRate
71 FixedPcdGet8 (PcdUartDefaultDataBits
), // DataBits
72 FixedPcdGet8 (PcdUartDefaultParity
), // Parity
73 FixedPcdGet8 (PcdUartDefaultStopBits
) // StopBits
77 // VENDOR_DEFINED_DEVICE_PATH TermType
81 MESSAGING_DEVICE_PATH
, MSG_VENDOR_DP
,
82 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH
)
85 // Guid to be filled in dynamically
90 // EFI_DEVICE_PATH_PROTOCOL End
93 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
94 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
101 USB_CLASS_DEVICE_PATH Keyboard
;
102 EFI_DEVICE_PATH_PROTOCOL End
;
103 } PLATFORM_USB_KEYBOARD
;
106 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard
= {
108 // USB_CLASS_DEVICE_PATH Keyboard
112 MESSAGING_DEVICE_PATH
, MSG_USB_CLASS_DP
,
113 DP_NODE_LEN (USB_CLASS_DEVICE_PATH
)
115 0xFFFF, // VendorId: any
116 0xFFFF, // ProductId: any
117 3, // DeviceClass: HID
118 1, // DeviceSubClass: boot
119 1 // DeviceProtocol: keyboard
123 // EFI_DEVICE_PATH_PROTOCOL End
126 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
127 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
133 Check if the handle satisfies a particular condition.
135 @param[in] Handle The handle to check.
136 @param[in] ReportText A caller-allocated string passed in for reporting
137 purposes. It must never be NULL.
139 @retval TRUE The condition is satisfied.
140 @retval FALSE Otherwise. This includes the case when the condition could not
141 be fully evaluated due to an error.
145 (EFIAPI
*FILTER_FUNCTION
) (
146 IN EFI_HANDLE Handle
,
147 IN CONST CHAR16
*ReportText
154 @param[in] Handle The handle to process.
155 @param[in] ReportText A caller-allocated string passed in for reporting
156 purposes. It must never be NULL.
160 (EFIAPI
*CALLBACK_FUNCTION
) (
161 IN EFI_HANDLE Handle
,
162 IN CONST CHAR16
*ReportText
166 Locate all handles that carry the specified protocol, filter them with a
167 callback function, and pass each handle that passes the filter to another
170 @param[in] ProtocolGuid The protocol to look for.
172 @param[in] Filter The filter function to pass each handle to. If this
173 parameter is NULL, then all handles are processed.
175 @param[in] Process The callback function to pass each handle to that
181 IN EFI_GUID
*ProtocolGuid
,
182 IN FILTER_FUNCTION Filter OPTIONAL
,
183 IN CALLBACK_FUNCTION Process
191 Status
= gBS
->LocateHandleBuffer (ByProtocol
, ProtocolGuid
,
192 NULL
/* SearchKey */, &NoHandles
, &Handles
);
193 if (EFI_ERROR (Status
)) {
195 // This is not an error, just an informative condition.
197 DEBUG ((EFI_D_VERBOSE
, "%a: %g: %r\n", __FUNCTION__
, ProtocolGuid
,
202 ASSERT (NoHandles
> 0);
203 for (Idx
= 0; Idx
< NoHandles
; ++Idx
) {
204 CHAR16
*DevicePathText
;
205 STATIC CHAR16 Fallback
[] = L
"<device path unavailable>";
208 // The ConvertDevicePathToText() function handles NULL input transparently.
210 DevicePathText
= ConvertDevicePathToText (
211 DevicePathFromHandle (Handles
[Idx
]),
212 FALSE
, // DisplayOnly
213 FALSE
// AllowShortcuts
215 if (DevicePathText
== NULL
) {
216 DevicePathText
= Fallback
;
219 if (Filter
== NULL
|| Filter (Handles
[Idx
], DevicePathText
)) {
220 Process (Handles
[Idx
], DevicePathText
);
223 if (DevicePathText
!= Fallback
) {
224 FreePool (DevicePathText
);
227 gBS
->FreePool (Handles
);
232 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
238 IN EFI_HANDLE Handle
,
239 IN CONST CHAR16
*ReportText
243 EFI_PCI_IO_PROTOCOL
*PciIo
;
246 Status
= gBS
->HandleProtocol (Handle
, &gEfiPciIoProtocolGuid
,
248 if (EFI_ERROR (Status
)) {
250 // This is not an error worth reporting.
255 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, 0 /* Offset */,
256 sizeof Pci
/ sizeof (UINT32
), &Pci
);
257 if (EFI_ERROR (Status
)) {
258 DEBUG ((EFI_D_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
262 return IS_PCI_DISPLAY (&Pci
);
267 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
268 the VIRTIO_DEVICE_PROTOCOL level.
274 IN EFI_HANDLE Handle
,
275 IN CONST CHAR16
*ReportText
279 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
281 Status
= gBS
->HandleProtocol (Handle
, &gVirtioDeviceProtocolGuid
,
283 if (EFI_ERROR (Status
)) {
286 return (BOOLEAN
)(VirtIo
->SubSystemDeviceId
==
287 VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
);
292 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
293 the EFI_PCI_IO_PROTOCOL level.
299 IN EFI_HANDLE Handle
,
300 IN CONST CHAR16
*ReportText
304 EFI_PCI_IO_PROTOCOL
*PciIo
;
311 Status
= gBS
->HandleProtocol (Handle
, &gEfiPciIoProtocolGuid
,
313 if (EFI_ERROR (Status
)) {
318 // Read and check VendorId.
320 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_VENDOR_ID_OFFSET
,
322 if (EFI_ERROR (Status
)) {
325 if (VendorId
!= VIRTIO_VENDOR_ID
) {
330 // Read DeviceId and RevisionId.
332 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_DEVICE_ID_OFFSET
,
334 if (EFI_ERROR (Status
)) {
337 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, PCI_REVISION_ID_OFFSET
,
339 if (EFI_ERROR (Status
)) {
344 // From DeviceId and RevisionId, determine whether the device is a
345 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
346 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
347 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
348 // only be sanity-checked, and SubsystemId will decide.
350 if (DeviceId
== 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
&&
351 RevisionId
>= 0x01) {
353 } else if (DeviceId
>= 0x1000 && DeviceId
<= 0x103F && RevisionId
== 0x00) {
360 // Read and check SubsystemId as dictated by Virtio10.
362 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
,
363 PCI_SUBSYSTEM_ID_OFFSET
, 1, &SubsystemId
);
364 if (EFI_ERROR (Status
)) {
367 if (Virtio10
&& SubsystemId
>= 0x40) {
370 if (!Virtio10
&& SubsystemId
== VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
) {
376 DEBUG ((DEBUG_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
382 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
383 the matching driver to produce all first-level child handles.
389 IN EFI_HANDLE Handle
,
390 IN CONST CHAR16
*ReportText
395 Status
= gBS
->ConnectController (
396 Handle
, // ControllerHandle
397 NULL
, // DriverImageHandle
398 NULL
, // RemainingDevicePath -- produce all children
401 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
, "%a: %s: %r\n",
402 __FUNCTION__
, ReportText
, Status
));
407 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
408 handle, and adds it to ConOut and ErrOut.
414 IN EFI_HANDLE Handle
,
415 IN CONST CHAR16
*ReportText
419 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
421 DevicePath
= DevicePathFromHandle (Handle
);
422 if (DevicePath
== NULL
) {
423 DEBUG ((EFI_D_ERROR
, "%a: %s: handle %p: device path not found\n",
424 __FUNCTION__
, ReportText
, Handle
));
428 Status
= EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
429 if (EFI_ERROR (Status
)) {
430 DEBUG ((EFI_D_ERROR
, "%a: %s: adding to ConOut: %r\n", __FUNCTION__
,
431 ReportText
, Status
));
435 Status
= EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
436 if (EFI_ERROR (Status
)) {
437 DEBUG ((EFI_D_ERROR
, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__
,
438 ReportText
, Status
));
442 DEBUG ((EFI_D_VERBOSE
, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__
,
448 PlatformRegisterFvBootOption (
456 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
457 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
458 UINTN BootOptionCount
;
459 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
460 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
461 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
463 Status
= gBS
->HandleProtocol (
465 &gEfiLoadedImageProtocolGuid
,
466 (VOID
**) &LoadedImage
468 ASSERT_EFI_ERROR (Status
);
470 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
471 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
472 ASSERT (DevicePath
!= NULL
);
473 DevicePath
= AppendDevicePathNode (
475 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
477 ASSERT (DevicePath
!= NULL
);
479 Status
= EfiBootManagerInitializeLoadOption (
481 LoadOptionNumberUnassigned
,
489 ASSERT_EFI_ERROR (Status
);
490 FreePool (DevicePath
);
492 BootOptions
= EfiBootManagerGetLoadOptions (
493 &BootOptionCount
, LoadOptionTypeBoot
496 OptionIndex
= EfiBootManagerFindLoadOption (
497 &NewOption
, BootOptions
, BootOptionCount
500 if (OptionIndex
== -1) {
501 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
502 ASSERT_EFI_ERROR (Status
);
504 EfiBootManagerFreeLoadOption (&NewOption
);
505 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
510 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
511 whose device paths do not resolve exactly to an FvFile in the system.
513 This removes any boot options that point to binaries built into the firmware
514 and have become stale due to any of the following:
515 - FvMain's base address or size changed (historical),
516 - FvMain's FvNameGuid changed,
517 - the FILE_GUID of the pointed-to binary changed,
518 - the referenced binary is no longer built into the firmware.
520 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
521 avoids exact duplicates.
525 RemoveStaleFvFileOptions (
529 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
530 UINTN BootOptionCount
;
533 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
,
536 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
537 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
542 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
543 // then keep the boot option.
545 Node1
= BootOptions
[Index
].FilePath
;
546 if (!(DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
&&
547 DevicePathSubType (Node1
) == HW_MEMMAP_DP
) &&
548 !(DevicePathType (Node1
) == MEDIA_DEVICE_PATH
&&
549 DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)) {
554 // If the second device path node is not FvFile(...), then keep the boot
557 Node2
= NextDevicePathNode (Node1
);
558 if (DevicePathType (Node2
) != MEDIA_DEVICE_PATH
||
559 DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
) {
564 // Locate the Firmware Volume2 protocol instance that is denoted by the
565 // boot option. If this lookup fails (i.e., the boot option references a
566 // firmware volume that doesn't exist), then we'll proceed to delete the
570 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
,
571 &SearchNode
, &FvHandle
);
573 if (!EFI_ERROR (Status
)) {
575 // The firmware volume was found; now let's see if it contains the FvFile
576 // identified by GUID.
578 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
579 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
581 EFI_FV_FILETYPE FoundType
;
582 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
583 UINT32 AuthenticationStatus
;
585 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiFirmwareVolume2ProtocolGuid
,
586 (VOID
**)&FvProtocol
);
587 ASSERT_EFI_ERROR (Status
);
589 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
591 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
594 Status
= FvProtocol
->ReadFile (
596 &FvFileNode
->FvFileName
, // NameGuid
601 &AuthenticationStatus
603 if (!EFI_ERROR (Status
)) {
605 // The FvFile was found. Keep the boot option.
612 // Delete the boot option.
614 Status
= EfiBootManagerDeleteLoadOptionVariable (
615 BootOptions
[Index
].OptionNumber
, LoadOptionTypeBoot
);
617 CHAR16
*DevicePathString
;
619 DevicePathString
= ConvertDevicePathToText(BootOptions
[Index
].FilePath
,
622 EFI_ERROR (Status
) ? EFI_D_WARN
: EFI_D_VERBOSE
,
623 "%a: removing stale Boot#%04x %s: %r\n",
625 (UINT32
)BootOptions
[Index
].OptionNumber
,
626 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
629 if (DevicePathString
!= NULL
) {
630 FreePool (DevicePathString
);
635 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
641 PlatformRegisterOptionsAndKeys (
649 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
652 // Register ENTER as CONTINUE key
654 Enter
.ScanCode
= SCAN_NULL
;
655 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
656 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
657 ASSERT_EFI_ERROR (Status
);
660 // Map F2 and ESC to Boot Manager Menu
662 F2
.ScanCode
= SCAN_F2
;
663 F2
.UnicodeChar
= CHAR_NULL
;
664 Esc
.ScanCode
= SCAN_ESC
;
665 Esc
.UnicodeChar
= CHAR_NULL
;
666 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
667 ASSERT_EFI_ERROR (Status
);
668 Status
= EfiBootManagerAddKeyOptionVariable (
669 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
671 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
672 Status
= EfiBootManagerAddKeyOptionVariable (
673 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
675 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
680 // BDS Platform Functions
683 Do the platform init, can be customized by OEM/IBV
684 Possible things that can be done in PlatformBootManagerBeforeConsole:
685 > Update console variable: 1. include hot-plug devices;
686 > 2. Clear ConIn and add SOL for AMT
687 > Register new Driver#### or Boot####
688 > Register new Key####: e.g.: F12
689 > Signal ReadyToLock event
690 > Authentication action: 1. connect Auth devices;
691 > 2. Identify auto logon user.
695 PlatformBootManagerBeforeConsole (
699 RETURN_STATUS PcdStatus
;
702 // Signal EndOfDxe PI Event
704 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
707 // Dispatch deferred images after EndOfDxe event.
709 EfiBootManagerDispatchDeferredImages ();
712 // Locate the PCI root bridges and make the PCI bus driver connect each,
713 // non-recursively. This will produce a number of child handles with PciIo on
716 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid
, NULL
, Connect
);
719 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
721 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
724 // Find all display class PCI devices (using the handles from the previous
725 // step), and connect them non-recursively. This should produce a number of
726 // child handles with GOPs on them.
728 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsPciDisplay
, Connect
);
731 // Now add the device path of all handles with GOP on them to ConOut and
734 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid
, NULL
, AddOutput
);
737 // Add the hardcoded short-form USB keyboard device path to ConIn.
739 EfiBootManagerUpdateConsoleVariable (ConIn
,
740 (EFI_DEVICE_PATH_PROTOCOL
*)&mUsbKeyboard
, NULL
);
743 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
745 CopyGuid (&mSerialConsole
.TermType
.Guid
,
746 PcdGetPtr (PcdTerminalTypeGuidBuffer
));
747 EfiBootManagerUpdateConsoleVariable (ConIn
,
748 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
749 EfiBootManagerUpdateConsoleVariable (ConOut
,
750 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
751 EfiBootManagerUpdateConsoleVariable (ErrOut
,
752 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
755 // Set the front page timeout from the QEMU configuration.
757 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
,
758 GetFrontPageTimeoutFromQemu ());
759 ASSERT_RETURN_ERROR (PcdStatus
);
762 // Register platform-specific boot options and keyboard shortcuts.
764 PlatformRegisterOptionsAndKeys ();
767 // At this point, VIRTIO_DEVICE_PROTOCOL instances exist only for Virtio MMIO
768 // transports. Install EFI_RNG_PROTOCOL instances on Virtio MMIO RNG devices.
770 FilterAndProcess (&gVirtioDeviceProtocolGuid
, IsVirtioRng
, Connect
);
773 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
774 // instances on Virtio PCI RNG devices.
776 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsVirtioPciRng
, Connect
);
780 Do the platform specific action after the console is ready
781 Possible things that can be done in PlatformBootManagerAfterConsole:
782 > Console post action:
783 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
784 > Signal console ready platform customized event
785 > Run diagnostics like memory testing
786 > Connect certain devices
787 > Dispatch additional option roms
788 > Special boot: e.g.: USB boot, enter UI
792 PlatformBootManagerAfterConsole (
796 RETURN_STATUS Status
;
799 // Show the splash screen.
801 BootLogoEnableLogo ();
804 // Process QEMU's -kernel command line option. The kernel booted this way
805 // will receive ACPI tables: in PlatformBootManagerBeforeConsole(), we
806 // connected any and all PCI root bridges, and then signaled the ACPI
809 TryRunningQemuKernel ();
812 // Connect the purported boot devices.
814 Status
= ConnectDevicesFromQemu ();
815 if (RETURN_ERROR (Status
)) {
817 // Connect the rest of the devices.
819 EfiBootManagerConnectAll ();
823 // Enumerate all possible boot options, then filter and reorder them based on
824 // the QEMU configuration.
826 EfiBootManagerRefreshAllBootOption ();
829 // Register UEFI Shell
831 PlatformRegisterFvBootOption (
832 &gUefiShellFileGuid
, L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
835 RemoveStaleFvFileOptions ();
836 SetBootOrderFromQemu ();
838 PlatformBmPrintScRegisterHandler ();
842 This function is called each second during the boot manager waits the
845 @param TimeoutRemain The remaining timeout.
849 PlatformBootManagerWaitCallback (
853 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
854 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
857 Timeout
= PcdGet16 (PcdPlatformBootTimeOut
);
859 Black
.Raw
= 0x00000000;
860 White
.Raw
= 0x00FFFFFF;
862 BootLogoUpdateProgress (
865 L
"Start boot option",
867 (Timeout
- TimeoutRemain
) * 100 / Timeout
,
873 The function is called when no boot option could be launched,
874 including platform recovery options and options pointing to applications
875 built into firmware volumes.
877 If this function returns, BDS attempts to enter an infinite loop.
881 PlatformBootManagerUnableToBoot (
887 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
891 // BootManagerMenu doesn't contain the correct information when return status
894 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
895 if (EFI_ERROR (Status
)) {
899 // Normally BdsDxe does not print anything to the system console, but this is
900 // a last resort -- the end-user will likely not see any DEBUG messages
901 // logged in this situation.
903 // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
904 // here to see if it makes sense to request and wait for a keypress.
906 if (gST
->ConIn
!= NULL
) {
908 "%a: No bootable option or device was found.\n"
909 "%a: Press any key to enter the Boot Manager Menu.\n",
913 Status
= gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
914 ASSERT_EFI_ERROR (Status
);
918 // Drain any queued keys.
920 while (!EFI_ERROR (gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
))) {
922 // just throw away Key
928 EfiBootManagerBoot (&BootManagerMenu
);