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 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
9 This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 #include "HwErrRecSupport.h"
23 #define SET_BOOT_OPTION_SUPPORT_KEY_COUNT(a, c) { \
24 (a) = ((a) & ~EFI_BOOT_OPTION_SUPPORT_COUNT) | (((c) << LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT)) & EFI_BOOT_OPTION_SUPPORT_COUNT); \
28 /// BDS arch protocol instance initial value.
30 EFI_BDS_ARCH_PROTOCOL gBds
= {
35 // gConnectConInEvent - Event which is signaled when ConIn connection is required
37 EFI_EVENT gConnectConInEvent
= NULL
;
40 /// The read-only variables defined in UEFI Spec.
42 CHAR16
*mReadOnlyVariables
[] = {
43 EFI_PLATFORM_LANG_CODES_VARIABLE_NAME
,
44 EFI_LANG_CODES_VARIABLE_NAME
,
45 EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME
,
46 EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME
,
47 EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME
50 CHAR16
*mBdsLoadOptionName
[] = {
56 CHAR16 mRecoveryBoot
[] = L
"Recovery Boot";
58 Event to Connect ConIn.
60 @param Event Event whose notification function is being invoked.
61 @param Context Pointer to the notification function's context,
62 which is implementation-dependent.
67 BdsDxeOnConnectConInCallBack (
75 // When Osloader call ReadKeyStroke to signal this event
76 // no driver dependency is assumed existing. So use a non-dispatch version
78 Status
= EfiBootManagerConnectConsoleVariable (ConIn
);
79 if (EFI_ERROR (Status
)) {
81 // Should not enter this case, if enter, the keyboard will not work.
82 // May need platfrom policy to connect keyboard.
84 DEBUG ((EFI_D_WARN
, "[Bds] Connect ConIn failed - %r!!!\n", Status
));
90 Install Boot Device Selection Protocol
92 @param ImageHandle The image handle.
93 @param SystemTable The system table.
95 @retval EFI_SUCEESS BDS has finished initializing.
96 Return the dispatcher and recall BDS.Entry
97 @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface
103 IN EFI_HANDLE ImageHandle
,
104 IN EFI_SYSTEM_TABLE
*SystemTable
110 // Install protocol interface
113 Status
= gBS
->InstallMultipleProtocolInterfaces (
115 &gEfiBdsArchProtocolGuid
, &gBds
,
118 ASSERT_EFI_ERROR (Status
);
124 Emuerate all possible bootable medias in the following order:
125 1. Removable BlockIo - The boot option only points to the removable media
126 device, like USB key, DVD, Floppy etc.
127 2. Fixed BlockIo - The boot option only points to a Fixed blockIo device,
129 3. Non-BlockIo SimpleFileSystem - The boot option points to a device supporting
130 SimpleFileSystem Protocol, but not supporting BlockIo
132 4. LoadFile - The boot option points to the media supporting
134 Reference: UEFI Spec chapter 3.3 Boot Option Variables Default Boot Behavior
136 @param BootOptionCount Return the boot option count which has been found.
138 @retval Pointer to the boot option array.
140 EFI_BOOT_MANAGER_LOAD_OPTION
*
141 BdsEnumerateBootOptions (
142 UINTN
*BootOptionCount
146 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
147 UINT16 NonBlockNumber
;
150 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
154 ASSERT (BootOptionCount
!= NULL
);
156 *BootOptionCount
= 0;
160 // Parse removable block io followed by fixed block io
162 gBS
->LocateHandleBuffer (
164 &gEfiBlockIoProtocolGuid
,
170 for (Removable
= 0; Removable
< 2; Removable
++) {
171 for (Index
= 0; Index
< HandleCount
; Index
++) {
172 Status
= gBS
->HandleProtocol (
174 &gEfiBlockIoProtocolGuid
,
177 if (EFI_ERROR (Status
)) {
182 // Skip the logical partitions
184 if (BlkIo
->Media
->LogicalPartition
) {
189 // Skip the fixed block io then the removable block io
191 if (BlkIo
->Media
->RemovableMedia
== ((Removable
== 0) ? FALSE
: TRUE
)) {
195 BootOptions
= ReallocatePool (
196 sizeof (EFI_BOOT_MANAGER_LOAD_OPTION
) * (*BootOptionCount
),
197 sizeof (EFI_BOOT_MANAGER_LOAD_OPTION
) * (*BootOptionCount
+ 1),
200 ASSERT (BootOptions
!= NULL
);
202 Status
= EfiBootManagerInitializeLoadOption (
203 &BootOptions
[(*BootOptionCount
)++],
204 LoadOptionNumberUnassigned
,
208 DevicePathFromHandle (Handles
[Index
]),
212 ASSERT_EFI_ERROR (Status
);
216 if (HandleCount
!= 0) {
221 // Parse simple file system not based on block io
224 gBS
->LocateHandleBuffer (
226 &gEfiSimpleFileSystemProtocolGuid
,
231 for (Index
= 0; Index
< HandleCount
; Index
++) {
232 Status
= gBS
->HandleProtocol (
234 &gEfiBlockIoProtocolGuid
,
237 if (!EFI_ERROR (Status
)) {
239 // Skip if the file system handle supports a BlkIo protocol, which we've handled in above
243 BootOptions
= ReallocatePool (
244 sizeof (EFI_BOOT_MANAGER_LOAD_OPTION
) * (*BootOptionCount
),
245 sizeof (EFI_BOOT_MANAGER_LOAD_OPTION
) * (*BootOptionCount
+ 1),
248 ASSERT (BootOptions
!= NULL
);
250 Status
= EfiBootManagerInitializeLoadOption (
251 &BootOptions
[(*BootOptionCount
)++],
252 LoadOptionNumberUnassigned
,
256 DevicePathFromHandle (Handles
[Index
]),
260 ASSERT_EFI_ERROR (Status
);
263 if (HandleCount
!= 0) {
268 // Parse load file, assuming UEFI Network boot option
270 gBS
->LocateHandleBuffer (
272 &gEfiLoadFileProtocolGuid
,
277 for (Index
= 0; Index
< HandleCount
; Index
++) {
279 BootOptions
= ReallocatePool (
280 sizeof (EFI_BOOT_MANAGER_LOAD_OPTION
) * (*BootOptionCount
),
281 sizeof (EFI_BOOT_MANAGER_LOAD_OPTION
) * (*BootOptionCount
+ 1),
284 ASSERT (BootOptions
!= NULL
);
286 Status
= EfiBootManagerInitializeLoadOption (
287 &BootOptions
[(*BootOptionCount
)++],
288 LoadOptionNumberUnassigned
,
292 DevicePathFromHandle (Handles
[Index
]),
296 ASSERT_EFI_ERROR (Status
);
299 if (HandleCount
!= 0) {
307 Function waits for a given event to fire, or for an optional timeout to expire.
309 @param Event The event to wait for
310 @param Timeout An optional timeout value in 100 ns units.
312 @retval EFI_SUCCESS Event fired before Timeout expired.
313 @retval EFI_TIME_OUT Timout expired before Event fired..
317 BdsWaitForSingleEvent (
319 IN UINT64 Timeout OPTIONAL
324 EFI_EVENT TimerEvent
;
325 EFI_EVENT WaitList
[2];
329 // Create a timer event
331 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
332 if (!EFI_ERROR (Status
)) {
334 // Set the timer event
343 // Wait for the original event or the timer
346 WaitList
[1] = TimerEvent
;
347 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
348 ASSERT_EFI_ERROR (Status
);
349 gBS
->CloseEvent (TimerEvent
);
352 // If the timer expired, change the return to timed out
355 Status
= EFI_TIMEOUT
;
360 // No timeout... just wait on the event
362 Status
= gBS
->WaitForEvent (1, &Event
, &Index
);
363 ASSERT (!EFI_ERROR (Status
));
371 The function reads user inputs.
382 if (PcdGetBool (PcdConInConnectOnDemand
)) {
386 while (gST
->ConIn
!= NULL
) {
388 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
390 if (EFI_ERROR (Status
)) {
400 The function waits for the boot manager timeout expires or hotkey is pressed.
402 It calls PlatformBootManagerWaitCallback each second.
404 @param HotkeyTriggered Input hotkey event.
408 IN EFI_EVENT HotkeyTriggered
412 UINT16 TimeoutRemain
;
414 DEBUG ((EFI_D_INFO
, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n"));
416 TimeoutRemain
= PcdGet16 (PcdPlatformBootTimeOut
);
417 while (TimeoutRemain
!= 0) {
418 DEBUG ((EFI_D_INFO
, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN
) TimeoutRemain
));
419 PlatformBootManagerWaitCallback (TimeoutRemain
);
421 BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered
422 // Can be removed after all keyboard drivers invoke callback in timer callback.
424 if (HotkeyTriggered
!= NULL
) {
425 Status
= BdsWaitForSingleEvent (HotkeyTriggered
, EFI_TIMER_PERIOD_SECONDS (1));
426 if (!EFI_ERROR (Status
)) {
430 gBS
->Stall (1000000);
434 // 0xffff means waiting forever
435 // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop
437 if (TimeoutRemain
!= 0xffff) {
441 DEBUG ((EFI_D_INFO
, "[Bds]Exit the waiting!\n"));
445 Attempt to boot each boot option in the BootOptions array.
447 @param BootOptions Input boot option array.
448 @param BootOptionCount Input boot option count.
450 @retval TRUE Successfully boot one of the boot options.
451 @retval FALSE Failed boot any of the boot options.
455 IN EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
,
456 IN UINTN BootOptionCount
462 // Attempt boot each boot option
464 for (Index
= 0; Index
< BootOptionCount
; Index
++) {
466 // According to EFI Specification, if a load option is not marked
467 // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
470 if ((BootOptions
[Index
].Attributes
& LOAD_OPTION_ACTIVE
) == 0) {
475 // Boot#### load options with LOAD_OPTION_CATEGORY_APP are executables which are not
476 // part of the normal boot processing. Boot options with reserved category values will be
477 // ignored by the boot manager.
479 if ((BootOptions
[Index
].Attributes
& LOAD_OPTION_CATEGORY
) != LOAD_OPTION_CATEGORY_BOOT
) {
484 // All the driver options should have been processed since
485 // now boot will be performed.
487 EfiBootManagerBoot (&BootOptions
[Index
]);
490 // Successful boot breaks the loop, otherwise tries next boot option
492 if (BootOptions
[Index
].Status
== EFI_SUCCESS
) {
497 return (BOOLEAN
) (Index
< BootOptionCount
);
501 This function attempts to boot per the boot order specified by platform policy.
503 If the boot via Boot#### returns with a status of EFI_SUCCESS the boot manager will stop
504 processing the BootOrder variable and present a boot manager menu to the user. If a boot via
505 Boot#### returns a status other than EFI_SUCCESS, the boot has failed and the next Boot####
506 in the BootOrder variable will be tried until all possibilities are exhausted.
507 -- Chapter 3.1.1 Boot Manager Programming, the 4th paragraph
510 DefaultBootBehavior (
514 UINTN BootOptionCount
;
515 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
516 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
518 EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
520 // BootManagerMenu always contains the correct information even the above function returns failure.
523 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
, LoadOptionTypeBoot
);
525 if (BootAllBootOptions (BootOptions
, BootOptionCount
)) {
527 // Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI
529 if (PcdGetBool (PcdConInConnectOnDemand
)) {
530 BdsDxeOnConnectConInCallBack (NULL
, NULL
);
534 // Show the Boot Manager Menu after successful boot
536 EfiBootManagerBoot (&BootManagerMenu
);
538 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
540 // Re-scan all EFI boot options in case all the boot#### are deleted or failed to boot
542 // If no valid boot options exist, the boot manager will enumerate all removable media
543 // devices followed by all fixed media devices. The order within each group is undefined.
544 // These new default boot options are not saved to non volatile storage.The boot manger
545 // will then attempt toboot from each boot option.
546 // -- Chapter 3.3 Boot Manager Programming, the 2nd paragraph
548 EfiBootManagerConnectAll ();
549 BootOptions
= BdsEnumerateBootOptions (&BootOptionCount
);
551 if (!BootAllBootOptions (BootOptions
, BootOptionCount
)) {
552 DEBUG ((EFI_D_ERROR
, "[Bds]No bootable device!\n"));
553 EfiBootManagerBoot (&BootManagerMenu
);
557 EfiBootManagerFreeLoadOption (&BootManagerMenu
);
558 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
562 The function will load and start every Driver####/SysPrep####.
564 @param LoadOptions Load option array.
565 @param LoadOptionCount Load option count.
570 IN EFI_BOOT_MANAGER_LOAD_OPTION
*LoadOptions
,
571 IN UINTN LoadOptionCount
576 BOOLEAN ReconnectAll
;
577 EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType
;
579 ReconnectAll
= FALSE
;
580 LoadOptionType
= LoadOptionTypeMax
;
583 // Process the driver option
585 for (Index
= 0; Index
< LoadOptionCount
; Index
++) {
587 // All the load options in the array should be of the same type.
589 if (LoadOptionType
== LoadOptionTypeMax
) {
590 LoadOptionType
= LoadOptions
[Index
].OptionType
;
592 ASSERT (LoadOptionType
== LoadOptions
[Index
].OptionType
);
593 ASSERT (LoadOptionType
== LoadOptionTypeDriver
|| LoadOptionType
== LoadOptionTypeSysPrep
);
595 Status
= EfiBootManagerProcessLoadOption (&LoadOptions
[Index
]);
597 if (!EFI_ERROR (Status
) && ((LoadOptions
[Index
].Attributes
& LOAD_OPTION_FORCE_RECONNECT
) != 0)) {
603 // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,
604 // then all of the EFI drivers in the system will be disconnected and
605 // reconnected after the last driver load option is processed.
607 if (ReconnectAll
&& LoadOptionType
== LoadOptionTypeDriver
) {
608 EfiBootManagerDisconnectAll ();
609 EfiBootManagerConnectAll ();
615 Validate input console variable data.
617 If found the device path is not a valid device path, remove the variable.
619 @param VariableName Input console variable name.
623 BdsFormalizeConsoleVariable (
624 IN CHAR16
*VariableName
627 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
631 GetEfiGlobalVariable2 (VariableName
, (VOID
**) &DevicePath
, &VariableSize
);
632 if ((DevicePath
!= NULL
) && !IsDevicePathValid (DevicePath
, VariableSize
)) {
633 Status
= gRT
->SetVariable (
635 &gEfiGlobalVariableGuid
,
636 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
641 // Deleting variable with current variable implementation shouldn't fail.
643 ASSERT_EFI_ERROR (Status
);
646 if (DevicePath
!= NULL
) {
647 FreePool (DevicePath
);
652 Formalize OsIndication related variables.
654 For OsIndicationsSupported, Create a BS/RT/UINT64 variable to report caps
655 Delete OsIndications variable if it is not NV/BS/RT UINT64.
657 Item 3 is used to solve case when OS corrupts OsIndications. Here simply delete this NV variable.
661 BdsFormalizeOSIndicationVariable (
666 UINT64 OsIndicationSupport
;
672 // OS indicater support variable
674 OsIndicationSupport
= EFI_OS_INDICATIONS_BOOT_TO_FW_UI
;
675 Status
= gRT
->SetVariable (
676 L
"OsIndicationsSupported",
677 &gEfiGlobalVariableGuid
,
678 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
683 // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail.
685 ASSERT_EFI_ERROR (Status
);
688 // If OsIndications is invalid, remove it.
690 // 1. Data size != UINT64
691 // 2. OsIndication value inconsistence
692 // 3. OsIndication attribute inconsistence
696 DataSize
= sizeof(UINT64
);
697 Status
= gRT
->GetVariable (
699 &gEfiGlobalVariableGuid
,
704 if (Status
== EFI_NOT_FOUND
) {
708 if ((DataSize
!= sizeof (OsIndication
)) ||
709 ((OsIndication
& ~OsIndicationSupport
) != 0) ||
710 (Attributes
!= (EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
))
713 DEBUG ((EFI_D_ERROR
, "[Bds] Unformalized OsIndications variable exists. Delete it\n"));
714 Status
= gRT
->SetVariable (
716 &gEfiGlobalVariableGuid
,
722 // Deleting variable with current variable implementation shouldn't fail.
724 ASSERT_EFI_ERROR(Status
);
734 BdsFormalizeEfiGlobalVariable (
739 // Validate Console variable.
741 BdsFormalizeConsoleVariable (L
"ConIn");
742 BdsFormalizeConsoleVariable (L
"ConOut");
743 BdsFormalizeConsoleVariable (L
"ErrOut");
746 // Validate OSIndication related variable.
748 BdsFormalizeOSIndicationVariable ();
753 Allocate a block of memory that will contain performance data to OS.
757 BdsAllocateMemoryForPerformanceData (
762 EFI_PHYSICAL_ADDRESS AcpiLowMemoryBase
;
763 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
;
765 AcpiLowMemoryBase
= 0x0FFFFFFFFULL
;
768 // Allocate a block of memory that will contain performance data to OS.
770 Status
= gBS
->AllocatePages (
772 EfiReservedMemoryType
,
773 EFI_SIZE_TO_PAGES (PERF_DATA_MAX_LENGTH
),
776 if (!EFI_ERROR (Status
)) {
778 // Save the pointer to variable for use in S3 resume.
780 Status
= BdsDxeSetVariableAndReportStatusCodeOnError (
782 &gPerformanceProtocolGuid
,
783 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
784 sizeof (EFI_PHYSICAL_ADDRESS
),
787 if (EFI_ERROR (Status
)) {
788 DEBUG ((EFI_D_ERROR
, "[Bds] PerfDataMemAddr (%08x) cannot be saved to NV storage.\n", AcpiLowMemoryBase
));
791 // Mark L"PerfDataMemAddr" variable to read-only if the Variable Lock protocol exists
792 // Still lock it even the variable cannot be saved to prevent it's set by 3rd party code.
794 Status
= gBS
->LocateProtocol (&gEdkiiVariableLockProtocolGuid
, NULL
, (VOID
**) &VariableLock
);
795 if (!EFI_ERROR (Status
)) {
796 Status
= VariableLock
->RequestToLock (VariableLock
, L
"PerfDataMemAddr", &gPerformanceProtocolGuid
);
797 ASSERT_EFI_ERROR (Status
);
804 Service routine for BdsInstance->Entry(). Devices are connected, the
805 consoles are initialized, and the boot options are tried.
807 @param This Protocol Instance structure.
813 IN EFI_BDS_ARCH_PROTOCOL
*This
816 EFI_BOOT_MANAGER_LOAD_OPTION
*LoadOptions
;
817 UINTN LoadOptionCount
;
818 CHAR16
*FirmwareVendor
;
819 EFI_EVENT HotkeyTriggered
;
823 UINT32 BootOptionSupport
;
825 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
;
827 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
829 CHAR16 BootNextVariableName
[sizeof ("Boot####")];
830 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu
;
833 HotkeyTriggered
= NULL
;
834 Status
= EFI_SUCCESS
;
837 // Insert the performance probe
839 PERF_END (NULL
, "DXE", NULL
, 0);
840 PERF_START (NULL
, "BDS", NULL
, 0);
841 DEBUG ((EFI_D_INFO
, "[Bds] Entry...\n"));
844 BdsAllocateMemoryForPerformanceData ();
848 // Fill in FirmwareVendor and FirmwareRevision from PCDs
850 FirmwareVendor
= (CHAR16
*) PcdGetPtr (PcdFirmwareVendor
);
851 gST
->FirmwareVendor
= AllocateRuntimeCopyPool (StrSize (FirmwareVendor
), FirmwareVendor
);
852 ASSERT (gST
->FirmwareVendor
!= NULL
);
853 gST
->FirmwareRevision
= PcdGet32 (PcdFirmwareRevision
);
856 // Fixup Tasble CRC after we updated Firmware Vendor and Revision
859 gBS
->CalculateCrc32 ((VOID
*) gST
, sizeof (EFI_SYSTEM_TABLE
), &gST
->Hdr
.CRC32
);
862 // Validate Variable.
864 BdsFormalizeEfiGlobalVariable ();
867 // Mark the read-only variables if the Variable Lock protocol exists
869 Status
= gBS
->LocateProtocol (&gEdkiiVariableLockProtocolGuid
, NULL
, (VOID
**) &VariableLock
);
870 DEBUG ((EFI_D_INFO
, "[BdsDxe] Locate Variable Lock protocol - %r\n", Status
));
871 if (!EFI_ERROR (Status
)) {
872 for (Index
= 0; Index
< sizeof (mReadOnlyVariables
) / sizeof (mReadOnlyVariables
[0]); Index
++) {
873 Status
= VariableLock
->RequestToLock (VariableLock
, mReadOnlyVariables
[Index
], &gEfiGlobalVariableGuid
);
874 ASSERT_EFI_ERROR (Status
);
878 InitializeHwErrRecSupport ();
881 // Initialize L"Timeout" EFI global variable.
883 BootTimeOut
= PcdGet16 (PcdPlatformBootTimeOut
);
884 if (BootTimeOut
!= 0xFFFF) {
886 // If time out value equal 0xFFFF, no need set to 0xFFFF to variable area because UEFI specification
887 // define same behavior between no value or 0xFFFF value for L"Timeout".
889 BdsDxeSetVariableAndReportStatusCodeOnError (
890 EFI_TIME_OUT_VARIABLE_NAME
,
891 &gEfiGlobalVariableGuid
,
892 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
899 // Initialize L"BootOptionSupport" EFI global variable.
900 // Lazy-ConIn implictly disables BDS hotkey.
902 BootOptionSupport
= EFI_BOOT_OPTION_SUPPORT_APP
| EFI_BOOT_OPTION_SUPPORT_SYSPREP
;
903 if (!PcdGetBool (PcdConInConnectOnDemand
)) {
904 BootOptionSupport
|= EFI_BOOT_OPTION_SUPPORT_KEY
;
905 SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport
, 3);
907 Status
= gRT
->SetVariable (
908 EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME
,
909 &gEfiGlobalVariableGuid
,
910 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
911 sizeof (BootOptionSupport
),
915 // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail.
917 ASSERT_EFI_ERROR (Status
);
920 // Cache and remove the "BootNext" NV variable.
922 GetEfiGlobalVariable2 (EFI_BOOT_NEXT_VARIABLE_NAME
, (VOID
**) &BootNext
, &DataSize
);
923 if (DataSize
!= sizeof (UINT16
)) {
924 if (BootNext
!= NULL
) {
929 Status
= gRT
->SetVariable (
930 EFI_BOOT_NEXT_VARIABLE_NAME
,
931 &gEfiGlobalVariableGuid
,
937 // Deleting NV variable shouldn't fail unless it doesn't exist.
939 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_NOT_FOUND
);
942 // Initialize the platform language variables
944 InitializeLanguage (TRUE
);
947 // Report Status Code to indicate connecting drivers will happen
951 (EFI_SOFTWARE_DXE_BS_DRIVER
| EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS
)
955 // Do the platform init, can be customized by OEM/IBV
956 // Possible things that can be done in PlatformBootManagerBeforeConsole:
957 // > Update console variable: 1. include hot-plug devices; 2. Clear ConIn and add SOL for AMT
958 // > Register new Driver#### or Boot####
959 // > Register new Key####: e.g.: F12
960 // > Signal ReadyToLock event
961 // > Authentication action: 1. connect Auth devices; 2. Identify auto logon user.
963 PERF_START (NULL
, "PlatformBootManagerBeforeConsole", "BDS", 0);
964 PlatformBootManagerBeforeConsole ();
965 PERF_END (NULL
, "PlatformBootManagerBeforeConsole", "BDS", 0);
968 // Initialize hotkey service
970 EfiBootManagerStartHotkeyService (&HotkeyTriggered
);
973 // Execute Driver Options
975 LoadOptions
= EfiBootManagerGetLoadOptions (&LoadOptionCount
, LoadOptionTypeDriver
);
976 ProcessLoadOptions (LoadOptions
, LoadOptionCount
);
977 EfiBootManagerFreeLoadOptions (LoadOptions
, LoadOptionCount
);
982 PERF_START (NULL
, "EfiBootManagerConnectAllDefaultConsoles", "BDS", 0);
983 if (PcdGetBool (PcdConInConnectOnDemand
)) {
984 EfiBootManagerConnectConsoleVariable (ConOut
);
985 EfiBootManagerConnectConsoleVariable (ErrOut
);
988 // Initialize ConnectConIn event
990 Status
= gBS
->CreateEventEx (
993 BdsDxeOnConnectConInCallBack
,
995 &gConnectConInEventGuid
,
998 if (EFI_ERROR (Status
)) {
999 gConnectConInEvent
= NULL
;
1002 EfiBootManagerConnectAllDefaultConsoles ();
1004 PERF_END (NULL
, "EfiBootManagerConnectAllDefaultConsoles", "BDS", 0);
1007 // Do the platform specific action after the console is ready
1008 // Possible things that can be done in PlatformBootManagerAfterConsole:
1009 // > Console post action:
1010 // > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
1011 // > Signal console ready platform customized event
1012 // > Run diagnostics like memory testing
1013 // > Connect certain devices
1014 // > Dispatch aditional option roms
1015 // > Special boot: e.g.: USB boot, enter UI
1017 PERF_START (NULL
, "PlatformBootManagerAfterConsole", "BDS", 0);
1018 PlatformBootManagerAfterConsole ();
1019 PERF_END (NULL
, "PlatformBootManagerAfterConsole", "BDS", 0);
1022 EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType
;
1023 DEBUG ((EFI_D_INFO
, "[Bds]=============Begin Load Options Dumping ...=============\n"));
1024 for (LoadOptionType
= 0; LoadOptionType
< LoadOptionTypeMax
; LoadOptionType
++) {
1026 EFI_D_INFO
, " %s Options:\n",
1027 mBdsLoadOptionName
[LoadOptionType
]
1029 LoadOptions
= EfiBootManagerGetLoadOptions (&LoadOptionCount
, LoadOptionType
);
1030 for (Index
= 0; Index
< LoadOptionCount
; Index
++) {
1032 EFI_D_INFO
, " %s%04x: %s \t\t 0x%04x\n",
1033 mBdsLoadOptionName
[LoadOptionType
],
1034 LoadOptions
[Index
].OptionNumber
,
1035 LoadOptions
[Index
].Description
,
1036 LoadOptions
[Index
].Attributes
1039 EfiBootManagerFreeLoadOptions (LoadOptions
, LoadOptionCount
);
1041 DEBUG ((EFI_D_INFO
, "[Bds]=============End Load Options Dumping=============\n"));
1045 // Boot to Boot Manager Menu when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot
1047 DataSize
= sizeof (UINT64
);
1048 Status
= gRT
->GetVariable (
1050 &gEfiGlobalVariableGuid
,
1055 if (EFI_ERROR (Status
)) {
1059 BootFwUi
= (BOOLEAN
) ((OsIndication
& EFI_OS_INDICATIONS_BOOT_TO_FW_UI
) != 0);
1061 // Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS
1064 OsIndication
&= ~((UINT64
) EFI_OS_INDICATIONS_BOOT_TO_FW_UI
);
1065 Status
= gRT
->SetVariable (
1067 &gEfiGlobalVariableGuid
,
1068 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1073 // Changing the content without increasing its size with current variable implementation shouldn't fail.
1075 ASSERT_EFI_ERROR (Status
);
1079 // Launch Boot Manager Menu directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot
1083 // Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI
1085 if (PcdGetBool (PcdConInConnectOnDemand
)) {
1086 BdsDxeOnConnectConInCallBack (NULL
, NULL
);
1090 // Directly enter the setup page.
1091 // BootManagerMenu always contains the correct information even call fails.
1093 EfiBootManagerGetBootManagerMenu (&BootManagerMenu
);
1094 EfiBootManagerBoot (&BootManagerMenu
);
1095 EfiBootManagerFreeLoadOption (&BootManagerMenu
);
1099 // Execute SysPrep####
1101 LoadOptions
= EfiBootManagerGetLoadOptions (&LoadOptionCount
, LoadOptionTypeSysPrep
);
1102 ProcessLoadOptions (LoadOptions
, LoadOptionCount
);
1103 EfiBootManagerFreeLoadOptions (LoadOptions
, LoadOptionCount
);
1108 PERF_START (NULL
, "BdsWait", "BDS", 0);
1109 BdsWait (HotkeyTriggered
);
1110 PERF_END (NULL
, "BdsWait", "BDS", 0);
1113 // BdsReadKeys() be removed after all keyboard drivers invoke callback in timer callback.
1117 EfiBootManagerHotkeyBoot ();
1120 // Boot to "BootNext"
1122 if (BootNext
!= NULL
) {
1123 UnicodeSPrint (BootNextVariableName
, sizeof (BootNextVariableName
), L
"Boot%04x", *BootNext
);
1124 Status
= EfiBootManagerVariableToLoadOption (BootNextVariableName
, &BootOption
);
1125 if (!EFI_ERROR (Status
)) {
1126 EfiBootManagerBoot (&BootOption
);
1127 EfiBootManagerFreeLoadOption (&BootOption
);
1128 if (BootOption
.Status
== EFI_SUCCESS
) {
1130 // Boot to Boot Manager Menu upon EFI_SUCCESS
1132 EfiBootManagerGetBootManagerMenu (&BootOption
);
1133 EfiBootManagerBoot (&BootOption
);
1134 EfiBootManagerFreeLoadOption (&BootOption
);
1141 // BDS select the boot device to load OS
1142 // Try next upon boot failure
1143 // Show Boot Manager Menu upon boot success
1145 DefaultBootBehavior ();
1150 Set the variable and report the error through status code upon failure.
1152 @param VariableName A Null-terminated string that is the name of the vendor's variable.
1153 Each VariableName is unique for each VendorGuid. VariableName must
1154 contain 1 or more characters. If VariableName is an empty string,
1155 then EFI_INVALID_PARAMETER is returned.
1156 @param VendorGuid A unique identifier for the vendor.
1157 @param Attributes Attributes bitmask to set for the variable.
1158 @param DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE,
1159 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or
1160 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero
1161 causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is
1162 set, then a SetVariable() call with a DataSize of zero will not cause any change to
1163 the variable value (the timestamp associated with the variable may be updated however
1164 even if no new data value is provided,see the description of the
1165 EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not
1166 be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated).
1167 @param Data The contents for the variable.
1169 @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
1170 defined by the Attributes.
1171 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the
1172 DataSize exceeds the maximum allowed.
1173 @retval EFI_INVALID_PARAMETER VariableName is an empty string.
1174 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
1175 @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error.
1176 @retval EFI_WRITE_PROTECTED The variable in question is read-only.
1177 @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted.
1178 @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
1179 or EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the AuthInfo
1180 does NOT pass the validation check carried out by the firmware.
1182 @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found.
1185 BdsDxeSetVariableAndReportStatusCodeOnError (
1186 IN CHAR16
*VariableName
,
1187 IN EFI_GUID
*VendorGuid
,
1188 IN UINT32 Attributes
,
1194 EDKII_SET_VARIABLE_STATUS
*SetVariableStatus
;
1197 Status
= gRT
->SetVariable (
1204 if (EFI_ERROR (Status
)) {
1205 NameSize
= StrSize (VariableName
);
1206 SetVariableStatus
= AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS
) + NameSize
+ DataSize
);
1207 if (SetVariableStatus
!= NULL
) {
1208 CopyGuid (&SetVariableStatus
->Guid
, VendorGuid
);
1209 SetVariableStatus
->NameSize
= NameSize
;
1210 SetVariableStatus
->DataSize
= DataSize
;
1211 SetVariableStatus
->SetStatus
= Status
;
1212 SetVariableStatus
->Attributes
= Attributes
;
1213 CopyMem (SetVariableStatus
+ 1, VariableName
, NameSize
);
1214 CopyMem (((UINT8
*) (SetVariableStatus
+ 1)) + NameSize
, Data
, DataSize
);
1216 REPORT_STATUS_CODE_EX (
1218 PcdGet32 (PcdErrorCodeSetVariable
),
1221 &gEdkiiStatusCodeDataTypeVariableGuid
,
1223 sizeof (EDKII_SET_VARIABLE_STATUS
) + NameSize
+ DataSize
1226 FreePool (SetVariableStatus
);