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/QemuBootOrderLib.h>
24 #include <Library/UefiBootManagerLib.h>
25 #include <Protocol/DevicePath.h>
26 #include <Protocol/FirmwareVolume2.h>
27 #include <Protocol/GraphicsOutput.h>
28 #include <Protocol/LoadedImage.h>
29 #include <Protocol/PciIo.h>
30 #include <Protocol/PciRootBridgeIo.h>
31 #include <Protocol/VirtioDevice.h>
32 #include <Guid/EventGroup.h>
33 #include <Guid/RootBridgesConnectedEventGroup.h>
35 #include "PlatformBm.h"
37 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
42 VENDOR_DEVICE_PATH SerialDxe
;
43 UART_DEVICE_PATH Uart
;
44 VENDOR_DEFINED_DEVICE_PATH TermType
;
45 EFI_DEVICE_PATH_PROTOCOL End
;
46 } PLATFORM_SERIAL_CONSOLE
;
49 #define SERIAL_DXE_FILE_GUID { \
50 0xD3987D4B, 0x971A, 0x435F, \
51 { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \
54 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole
= {
56 // VENDOR_DEVICE_PATH SerialDxe
59 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, DP_NODE_LEN (VENDOR_DEVICE_PATH
) },
64 // UART_DEVICE_PATH Uart
67 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, DP_NODE_LEN (UART_DEVICE_PATH
) },
69 FixedPcdGet64 (PcdUartDefaultBaudRate
), // BaudRate
70 FixedPcdGet8 (PcdUartDefaultDataBits
), // DataBits
71 FixedPcdGet8 (PcdUartDefaultParity
), // Parity
72 FixedPcdGet8 (PcdUartDefaultStopBits
) // StopBits
76 // VENDOR_DEFINED_DEVICE_PATH TermType
80 MESSAGING_DEVICE_PATH
, MSG_VENDOR_DP
,
81 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH
)
84 // Guid to be filled in dynamically
89 // EFI_DEVICE_PATH_PROTOCOL End
92 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
93 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
100 USB_CLASS_DEVICE_PATH Keyboard
;
101 EFI_DEVICE_PATH_PROTOCOL End
;
102 } PLATFORM_USB_KEYBOARD
;
105 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard
= {
107 // USB_CLASS_DEVICE_PATH Keyboard
111 MESSAGING_DEVICE_PATH
, MSG_USB_CLASS_DP
,
112 DP_NODE_LEN (USB_CLASS_DEVICE_PATH
)
114 0xFFFF, // VendorId: any
115 0xFFFF, // ProductId: any
116 3, // DeviceClass: HID
117 1, // DeviceSubClass: boot
118 1 // DeviceProtocol: keyboard
122 // EFI_DEVICE_PATH_PROTOCOL End
125 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
126 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
132 Check if the handle satisfies a particular condition.
134 @param[in] Handle The handle to check.
135 @param[in] ReportText A caller-allocated string passed in for reporting
136 purposes. It must never be NULL.
138 @retval TRUE The condition is satisfied.
139 @retval FALSE Otherwise. This includes the case when the condition could not
140 be fully evaluated due to an error.
144 (EFIAPI
*FILTER_FUNCTION
) (
145 IN EFI_HANDLE Handle
,
146 IN CONST CHAR16
*ReportText
153 @param[in] Handle The handle to process.
154 @param[in] ReportText A caller-allocated string passed in for reporting
155 purposes. It must never be NULL.
159 (EFIAPI
*CALLBACK_FUNCTION
) (
160 IN EFI_HANDLE Handle
,
161 IN CONST CHAR16
*ReportText
165 Locate all handles that carry the specified protocol, filter them with a
166 callback function, and pass each handle that passes the filter to another
169 @param[in] ProtocolGuid The protocol to look for.
171 @param[in] Filter The filter function to pass each handle to. If this
172 parameter is NULL, then all handles are processed.
174 @param[in] Process The callback function to pass each handle to that
180 IN EFI_GUID
*ProtocolGuid
,
181 IN FILTER_FUNCTION Filter OPTIONAL
,
182 IN CALLBACK_FUNCTION Process
190 Status
= gBS
->LocateHandleBuffer (ByProtocol
, ProtocolGuid
,
191 NULL
/* SearchKey */, &NoHandles
, &Handles
);
192 if (EFI_ERROR (Status
)) {
194 // This is not an error, just an informative condition.
196 DEBUG ((EFI_D_VERBOSE
, "%a: %g: %r\n", __FUNCTION__
, ProtocolGuid
,
201 ASSERT (NoHandles
> 0);
202 for (Idx
= 0; Idx
< NoHandles
; ++Idx
) {
203 CHAR16
*DevicePathText
;
204 STATIC CHAR16 Fallback
[] = L
"<device path unavailable>";
207 // The ConvertDevicePathToText() function handles NULL input transparently.
209 DevicePathText
= ConvertDevicePathToText (
210 DevicePathFromHandle (Handles
[Idx
]),
211 FALSE
, // DisplayOnly
212 FALSE
// AllowShortcuts
214 if (DevicePathText
== NULL
) {
215 DevicePathText
= Fallback
;
218 if (Filter
== NULL
|| Filter (Handles
[Idx
], DevicePathText
)) {
219 Process (Handles
[Idx
], DevicePathText
);
222 if (DevicePathText
!= Fallback
) {
223 FreePool (DevicePathText
);
226 gBS
->FreePool (Handles
);
231 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
237 IN EFI_HANDLE Handle
,
238 IN CONST CHAR16
*ReportText
242 EFI_PCI_IO_PROTOCOL
*PciIo
;
245 Status
= gBS
->HandleProtocol (Handle
, &gEfiPciIoProtocolGuid
,
247 if (EFI_ERROR (Status
)) {
249 // This is not an error worth reporting.
254 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, 0 /* Offset */,
255 sizeof Pci
/ sizeof (UINT32
), &Pci
);
256 if (EFI_ERROR (Status
)) {
257 DEBUG ((EFI_D_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
261 return IS_PCI_DISPLAY (&Pci
);
266 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
267 the VIRTIO_DEVICE_PROTOCOL level.
273 IN EFI_HANDLE Handle
,
274 IN CONST CHAR16
*ReportText
278 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
280 Status
= gBS
->HandleProtocol (Handle
, &gVirtioDeviceProtocolGuid
,
282 if (EFI_ERROR (Status
)) {
285 return (BOOLEAN
)(VirtIo
->SubSystemDeviceId
==
286 VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
);
291 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
292 the EFI_PCI_IO_PROTOCOL level.
298 IN EFI_HANDLE Handle
,
299 IN CONST CHAR16
*ReportText
303 EFI_PCI_IO_PROTOCOL
*PciIo
;
310 Status
= gBS
->HandleProtocol (Handle
, &gEfiPciIoProtocolGuid
,
312 if (EFI_ERROR (Status
)) {
317 // Read and check VendorId.
319 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_VENDOR_ID_OFFSET
,
321 if (EFI_ERROR (Status
)) {
324 if (VendorId
!= VIRTIO_VENDOR_ID
) {
329 // Read DeviceId and RevisionId.
331 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_DEVICE_ID_OFFSET
,
333 if (EFI_ERROR (Status
)) {
336 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, PCI_REVISION_ID_OFFSET
,
338 if (EFI_ERROR (Status
)) {
343 // From DeviceId and RevisionId, determine whether the device is a
344 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
345 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
346 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
347 // only be sanity-checked, and SubsystemId will decide.
349 if (DeviceId
== 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
&&
350 RevisionId
>= 0x01) {
352 } else if (DeviceId
>= 0x1000 && DeviceId
<= 0x103F && RevisionId
== 0x00) {
359 // Read and check SubsystemId as dictated by Virtio10.
361 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
,
362 PCI_SUBSYSTEM_ID_OFFSET
, 1, &SubsystemId
);
363 if (EFI_ERROR (Status
)) {
366 if (Virtio10
&& SubsystemId
>= 0x40) {
369 if (!Virtio10
&& SubsystemId
== VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
) {
375 DEBUG ((DEBUG_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
381 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
382 the matching driver to produce all first-level child handles.
388 IN EFI_HANDLE Handle
,
389 IN CONST CHAR16
*ReportText
394 Status
= gBS
->ConnectController (
395 Handle
, // ControllerHandle
396 NULL
, // DriverImageHandle
397 NULL
, // RemainingDevicePath -- produce all children
400 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
, "%a: %s: %r\n",
401 __FUNCTION__
, ReportText
, Status
));
406 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
407 handle, and adds it to ConOut and ErrOut.
413 IN EFI_HANDLE Handle
,
414 IN CONST CHAR16
*ReportText
418 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
420 DevicePath
= DevicePathFromHandle (Handle
);
421 if (DevicePath
== NULL
) {
422 DEBUG ((EFI_D_ERROR
, "%a: %s: handle %p: device path not found\n",
423 __FUNCTION__
, ReportText
, Handle
));
427 Status
= EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
428 if (EFI_ERROR (Status
)) {
429 DEBUG ((EFI_D_ERROR
, "%a: %s: adding to ConOut: %r\n", __FUNCTION__
,
430 ReportText
, Status
));
434 Status
= EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
435 if (EFI_ERROR (Status
)) {
436 DEBUG ((EFI_D_ERROR
, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__
,
437 ReportText
, Status
));
441 DEBUG ((EFI_D_VERBOSE
, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__
,
447 PlatformRegisterFvBootOption (
455 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
456 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
457 UINTN BootOptionCount
;
458 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
459 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
460 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
462 Status
= gBS
->HandleProtocol (
464 &gEfiLoadedImageProtocolGuid
,
465 (VOID
**) &LoadedImage
467 ASSERT_EFI_ERROR (Status
);
469 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
470 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
471 ASSERT (DevicePath
!= NULL
);
472 DevicePath
= AppendDevicePathNode (
474 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
476 ASSERT (DevicePath
!= NULL
);
478 Status
= EfiBootManagerInitializeLoadOption (
480 LoadOptionNumberUnassigned
,
488 ASSERT_EFI_ERROR (Status
);
489 FreePool (DevicePath
);
491 BootOptions
= EfiBootManagerGetLoadOptions (
492 &BootOptionCount
, LoadOptionTypeBoot
495 OptionIndex
= EfiBootManagerFindLoadOption (
496 &NewOption
, BootOptions
, BootOptionCount
499 if (OptionIndex
== -1) {
500 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
501 ASSERT_EFI_ERROR (Status
);
503 EfiBootManagerFreeLoadOption (&NewOption
);
504 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
509 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
510 whose device paths do not resolve exactly to an FvFile in the system.
512 This removes any boot options that point to binaries built into the firmware
513 and have become stale due to any of the following:
514 - FvMain's base address or size changed (historical),
515 - FvMain's FvNameGuid changed,
516 - the FILE_GUID of the pointed-to binary changed,
517 - the referenced binary is no longer built into the firmware.
519 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
520 avoids exact duplicates.
524 RemoveStaleFvFileOptions (
528 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
529 UINTN BootOptionCount
;
532 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
,
535 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
536 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
541 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
542 // then keep the boot option.
544 Node1
= BootOptions
[Index
].FilePath
;
545 if (!(DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
&&
546 DevicePathSubType (Node1
) == HW_MEMMAP_DP
) &&
547 !(DevicePathType (Node1
) == MEDIA_DEVICE_PATH
&&
548 DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)) {
553 // If the second device path node is not FvFile(...), then keep the boot
556 Node2
= NextDevicePathNode (Node1
);
557 if (DevicePathType (Node2
) != MEDIA_DEVICE_PATH
||
558 DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
) {
563 // Locate the Firmware Volume2 protocol instance that is denoted by the
564 // boot option. If this lookup fails (i.e., the boot option references a
565 // firmware volume that doesn't exist), then we'll proceed to delete the
569 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
,
570 &SearchNode
, &FvHandle
);
572 if (!EFI_ERROR (Status
)) {
574 // The firmware volume was found; now let's see if it contains the FvFile
575 // identified by GUID.
577 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
578 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
580 EFI_FV_FILETYPE FoundType
;
581 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
582 UINT32 AuthenticationStatus
;
584 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiFirmwareVolume2ProtocolGuid
,
585 (VOID
**)&FvProtocol
);
586 ASSERT_EFI_ERROR (Status
);
588 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
590 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
593 Status
= FvProtocol
->ReadFile (
595 &FvFileNode
->FvFileName
, // NameGuid
600 &AuthenticationStatus
602 if (!EFI_ERROR (Status
)) {
604 // The FvFile was found. Keep the boot option.
611 // Delete the boot option.
613 Status
= EfiBootManagerDeleteLoadOptionVariable (
614 BootOptions
[Index
].OptionNumber
, LoadOptionTypeBoot
);
616 CHAR16
*DevicePathString
;
618 DevicePathString
= ConvertDevicePathToText(BootOptions
[Index
].FilePath
,
621 EFI_ERROR (Status
) ? EFI_D_WARN
: EFI_D_VERBOSE
,
622 "%a: removing stale Boot#%04x %s: %r\n",
624 (UINT32
)BootOptions
[Index
].OptionNumber
,
625 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
628 if (DevicePathString
!= NULL
) {
629 FreePool (DevicePathString
);
634 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
640 PlatformRegisterOptionsAndKeys (
648 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
651 // Register ENTER as CONTINUE key
653 Enter
.ScanCode
= SCAN_NULL
;
654 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
655 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
656 ASSERT_EFI_ERROR (Status
);
659 // Map F2 and ESC to Boot Manager Menu
661 F2
.ScanCode
= SCAN_F2
;
662 F2
.UnicodeChar
= CHAR_NULL
;
663 Esc
.ScanCode
= SCAN_ESC
;
664 Esc
.UnicodeChar
= CHAR_NULL
;
665 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
666 ASSERT_EFI_ERROR (Status
);
667 Status
= EfiBootManagerAddKeyOptionVariable (
668 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
670 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
671 Status
= EfiBootManagerAddKeyOptionVariable (
672 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
674 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
679 // BDS Platform Functions
682 Do the platform init, can be customized by OEM/IBV
683 Possible things that can be done in PlatformBootManagerBeforeConsole:
684 > Update console variable: 1. include hot-plug devices;
685 > 2. Clear ConIn and add SOL for AMT
686 > Register new Driver#### or Boot####
687 > Register new Key####: e.g.: F12
688 > Signal ReadyToLock event
689 > Authentication action: 1. connect Auth devices;
690 > 2. Identify auto logon user.
694 PlatformBootManagerBeforeConsole (
698 RETURN_STATUS PcdStatus
;
701 // Signal EndOfDxe PI Event
703 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
706 // Dispatch deferred images after EndOfDxe event.
708 EfiBootManagerDispatchDeferredImages ();
711 // Locate the PCI root bridges and make the PCI bus driver connect each,
712 // non-recursively. This will produce a number of child handles with PciIo on
715 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid
, NULL
, Connect
);
718 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
720 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
723 // Find all display class PCI devices (using the handles from the previous
724 // step), and connect them non-recursively. This should produce a number of
725 // child handles with GOPs on them.
727 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsPciDisplay
, Connect
);
730 // Now add the device path of all handles with GOP on them to ConOut and
733 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid
, NULL
, AddOutput
);
736 // Add the hardcoded short-form USB keyboard device path to ConIn.
738 EfiBootManagerUpdateConsoleVariable (ConIn
,
739 (EFI_DEVICE_PATH_PROTOCOL
*)&mUsbKeyboard
, NULL
);
742 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
744 CopyGuid (&mSerialConsole
.TermType
.Guid
,
745 PcdGetPtr (PcdTerminalTypeGuidBuffer
));
746 EfiBootManagerUpdateConsoleVariable (ConIn
,
747 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
748 EfiBootManagerUpdateConsoleVariable (ConOut
,
749 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
750 EfiBootManagerUpdateConsoleVariable (ErrOut
,
751 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
754 // Set the front page timeout from the QEMU configuration.
756 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
,
757 GetFrontPageTimeoutFromQemu ());
758 ASSERT_RETURN_ERROR (PcdStatus
);
761 // Register platform-specific boot options and keyboard shortcuts.
763 PlatformRegisterOptionsAndKeys ();
766 // At this point, VIRTIO_DEVICE_PROTOCOL instances exist only for Virtio MMIO
767 // transports. Install EFI_RNG_PROTOCOL instances on Virtio MMIO RNG devices.
769 FilterAndProcess (&gVirtioDeviceProtocolGuid
, IsVirtioRng
, Connect
);
772 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
773 // instances on Virtio PCI RNG devices.
775 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsVirtioPciRng
, Connect
);
779 Do the platform specific action after the console is ready
780 Possible things that can be done in PlatformBootManagerAfterConsole:
781 > Console post action:
782 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
783 > Signal console ready platform customized event
784 > Run diagnostics like memory testing
785 > Connect certain devices
786 > Dispatch additional option roms
787 > Special boot: e.g.: USB boot, enter UI
791 PlatformBootManagerAfterConsole (
795 RETURN_STATUS Status
;
798 // Show the splash screen.
800 BootLogoEnableLogo ();
803 // Process QEMU's -kernel command line option. The kernel booted this way
804 // will receive ACPI tables: in PlatformBootManagerBeforeConsole(), we
805 // connected any and all PCI root bridges, and then signaled the ACPI
808 TryRunningQemuKernel ();
811 // Connect the purported boot devices.
813 Status
= ConnectDevicesFromQemu ();
814 if (RETURN_ERROR (Status
)) {
816 // Connect the rest of the devices.
818 EfiBootManagerConnectAll ();
822 // Enumerate all possible boot options, then filter and reorder them based on
823 // the QEMU configuration.
825 EfiBootManagerRefreshAllBootOption ();
828 // Register UEFI Shell
830 PlatformRegisterFvBootOption (
831 &gUefiShellFileGuid
, L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
834 RemoveStaleFvFileOptions ();
835 SetBootOrderFromQemu ();
839 This function is called each second during the boot manager waits the
842 @param TimeoutRemain The remaining timeout.
846 PlatformBootManagerWaitCallback (
850 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
851 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
854 Timeout
= PcdGet16 (PcdPlatformBootTimeOut
);
856 Black
.Raw
= 0x00000000;
857 White
.Raw
= 0x00FFFFFF;
859 BootLogoUpdateProgress (
862 L
"Start boot option",
864 (Timeout
- TimeoutRemain
) * 100 / Timeout
,
870 The function is called when no boot option could be launched,
871 including platform recovery options and options pointing to applications
872 built into firmware volumes.
874 If this function returns, BDS attempts to enter an infinite loop.
878 PlatformBootManagerUnableToBoot (
884 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
888 // BootManagerMenu doesn't contain the correct information when return status
891 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
892 if (EFI_ERROR (Status
)) {
896 // Normally BdsDxe does not print anything to the system console, but this is
897 // a last resort -- the end-user will likely not see any DEBUG messages
898 // logged in this situation.
900 // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
901 // here to see if it makes sense to request and wait for a keypress.
903 if (gST
->ConIn
!= NULL
) {
905 "%a: No bootable option or device was found.\n"
906 "%a: Press any key to enter the Boot Manager Menu.\n",
910 Status
= gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
911 ASSERT_EFI_ERROR (Status
);
915 // Drain any queued keys.
917 while (!EFI_ERROR (gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
))) {
919 // just throw away Key
925 EfiBootManagerBoot (&BootManagerMenu
);