2 This file include all platform action which can be customized
5 Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "PlatformBootManager.h"
11 #include "PlatformConsole.h"
12 #include <Protocol/PlatformBootManagerOverride.h>
13 #include <Guid/BootManagerMenu.h>
14 #include <Library/HobLib.h>
16 UNIVERSAL_PAYLOAD_PLATFORM_BOOT_MANAGER_OVERRIDE_PROTOCOL
*mUniversalPayloadPlatformBootManagerOverrideInstance
= NULL
;
25 EFI_SMM_ACCESS2_PROTOCOL
*SmmAccess
;
27 DEBUG((DEBUG_INFO
,"InstallReadyToLock entering......\n"));
29 // Inform the SMM infrastructure that we're entering BDS and may run 3rd party code hereafter
30 // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth
32 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
33 DEBUG((DEBUG_INFO
,"All EndOfDxe callbacks have returned successfully\n"));
36 // Install DxeSmmReadyToLock protocol in order to lock SMM
38 Status
= gBS
->LocateProtocol (&gEfiSmmAccess2ProtocolGuid
, NULL
, (VOID
**) &SmmAccess
);
39 if (!EFI_ERROR (Status
)) {
41 Status
= gBS
->InstallProtocolInterface (
43 &gEfiDxeSmmReadyToLockProtocolGuid
,
47 ASSERT_EFI_ERROR (Status
);
50 DEBUG((DEBUG_INFO
,"InstallReadyToLock end\n"));
55 Return the index of the load option in the load option array.
57 The function consider two load options are equal when the
58 OptionType, Attributes, Description, FilePath and OptionalData are equal.
60 @param Key Pointer to the load option to be found.
61 @param Array Pointer to the array of load options to be found.
62 @param Count Number of entries in the Array.
64 @retval -1 Key wasn't found in the Array.
65 @retval 0 ~ Count-1 The index of the Key in the Array.
68 PlatformFindLoadOption (
69 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION
*Key
,
70 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION
*Array
,
76 for (Index
= 0; Index
< Count
; Index
++) {
77 if ((Key
->OptionType
== Array
[Index
].OptionType
) &&
78 (Key
->Attributes
== Array
[Index
].Attributes
) &&
79 (StrCmp (Key
->Description
, Array
[Index
].Description
) == 0) &&
80 (CompareMem (Key
->FilePath
, Array
[Index
].FilePath
, GetDevicePathSize (Key
->FilePath
)) == 0) &&
81 (Key
->OptionalDataSize
== Array
[Index
].OptionalDataSize
) &&
82 (CompareMem (Key
->OptionalData
, Array
[Index
].OptionalData
, Key
->OptionalDataSize
) == 0)) {
91 Register a boot option using a file GUID in the FV.
93 @param FileGuid The file GUID name in FV.
94 @param Description The boot option description.
95 @param Attributes The attributes used for the boot option loading.
98 PlatformRegisterFvBootOption (
106 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
107 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
108 UINTN BootOptionCount
;
109 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
110 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
111 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
113 Status
= gBS
->HandleProtocol (gImageHandle
, &gEfiLoadedImageProtocolGuid
, (VOID
**) &LoadedImage
);
114 ASSERT_EFI_ERROR (Status
);
116 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
117 DevicePath
= AppendDevicePathNode (
118 DevicePathFromHandle (LoadedImage
->DeviceHandle
),
119 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
122 Status
= EfiBootManagerInitializeLoadOption (
124 LoadOptionNumberUnassigned
,
132 if (!EFI_ERROR (Status
)) {
133 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
, LoadOptionTypeBoot
);
135 OptionIndex
= PlatformFindLoadOption (&NewOption
, BootOptions
, BootOptionCount
);
137 if (OptionIndex
== -1) {
138 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, (UINTN
) -1);
139 ASSERT_EFI_ERROR (Status
);
141 EfiBootManagerFreeLoadOption (&NewOption
);
142 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
147 Do the platform specific action before the console is connected.
150 Update console variable;
151 Register new Driver#### or Boot####;
152 Signal ReadyToLock event.
156 PlatformBootManagerBeforeConsole (
163 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
166 Status
= gBS
->LocateProtocol (&gUniversalPayloadPlatformBootManagerOverrideProtocolGuid
, NULL
, (VOID
**) &mUniversalPayloadPlatformBootManagerOverrideInstance
);
167 if (EFI_ERROR (Status
)) {
168 mUniversalPayloadPlatformBootManagerOverrideInstance
= NULL
;
170 if (mUniversalPayloadPlatformBootManagerOverrideInstance
!= NULL
){
171 mUniversalPayloadPlatformBootManagerOverrideInstance
->BeforeConsole();
176 // Register ENTER as CONTINUE key
178 Enter
.ScanCode
= SCAN_NULL
;
179 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
180 EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
183 // Map F2 to Boot Manager Menu
185 F2
.ScanCode
= SCAN_F2
;
186 F2
.UnicodeChar
= CHAR_NULL
;
187 EfiBootManagerGetBootManagerMenu (&BootOption
);
188 EfiBootManagerAddKeyOptionVariable (NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
);
191 // Also add Down key to Boot Manager Menu since some serial terminals don't support F2 key.
193 Down
.ScanCode
= SCAN_DOWN
;
194 Down
.UnicodeChar
= CHAR_NULL
;
195 EfiBootManagerGetBootManagerMenu (&BootOption
);
196 EfiBootManagerAddKeyOptionVariable (NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Down
, NULL
);
199 // Install ready to lock.
200 // This needs to be done before option rom dispatched.
202 InstallReadyToLock ();
205 // Dispatch deferred images after EndOfDxe event and ReadyToLock installation.
207 EfiBootManagerDispatchDeferredImages ();
209 PlatformConsoleInit ();
213 Do the platform specific action after the console is connected.
216 Dynamically switch output mode;
217 Signal console ready platform customized event;
218 Run diagnostics like memory testing;
219 Connect certain devices;
220 Dispatch additional option roms.
224 PlatformBootManagerAfterConsole (
228 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black
;
229 EFI_GRAPHICS_OUTPUT_BLT_PIXEL White
;
231 if (mUniversalPayloadPlatformBootManagerOverrideInstance
!= NULL
){
232 mUniversalPayloadPlatformBootManagerOverrideInstance
->AfterConsole();
235 Black
.Blue
= Black
.Green
= Black
.Red
= Black
.Reserved
= 0;
236 White
.Blue
= White
.Green
= White
.Red
= White
.Reserved
= 0xFF;
238 EfiBootManagerConnectAll ();
239 EfiBootManagerRefreshAllBootOption ();
242 // Register UEFI Shell
244 PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile
), L
"UEFI Shell", LOAD_OPTION_ACTIVE
);
248 L
"F2 or Down to enter Boot Manager Menu.\n"
249 L
"ENTER to boot directly.\n"
256 This function is called each second during the boot manager waits the timeout.
258 @param TimeoutRemain The remaining timeout.
262 PlatformBootManagerWaitCallback (
266 if (mUniversalPayloadPlatformBootManagerOverrideInstance
!= NULL
){
267 mUniversalPayloadPlatformBootManagerOverrideInstance
->WaitCallback (TimeoutRemain
);
273 The function is called when no boot option could be launched,
274 including platform recovery options and options pointing to applications
275 built into firmware volumes.
277 If this function returns, BDS attempts to enter an infinite loop.
281 PlatformBootManagerUnableToBoot (
285 if (mUniversalPayloadPlatformBootManagerOverrideInstance
!= NULL
){
286 mUniversalPayloadPlatformBootManagerOverrideInstance
->UnableToBoot();
292 Get/update PcdBootManagerMenuFile from GUID HOB which will be assigned in bootloader.
294 @param ImageHandle The firmware allocated handle for the EFI image.
295 @param SystemTable A pointer to the EFI System Table.
297 @retval EFI_SUCCESS The entry point is executed successfully.
298 @retval other Some error occurs.
303 PlatformBootManagerLibConstructor (
304 IN EFI_HANDLE ImageHandle
,
305 IN EFI_SYSTEM_TABLE
*SystemTable
311 UNIVERSAL_PAYLOAD_GENERIC_HEADER
*GenericHeader
;
312 UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU
*BootManagerMenuFile
;
314 GuidHob
= GetFirstGuidHob (&gEdkiiBootManagerMenuFileGuid
);
316 if (GuidHob
== NULL
) {
318 // If the HOB is not create, the default value of PcdBootManagerMenuFile will be used.
323 GenericHeader
= (UNIVERSAL_PAYLOAD_GENERIC_HEADER
*) GET_GUID_HOB_DATA (GuidHob
);
324 if ((sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER
) > GET_GUID_HOB_DATA_SIZE (GuidHob
)) || (GenericHeader
->Length
> GET_GUID_HOB_DATA_SIZE (GuidHob
))) {
325 return EFI_NOT_FOUND
;
327 if (GenericHeader
->Revision
== UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU_REVISION
) {
328 BootManagerMenuFile
= (UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU
*) GET_GUID_HOB_DATA (GuidHob
);
329 if (BootManagerMenuFile
->Header
.Length
< UNIVERSAL_PAYLOAD_SIZEOF_THROUGH_FIELD (UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU
, FileName
)) {
330 return EFI_NOT_FOUND
;
332 Size
= sizeof (BootManagerMenuFile
->FileName
);
333 Status
= PcdSetPtrS (PcdBootManagerMenuFile
, &Size
, &BootManagerMenuFile
->FileName
);
334 ASSERT_EFI_ERROR (Status
);
336 return EFI_NOT_FOUND
;