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
)
97 USB_CLASS_DEVICE_PATH Keyboard
;
98 EFI_DEVICE_PATH_PROTOCOL End
;
99 } PLATFORM_USB_KEYBOARD
;
102 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard
= {
104 // USB_CLASS_DEVICE_PATH Keyboard
108 MESSAGING_DEVICE_PATH
, MSG_USB_CLASS_DP
,
109 DP_NODE_LEN (USB_CLASS_DEVICE_PATH
)
111 0xFFFF, // VendorId: any
112 0xFFFF, // ProductId: any
113 3, // DeviceClass: HID
114 1, // DeviceSubClass: boot
115 1 // DeviceProtocol: keyboard
119 // EFI_DEVICE_PATH_PROTOCOL End
122 END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
,
123 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL
)
129 Check if the handle satisfies a particular condition.
131 @param[in] Handle The handle to check.
132 @param[in] ReportText A caller-allocated string passed in for reporting
133 purposes. It must never be NULL.
135 @retval TRUE The condition is satisfied.
136 @retval FALSE Otherwise. This includes the case when the condition could not
137 be fully evaluated due to an error.
141 (EFIAPI
*FILTER_FUNCTION
) (
142 IN EFI_HANDLE Handle
,
143 IN CONST CHAR16
*ReportText
150 @param[in] Handle The handle to process.
151 @param[in] ReportText A caller-allocated string passed in for reporting
152 purposes. It must never be NULL.
156 (EFIAPI
*CALLBACK_FUNCTION
) (
157 IN EFI_HANDLE Handle
,
158 IN CONST CHAR16
*ReportText
162 Locate all handles that carry the specified protocol, filter them with a
163 callback function, and pass each handle that passes the filter to another
166 @param[in] ProtocolGuid The protocol to look for.
168 @param[in] Filter The filter function to pass each handle to. If this
169 parameter is NULL, then all handles are processed.
171 @param[in] Process The callback function to pass each handle to that
177 IN EFI_GUID
*ProtocolGuid
,
178 IN FILTER_FUNCTION Filter OPTIONAL
,
179 IN CALLBACK_FUNCTION Process
187 Status
= gBS
->LocateHandleBuffer (ByProtocol
, ProtocolGuid
,
188 NULL
/* SearchKey */, &NoHandles
, &Handles
);
189 if (EFI_ERROR (Status
)) {
191 // This is not an error, just an informative condition.
193 DEBUG ((EFI_D_VERBOSE
, "%a: %g: %r\n", __FUNCTION__
, ProtocolGuid
,
198 ASSERT (NoHandles
> 0);
199 for (Idx
= 0; Idx
< NoHandles
; ++Idx
) {
200 CHAR16
*DevicePathText
;
201 STATIC CHAR16 Fallback
[] = L
"<device path unavailable>";
204 // The ConvertDevicePathToText() function handles NULL input transparently.
206 DevicePathText
= ConvertDevicePathToText (
207 DevicePathFromHandle (Handles
[Idx
]),
208 FALSE
, // DisplayOnly
209 FALSE
// AllowShortcuts
211 if (DevicePathText
== NULL
) {
212 DevicePathText
= Fallback
;
215 if (Filter
== NULL
|| Filter (Handles
[Idx
], DevicePathText
)) {
216 Process (Handles
[Idx
], DevicePathText
);
219 if (DevicePathText
!= Fallback
) {
220 FreePool (DevicePathText
);
223 gBS
->FreePool (Handles
);
228 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
234 IN EFI_HANDLE Handle
,
235 IN CONST CHAR16
*ReportText
239 EFI_PCI_IO_PROTOCOL
*PciIo
;
242 Status
= gBS
->HandleProtocol (Handle
, &gEfiPciIoProtocolGuid
,
244 if (EFI_ERROR (Status
)) {
246 // This is not an error worth reporting.
251 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, 0 /* Offset */,
252 sizeof Pci
/ sizeof (UINT32
), &Pci
);
253 if (EFI_ERROR (Status
)) {
254 DEBUG ((EFI_D_ERROR
, "%a: %s: %r\n", __FUNCTION__
, ReportText
, Status
));
258 return IS_PCI_DISPLAY (&Pci
);
263 This FILTER_FUNCTION checks if a handle corresponds to a non-discoverable
270 IN EFI_HANDLE Handle
,
271 IN CONST CHAR16
*ReportText
274 NON_DISCOVERABLE_DEVICE
*Device
;
277 Status
= gBS
->HandleProtocol (Handle
,
278 &gEdkiiNonDiscoverableDeviceProtocolGuid
,
280 if (EFI_ERROR (Status
)) {
284 if (CompareGuid (Device
->Type
, &gEdkiiNonDiscoverableUhciDeviceGuid
) ||
285 CompareGuid (Device
->Type
, &gEdkiiNonDiscoverableEhciDeviceGuid
) ||
286 CompareGuid (Device
->Type
, &gEdkiiNonDiscoverableXhciDeviceGuid
)) {
294 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
295 the matching driver to produce all first-level child handles.
301 IN EFI_HANDLE Handle
,
302 IN CONST CHAR16
*ReportText
307 Status
= gBS
->ConnectController (
308 Handle
, // ControllerHandle
309 NULL
, // DriverImageHandle
310 NULL
, // RemainingDevicePath -- produce all children
313 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
, "%a: %s: %r\n",
314 __FUNCTION__
, ReportText
, Status
));
319 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
320 handle, and adds it to ConOut and ErrOut.
326 IN EFI_HANDLE Handle
,
327 IN CONST CHAR16
*ReportText
331 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
333 DevicePath
= DevicePathFromHandle (Handle
);
334 if (DevicePath
== NULL
) {
335 DEBUG ((EFI_D_ERROR
, "%a: %s: handle %p: device path not found\n",
336 __FUNCTION__
, ReportText
, Handle
));
340 Status
= EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
341 if (EFI_ERROR (Status
)) {
342 DEBUG ((EFI_D_ERROR
, "%a: %s: adding to ConOut: %r\n", __FUNCTION__
,
343 ReportText
, Status
));
347 Status
= EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
348 if (EFI_ERROR (Status
)) {
349 DEBUG ((EFI_D_ERROR
, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__
,
350 ReportText
, Status
));
354 DEBUG ((EFI_D_VERBOSE
, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__
,
360 PlatformRegisterFvBootOption (
361 CONST EFI_GUID
*FileGuid
,
369 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
370 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
371 UINTN BootOptionCount
;
372 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
373 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
374 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
376 Status
= gBS
->HandleProtocol (
378 &gEfiLoadedImageProtocolGuid
,
379 (VOID
**) &LoadedImage
381 ASSERT_EFI_ERROR (Status
);
383 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
384 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
385 ASSERT (DevicePath
!= NULL
);
386 DevicePath
= AppendDevicePathNode (
388 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
390 ASSERT (DevicePath
!= NULL
);
392 Status
= EfiBootManagerInitializeLoadOption (
394 LoadOptionNumberUnassigned
,
402 ASSERT_EFI_ERROR (Status
);
403 FreePool (DevicePath
);
405 BootOptions
= EfiBootManagerGetLoadOptions (
406 &BootOptionCount
, LoadOptionTypeBoot
409 OptionIndex
= EfiBootManagerFindLoadOption (
410 &NewOption
, BootOptions
, BootOptionCount
413 if (OptionIndex
== -1) {
414 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
415 ASSERT_EFI_ERROR (Status
);
416 Status
= EfiBootManagerAddKeyOptionVariable (NULL
,
417 (UINT16
)NewOption
.OptionNumber
, 0, Key
, NULL
);
418 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
420 EfiBootManagerFreeLoadOption (&NewOption
);
421 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
432 EFI_BOOT_MANAGER_LOAD_OPTION
*CurrentBootOptions
;
433 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
434 EFI_INPUT_KEY
*BootKeys
;
435 PLATFORM_BOOT_MANAGER_PROTOCOL
*PlatformBootManager
;
436 UINTN CurrentBootOptionCount
;
440 Status
= gBS
->LocateProtocol (&gPlatformBootManagerProtocolGuid
, NULL
,
441 (VOID
**)&PlatformBootManager
);
442 if (EFI_ERROR (Status
)) {
445 Status
= PlatformBootManager
->GetPlatformBootOptionsAndKeys (
450 if (EFI_ERROR (Status
)) {
454 // Fetch the existent boot options. If there are none, CurrentBootCount
457 CurrentBootOptions
= EfiBootManagerGetLoadOptions (
458 &CurrentBootOptionCount
,
462 // Process the platform boot options.
464 for (Index
= 0; Index
< BootCount
; Index
++) {
466 UINTN BootOptionNumber
;
469 // If there are any preexistent boot options, and the subject platform boot
470 // option is already among them, then don't try to add it. Just get its
471 // assigned boot option number so we can associate a hotkey with it. Note
472 // that EfiBootManagerFindLoadOption() deals fine with (CurrentBootOptions
473 // == NULL) if (CurrentBootCount == 0).
475 Match
= EfiBootManagerFindLoadOption (
478 CurrentBootOptionCount
481 BootOptionNumber
= CurrentBootOptions
[Match
].OptionNumber
;
484 // Add the platform boot options as a new one, at the end of the boot
485 // order. Note that if the platform provided this boot option with an
486 // unassigned option number, then the below function call will assign a
489 Status
= EfiBootManagerAddLoadOptionVariable (
493 if (EFI_ERROR (Status
)) {
494 DEBUG ((DEBUG_ERROR
, "%a: failed to register \"%s\": %r\n",
495 __FUNCTION__
, BootOptions
[Index
].Description
, Status
));
498 BootOptionNumber
= BootOptions
[Index
].OptionNumber
;
502 // Register a hotkey with the boot option, if requested.
504 if (BootKeys
[Index
].UnicodeChar
== L
'\0') {
508 Status
= EfiBootManagerAddKeyOptionVariable (
515 if (EFI_ERROR (Status
)) {
516 DEBUG ((DEBUG_ERROR
, "%a: failed to register hotkey for \"%s\": %r\n",
517 __FUNCTION__
, BootOptions
[Index
].Description
, Status
));
520 EfiBootManagerFreeLoadOptions (CurrentBootOptions
, CurrentBootOptionCount
);
521 EfiBootManagerFreeLoadOptions (BootOptions
, BootCount
);
527 PlatformRegisterOptionsAndKeys (
535 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
537 GetPlatformOptions ();
540 // Register ENTER as CONTINUE key
542 Enter
.ScanCode
= SCAN_NULL
;
543 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
544 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
545 ASSERT_EFI_ERROR (Status
);
548 // Map F2 and ESC to Boot Manager Menu
550 F2
.ScanCode
= SCAN_F2
;
551 F2
.UnicodeChar
= CHAR_NULL
;
552 Esc
.ScanCode
= SCAN_ESC
;
553 Esc
.UnicodeChar
= CHAR_NULL
;
554 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
555 ASSERT_EFI_ERROR (Status
);
556 Status
= EfiBootManagerAddKeyOptionVariable (
557 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
559 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
560 Status
= EfiBootManagerAddKeyOptionVariable (
561 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
563 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
568 // BDS Platform Functions
571 Do the platform init, can be customized by OEM/IBV
572 Possible things that can be done in PlatformBootManagerBeforeConsole:
573 > Update console variable: 1. include hot-plug devices;
574 > 2. Clear ConIn and add SOL for AMT
575 > Register new Driver#### or Boot####
576 > Register new Key####: e.g.: F12
577 > Signal ReadyToLock event
578 > Authentication action: 1. connect Auth devices;
579 > 2. Identify auto logon user.
583 PlatformBootManagerBeforeConsole (
588 // Signal EndOfDxe PI Event
590 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
593 // Dispatch deferred images after EndOfDxe event.
595 EfiBootManagerDispatchDeferredImages ();
598 // Locate the PCI root bridges and make the PCI bus driver connect each,
599 // non-recursively. This will produce a number of child handles with PciIo on
602 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid
, NULL
, Connect
);
605 // Find all display class PCI devices (using the handles from the previous
606 // step), and connect them non-recursively. This should produce a number of
607 // child handles with GOPs on them.
609 FilterAndProcess (&gEfiPciIoProtocolGuid
, IsPciDisplay
, Connect
);
612 // Now add the device path of all handles with GOP on them to ConOut and
615 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid
, NULL
, AddOutput
);
618 // The core BDS code connects short-form USB device paths by explicitly
619 // looking for handles with PCI I/O installed, and checking the PCI class
620 // code whether it matches the one for a USB host controller. This means
621 // non-discoverable USB host controllers need to have the non-discoverable
622 // PCI driver attached first.
624 FilterAndProcess (&gEdkiiNonDiscoverableDeviceProtocolGuid
, IsUsbHost
, Connect
);
627 // Add the hardcoded short-form USB keyboard device path to ConIn.
629 EfiBootManagerUpdateConsoleVariable (ConIn
,
630 (EFI_DEVICE_PATH_PROTOCOL
*)&mUsbKeyboard
, NULL
);
633 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
635 STATIC_ASSERT (FixedPcdGet8 (PcdDefaultTerminalType
) == 4,
636 "PcdDefaultTerminalType must be TTYTERM");
637 STATIC_ASSERT (FixedPcdGet8 (PcdUartDefaultParity
) != 0,
638 "PcdUartDefaultParity must be set to an actual value, not 'default'");
639 STATIC_ASSERT (FixedPcdGet8 (PcdUartDefaultStopBits
) != 0,
640 "PcdUartDefaultStopBits must be set to an actual value, not 'default'");
642 CopyGuid (&mSerialConsole
.TermType
.Guid
, &gEfiTtyTermGuid
);
644 EfiBootManagerUpdateConsoleVariable (ConIn
,
645 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
646 EfiBootManagerUpdateConsoleVariable (ConOut
,
647 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
648 EfiBootManagerUpdateConsoleVariable (ErrOut
,
649 (EFI_DEVICE_PATH_PROTOCOL
*)&mSerialConsole
, NULL
);
652 // Register platform-specific boot options and keyboard shortcuts.
654 PlatformRegisterOptionsAndKeys ();
663 ESRT_MANAGEMENT_PROTOCOL
*EsrtManagement
;
664 EFI_PEI_HOB_POINTERS HobPointer
;
665 EFI_CAPSULE_HEADER
*CapsuleHeader
;
669 DEBUG ((DEBUG_INFO
, "%a: processing capsules ...\n", __FUNCTION__
));
671 Status
= gBS
->LocateProtocol (&gEsrtManagementProtocolGuid
, NULL
,
672 (VOID
**)&EsrtManagement
);
673 if (!EFI_ERROR (Status
)) {
674 EsrtManagement
->SyncEsrtFmp ();
678 // Find all capsule images from hob
680 HobPointer
.Raw
= GetHobList ();
682 while ((HobPointer
.Raw
= GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE
,
683 HobPointer
.Raw
)) != NULL
) {
684 CapsuleHeader
= (VOID
*)(UINTN
)HobPointer
.Capsule
->BaseAddress
;
686 Status
= ProcessCapsuleImage (CapsuleHeader
);
687 if (EFI_ERROR (Status
)) {
688 DEBUG ((DEBUG_ERROR
, "%a: failed to process capsule %p - %r\n",
689 __FUNCTION__
, CapsuleHeader
, Status
));
694 HobPointer
.Raw
= GET_NEXT_HOB (HobPointer
);
698 DEBUG ((DEBUG_WARN
, "%a: capsule update successful, resetting ...\n",
701 gRT
->ResetSystem (EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
707 #define VERSION_STRING_PREFIX L"Tianocore/EDK2 firmware version "
710 This functions checks the value of BootDiscoverPolicy variable and
711 connect devices of class specified by that variable. Then it refreshes
712 Boot order for newly discovered boot device.
714 @retval EFI_SUCCESS Devices connected successfully or connection
716 @retval others Return values from GetVariable(), LocateProtocol()
717 and ConnectDeviceClass().
721 BootDiscoveryPolicyHandler (
726 UINT32 DiscoveryPolicy
;
727 UINT32 DiscoveryPolicyOld
;
729 EFI_BOOT_MANAGER_POLICY_PROTOCOL
*BMPolicy
;
732 Size
= sizeof (DiscoveryPolicy
);
733 Status
= gRT
->GetVariable (
734 BOOT_DISCOVERY_POLICY_VAR
,
735 &gBootDiscoveryPolicyMgrFormsetGuid
,
740 if (Status
== EFI_NOT_FOUND
) {
741 DiscoveryPolicy
= PcdGet32 (PcdBootDiscoveryPolicy
);
742 Status
= PcdSet32S (PcdBootDiscoveryPolicy
, DiscoveryPolicy
);
743 if (Status
== EFI_NOT_FOUND
) {
745 } else if (EFI_ERROR (Status
)) {
748 } else if (EFI_ERROR (Status
)) {
752 if (DiscoveryPolicy
== BDP_CONNECT_MINIMAL
) {
756 switch (DiscoveryPolicy
) {
757 case BDP_CONNECT_NET
:
758 Class
= &gEfiBootManagerPolicyNetworkGuid
;
760 case BDP_CONNECT_ALL
:
761 Class
= &gEfiBootManagerPolicyConnectAllGuid
;
766 "%a - Unexpected DiscoveryPolicy (0x%x). Run Minimal Discovery Policy\n",
773 Status
= gBS
->LocateProtocol (
774 &gEfiBootManagerPolicyProtocolGuid
,
778 if (EFI_ERROR (Status
)) {
779 DEBUG ((DEBUG_INFO
, "%a - Failed to locate gEfiBootManagerPolicyProtocolGuid."
780 "Driver connect will be skipped.\n", __FUNCTION__
));
784 Status
= BMPolicy
->ConnectDeviceClass (BMPolicy
, Class
);
785 if (EFI_ERROR (Status
)){
786 DEBUG ((DEBUG_ERROR
, "%a - ConnectDeviceClass returns - %r\n", __FUNCTION__
, Status
));
791 // Refresh Boot Options if Boot Discovery Policy has been changed
793 Size
= sizeof (DiscoveryPolicyOld
);
794 Status
= gRT
->GetVariable (
795 BOOT_DISCOVERY_POLICY_OLD_VAR
,
796 &gBootDiscoveryPolicyMgrFormsetGuid
,
801 if ((Status
== EFI_NOT_FOUND
) || (DiscoveryPolicyOld
!= DiscoveryPolicy
)) {
802 EfiBootManagerRefreshAllBootOption ();
804 Status
= gRT
->SetVariable (
805 BOOT_DISCOVERY_POLICY_OLD_VAR
,
806 &gBootDiscoveryPolicyMgrFormsetGuid
,
807 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
808 sizeof (DiscoveryPolicyOld
),
817 Do the platform specific action after the console is ready
818 Possible things that can be done in PlatformBootManagerAfterConsole:
819 > Console post action:
820 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
821 > Signal console ready platform customized event
822 > Run diagnostics like memory testing
823 > Connect certain devices
824 > Dispatch additional option roms
825 > Special boot: e.g.: USB boot, enter UI
829 PlatformBootManagerAfterConsole (
834 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
835 UINTN FirmwareVerLength
;
840 FirmwareVerLength
= StrLen (PcdGetPtr (PcdFirmwareVersionString
));
843 // Show the splash screen.
845 Status
= BootLogoEnableLogo ();
846 if (EFI_ERROR (Status
)) {
847 if (FirmwareVerLength
> 0) {
848 Print (VERSION_STRING_PREFIX L
"%s\n",
849 PcdGetPtr (PcdFirmwareVersionString
));
851 Print (L
"Press ESCAPE for boot options ");
852 } else if (FirmwareVerLength
> 0) {
853 Status
= gBS
->HandleProtocol (gST
->ConsoleOutHandle
,
854 &gEfiGraphicsOutputProtocolGuid
, (VOID
**)&GraphicsOutput
);
855 if (!EFI_ERROR (Status
)) {
856 PosX
= (GraphicsOutput
->Mode
->Info
->HorizontalResolution
-
857 (StrLen (VERSION_STRING_PREFIX
) + FirmwareVerLength
) *
858 EFI_GLYPH_WIDTH
) / 2;
861 PrintXY (PosX
, PosY
, NULL
, NULL
, VERSION_STRING_PREFIX L
"%s",
862 PcdGetPtr (PcdFirmwareVersionString
));
867 // Connect device specified by BootDiscoverPolicy variable and
868 // refresh Boot order for newly discovered boot devices
870 BootDiscoveryPolicyHandler ();
873 // On ARM, there is currently no reason to use the phased capsule
874 // update approach where some capsules are dispatched before EndOfDxe
875 // and some are dispatched after. So just handle all capsules here,
876 // when the console is up and we can actually give the user some
877 // feedback about what is going on.
882 // Register UEFI Shell
884 Key
.ScanCode
= SCAN_NULL
;
885 Key
.UnicodeChar
= L
's';
886 PlatformRegisterFvBootOption (&gUefiShellFileGuid
, L
"UEFI Shell", 0, &Key
);
890 This function is called each second during the boot manager waits the
893 @param TimeoutRemain The remaining timeout.
897 PlatformBootManagerWaitCallback (
901 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
902 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
906 Timeout
= PcdGet16 (PcdPlatformBootTimeOut
);
908 Black
.Raw
= 0x00000000;
909 White
.Raw
= 0x00FFFFFF;
911 Status
= BootLogoUpdateProgress (
914 L
"Press ESCAPE for boot options",
916 (Timeout
- TimeoutRemain
) * 100 / Timeout
,
919 if (EFI_ERROR (Status
)) {
925 The function is called when no boot option could be launched,
926 including platform recovery options and options pointing to applications
927 built into firmware volumes.
929 If this function returns, BDS attempts to enter an infinite loop.
933 PlatformBootManagerUnableToBoot (
938 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
939 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
940 UINTN OldBootOptionCount
;
941 UINTN NewBootOptionCount
;
944 // Record the total number of boot configured boot options
946 BootOptions
= EfiBootManagerGetLoadOptions (&OldBootOptionCount
,
948 EfiBootManagerFreeLoadOptions (BootOptions
, OldBootOptionCount
);
951 // Connect all devices, and regenerate all boot options
953 EfiBootManagerConnectAll ();
954 EfiBootManagerRefreshAllBootOption ();
957 // Record the updated number of boot configured boot options
959 BootOptions
= EfiBootManagerGetLoadOptions (&NewBootOptionCount
,
961 EfiBootManagerFreeLoadOptions (BootOptions
, NewBootOptionCount
);
964 // If the number of configured boot options has changed, reboot
965 // the system so the new boot options will be taken into account
966 // while executing the ordinary BDS bootflow sequence.
967 // *Unless* persistent varstore is being emulated, since we would
968 // then end up in an endless reboot loop.
970 if (!PcdGetBool (PcdEmuVariableNvModeEnable
)) {
971 if (NewBootOptionCount
!= OldBootOptionCount
) {
972 DEBUG ((DEBUG_WARN
, "%a: rebooting after refreshing all boot options\n",
974 gRT
->ResetSystem (EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
978 Status
= EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
979 if (EFI_ERROR (Status
)) {
984 EfiBootManagerBoot (&BootManagerMenu
);