2 Implementation for PlatformBootManagerLib library class interfaces.
4 Copyright (C) 2015-2016, Red Hat, Inc.
5 Copyright (c) 2014 - 2019, ARM Ltd. All rights reserved.<BR>
6 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
7 Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
9 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <IndustryStandard/Pci22.h>
14 #include <Library/BootLogoLib.h>
15 #include <Library/CapsuleLib.h>
16 #include <Library/DevicePathLib.h>
17 #include <Library/HobLib.h>
18 #include <Library/PcdLib.h>
19 #include <Library/UefiBootManagerLib.h>
20 #include <Library/UefiLib.h>
21 #include <Library/UefiRuntimeServicesTableLib.h>
22 #include <Protocol/DevicePath.h>
23 #include <Protocol/EsrtManagement.h>
24 #include <Protocol/GraphicsOutput.h>
25 #include <Protocol/LoadedImage.h>
26 #include <Protocol/NonDiscoverableDevice.h>
27 #include <Protocol/PciIo.h>
28 #include <Protocol/PciRootBridgeIo.h>
29 #include <Protocol/PlatformBootManager.h>
30 #include <Guid/EventGroup.h>
31 #include <Guid/NonDiscoverableDevice.h>
32 #include <Guid/TtyTerm.h>
33 #include <Guid/SerialPortLibVendor.h>
35 #include "PlatformBm.h"
37 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
41 VENDOR_DEVICE_PATH SerialDxe
;
42 UART_DEVICE_PATH Uart
;
43 VENDOR_DEFINED_DEVICE_PATH TermType
;
44 EFI_DEVICE_PATH_PROTOCOL End
;
45 } PLATFORM_SERIAL_CONSOLE
;
48 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole
= {
50 // VENDOR_DEVICE_PATH SerialDxe
53 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, DP_NODE_LEN (VENDOR_DEVICE_PATH
) },
54 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
58 // UART_DEVICE_PATH Uart
61 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, DP_NODE_LEN (UART_DEVICE_PATH
) },
63 FixedPcdGet64 (PcdUartDefaultBaudRate
), // BaudRate
64 FixedPcdGet8 (PcdUartDefaultDataBits
), // DataBits
65 FixedPcdGet8 (PcdUartDefaultParity
), // Parity
66 FixedPcdGet8 (PcdUartDefaultStopBits
) // StopBits
70 // VENDOR_DEFINED_DEVICE_PATH TermType
74 MESSAGING_DEVICE_PATH
, MSG_VENDOR_DP
,
75 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH
)
78 // Guid to be filled in dynamically
83 // EFI_DEVICE_PATH_PROTOCOL End
86 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
87 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
94 USB_CLASS_DEVICE_PATH Keyboard
;
95 EFI_DEVICE_PATH_PROTOCOL End
;
96 } PLATFORM_USB_KEYBOARD
;
99 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard
= {
101 // USB_CLASS_DEVICE_PATH Keyboard
105 MESSAGING_DEVICE_PATH
, MSG_USB_CLASS_DP
,
106 DP_NODE_LEN (USB_CLASS_DEVICE_PATH
)
108 0xFFFF, // VendorId: any
109 0xFFFF, // ProductId: any
110 3, // DeviceClass: HID
111 1, // DeviceSubClass: boot
112 1 // DeviceProtocol: keyboard
116 // EFI_DEVICE_PATH_PROTOCOL End
119 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
120 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
126 Check if the handle satisfies a particular condition.
128 @param[in] Handle The handle to check.
129 @param[in] ReportText A caller-allocated string passed in for reporting
130 purposes. It must never be NULL.
132 @retval TRUE The condition is satisfied.
133 @retval FALSE Otherwise. This includes the case when the condition could not
134 be fully evaluated due to an error.
138 (EFIAPI
*FILTER_FUNCTION
) (
139 IN EFI_HANDLE Handle
,
140 IN CONST CHAR16
*ReportText
147 @param[in] Handle The handle to process.
148 @param[in] ReportText A caller-allocated string passed in for reporting
149 purposes. It must never be NULL.
153 (EFIAPI
*CALLBACK_FUNCTION
) (
154 IN EFI_HANDLE Handle
,
155 IN CONST CHAR16
*ReportText
159 Locate all handles that carry the specified protocol, filter them with a
160 callback function, and pass each handle that passes the filter to another
163 @param[in] ProtocolGuid The protocol to look for.
165 @param[in] Filter The filter function to pass each handle to. If this
166 parameter is NULL, then all handles are processed.
168 @param[in] Process The callback function to pass each handle to that
174 IN EFI_GUID
*ProtocolGuid
,
175 IN FILTER_FUNCTION Filter OPTIONAL
,
176 IN CALLBACK_FUNCTION Process
184 Status
= gBS
->LocateHandleBuffer (ByProtocol
, ProtocolGuid
,
185 NULL
/* SearchKey */, &NoHandles
, &Handles
);
186 if (EFI_ERROR (Status
)) {
188 // This is not an error, just an informative condition.
190 DEBUG ((EFI_D_VERBOSE
, "%a: %g: %r\n", __FUNCTION__
, ProtocolGuid
,
195 ASSERT (NoHandles
> 0);
196 for (Idx
= 0; Idx
< NoHandles
; ++Idx
) {
197 CHAR16
*DevicePathText
;
198 STATIC CHAR16 Fallback
[] = L
"<device path unavailable>";
201 // The ConvertDevicePathToText() function handles NULL input transparently.
203 DevicePathText
= ConvertDevicePathToText (
204 DevicePathFromHandle (Handles
[Idx
]),
205 FALSE
, // DisplayOnly
206 FALSE
// AllowShortcuts
208 if (DevicePathText
== NULL
) {
209 DevicePathText
= Fallback
;
212 if (Filter
== NULL
|| Filter (Handles
[Idx
], DevicePathText
)) {
213 Process (Handles
[Idx
], DevicePathText
);
216 if (DevicePathText
!= Fallback
) {
217 FreePool (DevicePathText
);
220 gBS
->FreePool (Handles
);
225 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
231 IN EFI_HANDLE Handle
,
232 IN CONST CHAR16
*ReportText
236 EFI_PCI_IO_PROTOCOL
*PciIo
;
239 Status
= gBS
->HandleProtocol (Handle
, &gEfiPciIoProtocolGuid
,
241 if (EFI_ERROR (Status
)) {
243 // This is not an error worth reporting.
248 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, 0 /* Offset */,
249 sizeof Pci
/ sizeof (UINT32
), &Pci
);
250 if (EFI_ERROR (Status
)) {
251 DEBUG ((EFI_D_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
255 return IS_PCI_DISPLAY (&Pci
);
260 This FILTER_FUNCTION checks if a handle corresponds to a non-discoverable
267 IN EFI_HANDLE Handle
,
268 IN CONST CHAR16
*ReportText
271 NON_DISCOVERABLE_DEVICE
*Device
;
274 Status
= gBS
->HandleProtocol (Handle
,
275 &gEdkiiNonDiscoverableDeviceProtocolGuid
,
277 if (EFI_ERROR (Status
)) {
281 if (CompareGuid (Device
->Type
, &gEdkiiNonDiscoverableUhciDeviceGuid
) ||
282 CompareGuid (Device
->Type
, &gEdkiiNonDiscoverableEhciDeviceGuid
) ||
283 CompareGuid (Device
->Type
, &gEdkiiNonDiscoverableXhciDeviceGuid
)) {
291 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
292 the matching driver to produce all first-level child handles.
298 IN EFI_HANDLE Handle
,
299 IN CONST CHAR16
*ReportText
304 Status
= gBS
->ConnectController (
305 Handle
, // ControllerHandle
306 NULL
, // DriverImageHandle
307 NULL
, // RemainingDevicePath -- produce all children
310 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
, "%a: %s: %r\n",
311 __FUNCTION__
, ReportText
, Status
));
316 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
317 handle, and adds it to ConOut and ErrOut.
323 IN EFI_HANDLE Handle
,
324 IN CONST CHAR16
*ReportText
328 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
330 DevicePath
= DevicePathFromHandle (Handle
);
331 if (DevicePath
== NULL
) {
332 DEBUG ((EFI_D_ERROR
, "%a: %s: handle %p: device path not found\n",
333 __FUNCTION__
, ReportText
, Handle
));
337 Status
= EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
338 if (EFI_ERROR (Status
)) {
339 DEBUG ((EFI_D_ERROR
, "%a: %s: adding to ConOut: %r\n", __FUNCTION__
,
340 ReportText
, Status
));
344 Status
= EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
345 if (EFI_ERROR (Status
)) {
346 DEBUG ((EFI_D_ERROR
, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__
,
347 ReportText
, Status
));
351 DEBUG ((EFI_D_VERBOSE
, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__
,
357 PlatformRegisterFvBootOption (
358 CONST EFI_GUID
*FileGuid
,
366 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
367 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
368 UINTN BootOptionCount
;
369 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
370 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
371 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
373 Status
= gBS
->HandleProtocol (
375 &gEfiLoadedImageProtocolGuid
,
376 (VOID
**) &LoadedImage
378 ASSERT_EFI_ERROR (Status
);
380 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
381 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
382 ASSERT (DevicePath
!= NULL
);
383 DevicePath
= AppendDevicePathNode (
385 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
387 ASSERT (DevicePath
!= NULL
);
389 Status
= EfiBootManagerInitializeLoadOption (
391 LoadOptionNumberUnassigned
,
399 ASSERT_EFI_ERROR (Status
);
400 FreePool (DevicePath
);
402 BootOptions
= EfiBootManagerGetLoadOptions (
403 &BootOptionCount
, LoadOptionTypeBoot
406 OptionIndex
= EfiBootManagerFindLoadOption (
407 &NewOption
, BootOptions
, BootOptionCount
410 if (OptionIndex
== -1) {
411 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
412 ASSERT_EFI_ERROR (Status
);
413 Status
= EfiBootManagerAddKeyOptionVariable (NULL
,
414 (UINT16
)NewOption
.OptionNumber
, 0, Key
, NULL
);
415 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
417 EfiBootManagerFreeLoadOption (&NewOption
);
418 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
429 EFI_BOOT_MANAGER_LOAD_OPTION
*CurrentBootOptions
;
430 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
431 EFI_INPUT_KEY
*BootKeys
;
432 PLATFORM_BOOT_MANAGER_PROTOCOL
*PlatformBootManager
;
433 UINTN CurrentBootOptionCount
;
437 Status
= gBS
->LocateProtocol (&gPlatformBootManagerProtocolGuid
, NULL
,
438 (VOID
**)&PlatformBootManager
);
439 if (EFI_ERROR (Status
)) {
442 Status
= PlatformBootManager
->GetPlatformBootOptionsAndKeys (
447 if (EFI_ERROR (Status
)) {
451 // Fetch the existent boot options. If there are none, CurrentBootCount
454 CurrentBootOptions
= EfiBootManagerGetLoadOptions (
455 &CurrentBootOptionCount
,
459 // Process the platform boot options.
461 for (Index
= 0; Index
< BootCount
; Index
++) {
463 UINTN BootOptionNumber
;
466 // If there are any preexistent boot options, and the subject platform boot
467 // option is already among them, then don't try to add it. Just get its
468 // assigned boot option number so we can associate a hotkey with it. Note
469 // that EfiBootManagerFindLoadOption() deals fine with (CurrentBootOptions
470 // == NULL) if (CurrentBootCount == 0).
472 Match
= EfiBootManagerFindLoadOption (
475 CurrentBootOptionCount
478 BootOptionNumber
= CurrentBootOptions
[Match
].OptionNumber
;
481 // Add the platform boot options as a new one, at the end of the boot
482 // order. Note that if the platform provided this boot option with an
483 // unassigned option number, then the below function call will assign a
486 Status
= EfiBootManagerAddLoadOptionVariable (
490 if (EFI_ERROR (Status
)) {
491 DEBUG ((DEBUG_ERROR
, "%a: failed to register \"%s\": %r\n",
492 __FUNCTION__
, BootOptions
[Index
].Description
, Status
));
495 BootOptionNumber
= BootOptions
[Index
].OptionNumber
;
499 // Register a hotkey with the boot option, if requested.
501 if (BootKeys
[Index
].UnicodeChar
== L
'\0') {
505 Status
= EfiBootManagerAddKeyOptionVariable (
512 if (EFI_ERROR (Status
)) {
513 DEBUG ((DEBUG_ERROR
, "%a: failed to register hotkey for \"%s\": %r\n",
514 __FUNCTION__
, BootOptions
[Index
].Description
, Status
));
517 EfiBootManagerFreeLoadOptions (CurrentBootOptions
, CurrentBootOptionCount
);
518 EfiBootManagerFreeLoadOptions (BootOptions
, BootCount
);
524 PlatformRegisterOptionsAndKeys (
532 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
534 GetPlatformOptions ();
537 // Register ENTER as CONTINUE key
539 Enter
.ScanCode
= SCAN_NULL
;
540 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
541 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
542 ASSERT_EFI_ERROR (Status
);
545 // Map F2 and ESC to Boot Manager Menu
547 F2
.ScanCode
= SCAN_F2
;
548 F2
.UnicodeChar
= CHAR_NULL
;
549 Esc
.ScanCode
= SCAN_ESC
;
550 Esc
.UnicodeChar
= CHAR_NULL
;
551 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
552 ASSERT_EFI_ERROR (Status
);
553 Status
= EfiBootManagerAddKeyOptionVariable (
554 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
556 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
557 Status
= EfiBootManagerAddKeyOptionVariable (
558 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
560 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
565 // BDS Platform Functions
568 Do the platform init, can be customized by OEM/IBV
569 Possible things that can be done in PlatformBootManagerBeforeConsole:
570 > Update console variable: 1. include hot-plug devices;
571 > 2. Clear ConIn and add SOL for AMT
572 > Register new Driver#### or Boot####
573 > Register new Key####: e.g.: F12
574 > Signal ReadyToLock event
575 > Authentication action: 1. connect Auth devices;
576 > 2. Identify auto logon user.
580 PlatformBootManagerBeforeConsole (
585 // Signal EndOfDxe PI Event
587 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
590 // Dispatch deferred images after EndOfDxe event.
592 EfiBootManagerDispatchDeferredImages ();
595 // Locate the PCI root bridges and make the PCI bus driver connect each,
596 // non-recursively. This will produce a number of child handles with PciIo on
599 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid
, NULL
, Connect
);
602 // Find all display class PCI devices (using the handles from the previous
603 // step), and connect them non-recursively. This should produce a number of
604 // child handles with GOPs on them.
606 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsPciDisplay
, Connect
);
609 // Now add the device path of all handles with GOP on them to ConOut and
612 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid
, NULL
, AddOutput
);
615 // The core BDS code connects short-form USB device paths by explicitly
616 // looking for handles with PCI I/O installed, and checking the PCI class
617 // code whether it matches the one for a USB host controller. This means
618 // non-discoverable USB host controllers need to have the non-discoverable
619 // PCI driver attached first.
621 FilterAndProcess (&gEdkiiNonDiscoverableDeviceProtocolGuid
, IsUsbHost
, Connect
);
624 // Add the hardcoded short-form USB keyboard device path to ConIn.
626 EfiBootManagerUpdateConsoleVariable (ConIn
,
627 (EFI_DEVICE_PATH_PROTOCOL
*)&mUsbKeyboard
, NULL
);
630 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
632 STATIC_ASSERT (FixedPcdGet8 (PcdDefaultTerminalType
) == 4,
633 "PcdDefaultTerminalType must be TTYTERM");
634 STATIC_ASSERT (FixedPcdGet8 (PcdUartDefaultParity
) != 0,
635 "PcdUartDefaultParity must be set to an actual value, not 'default'");
636 STATIC_ASSERT (FixedPcdGet8 (PcdUartDefaultStopBits
) != 0,
637 "PcdUartDefaultStopBits must be set to an actual value, not 'default'");
639 CopyGuid (&mSerialConsole
.TermType
.Guid
, &gEfiTtyTermGuid
);
641 EfiBootManagerUpdateConsoleVariable (ConIn
,
642 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
643 EfiBootManagerUpdateConsoleVariable (ConOut
,
644 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
645 EfiBootManagerUpdateConsoleVariable (ErrOut
,
646 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
649 // Register platform-specific boot options and keyboard shortcuts.
651 PlatformRegisterOptionsAndKeys ();
660 ESRT_MANAGEMENT_PROTOCOL
*EsrtManagement
;
661 EFI_PEI_HOB_POINTERS HobPointer
;
662 EFI_CAPSULE_HEADER
*CapsuleHeader
;
666 DEBUG ((DEBUG_INFO
, "%a: processing capsules ...\n", __FUNCTION__
));
668 Status
= gBS
->LocateProtocol (&gEsrtManagementProtocolGuid
, NULL
,
669 (VOID
**)&EsrtManagement
);
670 if (!EFI_ERROR (Status
)) {
671 EsrtManagement
->SyncEsrtFmp ();
675 // Find all capsule images from hob
677 HobPointer
.Raw
= GetHobList ();
679 while ((HobPointer
.Raw
= GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE
,
680 HobPointer
.Raw
)) != NULL
) {
681 CapsuleHeader
= (VOID
*)(UINTN
)HobPointer
.Capsule
->BaseAddress
;
683 Status
= ProcessCapsuleImage (CapsuleHeader
);
684 if (EFI_ERROR (Status
)) {
685 DEBUG ((DEBUG_ERROR
, "%a: failed to process capsule %p - %r\n",
686 __FUNCTION__
, CapsuleHeader
, Status
));
691 HobPointer
.Raw
= GET_NEXT_HOB (HobPointer
);
695 DEBUG ((DEBUG_WARN
, "%a: capsule update successful, resetting ...\n",
698 gRT
->ResetSystem (EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
704 #define VERSION_STRING_PREFIX L"Tianocore/EDK2 firmware version "
707 Do the platform specific action after the console is ready
708 Possible things that can be done in PlatformBootManagerAfterConsole:
709 > Console post action:
710 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
711 > Signal console ready platform customized event
712 > Run diagnostics like memory testing
713 > Connect certain devices
714 > Dispatch additional option roms
715 > Special boot: e.g.: USB boot, enter UI
719 PlatformBootManagerAfterConsole (
724 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
725 UINTN FirmwareVerLength
;
730 FirmwareVerLength
= StrLen (PcdGetPtr (PcdFirmwareVersionString
));
733 // Show the splash screen.
735 Status
= BootLogoEnableLogo ();
736 if (EFI_ERROR (Status
)) {
737 if (FirmwareVerLength
> 0) {
738 Print (VERSION_STRING_PREFIX L
"%s\n",
739 PcdGetPtr (PcdFirmwareVersionString
));
741 Print (L
"Press ESCAPE for boot options ");
742 } else if (FirmwareVerLength
> 0) {
743 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
,
744 &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
745 if (!EFI_ERROR (Status
)) {
746 PosX
= (GraphicsOutput
->Mode
->Info
->HorizontalResolution
-
747 (StrLen (VERSION_STRING_PREFIX
) + FirmwareVerLength
) *
748 EFI_GLYPH_WIDTH
) / 2;
751 PrintXY (PosX
, PosY
, NULL
, NULL
, VERSION_STRING_PREFIX L
"%s",
752 PcdGetPtr (PcdFirmwareVersionString
));
757 // On ARM, there is currently no reason to use the phased capsule
758 // update approach where some capsules are dispatched before EndOfDxe
759 // and some are dispatched after. So just handle all capsules here,
760 // when the console is up and we can actually give the user some
761 // feedback about what is going on.
766 // Register UEFI Shell
768 Key
.ScanCode
= SCAN_NULL
;
769 Key
.UnicodeChar
= L
's';
770 PlatformRegisterFvBootOption (&gUefiShellFileGuid
, L
"UEFI Shell", 0, &Key
);
774 This function is called each second during the boot manager waits the
777 @param TimeoutRemain The remaining timeout.
781 PlatformBootManagerWaitCallback (
785 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
786 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
790 Timeout
= PcdGet16 (PcdPlatformBootTimeOut
);
792 Black
.Raw
= 0x00000000;
793 White
.Raw
= 0x00FFFFFF;
795 Status
= BootLogoUpdateProgress (
798 L
"Press ESCAPE for boot options",
800 (Timeout
- TimeoutRemain
) * 100 / Timeout
,
803 if (EFI_ERROR (Status
)) {
809 The function is called when no boot option could be launched,
810 including platform recovery options and options pointing to applications
811 built into firmware volumes.
813 If this function returns, BDS attempts to enter an infinite loop.
817 PlatformBootManagerUnableToBoot (
822 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
823 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
824 UINTN OldBootOptionCount
;
825 UINTN NewBootOptionCount
;
828 // Record the total number of boot configured boot options
830 BootOptions
= EfiBootManagerGetLoadOptions (&OldBootOptionCount
,
832 EfiBootManagerFreeLoadOptions (BootOptions
, OldBootOptionCount
);
835 // Connect all devices, and regenerate all boot options
837 EfiBootManagerConnectAll ();
838 EfiBootManagerRefreshAllBootOption ();
841 // Record the updated number of boot configured boot options
843 BootOptions
= EfiBootManagerGetLoadOptions (&NewBootOptionCount
,
845 EfiBootManagerFreeLoadOptions (BootOptions
, NewBootOptionCount
);
848 // If the number of configured boot options has changed, reboot
849 // the system so the new boot options will be taken into account
850 // while executing the ordinary BDS bootflow sequence.
852 if (NewBootOptionCount
!= OldBootOptionCount
) {
853 DEBUG ((DEBUG_WARN
, "%a: rebooting after refreshing all boot options\n",
855 gRT
->ResetSystem (EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
858 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
859 if (EFI_ERROR (Status
)) {
864 EfiBootManagerBoot (&BootManagerMenu
);