2 This module produce main entry for BDS phase - BdsEntry.
3 When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed
4 which contains interface of BdsEntry.
5 After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked
8 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
9 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
10 This program and the accompanying materials
11 are licensed and made available under the terms and conditions of the BSD License
12 which accompanies this distribution. The full text of the license may be found at
13 http://opensource.org/licenses/bsd-license.php
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 #include "HwErrRecSupport.h"
24 #define SET_BOOT_OPTION_SUPPORT_KEY_COUNT(a, c) { \
25 (a) = ((a) & ~EFI_BOOT_OPTION_SUPPORT_COUNT) | (((c) << LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT)) & EFI_BOOT_OPTION_SUPPORT_COUNT); \
29 /// BDS arch protocol instance initial value.
31 EFI_BDS_ARCH_PROTOCOL gBds
= {
36 // gConnectConInEvent - Event which is signaled when ConIn connection is required
38 EFI_EVENT gConnectConInEvent
= NULL
;
41 /// The read-only variables defined in UEFI Spec.
43 CHAR16
*mReadOnlyVariables
[] = {
44 EFI_PLATFORM_LANG_CODES_VARIABLE_NAME
,
45 EFI_LANG_CODES_VARIABLE_NAME
,
46 EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME
,
47 EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME
,
48 EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME
51 CHAR16
*mBdsLoadOptionName
[] = {
59 Event to Connect ConIn.
61 @param Event Event whose notification function is being invoked.
62 @param Context Pointer to the notification function's context,
63 which is implementation-dependent.
68 BdsDxeOnConnectConInCallBack (
76 // When Osloader call ReadKeyStroke to signal this event
77 // no driver dependency is assumed existing. So use a non-dispatch version
79 Status
= EfiBootManagerConnectConsoleVariable (ConIn
);
80 if (EFI_ERROR (Status
)) {
82 // Should not enter this case, if enter, the keyboard will not work.
83 // May need platfrom policy to connect keyboard.
85 DEBUG ((EFI_D_WARN
, "[Bds] Connect ConIn failed - %r!!!\n", Status
));
91 Install Boot Device Selection Protocol
93 @param ImageHandle The image handle.
94 @param SystemTable The system table.
96 @retval EFI_SUCEESS BDS has finished initializing.
97 Return the dispatcher and recall BDS.Entry
98 @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface
104 IN EFI_HANDLE ImageHandle
,
105 IN EFI_SYSTEM_TABLE
*SystemTable
111 // Install protocol interface
114 Status
= gBS
->InstallMultipleProtocolInterfaces (
116 &gEfiBdsArchProtocolGuid
, &gBds
,
119 ASSERT_EFI_ERROR (Status
);
125 Function waits for a given event to fire, or for an optional timeout to expire.
127 @param Event The event to wait for
128 @param Timeout An optional timeout value in 100 ns units.
130 @retval EFI_SUCCESS Event fired before Timeout expired.
131 @retval EFI_TIME_OUT Timout expired before Event fired..
135 BdsWaitForSingleEvent (
137 IN UINT64 Timeout OPTIONAL
142 EFI_EVENT TimerEvent
;
143 EFI_EVENT WaitList
[2];
147 // Create a timer event
149 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
150 if (!EFI_ERROR (Status
)) {
152 // Set the timer event
161 // Wait for the original event or the timer
164 WaitList
[1] = TimerEvent
;
165 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
166 ASSERT_EFI_ERROR (Status
);
167 gBS
->CloseEvent (TimerEvent
);
170 // If the timer expired, change the return to timed out
173 Status
= EFI_TIMEOUT
;
178 // No timeout... just wait on the event
180 Status
= gBS
->WaitForEvent (1, &Event
, &Index
);
181 ASSERT (!EFI_ERROR (Status
));
189 The function reads user inputs.
200 if (PcdGetBool (PcdConInConnectOnDemand
)) {
204 while (gST
->ConIn
!= NULL
) {
206 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
208 if (EFI_ERROR (Status
)) {
218 The function waits for the boot manager timeout expires or hotkey is pressed.
220 It calls PlatformBootManagerWaitCallback each second.
222 @param HotkeyTriggered Input hotkey event.
226 IN EFI_EVENT HotkeyTriggered
230 UINT16 TimeoutRemain
;
232 DEBUG ((EFI_D_INFO
, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n"));
234 TimeoutRemain
= PcdGet16 (PcdPlatformBootTimeOut
);
235 while (TimeoutRemain
!= 0) {
236 DEBUG ((EFI_D_INFO
, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN
) TimeoutRemain
));
237 PlatformBootManagerWaitCallback (TimeoutRemain
);
239 BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered
240 // Can be removed after all keyboard drivers invoke callback in timer callback.
242 if (HotkeyTriggered
!= NULL
) {
243 Status
= BdsWaitForSingleEvent (HotkeyTriggered
, EFI_TIMER_PERIOD_SECONDS (1));
244 if (!EFI_ERROR (Status
)) {
248 gBS
->Stall (1000000);
252 // 0xffff means waiting forever
253 // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop
255 if (TimeoutRemain
!= 0xffff) {
259 DEBUG ((EFI_D_INFO
, "[Bds]Exit the waiting!\n"));
263 Attempt to boot each boot option in the BootOptions array.
265 @param BootOptions Input boot option array.
266 @param BootOptionCount Input boot option count.
267 @param BootManagerMenu Input boot manager menu.
269 @retval TRUE Successfully boot one of the boot options.
270 @retval FALSE Failed boot any of the boot options.
274 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
,
275 IN UINTN BootOptionCount
,
276 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootManagerMenu
282 // Attempt boot each boot option
284 for (Index
= 0; Index
< BootOptionCount
; Index
++) {
286 // According to EFI Specification, if a load option is not marked
287 // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
290 if ((BootOptions
[Index
].Attributes
& LOAD_OPTION_ACTIVE
) == 0) {
295 // Boot#### load options with LOAD_OPTION_CATEGORY_APP are executables which are not
296 // part of the normal boot processing. Boot options with reserved category values will be
297 // ignored by the boot manager.
299 if ((BootOptions
[Index
].Attributes
& LOAD_OPTION_CATEGORY
) != LOAD_OPTION_CATEGORY_BOOT
) {
304 // All the driver options should have been processed since
305 // now boot will be performed.
307 EfiBootManagerBoot (&BootOptions
[Index
]);
310 // If the boot via Boot#### returns with a status of EFI_SUCCESS, platform firmware
// supports boot manager menu, and if firmware is configured to boot in an
// interactive mode, the boot manager will stop processing the BootOrder variable and
// present a boot manager menu to the user.
312 if (BootOptions
[Index
].Status
== EFI_SUCCESS
) {
313 EfiBootManagerBoot (BootManagerMenu
);
318 return (BOOLEAN
) (Index
< BootOptionCount
);
322 The function will load and start every Driver####, SysPrep#### or PlatformRecovery####.
324 @param LoadOptions Load option array.
325 @param LoadOptionCount Load option count.
329 IN EFI_BOOT_MANAGER_LOAD_OPTION
*LoadOptions
,
330 IN UINTN LoadOptionCount
335 BOOLEAN ReconnectAll
;
336 EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType
;
338 ReconnectAll
= FALSE
;
339 LoadOptionType
= LoadOptionTypeMax
;
342 // Process the driver option
344 for (Index
= 0; Index
< LoadOptionCount
; Index
++) {
346 // All the load options in the array should be of the same type.
349 LoadOptionType
= LoadOptions
[Index
].OptionType
;
351 ASSERT (LoadOptionType
== LoadOptions
[Index
].OptionType
);
353 Status
= EfiBootManagerProcessLoadOption (&LoadOptions
[Index
]);
355 if (!EFI_ERROR (Status
)) {
356 if (LoadOptionType
== LoadOptionTypePlatformRecovery
) {
358 // Stop processing if any entry is successful
362 if ((LoadOptions
[Index
].Attributes
& LOAD_OPTION_FORCE_RECONNECT
) != 0) {
369 // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,
370 // then all of the EFI drivers in the system will be disconnected and
371 // reconnected after the last driver load option is processed.
373 if (ReconnectAll
&& LoadOptionType
== LoadOptionTypeDriver
) {
374 EfiBootManagerDisconnectAll ();
375 EfiBootManagerConnectAll ();
381 Validate input console variable data.
383 If found the device path is not a valid device path, remove the variable.
385 @param VariableName Input console variable name.
389 BdsFormalizeConsoleVariable (
390 IN CHAR16
*VariableName
393 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
397 GetEfiGlobalVariable2 (VariableName
, (VOID
**) &DevicePath
, &VariableSize
);
398 if ((DevicePath
!= NULL
) && !IsDevicePathValid (DevicePath
, VariableSize
)) {
399 Status
= gRT
->SetVariable (
401 &gEfiGlobalVariableGuid
,
402 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
407 // Deleting variable with current variable implementation shouldn't fail.
409 ASSERT_EFI_ERROR (Status
);
412 if (DevicePath
!= NULL
) {
413 FreePool (DevicePath
);
418 Formalize OsIndication related variables.
420 For OsIndicationsSupported, Create a BS/RT/UINT64 variable to report caps
421 Delete OsIndications variable if it is not NV/BS/RT UINT64.
423 Item 3 is used to solve case when OS corrupts OsIndications. Here simply delete this NV variable.
427 BdsFormalizeOSIndicationVariable (
432 UINT64 OsIndicationSupport
;
438 // OS indicater support variable
440 OsIndicationSupport
= EFI_OS_INDICATIONS_BOOT_TO_FW_UI
| EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY
;
441 Status
= gRT
->SetVariable (
442 EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME
,
443 &gEfiGlobalVariableGuid
,
444 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
449 // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail.
451 ASSERT_EFI_ERROR (Status
);
454 // If OsIndications is invalid, remove it.
456 // 1. Data size != UINT64
457 // 2. OsIndication value inconsistence
458 // 3. OsIndication attribute inconsistence
462 DataSize
= sizeof(UINT64
);
463 Status
= gRT
->GetVariable (
464 EFI_OS_INDICATIONS_VARIABLE_NAME
,
465 &gEfiGlobalVariableGuid
,
470 if (Status
== EFI_NOT_FOUND
) {
474 if ((DataSize
!= sizeof (OsIndication
)) ||
475 ((OsIndication
& ~OsIndicationSupport
) != 0) ||
476 (Attributes
!= (EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
))
479 DEBUG ((EFI_D_ERROR
, "[Bds] Unformalized OsIndications variable exists. Delete it\n"));
480 Status
= gRT
->SetVariable (
481 EFI_OS_INDICATIONS_VARIABLE_NAME
,
482 &gEfiGlobalVariableGuid
,
488 // Deleting variable with current variable implementation shouldn't fail.
490 ASSERT_EFI_ERROR(Status
);
500 BdsFormalizeEfiGlobalVariable (
505 // Validate Console variable.
507 BdsFormalizeConsoleVariable (EFI_CON_IN_VARIABLE_NAME
);
508 BdsFormalizeConsoleVariable (EFI_CON_OUT_VARIABLE_NAME
);
509 BdsFormalizeConsoleVariable (EFI_ERR_OUT_VARIABLE_NAME
);
512 // Validate OSIndication related variable.
514 BdsFormalizeOSIndicationVariable ();
519 Allocate a block of memory that will contain performance data to OS.
523 BdsAllocateMemoryForPerformanceData (
528 EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase
;
529 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
;
531 AcpiLowMemoryBase
= 0x0FFFFFFFFULL
;
534 // Allocate a block of memory that will contain performance data to OS.
536 Status
= gBS
->AllocatePages (
538 EfiReservedMemoryType
,
539 EFI_SIZE_TO_PAGES (PERF_DATA_MAX_LENGTH
),
542 if (!EFI_ERROR (Status
)) {
544 // Save the pointer to variable for use in S3 resume.
546 Status
= BdsDxeSetVariableAndReportStatusCodeOnError (
548 &gPerformanceProtocolGuid
,
549 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
550 sizeof (EFI_PHYSICAL_ADDRESS
),
553 if (EFI_ERROR (Status
)) {
554 DEBUG ((EFI_D_ERROR
, "[Bds] PerfDataMemAddr (%08x) cannot be saved to NV storage.\n", AcpiLowMemoryBase
));
557 // Mark L"PerfDataMemAddr" variable to read-only if the Variable Lock protocol exists
558 // Still lock it even the variable cannot be saved to prevent it's set by 3rd party code.
560 Status
= gBS
->LocateProtocol (&gEdkiiVariableLockProtocolGuid
, NULL
, (VOID
**) &VariableLock
);
561 if (!EFI_ERROR (Status
)) {
562 Status
= VariableLock
->RequestToLock (VariableLock
, L
"PerfDataMemAddr", &gPerformanceProtocolGuid
);
563 ASSERT_EFI_ERROR (Status
);
570 Service routine for BdsInstance->Entry(). Devices are connected, the
571 consoles are initialized, and the boot options are tried.
573 @param This Protocol Instance structure.
579 IN EFI_BDS_ARCH_PROTOCOL
*This
582 EFI_BOOT_MANAGER_LOAD_OPTION
*LoadOptions
;
583 UINTN LoadOptionCount
;
584 CHAR16
*FirmwareVendor
;
585 EFI_EVENT HotkeyTriggered
;
589 UINT32 BootOptionSupport
;
591 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
;
593 EFI_BOOT_MANAGER_LOAD_OPTION LoadOption
;
595 CHAR16 BootNextVariableName
[sizeof ("Boot####")];
596 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
598 BOOLEAN PlatformRecovery
;
600 EFI_DEVICE_PATH_PROTOCOL
*FilePath
;
602 HotkeyTriggered
= NULL
;
603 Status
= EFI_SUCCESS
;
607 // Insert the performance probe
609 PERF_END (NULL
, "DXE", NULL
, 0);
610 PERF_START (NULL
, "BDS", NULL
, 0);
611 DEBUG ((EFI_D_INFO
, "[Bds] Entry...\n"));
614 BdsAllocateMemoryForPerformanceData ();
618 // Fill in FirmwareVendor and FirmwareRevision from PCDs
620 FirmwareVendor
= (CHAR16
*) PcdGetPtr (PcdFirmwareVendor
);
621 gST
->FirmwareVendor
= AllocateRuntimeCopyPool (StrSize (FirmwareVendor
), FirmwareVendor
);
622 ASSERT (gST
->FirmwareVendor
!= NULL
);
623 gST
->FirmwareRevision
= PcdGet32 (PcdFirmwareRevision
);
626 // Fixup Tasble CRC after we updated Firmware Vendor and Revision
629 gBS
->CalculateCrc32 ((VOID
*) gST
, sizeof (EFI_SYSTEM_TABLE
), &gST
->Hdr
.CRC32
);
632 // Validate Variable.
634 BdsFormalizeEfiGlobalVariable ();
637 // Mark the read-only variables if the Variable Lock protocol exists
639 Status
= gBS
->LocateProtocol (&gEdkiiVariableLockProtocolGuid
, NULL
, (VOID
**) &VariableLock
);
640 DEBUG ((EFI_D_INFO
, "[BdsDxe] Locate Variable Lock protocol - %r\n", Status
));
641 if (!EFI_ERROR (Status
)) {
642 for (Index
= 0; Index
< sizeof (mReadOnlyVariables
) / sizeof (mReadOnlyVariables
[0]); Index
++) {
643 Status
= VariableLock
->RequestToLock (VariableLock
, mReadOnlyVariables
[Index
], &gEfiGlobalVariableGuid
);
644 ASSERT_EFI_ERROR (Status
);
648 InitializeHwErrRecSupport ();
651 // Initialize L"Timeout" EFI global variable.
653 BootTimeOut
= PcdGet16 (PcdPlatformBootTimeOut
);
654 if (BootTimeOut
!= 0xFFFF) {
656 // If time out value equal 0xFFFF, no need set to 0xFFFF to variable area because UEFI specification
657 // define same behavior between no value or 0xFFFF value for L"Timeout".
659 BdsDxeSetVariableAndReportStatusCodeOnError (
660 EFI_TIME_OUT_VARIABLE_NAME
,
661 &gEfiGlobalVariableGuid
,
662 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
669 // Initialize L"BootOptionSupport" EFI global variable.
670 // Lazy-ConIn implictly disables BDS hotkey.
672 BootOptionSupport
= EFI_BOOT_OPTION_SUPPORT_APP
| EFI_BOOT_OPTION_SUPPORT_SYSPREP
;
673 if (!PcdGetBool (PcdConInConnectOnDemand
)) {
674 BootOptionSupport
|= EFI_BOOT_OPTION_SUPPORT_KEY
;
675 SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport
, 3);
677 Status
= gRT
->SetVariable (
678 EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME
,
679 &gEfiGlobalVariableGuid
,
680 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
681 sizeof (BootOptionSupport
),
685 // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail.
687 ASSERT_EFI_ERROR (Status
);
690 // Cache and remove the "BootNext" NV variable.
692 GetEfiGlobalVariable2 (EFI_BOOT_NEXT_VARIABLE_NAME
, (VOID
**) &BootNext
, &DataSize
);
693 if (DataSize
!= sizeof (UINT16
)) {
694 if (BootNext
!= NULL
) {
699 Status
= gRT
->SetVariable (
700 EFI_BOOT_NEXT_VARIABLE_NAME
,
701 &gEfiGlobalVariableGuid
,
707 // Deleting NV variable shouldn't fail unless it doesn't exist.
709 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_NOT_FOUND
);
712 // Initialize the platform language variables
714 InitializeLanguage (TRUE
);
717 // System firmware must include a PlatformRecovery#### variable specifying
718 // a short-form File Path Media Device Path containing the platform default
719 // file path for removable media
721 FilePath
= FileDevicePath (NULL
, EFI_REMOVABLE_MEDIA_FILE_NAME
);
722 Status
= EfiBootManagerInitializeLoadOption (
725 LoadOptionTypePlatformRecovery
,
727 L
"Default PlatformRecovery",
732 ASSERT_EFI_ERROR (Status
);
733 EfiBootManagerLoadOptionToVariable (&LoadOption
);
734 EfiBootManagerFreeLoadOption (&LoadOption
);
738 // Report Status Code to indicate connecting drivers will happen
742 (EFI_SOFTWARE_DXE_BS_DRIVER
| EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS
)
746 // Do the platform init, can be customized by OEM/IBV
747 // Possible things that can be done in PlatformBootManagerBeforeConsole:
748 // > Update console variable: 1. include hot-plug devices; 2. Clear ConIn and add SOL for AMT
749 // > Register new Driver#### or Boot####
750 // > Register new Key####: e.g.: F12
751 // > Signal ReadyToLock event
752 // > Authentication action: 1. connect Auth devices; 2. Identify auto logon user.
754 PERF_START (NULL
, "PlatformBootManagerBeforeConsole", "BDS", 0);
755 PlatformBootManagerBeforeConsole ();
756 PERF_END (NULL
, "PlatformBootManagerBeforeConsole", "BDS", 0);
759 // Initialize hotkey service
761 EfiBootManagerStartHotkeyService (&HotkeyTriggered
);
764 // Execute Driver Options
766 LoadOptions
= EfiBootManagerGetLoadOptions (&LoadOptionCount
, LoadOptionTypeDriver
);
767 ProcessLoadOptions (LoadOptions
, LoadOptionCount
);
768 EfiBootManagerFreeLoadOptions (LoadOptions
, LoadOptionCount
);
773 PERF_START (NULL
, "EfiBootManagerConnectAllDefaultConsoles", "BDS", 0);
774 if (PcdGetBool (PcdConInConnectOnDemand
)) {
775 EfiBootManagerConnectConsoleVariable (ConOut
);
776 EfiBootManagerConnectConsoleVariable (ErrOut
);
779 // Initialize ConnectConIn event
781 Status
= gBS
->CreateEventEx (
784 BdsDxeOnConnectConInCallBack
,
786 &gConnectConInEventGuid
,
789 if (EFI_ERROR (Status
)) {
790 gConnectConInEvent
= NULL
;
793 EfiBootManagerConnectAllDefaultConsoles ();
795 PERF_END (NULL
, "EfiBootManagerConnectAllDefaultConsoles", "BDS", 0);
798 // Do the platform specific action after the console is ready
799 // Possible things that can be done in PlatformBootManagerAfterConsole:
800 // > Console post action:
801 // > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
802 // > Signal console ready platform customized event
803 // > Run diagnostics like memory testing
804 // > Connect certain devices
805 // > Dispatch aditional option roms
806 // > Special boot: e.g.: USB boot, enter UI
808 PERF_START (NULL
, "PlatformBootManagerAfterConsole", "BDS", 0);
809 PlatformBootManagerAfterConsole ();
810 PERF_END (NULL
, "PlatformBootManagerAfterConsole", "BDS", 0);
812 // Boot to Boot Manager Menu when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot
814 DataSize
= sizeof (UINT64
);
815 Status
= gRT
->GetVariable (
816 EFI_OS_INDICATIONS_VARIABLE_NAME
,
817 &gEfiGlobalVariableGuid
,
822 if (EFI_ERROR (Status
)) {
827 EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType
;
828 DEBUG ((EFI_D_INFO
, "[Bds]OsIndication: %016x\n", OsIndication
));
829 DEBUG ((EFI_D_INFO
, "[Bds]=============Begin Load Options Dumping ...=============\n"));
830 for (LoadOptionType
= 0; LoadOptionType
< LoadOptionTypeMax
; LoadOptionType
++) {
832 EFI_D_INFO
, " %s Options:\n",
833 mBdsLoadOptionName
[LoadOptionType
]
835 LoadOptions
= EfiBootManagerGetLoadOptions (&LoadOptionCount
, LoadOptionType
);
836 for (Index
= 0; Index
< LoadOptionCount
; Index
++) {
838 EFI_D_INFO
, " %s%04x: %s \t\t 0x%04x\n",
839 mBdsLoadOptionName
[LoadOptionType
],
840 LoadOptions
[Index
].OptionNumber
,
841 LoadOptions
[Index
].Description
,
842 LoadOptions
[Index
].Attributes
845 EfiBootManagerFreeLoadOptions (LoadOptions
, LoadOptionCount
);
847 DEBUG ((EFI_D_INFO
, "[Bds]=============End Load Options Dumping=============\n"));
851 // BootManagerMenu always contains the correct information even call fails.
853 EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
855 BootFwUi
= (BOOLEAN
) ((OsIndication
& EFI_OS_INDICATIONS_BOOT_TO_FW_UI
) != 0);
856 PlatformRecovery
= (BOOLEAN
) ((OsIndication
& EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY
) != 0);
858 // Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS
860 if (BootFwUi
|| PlatformRecovery
) {
861 OsIndication
&= ~((UINT64
) (EFI_OS_INDICATIONS_BOOT_TO_FW_UI
| EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY
));
862 Status
= gRT
->SetVariable (
863 EFI_OS_INDICATIONS_VARIABLE_NAME
,
864 &gEfiGlobalVariableGuid
,
865 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
870 // Changing the content without increasing its size with current variable implementation shouldn't fail.
872 ASSERT_EFI_ERROR (Status
);
876 // Launch Boot Manager Menu directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot
880 // Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI
882 if (PcdGetBool (PcdConInConnectOnDemand
)) {
883 BdsDxeOnConnectConInCallBack (NULL
, NULL
);
887 // Directly enter the setup page.
889 EfiBootManagerBoot (&BootManagerMenu
);
892 if (!PlatformRecovery
) {
894 // Execute SysPrep####
896 LoadOptions
= EfiBootManagerGetLoadOptions (&LoadOptionCount
, LoadOptionTypeSysPrep
);
897 ProcessLoadOptions (LoadOptions
, LoadOptionCount
);
898 EfiBootManagerFreeLoadOptions (LoadOptions
, LoadOptionCount
);
903 PERF_START (NULL
, "BdsWait", "BDS", 0);
904 BdsWait (HotkeyTriggered
);
905 PERF_END (NULL
, "BdsWait", "BDS", 0);
908 // BdsReadKeys() can be removed after all keyboard drivers invoke callback in timer callback.
912 EfiBootManagerHotkeyBoot ();
915 // Boot to "BootNext"
917 if (BootNext
!= NULL
) {
918 UnicodeSPrint (BootNextVariableName
, sizeof (BootNextVariableName
), L
"Boot%04x", *BootNext
);
919 Status
= EfiBootManagerVariableToLoadOption (BootNextVariableName
, &LoadOption
);
920 if (!EFI_ERROR (Status
)) {
921 EfiBootManagerBoot (&LoadOption
);
922 EfiBootManagerFreeLoadOption (&LoadOption
);
923 if (LoadOption
.Status
== EFI_SUCCESS
) {
925 // Boot to Boot Manager Menu upon EFI_SUCCESS
927 EfiBootManagerBoot (&BootManagerMenu
);
934 // Retry to boot if any of the boot succeeds
936 LoadOptions
= EfiBootManagerGetLoadOptions (&LoadOptionCount
, LoadOptionTypeBoot
);
937 BootSuccess
= BootBootOptions (LoadOptions
, LoadOptionCount
, &BootManagerMenu
);
938 EfiBootManagerFreeLoadOptions (LoadOptions
, LoadOptionCount
);
939 } while (BootSuccess
);
942 EfiBootManagerFreeLoadOption (&BootManagerMenu
);
945 LoadOptions
= EfiBootManagerGetLoadOptions (&LoadOptionCount
, LoadOptionTypePlatformRecovery
);
946 ProcessLoadOptions (LoadOptions
, LoadOptionCount
);
947 EfiBootManagerFreeLoadOptions (LoadOptions
, LoadOptionCount
);
950 DEBUG ((EFI_D_ERROR
, "[Bds] Unable to boot!\n"));
955 Set the variable and report the error through status code upon failure.
957 @param VariableName A Null-terminated string that is the name of the vendor's variable.
958 Each VariableName is unique for each VendorGuid. VariableName must
959 contain 1 or more characters. If VariableName is an empty string,
960 then EFI_INVALID_PARAMETER is returned.
961 @param VendorGuid A unique identifier for the vendor.
962 @param Attributes Attributes bitmask to set for the variable.
963 @param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE,
964 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or
965 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero
966 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is
967 set, then a SetVariable() call with a DataSize of zero will not cause any change to
968 the variable value (the timestamp associated with the variable may be updated however
969 even if no new data value is provided,see the description of the
970 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not
971 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated).
972 @param Data The contents for the variable.
974 @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
975 defined by the Attributes.
976 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the
977 DataSize exceeds the maximum allowed.
978 @retval EFI_INVALID_PARAMETER VariableName is an empty string.
979 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
980 @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
981 @retval EFI_WRITE_PROTECTED The variable in question is read-only.
982 @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted.
983 @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
984 or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo
985 does NOT pass the validation check carried out by the firmware.
987 @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
990 BdsDxeSetVariableAndReportStatusCodeOnError (
991 IN CHAR16
*VariableName
,
992 IN EFI_GUID
*VendorGuid
,
993 IN UINT32 Attributes
,
999 EDKII_SET_VARIABLE_STATUS
*SetVariableStatus
;
1002 Status
= gRT
->SetVariable (
1009 if (EFI_ERROR (Status
)) {
1010 NameSize
= StrSize (VariableName
);
1011 SetVariableStatus
= AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS
) + NameSize
+ DataSize
);
1012 if (SetVariableStatus
!= NULL
) {
1013 CopyGuid (&SetVariableStatus
->Guid
, VendorGuid
);
1014 SetVariableStatus
->NameSize
= NameSize
;
1015 SetVariableStatus
->DataSize
= DataSize
;
1016 SetVariableStatus
->SetStatus
= Status
;
1017 SetVariableStatus
->Attributes
= Attributes
;
1018 CopyMem (SetVariableStatus
+ 1, VariableName
, NameSize
);
1019 CopyMem (((UINT8
*) (SetVariableStatus
+ 1)) + NameSize
, Data
, DataSize
);
1021 REPORT_STATUS_CODE_EX (
1023 PcdGet32 (PcdErrorCodeSetVariable
),
1026 &gEdkiiStatusCodeDataTypeVariableGuid
,
1028 sizeof (EDKII_SET_VARIABLE_STATUS
) + NameSize
+ DataSize
1031 FreePool (SetVariableStatus
);