2 Implementation for PlatformBootManagerLib library class interfaces.
4 Copyright (C) 2015-2016, Red Hat, Inc.
5 Copyright (c) 2014 - 2021, 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>
8 Copyright (c) 2021, Semihalf All rights reserved.<BR>
10 SPDX-License-Identifier: BSD-2-Clause-Patent
14 #include <IndustryStandard/Pci22.h>
15 #include <Library/BootLogoLib.h>
16 #include <Library/CapsuleLib.h>
17 #include <Library/DevicePathLib.h>
18 #include <Library/HobLib.h>
19 #include <Library/PcdLib.h>
20 #include <Library/UefiBootManagerLib.h>
21 #include <Library/UefiLib.h>
22 #include <Library/UefiRuntimeServicesTableLib.h>
23 #include <Protocol/BootManagerPolicy.h>
24 #include <Protocol/DevicePath.h>
25 #include <Protocol/EsrtManagement.h>
26 #include <Protocol/GraphicsOutput.h>
27 #include <Protocol/LoadedImage.h>
28 #include <Protocol/NonDiscoverableDevice.h>
29 #include <Protocol/PciIo.h>
30 #include <Protocol/PciRootBridgeIo.h>
31 #include <Protocol/PlatformBootManager.h>
32 #include <Guid/BootDiscoveryPolicy.h>
33 #include <Guid/EventGroup.h>
34 #include <Guid/NonDiscoverableDevice.h>
35 #include <Guid/TtyTerm.h>
36 #include <Guid/SerialPortLibVendor.h>
38 #include "PlatformBm.h"
40 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
44 VENDOR_DEVICE_PATH SerialDxe
;
45 UART_DEVICE_PATH Uart
;
46 VENDOR_DEFINED_DEVICE_PATH TermType
;
47 EFI_DEVICE_PATH_PROTOCOL End
;
48 } PLATFORM_SERIAL_CONSOLE
;
51 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole
= {
53 // VENDOR_DEVICE_PATH SerialDxe
56 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, DP_NODE_LEN (VENDOR_DEVICE_PATH
) },
57 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
61 // UART_DEVICE_PATH Uart
64 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, DP_NODE_LEN (UART_DEVICE_PATH
) },
66 FixedPcdGet64 (PcdUartDefaultBaudRate
), // BaudRate
67 FixedPcdGet8 (PcdUartDefaultDataBits
), // DataBits
68 FixedPcdGet8 (PcdUartDefaultParity
), // Parity
69 FixedPcdGet8 (PcdUartDefaultStopBits
) // StopBits
73 // VENDOR_DEFINED_DEVICE_PATH TermType
77 MESSAGING_DEVICE_PATH
, MSG_VENDOR_DP
,
78 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH
)
81 // Guid to be filled in dynamically
86 // EFI_DEVICE_PATH_PROTOCOL End
89 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
90 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
96 USB_CLASS_DEVICE_PATH Keyboard
;
97 EFI_DEVICE_PATH_PROTOCOL End
;
98 } PLATFORM_USB_KEYBOARD
;
101 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard
= {
103 // USB_CLASS_DEVICE_PATH Keyboard
107 MESSAGING_DEVICE_PATH
, MSG_USB_CLASS_DP
,
108 DP_NODE_LEN (USB_CLASS_DEVICE_PATH
)
110 0xFFFF, // VendorId: any
111 0xFFFF, // ProductId: any
112 3, // DeviceClass: HID
113 1, // DeviceSubClass: boot
114 1 // DeviceProtocol: keyboard
118 // EFI_DEVICE_PATH_PROTOCOL End
121 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
122 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
127 Check if the handle satisfies a particular condition.
129 @param[in] Handle The handle to check.
130 @param[in] ReportText A caller-allocated string passed in for reporting
131 purposes. It must never be NULL.
133 @retval TRUE The condition is satisfied.
134 @retval FALSE Otherwise. This includes the case when the condition could not
135 be fully evaluated due to an error.
139 (EFIAPI
*FILTER_FUNCTION
)(
140 IN EFI_HANDLE Handle
,
141 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 (
187 NULL
/* SearchKey */,
191 if (EFI_ERROR (Status
)) {
193 // This is not an error, just an informative condition.
205 ASSERT (NoHandles
> 0);
206 for (Idx
= 0; Idx
< NoHandles
; ++Idx
) {
207 CHAR16
*DevicePathText
;
208 STATIC CHAR16 Fallback
[] = L
"<device path unavailable>";
211 // The ConvertDevicePathToText() function handles NULL input transparently.
213 DevicePathText
= ConvertDevicePathToText (
214 DevicePathFromHandle (Handles
[Idx
]),
215 FALSE
, // DisplayOnly
216 FALSE
// AllowShortcuts
218 if (DevicePathText
== NULL
) {
219 DevicePathText
= Fallback
;
222 if ((Filter
== NULL
) || Filter (Handles
[Idx
], DevicePathText
)) {
223 Process (Handles
[Idx
], DevicePathText
);
226 if (DevicePathText
!= Fallback
) {
227 FreePool (DevicePathText
);
231 gBS
->FreePool (Handles
);
235 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
241 IN EFI_HANDLE Handle
,
242 IN CONST CHAR16
*ReportText
246 EFI_PCI_IO_PROTOCOL
*PciIo
;
249 Status
= gBS
->HandleProtocol (
251 &gEfiPciIoProtocolGuid
,
254 if (EFI_ERROR (Status
)) {
256 // This is not an error worth reporting.
261 Status
= PciIo
->Pci
.Read (
265 sizeof Pci
/ sizeof (UINT32
),
268 if (EFI_ERROR (Status
)) {
269 DEBUG ((DEBUG_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
273 return IS_PCI_DISPLAY (&Pci
);
277 This FILTER_FUNCTION checks if a handle corresponds to a non-discoverable
284 IN EFI_HANDLE Handle
,
285 IN CONST CHAR16
*ReportText
288 NON_DISCOVERABLE_DEVICE
*Device
;
291 Status
= gBS
->HandleProtocol (
293 &gEdkiiNonDiscoverableDeviceProtocolGuid
,
296 if (EFI_ERROR (Status
)) {
300 if (CompareGuid (Device
->Type
, &gEdkiiNonDiscoverableUhciDeviceGuid
) ||
301 CompareGuid (Device
->Type
, &gEdkiiNonDiscoverableEhciDeviceGuid
) ||
302 CompareGuid (Device
->Type
, &gEdkiiNonDiscoverableXhciDeviceGuid
))
311 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
312 the matching driver to produce all first-level child handles.
318 IN EFI_HANDLE Handle
,
319 IN CONST CHAR16
*ReportText
324 Status
= gBS
->ConnectController (
325 Handle
, // ControllerHandle
326 NULL
, // DriverImageHandle
327 NULL
, // RemainingDevicePath -- produce all children
331 EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
,
340 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
341 handle, and adds it to ConOut and ErrOut.
347 IN EFI_HANDLE Handle
,
348 IN CONST CHAR16
*ReportText
352 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
354 DevicePath
= DevicePathFromHandle (Handle
);
355 if (DevicePath
== NULL
) {
358 "%a: %s: handle %p: device path not found\n",
366 Status
= EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
367 if (EFI_ERROR (Status
)) {
370 "%a: %s: adding to ConOut: %r\n",
378 Status
= EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
379 if (EFI_ERROR (Status
)) {
382 "%a: %s: adding to ErrOut: %r\n",
392 "%a: %s: added to ConOut and ErrOut\n",
400 PlatformRegisterFvBootOption (
401 CONST EFI_GUID
*FileGuid
,
409 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
410 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
411 UINTN BootOptionCount
;
412 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
413 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
414 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
416 Status
= gBS
->HandleProtocol (
418 &gEfiLoadedImageProtocolGuid
,
419 (VOID
**)&LoadedImage
421 ASSERT_EFI_ERROR (Status
);
423 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
424 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
425 ASSERT (DevicePath
!= NULL
);
426 DevicePath
= AppendDevicePathNode (
428 (EFI_DEVICE_PATH_PROTOCOL
*)&FileNode
430 ASSERT (DevicePath
!= NULL
);
432 Status
= EfiBootManagerInitializeLoadOption (
434 LoadOptionNumberUnassigned
,
442 ASSERT_EFI_ERROR (Status
);
443 FreePool (DevicePath
);
445 BootOptions
= EfiBootManagerGetLoadOptions (
450 OptionIndex
= EfiBootManagerFindLoadOption (
456 if (OptionIndex
== -1) {
457 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
458 ASSERT_EFI_ERROR (Status
);
459 Status
= EfiBootManagerAddKeyOptionVariable (
461 (UINT16
)NewOption
.OptionNumber
,
466 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
469 EfiBootManagerFreeLoadOption (&NewOption
);
470 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
480 EFI_BOOT_MANAGER_LOAD_OPTION
*CurrentBootOptions
;
481 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
482 EFI_INPUT_KEY
*BootKeys
;
483 PLATFORM_BOOT_MANAGER_PROTOCOL
*PlatformBootManager
;
484 UINTN CurrentBootOptionCount
;
488 Status
= gBS
->LocateProtocol (
489 &gPlatformBootManagerProtocolGuid
,
491 (VOID
**)&PlatformBootManager
493 if (EFI_ERROR (Status
)) {
497 Status
= PlatformBootManager
->GetPlatformBootOptionsAndKeys (
502 if (EFI_ERROR (Status
)) {
507 // Fetch the existent boot options. If there are none, CurrentBootCount
510 CurrentBootOptions
= EfiBootManagerGetLoadOptions (
511 &CurrentBootOptionCount
,
515 // Process the platform boot options.
517 for (Index
= 0; Index
< BootCount
; Index
++) {
519 UINTN BootOptionNumber
;
522 // If there are any preexistent boot options, and the subject platform boot
523 // option is already among them, then don't try to add it. Just get its
524 // assigned boot option number so we can associate a hotkey with it. Note
525 // that EfiBootManagerFindLoadOption() deals fine with (CurrentBootOptions
526 // == NULL) if (CurrentBootCount == 0).
528 Match
= EfiBootManagerFindLoadOption (
531 CurrentBootOptionCount
534 BootOptionNumber
= CurrentBootOptions
[Match
].OptionNumber
;
537 // Add the platform boot options as a new one, at the end of the boot
538 // order. Note that if the platform provided this boot option with an
539 // unassigned option number, then the below function call will assign a
542 Status
= EfiBootManagerAddLoadOptionVariable (
546 if (EFI_ERROR (Status
)) {
549 "%a: failed to register \"%s\": %r\n",
551 BootOptions
[Index
].Description
,
557 BootOptionNumber
= BootOptions
[Index
].OptionNumber
;
561 // Register a hotkey with the boot option, if requested.
563 if (BootKeys
[Index
].UnicodeChar
== L
'\0') {
567 Status
= EfiBootManagerAddKeyOptionVariable (
574 if (EFI_ERROR (Status
)) {
577 "%a: failed to register hotkey for \"%s\": %r\n",
579 BootOptions
[Index
].Description
,
585 EfiBootManagerFreeLoadOptions (CurrentBootOptions
, CurrentBootOptionCount
);
586 EfiBootManagerFreeLoadOptions (BootOptions
, BootCount
);
592 PlatformRegisterOptionsAndKeys (
600 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
602 GetPlatformOptions ();
605 // Register ENTER as CONTINUE key
607 Enter
.ScanCode
= SCAN_NULL
;
608 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
609 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
610 ASSERT_EFI_ERROR (Status
);
613 // Map F2 and ESC to Boot Manager Menu
615 F2
.ScanCode
= SCAN_F2
;
616 F2
.UnicodeChar
= CHAR_NULL
;
617 Esc
.ScanCode
= SCAN_ESC
;
618 Esc
.UnicodeChar
= CHAR_NULL
;
619 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
620 ASSERT_EFI_ERROR (Status
);
621 Status
= EfiBootManagerAddKeyOptionVariable (
623 (UINT16
)BootOption
.OptionNumber
,
628 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
629 Status
= EfiBootManagerAddKeyOptionVariable (
631 (UINT16
)BootOption
.OptionNumber
,
636 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
640 // BDS Platform Functions
644 Do the platform init, can be customized by OEM/IBV
645 Possible things that can be done in PlatformBootManagerBeforeConsole:
646 > Update console variable: 1. include hot-plug devices;
647 > 2. Clear ConIn and add SOL for AMT
648 > Register new Driver#### or Boot####
649 > Register new Key####: e.g.: F12
650 > Signal ReadyToLock event
651 > Authentication action: 1. connect Auth devices;
652 > 2. Identify auto logon user.
656 PlatformBootManagerBeforeConsole (
661 // Signal EndOfDxe PI Event
663 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
666 // Dispatch deferred images after EndOfDxe event.
668 EfiBootManagerDispatchDeferredImages ();
671 // Locate the PCI root bridges and make the PCI bus driver connect each,
672 // non-recursively. This will produce a number of child handles with PciIo on
675 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid
, NULL
, Connect
);
678 // Find all display class PCI devices (using the handles from the previous
679 // step), and connect them non-recursively. This should produce a number of
680 // child handles with GOPs on them.
682 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsPciDisplay
, Connect
);
685 // Now add the device path of all handles with GOP on them to ConOut and
688 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid
, NULL
, AddOutput
);
691 // The core BDS code connects short-form USB device paths by explicitly
692 // looking for handles with PCI I/O installed, and checking the PCI class
693 // code whether it matches the one for a USB host controller. This means
694 // non-discoverable USB host controllers need to have the non-discoverable
695 // PCI driver attached first.
697 FilterAndProcess (&gEdkiiNonDiscoverableDeviceProtocolGuid
, IsUsbHost
, Connect
);
700 // Add the hardcoded short-form USB keyboard device path to ConIn.
702 EfiBootManagerUpdateConsoleVariable (
704 (EFI_DEVICE_PATH_PROTOCOL
*)&mUsbKeyboard
,
709 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
712 FixedPcdGet8 (PcdDefaultTerminalType
) == 4,
713 "PcdDefaultTerminalType must be TTYTERM"
716 FixedPcdGet8 (PcdUartDefaultParity
) != 0,
717 "PcdUartDefaultParity must be set to an actual value, not 'default'"
720 FixedPcdGet8 (PcdUartDefaultStopBits
) != 0,
721 "PcdUartDefaultStopBits must be set to an actual value, not 'default'"
724 CopyGuid (&mSerialConsole
.TermType
.Guid
, &gEfiTtyTermGuid
);
726 EfiBootManagerUpdateConsoleVariable (
728 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
,
731 EfiBootManagerUpdateConsoleVariable (
733 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
,
736 EfiBootManagerUpdateConsoleVariable (
738 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
,
743 // Register platform-specific boot options and keyboard shortcuts.
745 PlatformRegisterOptionsAndKeys ();
754 ESRT_MANAGEMENT_PROTOCOL
*EsrtManagement
;
755 EFI_PEI_HOB_POINTERS HobPointer
;
756 EFI_CAPSULE_HEADER
*CapsuleHeader
;
760 DEBUG ((DEBUG_INFO
, "%a: processing capsules ...\n", __FUNCTION__
));
762 Status
= gBS
->LocateProtocol (
763 &gEsrtManagementProtocolGuid
,
765 (VOID
**)&EsrtManagement
767 if (!EFI_ERROR (Status
)) {
768 EsrtManagement
->SyncEsrtFmp ();
772 // Find all capsule images from hob
774 HobPointer
.Raw
= GetHobList ();
776 while ((HobPointer
.Raw
= GetNextHob (
777 EFI_HOB_TYPE_UEFI_CAPSULE
,
781 CapsuleHeader
= (VOID
*)(UINTN
)HobPointer
.Capsule
->BaseAddress
;
783 Status
= ProcessCapsuleImage (CapsuleHeader
);
784 if (EFI_ERROR (Status
)) {
787 "%a: failed to process capsule %p - %r\n",
796 HobPointer
.Raw
= GET_NEXT_HOB (HobPointer
);
802 "%a: capsule update successful, resetting ...\n",
806 gRT
->ResetSystem (EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
811 #define VERSION_STRING_PREFIX L"Tianocore/EDK2 firmware version "
814 This functions checks the value of BootDiscoverPolicy variable and
815 connect devices of class specified by that variable. Then it refreshes
816 Boot order for newly discovered boot device.
818 @retval EFI_SUCCESS Devices connected successfully or connection
820 @retval others Return values from GetVariable(), LocateProtocol()
821 and ConnectDeviceClass().
825 BootDiscoveryPolicyHandler (
830 UINT32 DiscoveryPolicy
;
831 UINT32 DiscoveryPolicyOld
;
833 EFI_BOOT_MANAGER_POLICY_PROTOCOL
*BMPolicy
;
836 Size
= sizeof (DiscoveryPolicy
);
837 Status
= gRT
->GetVariable (
838 BOOT_DISCOVERY_POLICY_VAR
,
839 &gBootDiscoveryPolicyMgrFormsetGuid
,
844 if (Status
== EFI_NOT_FOUND
) {
845 DiscoveryPolicy
= PcdGet32 (PcdBootDiscoveryPolicy
);
846 Status
= PcdSet32S (PcdBootDiscoveryPolicy
, DiscoveryPolicy
);
847 if (Status
== EFI_NOT_FOUND
) {
849 } else if (EFI_ERROR (Status
)) {
852 } else if (EFI_ERROR (Status
)) {
856 if (DiscoveryPolicy
== BDP_CONNECT_MINIMAL
) {
860 switch (DiscoveryPolicy
) {
861 case BDP_CONNECT_NET
:
862 Class
= &gEfiBootManagerPolicyNetworkGuid
;
864 case BDP_CONNECT_ALL
:
865 Class
= &gEfiBootManagerPolicyConnectAllGuid
;
870 "%a - Unexpected DiscoveryPolicy (0x%x). Run Minimal Discovery Policy\n",
877 Status
= gBS
->LocateProtocol (
878 &gEfiBootManagerPolicyProtocolGuid
,
882 if (EFI_ERROR (Status
)) {
885 "%a - Failed to locate gEfiBootManagerPolicyProtocolGuid."
886 "Driver connect will be skipped.\n",
892 Status
= BMPolicy
->ConnectDeviceClass (BMPolicy
, Class
);
893 if (EFI_ERROR (Status
)) {
894 DEBUG ((DEBUG_ERROR
, "%a - ConnectDeviceClass returns - %r\n", __FUNCTION__
, Status
));
899 // Refresh Boot Options if Boot Discovery Policy has been changed
901 Size
= sizeof (DiscoveryPolicyOld
);
902 Status
= gRT
->GetVariable (
903 BOOT_DISCOVERY_POLICY_OLD_VAR
,
904 &gBootDiscoveryPolicyMgrFormsetGuid
,
909 if ((Status
== EFI_NOT_FOUND
) || (DiscoveryPolicyOld
!= DiscoveryPolicy
)) {
910 EfiBootManagerRefreshAllBootOption ();
912 Status
= gRT
->SetVariable (
913 BOOT_DISCOVERY_POLICY_OLD_VAR
,
914 &gBootDiscoveryPolicyMgrFormsetGuid
,
915 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
916 sizeof (DiscoveryPolicyOld
),
925 Do the platform specific action after the console is ready
926 Possible things that can be done in PlatformBootManagerAfterConsole:
927 > Console post action:
928 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
929 > Signal console ready platform customized event
930 > Run diagnostics like memory testing
931 > Connect certain devices
932 > Dispatch additional option roms
933 > Special boot: e.g.: USB boot, enter UI
937 PlatformBootManagerAfterConsole (
942 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
943 UINTN FirmwareVerLength
;
948 FirmwareVerLength
= StrLen (PcdGetPtr (PcdFirmwareVersionString
));
951 // Show the splash screen.
953 Status
= BootLogoEnableLogo ();
954 if (EFI_ERROR (Status
)) {
955 if (FirmwareVerLength
> 0) {
957 VERSION_STRING_PREFIX L
"%s\n",
958 PcdGetPtr (PcdFirmwareVersionString
)
962 Print (L
"Press ESCAPE for boot options ");
963 } else if (FirmwareVerLength
> 0) {
964 Status
= gBS
->HandleProtocol (
965 gST
->ConsoleOutHandle
,
966 &gEfiGraphicsOutputProtocolGuid
,
967 (VOID
**)&GraphicsOutput
969 if (!EFI_ERROR (Status
)) {
970 PosX
= (GraphicsOutput
->Mode
->Info
->HorizontalResolution
-
971 (StrLen (VERSION_STRING_PREFIX
) + FirmwareVerLength
) *
972 EFI_GLYPH_WIDTH
) / 2;
980 VERSION_STRING_PREFIX L
"%s",
981 PcdGetPtr (PcdFirmwareVersionString
)
987 // Connect device specified by BootDiscoverPolicy variable and
988 // refresh Boot order for newly discovered boot devices
990 BootDiscoveryPolicyHandler ();
993 // On ARM, there is currently no reason to use the phased capsule
994 // update approach where some capsules are dispatched before EndOfDxe
995 // and some are dispatched after. So just handle all capsules here,
996 // when the console is up and we can actually give the user some
997 // feedback about what is going on.
1002 // Register UEFI Shell
1004 Key
.ScanCode
= SCAN_NULL
;
1005 Key
.UnicodeChar
= L
's';
1006 PlatformRegisterFvBootOption (&gUefiShellFileGuid
, L
"UEFI Shell", 0, &Key
);
1010 This function is called each second during the boot manager waits the
1013 @param TimeoutRemain The remaining timeout.
1017 PlatformBootManagerWaitCallback (
1018 UINT16 TimeoutRemain
1021 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
1022 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
1026 Timeout
= PcdGet16 (PcdPlatformBootTimeOut
);
1028 Black
.Raw
= 0x00000000;
1029 White
.Raw
= 0x00FFFFFF;
1031 Status
= BootLogoUpdateProgress (
1034 L
"Press ESCAPE for boot options",
1036 (Timeout
- TimeoutRemain
) * 100 / Timeout
,
1039 if (EFI_ERROR (Status
)) {
1045 The function is called when no boot option could be launched,
1046 including platform recovery options and options pointing to applications
1047 built into firmware volumes.
1049 If this function returns, BDS attempts to enter an infinite loop.
1053 PlatformBootManagerUnableToBoot (
1058 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
1059 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
1060 UINTN OldBootOptionCount
;
1061 UINTN NewBootOptionCount
;
1064 // Record the total number of boot configured boot options
1066 BootOptions
= EfiBootManagerGetLoadOptions (
1067 &OldBootOptionCount
,
1070 EfiBootManagerFreeLoadOptions (BootOptions
, OldBootOptionCount
);
1073 // Connect all devices, and regenerate all boot options
1075 EfiBootManagerConnectAll ();
1076 EfiBootManagerRefreshAllBootOption ();
1079 // Record the updated number of boot configured boot options
1081 BootOptions
= EfiBootManagerGetLoadOptions (
1082 &NewBootOptionCount
,
1085 EfiBootManagerFreeLoadOptions (BootOptions
, NewBootOptionCount
);
1088 // If the number of configured boot options has changed, reboot
1089 // the system so the new boot options will be taken into account
1090 // while executing the ordinary BDS bootflow sequence.
1091 // *Unless* persistent varstore is being emulated, since we would
1092 // then end up in an endless reboot loop.
1094 if (!PcdGetBool (PcdEmuVariableNvModeEnable
)) {
1095 if (NewBootOptionCount
!= OldBootOptionCount
) {
1098 "%a: rebooting after refreshing all boot options\n",
1101 gRT
->ResetSystem (EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
1105 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
1106 if (EFI_ERROR (Status
)) {
1111 EfiBootManagerBoot (&BootManagerMenu
);