2 This file include all platform action which can be customized
5 Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "PlatformBootManager.h"
19 Return the index of the load option in the load option array.
21 The function consider two load options are equal when the
22 OptionType, Attributes, Description, FilePath and OptionalData are equal.
24 @param Key Pointer to the load option to be found.
25 @param Array Pointer to the array of load options to be found.
26 @param Count Number of entries in the Array.
28 @retval -1 Key wasn't found in the Array.
29 @retval 0 ~ Count-1 The index of the Key in the Array.
32 PlatformFindLoadOption (
33 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION
*Key
,
34 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION
*Array
,
40 for (Index
= 0; Index
< Count
; Index
++) {
41 if ((Key
->OptionType
== Array
[Index
].OptionType
) &&
42 (Key
->Attributes
== Array
[Index
].Attributes
) &&
43 (StrCmp (Key
->Description
, Array
[Index
].Description
) == 0) &&
44 (CompareMem (Key
->FilePath
, Array
[Index
].FilePath
, GetDevicePathSize (Key
->FilePath
)) == 0) &&
45 (Key
->OptionalDataSize
== Array
[Index
].OptionalDataSize
) &&
46 (CompareMem (Key
->OptionalData
, Array
[Index
].OptionalData
, Key
->OptionalDataSize
) == 0)) {
55 PlatformRegisterFvBootOption (
62 EFI_HANDLE
*HandleBuffer
;
65 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
67 UINTN UiSectionLength
;
68 UINT32 AuthenticationStatus
;
70 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
71 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
72 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
73 UINTN BootOptionCount
;
75 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
78 // Locate all available FVs.
81 Status
= gBS
->LocateHandleBuffer (
83 &gEfiFirmwareVolume2ProtocolGuid
,
88 if (EFI_ERROR (Status
)) {
93 // Go through FVs one by one to find the required FFS file
95 for (IndexFv
= 0, FvHandle
= NULL
; IndexFv
< HandleCount
&& FvHandle
== NULL
; IndexFv
++) {
96 Status
= gBS
->HandleProtocol (
97 HandleBuffer
[IndexFv
],
98 &gEfiFirmwareVolume2ProtocolGuid
,
101 if (EFI_ERROR (Status
)) {
106 // Attempt to read a EFI_SECTION_USER_INTERFACE section from the required FFS file
109 Status
= Fv
->ReadSection (
112 EFI_SECTION_USER_INTERFACE
,
114 (VOID
**) &UiSection
,
116 &AuthenticationStatus
118 if (EFI_ERROR (Status
)) {
121 FreePool (UiSection
);
124 // Save the handle of the FV where the FFS file was found
126 FvHandle
= HandleBuffer
[IndexFv
];
130 // Free the buffer of FV handles
132 FreePool (HandleBuffer
);
135 // If the FFS file was not found, then return
137 if (FvHandle
== NULL
) {
142 // Create a device path for the FFS file that was found
144 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
145 DevicePath
= AppendDevicePathNode (
146 DevicePathFromHandle (FvHandle
),
147 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
151 // Create and add a new load option for the FFS file that was found
153 Status
= EfiBootManagerInitializeLoadOption (
155 LoadOptionNumberUnassigned
,
163 if (!EFI_ERROR (Status
)) {
164 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
, LoadOptionTypeBoot
);
166 OptionIndex
= PlatformFindLoadOption (&NewOption
, BootOptions
, BootOptionCount
);
168 if (OptionIndex
== -1) {
169 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, (UINTN
) -1);
170 ASSERT_EFI_ERROR (Status
);
172 EfiBootManagerFreeLoadOption (&NewOption
);
173 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
179 InternalBdsEmptyCallbackFuntion (
188 Do the platform specific action before the console is connected.
191 Update console variable;
192 Register new Driver#### or Boot####;
193 Signal ReadyToLock event.
197 PlatformBootManagerBeforeConsole (
205 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
206 ESRT_MANAGEMENT_PROTOCOL
*EsrtManagement
;
207 EFI_BOOT_MODE BootMode
;
208 EFI_ACPI_S3_SAVE_PROTOCOL
*AcpiS3Save
;
210 EFI_EVENT EndOfDxeEvent
;
213 // Update the console variables.
215 for (Index
= 0; gPlatformConsole
[Index
].DevicePath
!= NULL
; Index
++) {
216 if ((gPlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
217 EfiBootManagerUpdateConsoleVariable (ConIn
, gPlatformConsole
[Index
].DevicePath
, NULL
);
220 if ((gPlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
221 EfiBootManagerUpdateConsoleVariable (ConOut
, gPlatformConsole
[Index
].DevicePath
, NULL
);
224 if ((gPlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
225 EfiBootManagerUpdateConsoleVariable (ErrOut
, gPlatformConsole
[Index
].DevicePath
, NULL
);
230 // Register ENTER as CONTINUE key
232 Enter
.ScanCode
= SCAN_NULL
;
233 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
234 EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
237 // Map F2 to Boot Manager Menu
239 F2
.ScanCode
= SCAN_F2
;
240 F2
.UnicodeChar
= CHAR_NULL
;
241 EfiBootManagerGetBootManagerMenu (&BootOption
);
242 EfiBootManagerAddKeyOptionVariable (NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
);
245 // Register UEFI Shell
247 PlatformRegisterFvBootOption (&gUefiShellFileGuid
, L
"UEFI Shell", LOAD_OPTION_ACTIVE
);
249 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtManagement
);
250 if (EFI_ERROR(Status
)) {
251 EsrtManagement
= NULL
;
254 BootMode
= GetBootModeHob();
256 case BOOT_ON_FLASH_UPDATE
:
257 DEBUG((DEBUG_INFO
, "ProcessCapsules Before EndOfDxe ......\n"));
258 Status
= ProcessCapsules ();
259 DEBUG((DEBUG_INFO
, "ProcessCapsules %r\n", Status
));
261 case BOOT_IN_RECOVERY_MODE
:
263 case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
:
264 case BOOT_WITH_MINIMAL_CONFIGURATION
:
265 case BOOT_ON_S4_RESUME
:
266 if (EsrtManagement
!= NULL
) {
268 // Lock ESRT cache repository before EndofDxe if ESRT sync is not needed
270 EsrtManagement
->LockEsrtRepository();
275 // Require to sync ESRT from FMP in a new boot
277 if (EsrtManagement
!= NULL
) {
278 EsrtManagement
->SyncEsrtFmp();
286 Status
= gBS
->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid
, NULL
, (VOID
**)&AcpiS3Save
);
287 if (!EFI_ERROR (Status
)) {
288 AcpiS3Save
->S3Save (AcpiS3Save
, NULL
);
292 // Inform PI SMM drivers that BDS may run 3rd party code
293 // Create and signal End of DXE event group
295 Status
= gBS
->CreateEventEx (
298 InternalBdsEmptyCallbackFuntion
,
300 &gEfiEndOfDxeEventGroupGuid
,
303 ASSERT_EFI_ERROR (Status
);
304 gBS
->SignalEvent (EndOfDxeEvent
);
305 gBS
->CloseEvent (EndOfDxeEvent
);
307 DEBUG((EFI_D_INFO
,"All EndOfDxe callbacks have returned successfully\n"));
310 // Install SMM Ready To Lock protocol so all resources can be locked down
311 // before BDS runs 3rd party code. This action must be done last so all
312 // other SMM driver signals are processed before this final lock down action.
315 Status
= gBS
->InstallProtocolInterface (
317 &gEfiDxeSmmReadyToLockProtocolGuid
,
318 EFI_NATIVE_INTERFACE
,
321 ASSERT_EFI_ERROR (Status
);
324 // Dispatch deferred images after EndOfDxe event and ReadyToLock installation.
326 EfiBootManagerDispatchDeferredImages ();
330 Do the platform specific action after the console is connected.
333 Dynamically switch output mode;
334 Signal console ready platform customized event;
335 Run diagnostics like memory testing;
336 Connect certain devices;
337 Dispatch additional option ROMs
341 PlatformBootManagerAfterConsole (
346 EFI_BOOT_MODE BootMode
;
347 ESRT_MANAGEMENT_PROTOCOL
*EsrtManagement
;
351 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtManagement
);
352 if (EFI_ERROR(Status
)) {
353 EsrtManagement
= NULL
;
356 BootMode
= GetBootModeHob();
358 case BOOT_ON_FLASH_UPDATE
:
359 DEBUG((DEBUG_INFO
, "Capsule Mode detected\n"));
360 if (FeaturePcdGet(PcdSupportUpdateCapsuleReset
)) {
361 EfiBootManagerConnectAll ();
362 EfiBootManagerRefreshAllBootOption ();
365 // Always sync ESRT Cache from FMP Instances after connect all and before capsule process
367 if (EsrtManagement
!= NULL
) {
368 EsrtManagement
->SyncEsrtFmp();
371 DEBUG((DEBUG_INFO
, "ProcessCapsules After ConnectAll ......\n"));
372 Status
= ProcessCapsules();
373 DEBUG((DEBUG_INFO
, "ProcessCapsules %r\n", Status
));
377 case BOOT_IN_RECOVERY_MODE
:
378 DEBUG((DEBUG_INFO
, "Recovery Mode detected\n"));
381 case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
:
382 case BOOT_WITH_MINIMAL_CONFIGURATION
:
383 case BOOT_WITH_FULL_CONFIGURATION
:
384 case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS
:
385 case BOOT_WITH_DEFAULT_SETTINGS
:
387 EfiBootManagerConnectAll ();
388 EfiBootManagerRefreshAllBootOption ();
391 // Sync ESRT Cache from FMP Instance on demand after Connect All
393 if ((BootMode
!= BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
) &&
394 (BootMode
!= BOOT_WITH_MINIMAL_CONFIGURATION
) &&
395 (BootMode
!= BOOT_ON_S4_RESUME
)) {
396 if (EsrtManagement
!= NULL
) {
397 EsrtManagement
->SyncEsrtFmp();
406 L
"F2 to enter Boot Manager Menu.\n"
407 L
"ENTER to boot directly.\n"
412 // Check if the platform is using test key.
414 Status
= GetSectionFromAnyFv(
415 PcdGetPtr(PcdEdkiiRsa2048Sha256TestPublicKeyFileGuid
),
421 if (!EFI_ERROR(Status
)) {
422 if ((Size
== PcdGetSize(PcdRsa2048Sha256PublicKeyBuffer
)) &&
423 (CompareMem(Buffer
, PcdGetPtr(PcdRsa2048Sha256PublicKeyBuffer
), Size
) == 0)) {
424 Print(L
"WARNING: Recovery Test Key is used.\n");
425 PcdSetBoolS(PcdTestKeyUsed
, TRUE
);
429 Status
= GetSectionFromAnyFv(
430 PcdGetPtr(PcdEdkiiPkcs7TestPublicKeyFileGuid
),
436 if (!EFI_ERROR(Status
)) {
437 if ((Size
== PcdGetSize(PcdPkcs7CertBuffer
)) &&
438 (CompareMem(Buffer
, PcdGetPtr(PcdPkcs7CertBuffer
), Size
) == 0)) {
439 Print(L
"WARNING: Capsule Test Key is used.\n");
440 PcdSetBoolS(PcdTestKeyUsed
, TRUE
);
446 // Use a DynamicHii type pcd to save the boot status, which is used to
447 // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration.
449 if (PcdGetBool(PcdBootState
)) {
450 Status
= PcdSetBoolS (PcdBootState
, FALSE
);
451 ASSERT_EFI_ERROR (Status
);
456 This function is called each second during the boot manager waits the timeout.
458 @param TimeoutRemain The remaining timeout.
462 PlatformBootManagerWaitCallback (
466 Print (L
"\r%-2d seconds remained...", TimeoutRemain
);