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"
18 EFI_GUID mUefiShellFileGuid
= {0x7C04A583, 0x9E3E, 0x4f1c, {0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 }};
21 Return the index of the load option in the load option array.
23 The function consider two load options are equal when the
24 OptionType, Attributes, Description, FilePath and OptionalData are equal.
26 @param Key Pointer to the load option to be found.
27 @param Array Pointer to the array of load options to be found.
28 @param Count Number of entries in the Array.
30 @retval -1 Key wasn't found in the Array.
31 @retval 0 ~ Count-1 The index of the Key in the Array.
34 PlatformFindLoadOption (
35 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION
*Key
,
36 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION
*Array
,
42 for (Index
= 0; Index
< Count
; Index
++) {
43 if ((Key
->OptionType
== Array
[Index
].OptionType
) &&
44 (Key
->Attributes
== Array
[Index
].Attributes
) &&
45 (StrCmp (Key
->Description
, Array
[Index
].Description
) == 0) &&
46 (CompareMem (Key
->FilePath
, Array
[Index
].FilePath
, GetDevicePathSize (Key
->FilePath
)) == 0) &&
47 (Key
->OptionalDataSize
== Array
[Index
].OptionalDataSize
) &&
48 (CompareMem (Key
->OptionalData
, Array
[Index
].OptionalData
, Key
->OptionalDataSize
) == 0)) {
57 PlatformRegisterFvBootOption (
64 EFI_HANDLE
*HandleBuffer
;
67 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
69 UINTN UiSectionLength
;
70 UINT32 AuthenticationStatus
;
72 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
73 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
74 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
75 UINTN BootOptionCount
;
77 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
80 // Locate all available FVs.
83 Status
= gBS
->LocateHandleBuffer (
85 &gEfiFirmwareVolume2ProtocolGuid
,
90 if (EFI_ERROR (Status
)) {
95 // Go through FVs one by one to find the required FFS file
97 for (IndexFv
= 0, FvHandle
= NULL
; IndexFv
< HandleCount
&& FvHandle
== NULL
; IndexFv
++) {
98 Status
= gBS
->HandleProtocol (
99 HandleBuffer
[IndexFv
],
100 &gEfiFirmwareVolume2ProtocolGuid
,
103 if (EFI_ERROR (Status
)) {
108 // Attempt to read a EFI_SECTION_USER_INTERFACE section from the required FFS file
111 Status
= Fv
->ReadSection (
114 EFI_SECTION_USER_INTERFACE
,
116 (VOID
**) &UiSection
,
118 &AuthenticationStatus
120 if (EFI_ERROR (Status
)) {
123 FreePool (UiSection
);
126 // Save the handle of the FV where the FFS file was found
128 FvHandle
= HandleBuffer
[IndexFv
];
132 // Free the buffer of FV handles
134 FreePool (HandleBuffer
);
137 // If the FFS file was not found, then return
139 if (FvHandle
== NULL
) {
144 // Create a device path for the FFS file that was found
146 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
147 DevicePath
= AppendDevicePathNode (
148 DevicePathFromHandle (FvHandle
),
149 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
153 // Create and add a new load option for the FFS file that was found
155 Status
= EfiBootManagerInitializeLoadOption (
157 LoadOptionNumberUnassigned
,
165 if (!EFI_ERROR (Status
)) {
166 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
, LoadOptionTypeBoot
);
168 OptionIndex
= PlatformFindLoadOption (&NewOption
, BootOptions
, BootOptionCount
);
170 if (OptionIndex
== -1) {
171 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, (UINTN
) -1);
172 ASSERT_EFI_ERROR (Status
);
174 EfiBootManagerFreeLoadOption (&NewOption
);
175 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
181 InternalBdsEmptyCallbackFuntion (
190 Do the platform specific action before the console is connected.
193 Update console variable;
194 Register new Driver#### or Boot####;
195 Signal ReadyToLock event.
199 PlatformBootManagerBeforeConsole (
207 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
208 ESRT_MANAGEMENT_PROTOCOL
*EsrtManagement
;
209 EFI_BOOT_MODE BootMode
;
210 EFI_ACPI_S3_SAVE_PROTOCOL
*AcpiS3Save
;
212 EFI_EVENT EndOfDxeEvent
;
215 // Update the console variables.
217 for (Index
= 0; gPlatformConsole
[Index
].DevicePath
!= NULL
; Index
++) {
218 if ((gPlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
219 EfiBootManagerUpdateConsoleVariable (ConIn
, gPlatformConsole
[Index
].DevicePath
, NULL
);
222 if ((gPlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
223 EfiBootManagerUpdateConsoleVariable (ConOut
, gPlatformConsole
[Index
].DevicePath
, NULL
);
226 if ((gPlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
227 EfiBootManagerUpdateConsoleVariable (ErrOut
, gPlatformConsole
[Index
].DevicePath
, NULL
);
232 // Register ENTER as CONTINUE key
234 Enter
.ScanCode
= SCAN_NULL
;
235 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
236 EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
239 // Map F2 to Boot Manager Menu
241 F2
.ScanCode
= SCAN_F2
;
242 F2
.UnicodeChar
= CHAR_NULL
;
243 EfiBootManagerGetBootManagerMenu (&BootOption
);
244 EfiBootManagerAddKeyOptionVariable (NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
);
247 // Register UEFI Shell
249 PlatformRegisterFvBootOption (&mUefiShellFileGuid
, L
"UEFI Shell", LOAD_OPTION_ACTIVE
);
251 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtManagement
);
252 if (EFI_ERROR(Status
)) {
253 EsrtManagement
= NULL
;
256 BootMode
= GetBootModeHob();
258 case BOOT_ON_FLASH_UPDATE
:
259 DEBUG((DEBUG_INFO
, "ProcessCapsules Before EndOfDxe ......\n"));
260 Status
= ProcessCapsules ();
261 DEBUG((DEBUG_INFO
, "ProcessCapsules %r\n", Status
));
263 case BOOT_IN_RECOVERY_MODE
:
265 case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
:
266 case BOOT_WITH_MINIMAL_CONFIGURATION
:
267 case BOOT_ON_S4_RESUME
:
268 if (EsrtManagement
!= NULL
) {
270 // Lock ESRT cache repository before EndofDxe if ESRT sync is not needed
272 EsrtManagement
->LockEsrtRepository();
277 // Require to sync ESRT from FMP in a new boot
279 if (EsrtManagement
!= NULL
) {
280 EsrtManagement
->SyncEsrtFmp();
288 Status
= gBS
->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid
, NULL
, (VOID
**)&AcpiS3Save
);
289 if (!EFI_ERROR (Status
)) {
290 AcpiS3Save
->S3Save (AcpiS3Save
, NULL
);
294 // Inform PI SMM drivers that BDS may run 3rd party code
295 // Create and signal End of DXE event group
297 Status
= gBS
->CreateEventEx (
300 InternalBdsEmptyCallbackFuntion
,
302 &gEfiEndOfDxeEventGroupGuid
,
305 ASSERT_EFI_ERROR (Status
);
306 gBS
->SignalEvent (EndOfDxeEvent
);
307 gBS
->CloseEvent (EndOfDxeEvent
);
309 DEBUG((EFI_D_INFO
,"All EndOfDxe callbacks have returned successfully\n"));
312 // Install SMM Ready To Lock protocol so all resources can be locked down
313 // before BDS runs 3rd party code. This action must be done last so all
314 // other SMM driver signals are processed before this final lock down action.
317 Status
= gBS
->InstallProtocolInterface (
319 &gEfiDxeSmmReadyToLockProtocolGuid
,
320 EFI_NATIVE_INTERFACE
,
323 ASSERT_EFI_ERROR (Status
);
327 Do the platform specific action after the console is connected.
330 Dynamically switch output mode;
331 Signal console ready platform customized event;
332 Run diagnostics like memory testing;
333 Connect certain devices;
334 Dispatch additional option ROMs
338 PlatformBootManagerAfterConsole (
343 EFI_BOOT_MODE BootMode
;
344 ESRT_MANAGEMENT_PROTOCOL
*EsrtManagement
;
348 Status
= gBS
->LocateProtocol(&gEsrtManagementProtocolGuid
, NULL
, (VOID
**)&EsrtManagement
);
349 if (EFI_ERROR(Status
)) {
350 EsrtManagement
= NULL
;
353 BootMode
= GetBootModeHob();
355 case BOOT_ON_FLASH_UPDATE
:
356 DEBUG((DEBUG_INFO
, "Capsule Mode detected\n"));
357 if (FeaturePcdGet(PcdSupportUpdateCapsuleReset
)) {
358 EfiBootManagerConnectAll ();
359 EfiBootManagerRefreshAllBootOption ();
362 // Always sync ESRT Cache from FMP Instances after connect all and before capsule process
364 if (EsrtManagement
!= NULL
) {
365 EsrtManagement
->SyncEsrtFmp();
368 DEBUG((DEBUG_INFO
, "ProcessCapsules After ConnectAll ......\n"));
369 Status
= ProcessCapsules();
370 DEBUG((DEBUG_INFO
, "ProcessCapsules %r\n", Status
));
374 case BOOT_IN_RECOVERY_MODE
:
375 DEBUG((DEBUG_INFO
, "Recovery Mode detected\n"));
378 case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
:
379 case BOOT_WITH_MINIMAL_CONFIGURATION
:
380 case BOOT_WITH_FULL_CONFIGURATION
:
381 case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS
:
382 case BOOT_WITH_DEFAULT_SETTINGS
:
384 EfiBootManagerConnectAll ();
385 EfiBootManagerRefreshAllBootOption ();
388 // Sync ESRT Cache from FMP Instance on demand after Connect All
390 if ((BootMode
!= BOOT_ASSUMING_NO_CONFIGURATION_CHANGES
) &&
391 (BootMode
!= BOOT_WITH_MINIMAL_CONFIGURATION
) &&
392 (BootMode
!= BOOT_ON_S4_RESUME
)) {
393 if (EsrtManagement
!= NULL
) {
394 EsrtManagement
->SyncEsrtFmp();
403 L
"F2 to enter Boot Manager Menu.\n"
404 L
"ENTER to boot directly.\n"
409 // Check if the platform is using test key.
411 Status
= GetSectionFromAnyFv(
412 PcdGetPtr(PcdEdkiiRsa2048Sha256TestPublicKeyFileGuid
),
418 if (!EFI_ERROR(Status
)) {
419 if ((Size
== PcdGetSize(PcdRsa2048Sha256PublicKeyBuffer
)) &&
420 (CompareMem(Buffer
, PcdGetPtr(PcdRsa2048Sha256PublicKeyBuffer
), Size
) == 0)) {
421 Print(L
"WARNING: Recovery Test Key is used.\n");
422 PcdSetBoolS(PcdTestKeyUsed
, TRUE
);
426 Status
= GetSectionFromAnyFv(
427 PcdGetPtr(PcdEdkiiPkcs7TestPublicKeyFileGuid
),
433 if (!EFI_ERROR(Status
)) {
434 if ((Size
== PcdGetSize(PcdPkcs7CertBuffer
)) &&
435 (CompareMem(Buffer
, PcdGetPtr(PcdPkcs7CertBuffer
), Size
) == 0)) {
436 Print(L
"WARNING: Capsule Test Key is used.\n");
437 PcdSetBoolS(PcdTestKeyUsed
, TRUE
);
443 // Use a DynamicHii type pcd to save the boot status, which is used to
444 // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration.
446 if (PcdGetBool(PcdBootState
)) {
447 Status
= PcdSetBoolS (PcdBootState
, FALSE
);
448 ASSERT_EFI_ERROR (Status
);
453 This function is called each second during the boot manager waits the timeout.
455 @param TimeoutRemain The remaining timeout.
459 PlatformBootManagerWaitCallback (
463 Print (L
"\r%-2d seconds remained...", TimeoutRemain
);