2 This file include all platform action which can be customized
5 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "PlatformBootManager.h"
13 Return the index of the load option in the load option array.
15 The function consider two load options are equal when the
16 OptionType, Attributes, Description, FilePath and OptionalData are equal.
18 @param Key Pointer to the load option to be found.
19 @param Array Pointer to the array of load options to be found.
20 @param Count Number of entries in the Array.
22 @retval -1 Key wasn't found in the Array.
23 @retval 0 ~ Count-1 The index of the Key in the Array.
26 PlatformFindLoadOption (
27 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION
*Key
,
28 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION
*Array
,
34 for (Index
= 0; Index
< Count
; Index
++) {
35 if ((Key
->OptionType
== Array
[Index
].OptionType
) &&
36 (Key
->Attributes
== Array
[Index
].Attributes
) &&
37 (StrCmp (Key
->Description
, Array
[Index
].Description
) == 0) &&
38 (CompareMem (Key
->FilePath
, Array
[Index
].FilePath
, GetDevicePathSize (Key
->FilePath
)) == 0) &&
39 (Key
->OptionalDataSize
== Array
[Index
].OptionalDataSize
) &&
40 (CompareMem (Key
->OptionalData
, Array
[Index
].OptionalData
, Key
->OptionalDataSize
) == 0)) {
49 PlatformRegisterFvBootOption (
56 EFI_HANDLE
*HandleBuffer
;
59 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
61 UINTN UiSectionLength
;
62 UINT32 AuthenticationStatus
;
64 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
65 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
66 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
67 UINTN BootOptionCount
;
69 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
72 // Locate all available FVs.
75 Status
= gBS
->LocateHandleBuffer (
77 &gEfiFirmwareVolume2ProtocolGuid
,
82 if (EFI_ERROR (Status
)) {
87 // Go through FVs one by one to find the required FFS file
89 for (IndexFv
= 0, FvHandle
= NULL
; IndexFv
< HandleCount
&& FvHandle
== NULL
; IndexFv
++) {
90 Status
= gBS
->HandleProtocol (
91 HandleBuffer
[IndexFv
],
92 &gEfiFirmwareVolume2ProtocolGuid
,
95 if (EFI_ERROR (Status
)) {
100 // Attempt to read a EFI_SECTION_USER_INTERFACE section from the required FFS file
103 Status
= Fv
->ReadSection (
106 EFI_SECTION_USER_INTERFACE
,
108 (VOID
**) &UiSection
,
110 &AuthenticationStatus
112 if (EFI_ERROR (Status
)) {
115 FreePool (UiSection
);
118 // Save the handle of the FV where the FFS file was found
120 FvHandle
= HandleBuffer
[IndexFv
];
124 // Free the buffer of FV handles
126 FreePool (HandleBuffer
);
129 // If the FFS file was not found, then return
131 if (FvHandle
== NULL
) {
136 // Create a device path for the FFS file that was found
138 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
139 DevicePath
= AppendDevicePathNode (
140 DevicePathFromHandle (FvHandle
),
141 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
145 // Create and add a new load option for the FFS file that was found
147 Status
= EfiBootManagerInitializeLoadOption (
149 LoadOptionNumberUnassigned
,
157 if (!EFI_ERROR (Status
)) {
158 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
, LoadOptionTypeBoot
);
160 OptionIndex
= PlatformFindLoadOption (&NewOption
, BootOptions
, BootOptionCount
);
162 if (OptionIndex
== -1) {
163 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, (UINTN
) -1);
164 ASSERT_EFI_ERROR (Status
);
166 EfiBootManagerFreeLoadOption (&NewOption
);
167 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
173 InternalBdsEmptyCallbackFuntion (
182 Do the platform specific action before the console is connected.
185 Update console variable;
186 Register new Driver#### or Boot####;
187 Signal ReadyToLock event.
191 PlatformBootManagerBeforeConsole (
199 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
200 ESRT_MANAGEMENT_PROTOCOL
*EsrtManagement
;
201 EFI_BOOT_MODE BootMode
;
202 EFI_ACPI_S3_SAVE_PROTOCOL
*AcpiS3Save
;
204 EFI_EVENT EndOfDxeEvent
;
207 // Update the console variables.
209 for (Index
= 0; gPlatformConsole
[Index
].DevicePath
!= NULL
; Index
++) {
210 if ((gPlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
211 EfiBootManagerUpdateConsoleVariable (ConIn
, gPlatformConsole
[Index
].DevicePath
, NULL
);
214 if ((gPlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
215 EfiBootManagerUpdateConsoleVariable (ConOut
, gPlatformConsole
[Index
].DevicePath
, NULL
);
218 if ((gPlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
219 EfiBootManagerUpdateConsoleVariable (ErrOut
, gPlatformConsole
[Index
].DevicePath
, NULL
);
224 // Register ENTER as CONTINUE key
226 Enter
.ScanCode
= SCAN_NULL
;
227 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
228 EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
231 // Map F2 to Boot Manager Menu
233 F2
.ScanCode
= SCAN_F2
;
234 F2
.UnicodeChar
= CHAR_NULL
;
235 EfiBootManagerGetBootManagerMenu (&BootOption
);
236 EfiBootManagerAddKeyOptionVariable (NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
);
239 // Register UEFI Shell
241 PlatformRegisterFvBootOption (&gUefiShellFileGuid
, L
"UEFI Shell", LOAD_OPTION_ACTIVE
);
243 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtManagement
);
244 if (EFI_ERROR(Status
)) {
245 EsrtManagement
= NULL
;
248 BootMode
= GetBootModeHob();
250 case BOOT_ON_FLASH_UPDATE
:
251 DEBUG((DEBUG_INFO
, "ProcessCapsules Before EndOfDxe ......\n"));
252 Status
= ProcessCapsules ();
253 DEBUG((DEBUG_INFO
, "ProcessCapsules %r\n", Status
));
255 case BOOT_IN_RECOVERY_MODE
:
257 case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
:
258 case BOOT_WITH_MINIMAL_CONFIGURATION
:
259 case BOOT_ON_S4_RESUME
:
260 if (EsrtManagement
!= NULL
) {
262 // Lock ESRT cache repository before EndofDxe if ESRT sync is not needed
264 EsrtManagement
->LockEsrtRepository();
269 // Require to sync ESRT from FMP in a new boot
271 if (EsrtManagement
!= NULL
) {
272 EsrtManagement
->SyncEsrtFmp();
280 Status
= gBS
->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid
, NULL
, (VOID
**)&AcpiS3Save
);
281 if (!EFI_ERROR (Status
)) {
282 AcpiS3Save
->S3Save (AcpiS3Save
, NULL
);
286 // Inform PI SMM drivers that BDS may run 3rd party code
287 // Create and signal End of DXE event group
289 Status
= gBS
->CreateEventEx (
292 InternalBdsEmptyCallbackFuntion
,
294 &gEfiEndOfDxeEventGroupGuid
,
297 ASSERT_EFI_ERROR (Status
);
298 gBS
->SignalEvent (EndOfDxeEvent
);
299 gBS
->CloseEvent (EndOfDxeEvent
);
301 DEBUG((EFI_D_INFO
,"All EndOfDxe callbacks have returned successfully\n"));
304 // Install SMM Ready To Lock protocol so all resources can be locked down
305 // before BDS runs 3rd party code. This action must be done last so all
306 // other SMM driver signals are processed before this final lock down action.
309 Status
= gBS
->InstallProtocolInterface (
311 &gEfiDxeSmmReadyToLockProtocolGuid
,
312 EFI_NATIVE_INTERFACE
,
315 ASSERT_EFI_ERROR (Status
);
318 // Dispatch deferred images after EndOfDxe event and ReadyToLock installation.
320 EfiBootManagerDispatchDeferredImages ();
324 Do the platform specific action after the console is connected.
327 Dynamically switch output mode;
328 Signal console ready platform customized event;
329 Run diagnostics like memory testing;
330 Connect certain devices;
331 Dispatch additional option ROMs
335 PlatformBootManagerAfterConsole (
340 EFI_BOOT_MODE BootMode
;
341 ESRT_MANAGEMENT_PROTOCOL
*EsrtManagement
;
345 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtManagement
);
346 if (EFI_ERROR(Status
)) {
347 EsrtManagement
= NULL
;
350 BootMode
= GetBootModeHob();
352 DEBUG((DEBUG_INFO
, "PlatformBootManagerAfterConsole(): BootMode = %02x\n", BootMode
));
355 case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
:
356 case BOOT_WITH_MINIMAL_CONFIGURATION
:
357 case BOOT_ON_S4_RESUME
:
358 EfiBootManagerRefreshAllBootOption ();
361 case BOOT_ON_FLASH_UPDATE
:
362 if (FeaturePcdGet(PcdSupportUpdateCapsuleReset
)) {
363 EfiBootManagerConnectAll ();
364 EfiBootManagerRefreshAllBootOption ();
367 // Always sync ESRT Cache from FMP Instances after connect all and before capsule process
369 if (EsrtManagement
!= NULL
) {
370 EsrtManagement
->SyncEsrtFmp();
373 DEBUG((DEBUG_INFO
, "ProcessCapsules After ConnectAll ......\n"));
374 Status
= ProcessCapsules();
375 DEBUG((DEBUG_INFO
, "ProcessCapsules %r\n", Status
));
380 EfiBootManagerConnectAll ();
381 EfiBootManagerRefreshAllBootOption ();
384 // Sync ESRT Cache from FMP Instance on demand after Connect All
386 if (EsrtManagement
!= NULL
) {
387 EsrtManagement
->SyncEsrtFmp();
394 L
"F2 to enter Boot Manager Menu.\n"
395 L
"ENTER to boot directly.\n"
400 // Check if the platform is using test key.
402 Status
= GetSectionFromAnyFv(
403 PcdGetPtr(PcdEdkiiRsa2048Sha256TestPublicKeyFileGuid
),
409 if (!EFI_ERROR(Status
)) {
410 if ((Size
== PcdGetSize(PcdRsa2048Sha256PublicKeyBuffer
)) &&
411 (CompareMem(Buffer
, PcdGetPtr(PcdRsa2048Sha256PublicKeyBuffer
), Size
) == 0)) {
412 Print(L
"WARNING: Recovery Test Key is used.\n");
413 PcdSetBoolS(PcdTestKeyUsed
, TRUE
);
417 Status
= GetSectionFromAnyFv(
418 PcdGetPtr(PcdEdkiiPkcs7TestPublicKeyFileGuid
),
424 if (!EFI_ERROR(Status
)) {
425 if ((Size
== PcdGetSize(PcdPkcs7CertBuffer
)) &&
426 (CompareMem(Buffer
, PcdGetPtr(PcdPkcs7CertBuffer
), Size
) == 0)) {
427 Print(L
"WARNING: Capsule Test Key is used.\n");
428 PcdSetBoolS(PcdTestKeyUsed
, TRUE
);
434 // Use a DynamicHii type pcd to save the boot status, which is used to
435 // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration.
437 if (PcdGetBool(PcdBootState
)) {
438 Status
= PcdSetBoolS (PcdBootState
, FALSE
);
439 ASSERT_EFI_ERROR (Status
);
444 This function is called each second during the boot manager waits the timeout.
446 @param TimeoutRemain The remaining timeout.
450 PlatformBootManagerWaitCallback (
454 Print (L
"\r%-2d seconds remained...", TimeoutRemain
);
458 The function is called when no boot option could be launched,
459 including platform recovery options and options pointing to applications
460 built into firmware volumes.
462 If this function returns, BDS attempts to enter an infinite loop.
466 PlatformBootManagerUnableToBoot (