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/TpmPlatformHierarchyLib.h>
20 #include <Library/UefiBootManagerLib.h>
21 #include <Protocol/DevicePath.h>
22 #include <Protocol/FirmwareVolume2.h>
23 #include <Protocol/GraphicsOutput.h>
24 #include <Protocol/LoadedImage.h>
25 #include <Protocol/PciIo.h>
26 #include <Protocol/PciRootBridgeIo.h>
27 #include <Protocol/VirtioDevice.h>
28 #include <Guid/EventGroup.h>
29 #include <Guid/GlobalVariable.h>
30 #include <Guid/RootBridgesConnectedEventGroup.h>
31 #include <Guid/SerialPortLibVendor.h>
33 #include "PlatformBm.h"
35 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
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
;
47 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole
= {
49 // VENDOR_DEVICE_PATH SerialDxe
52 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, DP_NODE_LEN (VENDOR_DEVICE_PATH
) },
53 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
57 // UART_DEVICE_PATH Uart
60 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, DP_NODE_LEN (UART_DEVICE_PATH
) },
62 FixedPcdGet64 (PcdUartDefaultBaudRate
), // BaudRate
63 FixedPcdGet8 (PcdUartDefaultDataBits
), // DataBits
64 FixedPcdGet8 (PcdUartDefaultParity
), // Parity
65 FixedPcdGet8 (PcdUartDefaultStopBits
) // StopBits
69 // VENDOR_DEFINED_DEVICE_PATH TermType
73 MESSAGING_DEVICE_PATH
, MSG_VENDOR_DP
,
74 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH
)
77 // Guid to be filled in dynamically
82 // EFI_DEVICE_PATH_PROTOCOL End
85 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
86 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
93 USB_CLASS_DEVICE_PATH Keyboard
;
94 EFI_DEVICE_PATH_PROTOCOL End
;
95 } PLATFORM_USB_KEYBOARD
;
98 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard
= {
100 // USB_CLASS_DEVICE_PATH Keyboard
104 MESSAGING_DEVICE_PATH
, MSG_USB_CLASS_DP
,
105 DP_NODE_LEN (USB_CLASS_DEVICE_PATH
)
107 0xFFFF, // VendorId: any
108 0xFFFF, // ProductId: any
109 3, // DeviceClass: HID
110 1, // DeviceSubClass: boot
111 1 // DeviceProtocol: keyboard
115 // EFI_DEVICE_PATH_PROTOCOL End
118 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
119 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
125 Check if the handle satisfies a particular condition.
127 @param[in] Handle The handle to check.
128 @param[in] ReportText A caller-allocated string passed in for reporting
129 purposes. It must never be NULL.
131 @retval TRUE The condition is satisfied.
132 @retval FALSE Otherwise. This includes the case when the condition could not
133 be fully evaluated due to an error.
137 (EFIAPI
*FILTER_FUNCTION
) (
138 IN EFI_HANDLE Handle
,
139 IN CONST CHAR16
*ReportText
146 @param[in] Handle The handle to process.
147 @param[in] ReportText A caller-allocated string passed in for reporting
148 purposes. It must never be NULL.
152 (EFIAPI
*CALLBACK_FUNCTION
) (
153 IN EFI_HANDLE Handle
,
154 IN CONST CHAR16
*ReportText
158 Locate all handles that carry the specified protocol, filter them with a
159 callback function, and pass each handle that passes the filter to another
162 @param[in] ProtocolGuid The protocol to look for.
164 @param[in] Filter The filter function to pass each handle to. If this
165 parameter is NULL, then all handles are processed.
167 @param[in] Process The callback function to pass each handle to that
173 IN EFI_GUID
*ProtocolGuid
,
174 IN FILTER_FUNCTION Filter OPTIONAL
,
175 IN CALLBACK_FUNCTION Process
183 Status
= gBS
->LocateHandleBuffer (ByProtocol
, ProtocolGuid
,
184 NULL
/* SearchKey */, &NoHandles
, &Handles
);
185 if (EFI_ERROR (Status
)) {
187 // This is not an error, just an informative condition.
189 DEBUG ((DEBUG_VERBOSE
, "%a: %g: %r\n", __FUNCTION__
, ProtocolGuid
,
194 ASSERT (NoHandles
> 0);
195 for (Idx
= 0; Idx
< NoHandles
; ++Idx
) {
196 CHAR16
*DevicePathText
;
197 STATIC CHAR16 Fallback
[] = L
"<device path unavailable>";
200 // The ConvertDevicePathToText() function handles NULL input transparently.
202 DevicePathText
= ConvertDevicePathToText (
203 DevicePathFromHandle (Handles
[Idx
]),
204 FALSE
, // DisplayOnly
205 FALSE
// AllowShortcuts
207 if (DevicePathText
== NULL
) {
208 DevicePathText
= Fallback
;
211 if (Filter
== NULL
|| Filter (Handles
[Idx
], DevicePathText
)) {
212 Process (Handles
[Idx
], DevicePathText
);
215 if (DevicePathText
!= Fallback
) {
216 FreePool (DevicePathText
);
219 gBS
->FreePool (Handles
);
224 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
230 IN EFI_HANDLE Handle
,
231 IN CONST CHAR16
*ReportText
235 EFI_PCI_IO_PROTOCOL
*PciIo
;
238 Status
= gBS
->HandleProtocol (Handle
, &gEfiPciIoProtocolGuid
,
240 if (EFI_ERROR (Status
)) {
242 // This is not an error worth reporting.
247 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, 0 /* Offset */,
248 sizeof Pci
/ sizeof (UINT32
), &Pci
);
249 if (EFI_ERROR (Status
)) {
250 DEBUG ((DEBUG_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
254 return IS_PCI_DISPLAY (&Pci
);
259 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
260 the VIRTIO_DEVICE_PROTOCOL level.
266 IN EFI_HANDLE Handle
,
267 IN CONST CHAR16
*ReportText
271 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
273 Status
= gBS
->HandleProtocol (Handle
, &gVirtioDeviceProtocolGuid
,
275 if (EFI_ERROR (Status
)) {
278 return (BOOLEAN
)(VirtIo
->SubSystemDeviceId
==
279 VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
);
284 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
285 the EFI_PCI_IO_PROTOCOL level.
291 IN EFI_HANDLE Handle
,
292 IN CONST CHAR16
*ReportText
296 EFI_PCI_IO_PROTOCOL
*PciIo
;
303 Status
= gBS
->HandleProtocol (Handle
, &gEfiPciIoProtocolGuid
,
305 if (EFI_ERROR (Status
)) {
310 // Read and check VendorId.
312 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_VENDOR_ID_OFFSET
,
314 if (EFI_ERROR (Status
)) {
317 if (VendorId
!= VIRTIO_VENDOR_ID
) {
322 // Read DeviceId and RevisionId.
324 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_DEVICE_ID_OFFSET
,
326 if (EFI_ERROR (Status
)) {
329 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, PCI_REVISION_ID_OFFSET
,
331 if (EFI_ERROR (Status
)) {
336 // From DeviceId and RevisionId, determine whether the device is a
337 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
338 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
339 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
340 // only be sanity-checked, and SubsystemId will decide.
342 if (DeviceId
== 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
&&
343 RevisionId
>= 0x01) {
345 } else if (DeviceId
>= 0x1000 && DeviceId
<= 0x103F && RevisionId
== 0x00) {
352 // Read and check SubsystemId as dictated by Virtio10.
354 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
,
355 PCI_SUBSYSTEM_ID_OFFSET
, 1, &SubsystemId
);
356 if (EFI_ERROR (Status
)) {
359 if (Virtio10
&& SubsystemId
>= 0x40) {
362 if (!Virtio10
&& SubsystemId
== VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
) {
368 DEBUG ((DEBUG_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
374 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
375 the matching driver to produce all first-level child handles.
381 IN EFI_HANDLE Handle
,
382 IN CONST CHAR16
*ReportText
387 Status
= gBS
->ConnectController (
388 Handle
, // ControllerHandle
389 NULL
, // DriverImageHandle
390 NULL
, // RemainingDevicePath -- produce all children
393 DEBUG ((EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
, "%a: %s: %r\n",
394 __FUNCTION__
, ReportText
, Status
));
399 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
400 handle, and adds it to ConOut and ErrOut.
406 IN EFI_HANDLE Handle
,
407 IN CONST CHAR16
*ReportText
411 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
413 DevicePath
= DevicePathFromHandle (Handle
);
414 if (DevicePath
== NULL
) {
415 DEBUG ((DEBUG_ERROR
, "%a: %s: handle %p: device path not found\n",
416 __FUNCTION__
, ReportText
, Handle
));
420 Status
= EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
421 if (EFI_ERROR (Status
)) {
422 DEBUG ((DEBUG_ERROR
, "%a: %s: adding to ConOut: %r\n", __FUNCTION__
,
423 ReportText
, Status
));
427 Status
= EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
428 if (EFI_ERROR (Status
)) {
429 DEBUG ((DEBUG_ERROR
, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__
,
430 ReportText
, Status
));
434 DEBUG ((DEBUG_VERBOSE
, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__
,
440 PlatformRegisterFvBootOption (
448 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
449 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
450 UINTN BootOptionCount
;
451 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
452 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
453 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
455 Status
= gBS
->HandleProtocol (
457 &gEfiLoadedImageProtocolGuid
,
458 (VOID
**) &LoadedImage
460 ASSERT_EFI_ERROR (Status
);
462 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
463 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
464 ASSERT (DevicePath
!= NULL
);
465 DevicePath
= AppendDevicePathNode (
467 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
469 ASSERT (DevicePath
!= NULL
);
471 Status
= EfiBootManagerInitializeLoadOption (
473 LoadOptionNumberUnassigned
,
481 ASSERT_EFI_ERROR (Status
);
482 FreePool (DevicePath
);
484 BootOptions
= EfiBootManagerGetLoadOptions (
485 &BootOptionCount
, LoadOptionTypeBoot
488 OptionIndex
= EfiBootManagerFindLoadOption (
489 &NewOption
, BootOptions
, BootOptionCount
492 if (OptionIndex
== -1) {
493 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
494 ASSERT_EFI_ERROR (Status
);
496 EfiBootManagerFreeLoadOption (&NewOption
);
497 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
502 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
503 whose device paths do not resolve exactly to an FvFile in the system.
505 This removes any boot options that point to binaries built into the firmware
506 and have become stale due to any of the following:
507 - FvMain's base address or size changed (historical),
508 - FvMain's FvNameGuid changed,
509 - the FILE_GUID of the pointed-to binary changed,
510 - the referenced binary is no longer built into the firmware.
512 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
513 avoids exact duplicates.
517 RemoveStaleFvFileOptions (
521 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
522 UINTN BootOptionCount
;
525 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
,
528 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
529 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
534 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
535 // then keep the boot option.
537 Node1
= BootOptions
[Index
].FilePath
;
538 if (!(DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
&&
539 DevicePathSubType (Node1
) == HW_MEMMAP_DP
) &&
540 !(DevicePathType (Node1
) == MEDIA_DEVICE_PATH
&&
541 DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)) {
546 // If the second device path node is not FvFile(...), then keep the boot
549 Node2
= NextDevicePathNode (Node1
);
550 if (DevicePathType (Node2
) != MEDIA_DEVICE_PATH
||
551 DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
) {
556 // Locate the Firmware Volume2 protocol instance that is denoted by the
557 // boot option. If this lookup fails (i.e., the boot option references a
558 // firmware volume that doesn't exist), then we'll proceed to delete the
562 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
,
563 &SearchNode
, &FvHandle
);
565 if (!EFI_ERROR (Status
)) {
567 // The firmware volume was found; now let's see if it contains the FvFile
568 // identified by GUID.
570 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
571 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
573 EFI_FV_FILETYPE FoundType
;
574 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
575 UINT32 AuthenticationStatus
;
577 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiFirmwareVolume2ProtocolGuid
,
578 (VOID
**)&FvProtocol
);
579 ASSERT_EFI_ERROR (Status
);
581 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
583 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
586 Status
= FvProtocol
->ReadFile (
588 &FvFileNode
->FvFileName
, // NameGuid
593 &AuthenticationStatus
595 if (!EFI_ERROR (Status
)) {
597 // The FvFile was found. Keep the boot option.
604 // Delete the boot option.
606 Status
= EfiBootManagerDeleteLoadOptionVariable (
607 BootOptions
[Index
].OptionNumber
, LoadOptionTypeBoot
);
609 CHAR16
*DevicePathString
;
611 DevicePathString
= ConvertDevicePathToText(BootOptions
[Index
].FilePath
,
614 EFI_ERROR (Status
) ? DEBUG_WARN
: DEBUG_VERBOSE
,
615 "%a: removing stale Boot#%04x %s: %r\n",
617 (UINT32
)BootOptions
[Index
].OptionNumber
,
618 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
621 if (DevicePathString
!= NULL
) {
622 FreePool (DevicePathString
);
627 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
633 PlatformRegisterOptionsAndKeys (
641 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
644 // Register ENTER as CONTINUE key
646 Enter
.ScanCode
= SCAN_NULL
;
647 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
648 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
649 ASSERT_EFI_ERROR (Status
);
652 // Map F2 and ESC to Boot Manager Menu
654 F2
.ScanCode
= SCAN_F2
;
655 F2
.UnicodeChar
= CHAR_NULL
;
656 Esc
.ScanCode
= SCAN_ESC
;
657 Esc
.UnicodeChar
= CHAR_NULL
;
658 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
659 ASSERT_EFI_ERROR (Status
);
660 Status
= EfiBootManagerAddKeyOptionVariable (
661 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
663 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
664 Status
= EfiBootManagerAddKeyOptionVariable (
665 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
667 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
672 // BDS Platform Functions
675 Do the platform init, can be customized by OEM/IBV
676 Possible things that can be done in PlatformBootManagerBeforeConsole:
677 > Update console variable: 1. include hot-plug devices;
678 > 2. Clear ConIn and add SOL for AMT
679 > Register new Driver#### or Boot####
680 > Register new Key####: e.g.: F12
681 > Signal ReadyToLock event
682 > Authentication action: 1. connect Auth devices;
683 > 2. Identify auto logon user.
687 PlatformBootManagerBeforeConsole (
691 UINT16 FrontPageTimeout
;
692 RETURN_STATUS PcdStatus
;
696 // Signal EndOfDxe PI Event
698 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
701 // Disable the TPM 2 platform hierarchy
703 ConfigureTpmPlatformHierarchy ();
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 FrontPageTimeout
= GetFrontPageTimeoutFromQemu ();
757 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
, FrontPageTimeout
);
758 ASSERT_RETURN_ERROR (PcdStatus
);
760 // Reflect the PCD in the standard Timeout variable.
762 Status
= gRT
->SetVariable (
763 EFI_TIME_OUT_VARIABLE_NAME
,
764 &gEfiGlobalVariableGuid
,
765 (EFI_VARIABLE_NON_VOLATILE
|
766 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
767 EFI_VARIABLE_RUNTIME_ACCESS
),
768 sizeof FrontPageTimeout
,
772 EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
,
773 "%a: SetVariable(%s, %u): %r\n",
775 EFI_TIME_OUT_VARIABLE_NAME
,
781 // Register platform-specific boot options and keyboard shortcuts.
783 PlatformRegisterOptionsAndKeys ();
786 // At this point, VIRTIO_DEVICE_PROTOCOL instances exist only for Virtio MMIO
787 // transports. Install EFI_RNG_PROTOCOL instances on Virtio MMIO RNG devices.
789 FilterAndProcess (&gVirtioDeviceProtocolGuid
, IsVirtioRng
, Connect
);
792 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
793 // instances on Virtio PCI RNG devices.
795 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsVirtioPciRng
, Connect
);
799 Do the platform specific action after the console is ready
800 Possible things that can be done in PlatformBootManagerAfterConsole:
801 > Console post action:
802 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
803 > Signal console ready platform customized event
804 > Run diagnostics like memory testing
805 > Connect certain devices
806 > Dispatch additional option roms
807 > Special boot: e.g.: USB boot, enter UI
811 PlatformBootManagerAfterConsole (
815 RETURN_STATUS Status
;
818 // Show the splash screen.
820 BootLogoEnableLogo ();
823 // Process QEMU's -kernel command line option. The kernel booted this way
824 // will receive ACPI tables: in PlatformBootManagerBeforeConsole(), we
825 // connected any and all PCI root bridges, and then signaled the ACPI
828 TryRunningQemuKernel ();
831 // Connect the purported boot devices.
833 Status
= ConnectDevicesFromQemu ();
834 if (RETURN_ERROR (Status
)) {
836 // Connect the rest of the devices.
838 EfiBootManagerConnectAll ();
842 // Enumerate all possible boot options, then filter and reorder them based on
843 // the QEMU configuration.
845 EfiBootManagerRefreshAllBootOption ();
848 // Register UEFI Shell
850 PlatformRegisterFvBootOption (
851 &gUefiShellFileGuid
, L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
854 RemoveStaleFvFileOptions ();
855 SetBootOrderFromQemu ();
857 PlatformBmPrintScRegisterHandler ();
861 This function is called each second during the boot manager waits the
864 @param TimeoutRemain The remaining timeout.
868 PlatformBootManagerWaitCallback (
872 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
873 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
874 UINT16 TimeoutInitial
;
876 TimeoutInitial
= PcdGet16 (PcdPlatformBootTimeOut
);
879 // If PcdPlatformBootTimeOut is set to zero, then we consider
880 // that no progress update should be enacted.
882 if (TimeoutInitial
== 0) {
886 Black
.Raw
= 0x00000000;
887 White
.Raw
= 0x00FFFFFF;
889 BootLogoUpdateProgress (
892 L
"Start boot option",
894 (TimeoutInitial
- TimeoutRemain
) * 100 / TimeoutInitial
,
900 The function is called when no boot option could be launched,
901 including platform recovery options and options pointing to applications
902 built into firmware volumes.
904 If this function returns, BDS attempts to enter an infinite loop.
908 PlatformBootManagerUnableToBoot (
914 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
918 // BootManagerMenu doesn't contain the correct information when return status
921 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
922 if (EFI_ERROR (Status
)) {
926 // Normally BdsDxe does not print anything to the system console, but this is
927 // a last resort -- the end-user will likely not see any DEBUG messages
928 // logged in this situation.
930 // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
931 // here to see if it makes sense to request and wait for a keypress.
933 if (gST
->ConIn
!= NULL
) {
935 "%a: No bootable option or device was found.\n"
936 "%a: Press any key to enter the Boot Manager Menu.\n",
940 Status
= gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
941 ASSERT_EFI_ERROR (Status
);
945 // Drain any queued keys.
947 while (!EFI_ERROR (gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
))) {
949 // just throw away Key
955 EfiBootManagerBoot (&BootManagerMenu
);