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/GlobalVariable.h>
29 #include <Guid/RootBridgesConnectedEventGroup.h>
30 #include <Guid/SerialPortLibVendor.h>
32 #include "PlatformBm.h"
34 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
39 VENDOR_DEVICE_PATH SerialDxe
;
40 UART_DEVICE_PATH Uart
;
41 VENDOR_DEFINED_DEVICE_PATH TermType
;
42 EFI_DEVICE_PATH_PROTOCOL End
;
43 } PLATFORM_SERIAL_CONSOLE
;
46 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole
= {
48 // VENDOR_DEVICE_PATH SerialDxe
51 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, DP_NODE_LEN (VENDOR_DEVICE_PATH
) },
52 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
56 // UART_DEVICE_PATH Uart
59 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, DP_NODE_LEN (UART_DEVICE_PATH
) },
61 FixedPcdGet64 (PcdUartDefaultBaudRate
), // BaudRate
62 FixedPcdGet8 (PcdUartDefaultDataBits
), // DataBits
63 FixedPcdGet8 (PcdUartDefaultParity
), // Parity
64 FixedPcdGet8 (PcdUartDefaultStopBits
) // StopBits
68 // VENDOR_DEFINED_DEVICE_PATH TermType
72 MESSAGING_DEVICE_PATH
, MSG_VENDOR_DP
,
73 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH
)
76 // Guid to be filled in dynamically
81 // EFI_DEVICE_PATH_PROTOCOL End
84 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
85 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
92 USB_CLASS_DEVICE_PATH Keyboard
;
93 EFI_DEVICE_PATH_PROTOCOL End
;
94 } PLATFORM_USB_KEYBOARD
;
97 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard
= {
99 // USB_CLASS_DEVICE_PATH Keyboard
103 MESSAGING_DEVICE_PATH
, MSG_USB_CLASS_DP
,
104 DP_NODE_LEN (USB_CLASS_DEVICE_PATH
)
106 0xFFFF, // VendorId: any
107 0xFFFF, // ProductId: any
108 3, // DeviceClass: HID
109 1, // DeviceSubClass: boot
110 1 // DeviceProtocol: keyboard
114 // EFI_DEVICE_PATH_PROTOCOL End
117 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
118 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
124 Check if the handle satisfies a particular condition.
126 @param[in] Handle The handle to check.
127 @param[in] ReportText A caller-allocated string passed in for reporting
128 purposes. It must never be NULL.
130 @retval TRUE The condition is satisfied.
131 @retval FALSE Otherwise. This includes the case when the condition could not
132 be fully evaluated due to an error.
136 (EFIAPI
*FILTER_FUNCTION
) (
137 IN EFI_HANDLE Handle
,
138 IN CONST CHAR16
*ReportText
145 @param[in] Handle The handle to process.
146 @param[in] ReportText A caller-allocated string passed in for reporting
147 purposes. It must never be NULL.
151 (EFIAPI
*CALLBACK_FUNCTION
) (
152 IN EFI_HANDLE Handle
,
153 IN CONST CHAR16
*ReportText
157 Locate all handles that carry the specified protocol, filter them with a
158 callback function, and pass each handle that passes the filter to another
161 @param[in] ProtocolGuid The protocol to look for.
163 @param[in] Filter The filter function to pass each handle to. If this
164 parameter is NULL, then all handles are processed.
166 @param[in] Process The callback function to pass each handle to that
172 IN EFI_GUID
*ProtocolGuid
,
173 IN FILTER_FUNCTION Filter OPTIONAL
,
174 IN CALLBACK_FUNCTION Process
182 Status
= gBS
->LocateHandleBuffer (ByProtocol
, ProtocolGuid
,
183 NULL
/* SearchKey */, &NoHandles
, &Handles
);
184 if (EFI_ERROR (Status
)) {
186 // This is not an error, just an informative condition.
188 DEBUG ((EFI_D_VERBOSE
, "%a: %g: %r\n", __FUNCTION__
, ProtocolGuid
,
193 ASSERT (NoHandles
> 0);
194 for (Idx
= 0; Idx
< NoHandles
; ++Idx
) {
195 CHAR16
*DevicePathText
;
196 STATIC CHAR16 Fallback
[] = L
"<device path unavailable>";
199 // The ConvertDevicePathToText() function handles NULL input transparently.
201 DevicePathText
= ConvertDevicePathToText (
202 DevicePathFromHandle (Handles
[Idx
]),
203 FALSE
, // DisplayOnly
204 FALSE
// AllowShortcuts
206 if (DevicePathText
== NULL
) {
207 DevicePathText
= Fallback
;
210 if (Filter
== NULL
|| Filter (Handles
[Idx
], DevicePathText
)) {
211 Process (Handles
[Idx
], DevicePathText
);
214 if (DevicePathText
!= Fallback
) {
215 FreePool (DevicePathText
);
218 gBS
->FreePool (Handles
);
223 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
229 IN EFI_HANDLE Handle
,
230 IN CONST CHAR16
*ReportText
234 EFI_PCI_IO_PROTOCOL
*PciIo
;
237 Status
= gBS
->HandleProtocol (Handle
, &gEfiPciIoProtocolGuid
,
239 if (EFI_ERROR (Status
)) {
241 // This is not an error worth reporting.
246 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, 0 /* Offset */,
247 sizeof Pci
/ sizeof (UINT32
), &Pci
);
248 if (EFI_ERROR (Status
)) {
249 DEBUG ((EFI_D_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
253 return IS_PCI_DISPLAY (&Pci
);
258 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
259 the VIRTIO_DEVICE_PROTOCOL level.
265 IN EFI_HANDLE Handle
,
266 IN CONST CHAR16
*ReportText
270 VIRTIO_DEVICE_PROTOCOL
*VirtIo
;
272 Status
= gBS
->HandleProtocol (Handle
, &gVirtioDeviceProtocolGuid
,
274 if (EFI_ERROR (Status
)) {
277 return (BOOLEAN
)(VirtIo
->SubSystemDeviceId
==
278 VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
);
283 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
284 the EFI_PCI_IO_PROTOCOL level.
290 IN EFI_HANDLE Handle
,
291 IN CONST CHAR16
*ReportText
295 EFI_PCI_IO_PROTOCOL
*PciIo
;
302 Status
= gBS
->HandleProtocol (Handle
, &gEfiPciIoProtocolGuid
,
304 if (EFI_ERROR (Status
)) {
309 // Read and check VendorId.
311 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_VENDOR_ID_OFFSET
,
313 if (EFI_ERROR (Status
)) {
316 if (VendorId
!= VIRTIO_VENDOR_ID
) {
321 // Read DeviceId and RevisionId.
323 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_DEVICE_ID_OFFSET
,
325 if (EFI_ERROR (Status
)) {
328 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, PCI_REVISION_ID_OFFSET
,
330 if (EFI_ERROR (Status
)) {
335 // From DeviceId and RevisionId, determine whether the device is a
336 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
337 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
338 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
339 // only be sanity-checked, and SubsystemId will decide.
341 if (DeviceId
== 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
&&
342 RevisionId
>= 0x01) {
344 } else if (DeviceId
>= 0x1000 && DeviceId
<= 0x103F && RevisionId
== 0x00) {
351 // Read and check SubsystemId as dictated by Virtio10.
353 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
,
354 PCI_SUBSYSTEM_ID_OFFSET
, 1, &SubsystemId
);
355 if (EFI_ERROR (Status
)) {
358 if (Virtio10
&& SubsystemId
>= 0x40) {
361 if (!Virtio10
&& SubsystemId
== VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
) {
367 DEBUG ((DEBUG_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
373 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
374 the matching driver to produce all first-level child handles.
380 IN EFI_HANDLE Handle
,
381 IN CONST CHAR16
*ReportText
386 Status
= gBS
->ConnectController (
387 Handle
, // ControllerHandle
388 NULL
, // DriverImageHandle
389 NULL
, // RemainingDevicePath -- produce all children
392 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
, "%a: %s: %r\n",
393 __FUNCTION__
, ReportText
, Status
));
398 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
399 handle, and adds it to ConOut and ErrOut.
405 IN EFI_HANDLE Handle
,
406 IN CONST CHAR16
*ReportText
410 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
412 DevicePath
= DevicePathFromHandle (Handle
);
413 if (DevicePath
== NULL
) {
414 DEBUG ((EFI_D_ERROR
, "%a: %s: handle %p: device path not found\n",
415 __FUNCTION__
, ReportText
, Handle
));
419 Status
= EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
420 if (EFI_ERROR (Status
)) {
421 DEBUG ((EFI_D_ERROR
, "%a: %s: adding to ConOut: %r\n", __FUNCTION__
,
422 ReportText
, Status
));
426 Status
= EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
427 if (EFI_ERROR (Status
)) {
428 DEBUG ((EFI_D_ERROR
, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__
,
429 ReportText
, Status
));
433 DEBUG ((EFI_D_VERBOSE
, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__
,
439 PlatformRegisterFvBootOption (
447 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
448 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
449 UINTN BootOptionCount
;
450 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
451 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
452 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
454 Status
= gBS
->HandleProtocol (
456 &gEfiLoadedImageProtocolGuid
,
457 (VOID
**) &LoadedImage
459 ASSERT_EFI_ERROR (Status
);
461 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
462 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
463 ASSERT (DevicePath
!= NULL
);
464 DevicePath
= AppendDevicePathNode (
466 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
468 ASSERT (DevicePath
!= NULL
);
470 Status
= EfiBootManagerInitializeLoadOption (
472 LoadOptionNumberUnassigned
,
480 ASSERT_EFI_ERROR (Status
);
481 FreePool (DevicePath
);
483 BootOptions
= EfiBootManagerGetLoadOptions (
484 &BootOptionCount
, LoadOptionTypeBoot
487 OptionIndex
= EfiBootManagerFindLoadOption (
488 &NewOption
, BootOptions
, BootOptionCount
491 if (OptionIndex
== -1) {
492 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
493 ASSERT_EFI_ERROR (Status
);
495 EfiBootManagerFreeLoadOption (&NewOption
);
496 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
501 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
502 whose device paths do not resolve exactly to an FvFile in the system.
504 This removes any boot options that point to binaries built into the firmware
505 and have become stale due to any of the following:
506 - FvMain's base address or size changed (historical),
507 - FvMain's FvNameGuid changed,
508 - the FILE_GUID of the pointed-to binary changed,
509 - the referenced binary is no longer built into the firmware.
511 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
512 avoids exact duplicates.
516 RemoveStaleFvFileOptions (
520 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
521 UINTN BootOptionCount
;
524 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
,
527 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
528 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
533 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
534 // then keep the boot option.
536 Node1
= BootOptions
[Index
].FilePath
;
537 if (!(DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
&&
538 DevicePathSubType (Node1
) == HW_MEMMAP_DP
) &&
539 !(DevicePathType (Node1
) == MEDIA_DEVICE_PATH
&&
540 DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)) {
545 // If the second device path node is not FvFile(...), then keep the boot
548 Node2
= NextDevicePathNode (Node1
);
549 if (DevicePathType (Node2
) != MEDIA_DEVICE_PATH
||
550 DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
) {
555 // Locate the Firmware Volume2 protocol instance that is denoted by the
556 // boot option. If this lookup fails (i.e., the boot option references a
557 // firmware volume that doesn't exist), then we'll proceed to delete the
561 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
,
562 &SearchNode
, &FvHandle
);
564 if (!EFI_ERROR (Status
)) {
566 // The firmware volume was found; now let's see if it contains the FvFile
567 // identified by GUID.
569 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
570 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
572 EFI_FV_FILETYPE FoundType
;
573 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
574 UINT32 AuthenticationStatus
;
576 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiFirmwareVolume2ProtocolGuid
,
577 (VOID
**)&FvProtocol
);
578 ASSERT_EFI_ERROR (Status
);
580 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
582 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
585 Status
= FvProtocol
->ReadFile (
587 &FvFileNode
->FvFileName
, // NameGuid
592 &AuthenticationStatus
594 if (!EFI_ERROR (Status
)) {
596 // The FvFile was found. Keep the boot option.
603 // Delete the boot option.
605 Status
= EfiBootManagerDeleteLoadOptionVariable (
606 BootOptions
[Index
].OptionNumber
, LoadOptionTypeBoot
);
608 CHAR16
*DevicePathString
;
610 DevicePathString
= ConvertDevicePathToText(BootOptions
[Index
].FilePath
,
613 EFI_ERROR (Status
) ? EFI_D_WARN
: EFI_D_VERBOSE
,
614 "%a: removing stale Boot#%04x %s: %r\n",
616 (UINT32
)BootOptions
[Index
].OptionNumber
,
617 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
620 if (DevicePathString
!= NULL
) {
621 FreePool (DevicePathString
);
626 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
632 PlatformRegisterOptionsAndKeys (
640 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
643 // Register ENTER as CONTINUE key
645 Enter
.ScanCode
= SCAN_NULL
;
646 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
647 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
648 ASSERT_EFI_ERROR (Status
);
651 // Map F2 and ESC to Boot Manager Menu
653 F2
.ScanCode
= SCAN_F2
;
654 F2
.UnicodeChar
= CHAR_NULL
;
655 Esc
.ScanCode
= SCAN_ESC
;
656 Esc
.UnicodeChar
= CHAR_NULL
;
657 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
658 ASSERT_EFI_ERROR (Status
);
659 Status
= EfiBootManagerAddKeyOptionVariable (
660 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
662 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
663 Status
= EfiBootManagerAddKeyOptionVariable (
664 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
666 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
671 // BDS Platform Functions
674 Do the platform init, can be customized by OEM/IBV
675 Possible things that can be done in PlatformBootManagerBeforeConsole:
676 > Update console variable: 1. include hot-plug devices;
677 > 2. Clear ConIn and add SOL for AMT
678 > Register new Driver#### or Boot####
679 > Register new Key####: e.g.: F12
680 > Signal ReadyToLock event
681 > Authentication action: 1. connect Auth devices;
682 > 2. Identify auto logon user.
686 PlatformBootManagerBeforeConsole (
690 UINT16 FrontPageTimeout
;
691 RETURN_STATUS PcdStatus
;
695 // Signal EndOfDxe PI Event
697 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
700 // Dispatch deferred images after EndOfDxe event.
702 EfiBootManagerDispatchDeferredImages ();
705 // Locate the PCI root bridges and make the PCI bus driver connect each,
706 // non-recursively. This will produce a number of child handles with PciIo on
709 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid
, NULL
, Connect
);
712 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
714 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
717 // Find all display class PCI devices (using the handles from the previous
718 // step), and connect them non-recursively. This should produce a number of
719 // child handles with GOPs on them.
721 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsPciDisplay
, Connect
);
724 // Now add the device path of all handles with GOP on them to ConOut and
727 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid
, NULL
, AddOutput
);
730 // Add the hardcoded short-form USB keyboard device path to ConIn.
732 EfiBootManagerUpdateConsoleVariable (ConIn
,
733 (EFI_DEVICE_PATH_PROTOCOL
*)&mUsbKeyboard
, NULL
);
736 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
738 CopyGuid (&mSerialConsole
.TermType
.Guid
,
739 PcdGetPtr (PcdTerminalTypeGuidBuffer
));
740 EfiBootManagerUpdateConsoleVariable (ConIn
,
741 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
742 EfiBootManagerUpdateConsoleVariable (ConOut
,
743 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
744 EfiBootManagerUpdateConsoleVariable (ErrOut
,
745 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
748 // Set the front page timeout from the QEMU configuration.
750 FrontPageTimeout
= GetFrontPageTimeoutFromQemu ();
751 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
, FrontPageTimeout
);
752 ASSERT_RETURN_ERROR (PcdStatus
);
754 // Reflect the PCD in the standard Timeout variable.
756 Status
= gRT
->SetVariable (
757 EFI_TIME_OUT_VARIABLE_NAME
,
758 &gEfiGlobalVariableGuid
,
759 (EFI_VARIABLE_NON_VOLATILE
|
760 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
761 EFI_VARIABLE_RUNTIME_ACCESS
),
762 sizeof FrontPageTimeout
,
766 EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
,
767 "%a: SetVariable(%s, %u): %r\n",
769 EFI_TIME_OUT_VARIABLE_NAME
,
775 // Register platform-specific boot options and keyboard shortcuts.
777 PlatformRegisterOptionsAndKeys ();
780 // At this point, VIRTIO_DEVICE_PROTOCOL instances exist only for Virtio MMIO
781 // transports. Install EFI_RNG_PROTOCOL instances on Virtio MMIO RNG devices.
783 FilterAndProcess (&gVirtioDeviceProtocolGuid
, IsVirtioRng
, Connect
);
786 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
787 // instances on Virtio PCI RNG devices.
789 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsVirtioPciRng
, Connect
);
793 Do the platform specific action after the console is ready
794 Possible things that can be done in PlatformBootManagerAfterConsole:
795 > Console post action:
796 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
797 > Signal console ready platform customized event
798 > Run diagnostics like memory testing
799 > Connect certain devices
800 > Dispatch additional option roms
801 > Special boot: e.g.: USB boot, enter UI
805 PlatformBootManagerAfterConsole (
809 RETURN_STATUS Status
;
812 // Show the splash screen.
814 BootLogoEnableLogo ();
817 // Process QEMU's -kernel command line option. The kernel booted this way
818 // will receive ACPI tables: in PlatformBootManagerBeforeConsole(), we
819 // connected any and all PCI root bridges, and then signaled the ACPI
822 TryRunningQemuKernel ();
825 // Connect the purported boot devices.
827 Status
= ConnectDevicesFromQemu ();
828 if (RETURN_ERROR (Status
)) {
830 // Connect the rest of the devices.
832 EfiBootManagerConnectAll ();
836 // Enumerate all possible boot options, then filter and reorder them based on
837 // the QEMU configuration.
839 EfiBootManagerRefreshAllBootOption ();
842 // Register UEFI Shell
844 PlatformRegisterFvBootOption (
845 &gUefiShellFileGuid
, L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
848 RemoveStaleFvFileOptions ();
849 SetBootOrderFromQemu ();
851 PlatformBmPrintScRegisterHandler ();
855 This function is called each second during the boot manager waits the
858 @param TimeoutRemain The remaining timeout.
862 PlatformBootManagerWaitCallback (
866 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
867 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
868 UINT16 TimeoutInitial
;
870 TimeoutInitial
= PcdGet16 (PcdPlatformBootTimeOut
);
873 // If PcdPlatformBootTimeOut is set to zero, then we consider
874 // that no progress update should be enacted.
876 if (TimeoutInitial
== 0) {
880 Black
.Raw
= 0x00000000;
881 White
.Raw
= 0x00FFFFFF;
883 BootLogoUpdateProgress (
886 L
"Start boot option",
888 (TimeoutInitial
- TimeoutRemain
) * 100 / TimeoutInitial
,
894 The function is called when no boot option could be launched,
895 including platform recovery options and options pointing to applications
896 built into firmware volumes.
898 If this function returns, BDS attempts to enter an infinite loop.
902 PlatformBootManagerUnableToBoot (
908 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
912 // BootManagerMenu doesn't contain the correct information when return status
915 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
916 if (EFI_ERROR (Status
)) {
920 // Normally BdsDxe does not print anything to the system console, but this is
921 // a last resort -- the end-user will likely not see any DEBUG messages
922 // logged in this situation.
924 // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
925 // here to see if it makes sense to request and wait for a keypress.
927 if (gST
->ConIn
!= NULL
) {
929 "%a: No bootable option or device was found.\n"
930 "%a: Press any key to enter the Boot Manager Menu.\n",
934 Status
= gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &Index
);
935 ASSERT_EFI_ERROR (Status
);
939 // Drain any queued keys.
941 while (!EFI_ERROR (gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
))) {
943 // just throw away Key
949 EfiBootManagerBoot (&BootManagerMenu
);