TianoCore EDK2 master
Loading...
Searching...
No Matches
BdsEntry.c
Go to the documentation of this file.
1
15#include "Bds.h"
16#include "Language.h"
17#include "HwErrRecSupport.h"
18#include <Library/VariablePolicyHelperLib.h>
19
20#define SET_BOOT_OPTION_SUPPORT_KEY_COUNT(a, c) { \
21 (a) = ((a) & ~EFI_BOOT_OPTION_SUPPORT_COUNT) | (((c) << LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT)) & EFI_BOOT_OPTION_SUPPORT_COUNT); \
22 }
23
29};
30
31//
32// gConnectConInEvent - Event which is signaled when ConIn connection is required
33//
34EFI_EVENT gConnectConInEvent = NULL;
35
39CHAR16 *mReadOnlyVariables[] = {
45};
46
47CHAR16 *mBdsLoadOptionName[] = {
48 L"Driver",
49 L"SysPrep",
50 L"Boot",
51 L"PlatformRecovery"
52};
53
62VOID
63EFIAPI
65 IN EFI_EVENT Event,
66 IN VOID *Context
67 )
68{
69 EFI_STATUS Status;
70
71 //
72 // When Osloader call ReadKeyStroke to signal this event
73 // no driver dependency is assumed existing. So use a non-dispatch version
74 //
76 if (EFI_ERROR (Status)) {
77 //
78 // Should not enter this case, if enter, the keyboard will not work.
79 // May need platfrom policy to connect keyboard.
80 //
81 DEBUG ((DEBUG_WARN, "[Bds] Connect ConIn failed - %r!!!\n", Status));
82 }
83}
84
93VOID
94EFIAPI
96 IN EFI_EVENT Event,
97 IN VOID *Context
98 )
99{
100 EFI_STATUS Status;
102 UINTN HandleCount;
103 EFI_HANDLE *Handles;
104 UINTN Index;
105 UINTN ImageIndex;
106 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
107 VOID *Image;
108 UINTN ImageSize;
109 BOOLEAN BootOption;
110 CHAR16 *DevicePathStr;
111
112 //
113 // Find all the deferred image load protocols.
114 //
115 HandleCount = 0;
116 Handles = NULL;
117 Status = gBS->LocateHandleBuffer (
119 &gEfiDeferredImageLoadProtocolGuid,
120 NULL,
121 &HandleCount,
122 &Handles
123 );
124 if (EFI_ERROR (Status)) {
125 return;
126 }
127
128 for (Index = 0; Index < HandleCount; Index++) {
129 Status = gBS->HandleProtocol (Handles[Index], &gEfiDeferredImageLoadProtocolGuid, (VOID **)&DeferredImage);
130 if (EFI_ERROR (Status)) {
131 continue;
132 }
133
134 for (ImageIndex = 0; ; ImageIndex++) {
135 //
136 // Load all the deferred images in this protocol instance.
137 //
138 Status = DeferredImage->GetImageInfo (
139 DeferredImage,
140 ImageIndex,
141 &ImageDevicePath,
142 (VOID **)&Image,
143 &ImageSize,
144 &BootOption
145 );
146 if (EFI_ERROR (Status)) {
147 break;
148 }
149
150 DevicePathStr = ConvertDevicePathToText (ImageDevicePath, FALSE, FALSE);
151 DEBUG ((DEBUG_LOAD, "[Bds] Image was deferred but not loaded: %s.\n", DevicePathStr));
152 if (DevicePathStr != NULL) {
153 FreePool (DevicePathStr);
154 }
155 }
156 }
157
158 if (Handles != NULL) {
159 FreePool (Handles);
160 }
161}
162
176EFIAPI
178 IN EFI_HANDLE ImageHandle,
179 IN EFI_SYSTEM_TABLE *SystemTable
180 )
181{
182 EFI_STATUS Status;
183 EFI_HANDLE Handle;
184
185 //
186 // Install protocol interface
187 //
188 Handle = NULL;
189 Status = gBS->InstallMultipleProtocolInterfaces (
190 &Handle,
191 &gEfiBdsArchProtocolGuid,
192 &gBds,
193 NULL
194 );
195 ASSERT_EFI_ERROR (Status);
196
197 DEBUG_CODE (
198 EFI_EVENT Event;
199 //
200 // Register notify function to check deferred images on ReadyToBoot Event.
201 //
202 Status = gBS->CreateEventEx (
203 EVT_NOTIFY_SIGNAL,
204 TPL_CALLBACK,
206 NULL,
207 &gEfiEventReadyToBootGuid,
208 &Event
209 );
210 ASSERT_EFI_ERROR (Status);
211 );
212 return Status;
213}
214
227 IN EFI_EVENT Event,
228 IN UINT64 Timeout OPTIONAL
229 )
230{
231 UINTN Index;
232 EFI_STATUS Status;
233 EFI_EVENT TimerEvent;
234 EFI_EVENT WaitList[2];
235
236 if (Timeout != 0) {
237 //
238 // Create a timer event
239 //
240 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
241 if (!EFI_ERROR (Status)) {
242 //
243 // Set the timer event
244 //
245 gBS->SetTimer (
246 TimerEvent,
248 Timeout
249 );
250
251 //
252 // Wait for the original event or the timer
253 //
254 WaitList[0] = Event;
255 WaitList[1] = TimerEvent;
256 Status = gBS->WaitForEvent (2, WaitList, &Index);
257 ASSERT_EFI_ERROR (Status);
258 gBS->CloseEvent (TimerEvent);
259
260 //
261 // If the timer expired, change the return to timed out
262 //
263 if (Index == 1) {
264 Status = EFI_TIMEOUT;
265 }
266 }
267 } else {
268 //
269 // No timeout... just wait on the event
270 //
271 Status = gBS->WaitForEvent (1, &Event, &Index);
272 ASSERT (!EFI_ERROR (Status));
273 ASSERT (Index == 0);
274 }
275
276 return Status;
277}
278
283VOID
285 VOID
286 )
287{
288 EFI_STATUS Status;
289 EFI_INPUT_KEY Key;
290
291 if (PcdGetBool (PcdConInConnectOnDemand)) {
292 return;
293 }
294
295 while (gST->ConIn != NULL) {
296 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
297
298 if (EFI_ERROR (Status)) {
299 //
300 // No more keys.
301 //
302 break;
303 }
304 }
305}
306
314VOID
316 IN EFI_EVENT HotkeyTriggered
317 )
318{
319 EFI_STATUS Status;
320 UINT16 TimeoutRemain;
321
322 DEBUG ((DEBUG_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n"));
323
324 TimeoutRemain = PcdGet16 (PcdPlatformBootTimeOut);
325 while (TimeoutRemain != 0) {
326 DEBUG ((DEBUG_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN)TimeoutRemain));
327 PlatformBootManagerWaitCallback (TimeoutRemain);
328
329 BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered
330 // Can be removed after all keyboard drivers invoke callback in timer callback.
331
332 if (HotkeyTriggered != NULL) {
333 Status = BdsWaitForSingleEvent (HotkeyTriggered, EFI_TIMER_PERIOD_SECONDS (1));
334 if (!EFI_ERROR (Status)) {
335 break;
336 }
337 } else {
338 gBS->Stall (1000000);
339 }
340
341 //
342 // 0xffff means waiting forever
343 // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop
344 //
345 if (TimeoutRemain != 0xffff) {
346 TimeoutRemain--;
347 }
348 }
349
350 //
351 // If the platform configured a nonzero and finite time-out, and we have
352 // actually reached that, report 100% completion to the platform.
353 //
354 // Note that the (TimeoutRemain == 0) condition excludes
355 // PcdPlatformBootTimeOut=0xFFFF, and that's deliberate.
356 //
357 if ((PcdGet16 (PcdPlatformBootTimeOut) != 0) && (TimeoutRemain == 0)) {
359 }
360
361 DEBUG ((DEBUG_INFO, "[Bds]Exit the waiting!\n"));
362}
363
374BOOLEAN
376 IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions,
377 IN UINTN BootOptionCount,
378 IN EFI_BOOT_MANAGER_LOAD_OPTION *BootManagerMenu OPTIONAL
379 )
380{
381 UINTN Index;
382
383 //
384 // Report Status Code to indicate BDS starts attempting booting from the UEFI BootOrder list.
385 //
386 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_ATTEMPT_BOOT_ORDER_EVENT));
387
388 //
389 // Attempt boot each boot option
390 //
391 for (Index = 0; Index < BootOptionCount; Index++) {
392 //
393 // According to EFI Specification, if a load option is not marked
394 // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
395 // load the option.
396 //
397 if ((BootOptions[Index].Attributes & LOAD_OPTION_ACTIVE) == 0) {
398 continue;
399 }
400
401 //
402 // Boot#### load options with LOAD_OPTION_CATEGORY_APP are executables which are not
403 // part of the normal boot processing. Boot options with reserved category values will be
404 // ignored by the boot manager.
405 //
406 if ((BootOptions[Index].Attributes & LOAD_OPTION_CATEGORY) != LOAD_OPTION_CATEGORY_BOOT) {
407 continue;
408 }
409
410 //
411 // All the driver options should have been processed since
412 // now boot will be performed.
413 //
414 EfiBootManagerBoot (&BootOptions[Index]);
415
416 //
417 // If the boot via Boot#### returns with a status of EFI_SUCCESS, platform firmware
418 // supports boot manager menu, and if firmware is configured to boot in an
419 // interactive mode, the boot manager will stop processing the BootOrder variable and
420 // present a boot manager menu to the user.
421 //
422 if ((BootManagerMenu != NULL) && (BootOptions[Index].Status == EFI_SUCCESS)) {
423 EfiBootManagerBoot (BootManagerMenu);
424 break;
425 }
426 }
427
428 return (BOOLEAN)(Index < BootOptionCount);
429}
430
437VOID
439 IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOptions,
440 IN UINTN LoadOptionCount
441 )
442{
443 EFI_STATUS Status;
444 UINTN Index;
445 BOOLEAN ReconnectAll;
446 EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType;
447
448 ReconnectAll = FALSE;
449 LoadOptionType = LoadOptionTypeMax;
450
451 //
452 // Process the driver option
453 //
454 for (Index = 0; Index < LoadOptionCount; Index++) {
455 //
456 // All the load options in the array should be of the same type.
457 //
458 if (Index == 0) {
459 LoadOptionType = LoadOptions[Index].OptionType;
460 }
461
462 ASSERT (LoadOptionType == LoadOptions[Index].OptionType);
463 ASSERT (LoadOptionType != LoadOptionTypeBoot);
464
465 Status = EfiBootManagerProcessLoadOption (&LoadOptions[Index]);
466
467 //
468 // Status indicates whether the load option is loaded and executed
469 // LoadOptions[Index].Status is what the load option returns
470 //
471 if (!EFI_ERROR (Status)) {
472 //
473 // Stop processing if any PlatformRecovery#### returns success.
474 //
475 if ((LoadOptions[Index].Status == EFI_SUCCESS) &&
476 (LoadOptionType == LoadOptionTypePlatformRecovery))
477 {
478 break;
479 }
480
481 //
482 // Only set ReconnectAll flag when the load option executes successfully.
483 //
484 if (!EFI_ERROR (LoadOptions[Index].Status) &&
485 ((LoadOptions[Index].Attributes & LOAD_OPTION_FORCE_RECONNECT) != 0))
486 {
487 ReconnectAll = TRUE;
488 }
489 }
490 }
491
492 //
493 // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,
494 // then all of the EFI drivers in the system will be disconnected and
495 // reconnected after the last driver load option is processed.
496 //
497 if (ReconnectAll && (LoadOptionType == LoadOptionTypeDriver)) {
500 }
501}
502
512VOID
514 IN CHAR16 *VariableName
515 )
516{
517 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
518 UINTN VariableSize;
519 EFI_STATUS Status;
520
521 GetEfiGlobalVariable2 (VariableName, (VOID **)&DevicePath, &VariableSize);
522 if ((DevicePath != NULL) && !IsDevicePathValid (DevicePath, VariableSize)) {
523 Status = gRT->SetVariable (
524 VariableName,
525 &gEfiGlobalVariableGuid,
526 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
527 0,
528 NULL
529 );
530 //
531 // Deleting variable with current variable implementation shouldn't fail.
532 //
533 ASSERT_EFI_ERROR (Status);
534 }
535
536 if (DevicePath != NULL) {
537 FreePool (DevicePath);
538 }
539}
540
552VOID
554 VOID
555 )
556{
557 EFI_STATUS Status;
558 UINT64 OsIndicationSupport;
559 UINT64 OsIndication;
560 UINTN DataSize;
561 UINT32 Attributes;
562 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
563
564 //
565 // OS indicater support variable
566 //
567 Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
568 if (Status != EFI_NOT_FOUND) {
569 OsIndicationSupport = EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
570 EfiBootManagerFreeLoadOption (&BootManagerMenu);
571 } else {
572 OsIndicationSupport = 0;
573 }
574
575 if (PcdGetBool (PcdPlatformRecoverySupport)) {
576 OsIndicationSupport |= EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY;
577 }
578
579 if (PcdGetBool (PcdCapsuleOnDiskSupport)) {
580 OsIndicationSupport |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
581 }
582
583 Status = gRT->SetVariable (
585 &gEfiGlobalVariableGuid,
586 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
587 sizeof (UINT64),
588 &OsIndicationSupport
589 );
590 //
591 // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail.
592 //
593 ASSERT_EFI_ERROR (Status);
594
595 //
596 // If OsIndications is invalid, remove it.
597 // Invalid case
598 // 1. Data size != UINT64
599 // 2. OsIndication value inconsistence
600 // 3. OsIndication attribute inconsistence
601 //
602 OsIndication = 0;
603 Attributes = 0;
604 DataSize = sizeof (UINT64);
605 Status = gRT->GetVariable (
607 &gEfiGlobalVariableGuid,
608 &Attributes,
609 &DataSize,
610 &OsIndication
611 );
612 if (Status == EFI_NOT_FOUND) {
613 return;
614 }
615
616 if ((DataSize != sizeof (OsIndication)) ||
617 ((OsIndication & ~OsIndicationSupport) != 0) ||
618 (Attributes != (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE))
619 )
620 {
621 DEBUG ((DEBUG_ERROR, "[Bds] Unformalized OsIndications variable exists. Delete it\n"));
622 Status = gRT->SetVariable (
624 &gEfiGlobalVariableGuid,
625 0,
626 0,
627 NULL
628 );
629 //
630 // Deleting variable with current variable implementation shouldn't fail.
631 //
632 ASSERT_EFI_ERROR (Status);
633 }
634}
635
641VOID
643 VOID
644 )
645{
646 //
647 // Validate Console variable.
648 //
650 BdsFormalizeConsoleVariable (EFI_CON_OUT_VARIABLE_NAME);
651 BdsFormalizeConsoleVariable (EFI_ERR_OUT_VARIABLE_NAME);
652
653 //
654 // Validate OSIndication related variable.
655 //
657}
658
667VOID
668EFIAPI
671 )
672{
673 EFI_BOOT_MANAGER_LOAD_OPTION *LoadOptions;
674 UINTN LoadOptionCount;
675 CHAR16 *FirmwareVendor;
676 EFI_EVENT HotkeyTriggered;
677 UINT64 OsIndication;
678 UINTN DataSize;
679 EFI_STATUS Status;
680 UINT32 BootOptionSupport;
681 UINT16 BootTimeOut;
682 EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy;
683 UINTN Index;
685 UINT16 *BootNext;
686 CHAR16 BootNextVariableName[sizeof ("Boot####")];
687 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
688 BOOLEAN BootFwUi;
689 BOOLEAN PlatformRecovery;
690 BOOLEAN BootSuccess;
691 EFI_DEVICE_PATH_PROTOCOL *FilePath;
692 EFI_STATUS BootManagerMenuStatus;
693 EFI_BOOT_MANAGER_LOAD_OPTION PlatformDefaultBootOption;
694 BOOLEAN PlatformDefaultBootOptionValid;
695
696 HotkeyTriggered = NULL;
697 Status = EFI_SUCCESS;
698 BootSuccess = FALSE;
699
700 //
701 // Insert the performance probe
702 //
703 PERF_CROSSMODULE_END ("DXE");
705 DEBUG ((DEBUG_INFO, "[Bds] Entry...\n"));
706
707 //
708 // Fill in FirmwareVendor and FirmwareRevision from PCDs
709 //
710 FirmwareVendor = (CHAR16 *)PcdGetPtr (PcdFirmwareVendor);
711 gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor);
712 ASSERT (gST->FirmwareVendor != NULL);
713 gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision);
714
715 //
716 // Fixup Tasble CRC after we updated Firmware Vendor and Revision
717 //
718 gST->Hdr.CRC32 = 0;
719 gBS->CalculateCrc32 ((VOID *)gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);
720
721 //
722 // Validate Variable.
723 //
725
726 //
727 // Mark the read-only variables if the Variable Lock protocol exists
728 //
729 Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicy);
730 DEBUG ((DEBUG_INFO, "[BdsDxe] Locate Variable Policy protocol - %r\n", Status));
731 if (!EFI_ERROR (Status)) {
732 for (Index = 0; Index < ARRAY_SIZE (mReadOnlyVariables); Index++) {
733 Status = RegisterBasicVariablePolicy (
734 VariablePolicy,
735 &gEfiGlobalVariableGuid,
736 mReadOnlyVariables[Index],
737 VARIABLE_POLICY_NO_MIN_SIZE,
738 VARIABLE_POLICY_NO_MAX_SIZE,
739 VARIABLE_POLICY_NO_MUST_ATTR,
740 VARIABLE_POLICY_NO_CANT_ATTR,
741 VARIABLE_POLICY_TYPE_LOCK_NOW
742 );
743 ASSERT_EFI_ERROR (Status);
744 }
745 }
746
748
749 //
750 // Initialize L"Timeout" EFI global variable.
751 //
752 BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut);
753 if (BootTimeOut != 0xFFFF) {
754 //
755 // If time out value equal 0xFFFF, no need set to 0xFFFF to variable area because UEFI specification
756 // define same behavior between no value or 0xFFFF value for L"Timeout".
757 //
760 &gEfiGlobalVariableGuid,
761 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
762 sizeof (UINT16),
763 &BootTimeOut
764 );
765 }
766
767 //
768 // Initialize L"BootOptionSupport" EFI global variable.
769 // Lazy-ConIn implictly disables BDS hotkey.
770 //
771 BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_APP | EFI_BOOT_OPTION_SUPPORT_SYSPREP;
772 if (!PcdGetBool (PcdConInConnectOnDemand)) {
773 BootOptionSupport |= EFI_BOOT_OPTION_SUPPORT_KEY;
774 SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);
775 }
776
777 Status = gRT->SetVariable (
779 &gEfiGlobalVariableGuid,
780 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
781 sizeof (BootOptionSupport),
782 &BootOptionSupport
783 );
784 //
785 // Platform needs to make sure setting volatile variable before calling 3rd party code shouldn't fail.
786 //
787 ASSERT_EFI_ERROR (Status);
788
789 //
790 // Cache the "BootNext" NV variable before calling any PlatformBootManagerLib APIs
791 // This could avoid the "BootNext" set by PlatformBootManagerLib be consumed in this boot.
792 //
793 GetEfiGlobalVariable2 (EFI_BOOT_NEXT_VARIABLE_NAME, (VOID **)&BootNext, &DataSize);
794 if (DataSize != sizeof (UINT16)) {
795 if (BootNext != NULL) {
796 FreePool (BootNext);
797 }
798
799 BootNext = NULL;
800 }
801
802 //
803 // Initialize the platform language variables
804 //
806
807 FilePath = FileDevicePath (NULL, EFI_REMOVABLE_MEDIA_FILE_NAME);
808 if (FilePath == NULL) {
809 DEBUG ((DEBUG_ERROR, "Fail to allocate memory for default boot file path. Unable to boot.\n"));
810 CpuDeadLoop ();
811 }
812
813 PlatformDefaultBootOptionValid = EfiBootManagerInitializeLoadOption (
814 &PlatformDefaultBootOption,
815 LoadOptionNumberUnassigned,
816 LoadOptionTypePlatformRecovery,
817 LOAD_OPTION_ACTIVE,
818 L"Default PlatformRecovery",
819 FilePath,
820 NULL,
821 0
822 ) == EFI_SUCCESS;
823 ASSERT (PlatformDefaultBootOptionValid == TRUE);
824
825 //
826 // System firmware must include a PlatformRecovery#### variable specifying
827 // a short-form File Path Media Device Path containing the platform default
828 // file path for removable media if the platform supports Platform Recovery.
829 //
830 if (PlatformDefaultBootOptionValid && PcdGetBool (PcdPlatformRecoverySupport)) {
831 LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypePlatformRecovery);
832 if (EfiBootManagerFindLoadOption (&PlatformDefaultBootOption, LoadOptions, LoadOptionCount) == -1) {
833 for (Index = 0; Index < LoadOptionCount; Index++) {
834 //
835 // The PlatformRecovery#### options are sorted by OptionNumber.
836 // Find the the smallest unused number as the new OptionNumber.
837 //
838 if (LoadOptions[Index].OptionNumber != Index) {
839 break;
840 }
841 }
842
843 PlatformDefaultBootOption.OptionNumber = Index;
844 Status = EfiBootManagerLoadOptionToVariable (&PlatformDefaultBootOption);
845 ASSERT_EFI_ERROR (Status);
846 }
847
848 EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
849 }
850
851 FreePool (FilePath);
852
853 //
854 // Report Status Code to indicate connecting drivers will happen
855 //
858 (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS)
859 );
860
861 //
862 // Initialize ConnectConIn event before calling platform code.
863 //
864 if (PcdGetBool (PcdConInConnectOnDemand)) {
865 Status = gBS->CreateEventEx (
866 EVT_NOTIFY_SIGNAL,
867 TPL_CALLBACK,
869 NULL,
870 &gConnectConInEventGuid,
871 &gConnectConInEvent
872 );
873 if (EFI_ERROR (Status)) {
874 gConnectConInEvent = NULL;
875 }
876 }
877
878 //
879 // Do the platform init, can be customized by OEM/IBV
880 // Possible things that can be done in PlatformBootManagerBeforeConsole:
881 // > Update console variable: 1. include hot-plug devices; 2. Clear ConIn and add SOL for AMT
882 // > Register new Driver#### or Boot####
883 // > Register new Key####: e.g.: F12
884 // > Signal ReadyToLock event
885 // > Authentication action: 1. connect Auth devices; 2. Identify auto logon user.
886 //
887 PERF_INMODULE_BEGIN ("PlatformBootManagerBeforeConsole");
889 PERF_INMODULE_END ("PlatformBootManagerBeforeConsole");
890
891 //
892 // Initialize hotkey service
893 //
894 EfiBootManagerStartHotkeyService (&HotkeyTriggered);
895
896 //
897 // Execute Driver Options
898 //
899 LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypeDriver);
900 ProcessLoadOptions (LoadOptions, LoadOptionCount);
901 EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
902
903 //
904 // Connect consoles
905 //
906 PERF_INMODULE_BEGIN ("EfiBootManagerConnectAllDefaultConsoles");
907 if (PcdGetBool (PcdConInConnectOnDemand)) {
910 //
911 // Do not connect ConIn devices when lazy ConIn feature is ON.
912 //
913 } else {
915 }
916
917 PERF_INMODULE_END ("EfiBootManagerConnectAllDefaultConsoles");
918
919 //
920 // Do the platform specific action after the console is ready
921 // Possible things that can be done in PlatformBootManagerAfterConsole:
922 // > Console post action:
923 // > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
924 // > Signal console ready platform customized event
925 // > Run diagnostics like memory testing
926 // > Connect certain devices
927 // > Dispatch aditional option roms
928 // > Special boot: e.g.: USB boot, enter UI
929 //
930 PERF_INMODULE_BEGIN ("PlatformBootManagerAfterConsole");
932 PERF_INMODULE_END ("PlatformBootManagerAfterConsole");
933
934 //
935 // If any component set PcdTestKeyUsed to TRUE because use of a test key
936 // was detected, then display a warning message on the debug log and the console
937 //
938 if (PcdGetBool (PcdTestKeyUsed)) {
939 DEBUG ((DEBUG_ERROR, "**********************************\n"));
940 DEBUG ((DEBUG_ERROR, "** WARNING: Test Key is used. **\n"));
941 DEBUG ((DEBUG_ERROR, "**********************************\n"));
942 Print (L"** WARNING: Test Key is used. **\n");
943 }
944
945 //
946 // Boot to Boot Manager Menu when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot
947 //
948 DataSize = sizeof (UINT64);
949 Status = gRT->GetVariable (
951 &gEfiGlobalVariableGuid,
952 NULL,
953 &DataSize,
954 &OsIndication
955 );
956 if (EFI_ERROR (Status)) {
957 OsIndication = 0;
958 }
959
961 EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType;
962
963 DEBUG ((DEBUG_INFO, "[Bds]OsIndication: %016x\n", OsIndication));
964 DEBUG ((DEBUG_INFO, "[Bds]=============Begin Load Options Dumping ...=============\n"));
965 for (LoadOptionType = 0; LoadOptionType < LoadOptionTypeMax; LoadOptionType++) {
966 DEBUG ((
967 DEBUG_INFO,
968 " %s Options:\n",
969 mBdsLoadOptionName[LoadOptionType]
970 ));
971 LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionType);
972 for (Index = 0; Index < LoadOptionCount; Index++) {
973 DEBUG ((
974 DEBUG_INFO,
975 " %s%04x: %s \t\t 0x%04x\n",
976 mBdsLoadOptionName[LoadOptionType],
977 LoadOptions[Index].OptionNumber,
978 LoadOptions[Index].Description,
979 LoadOptions[Index].Attributes
980 ));
981 }
982
983 EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
984 }
985
986 DEBUG ((DEBUG_INFO, "[Bds]=============End Load Options Dumping=============\n"));
988
989 //
990 // BootManagerMenu doesn't contain the correct information when return status is EFI_NOT_FOUND.
991 //
992 BootManagerMenuStatus = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
993
994 BootFwUi = (BOOLEAN)((OsIndication & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0);
995 PlatformRecovery = (BOOLEAN)((OsIndication & EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY) != 0);
996 //
997 // Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS
998 //
999 if (BootFwUi || PlatformRecovery) {
1000 OsIndication &= ~((UINT64)(EFI_OS_INDICATIONS_BOOT_TO_FW_UI | EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY));
1001 Status = gRT->SetVariable (
1003 &gEfiGlobalVariableGuid,
1004 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
1005 sizeof (UINT64),
1006 &OsIndication
1007 );
1008 //
1009 // Changing the content without increasing its size with current variable implementation shouldn't fail.
1010 //
1011 ASSERT_EFI_ERROR (Status);
1012 }
1013
1014 //
1015 // Launch Boot Manager Menu directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot
1016 //
1017 if (BootFwUi && (BootManagerMenuStatus != EFI_NOT_FOUND)) {
1018 //
1019 // Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI
1020 //
1021 if (PcdGetBool (PcdConInConnectOnDemand)) {
1023 }
1024
1025 //
1026 // Directly enter the setup page.
1027 //
1028 EfiBootManagerBoot (&BootManagerMenu);
1029 }
1030
1031 if (!PlatformRecovery) {
1032 //
1033 // Execute SysPrep####
1034 //
1035 LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypeSysPrep);
1036 ProcessLoadOptions (LoadOptions, LoadOptionCount);
1037 EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
1038
1039 //
1040 // Execute Key####
1041 //
1042 PERF_INMODULE_BEGIN ("BdsWait");
1043 BdsWait (HotkeyTriggered);
1044 PERF_INMODULE_END ("BdsWait");
1045 //
1046 // BdsReadKeys() can be removed after all keyboard drivers invoke callback in timer callback.
1047 //
1048 BdsReadKeys ();
1049
1051
1052 if (BootNext != NULL) {
1053 //
1054 // Delete "BootNext" NV variable before transferring control to it to prevent loops.
1055 //
1056 Status = gRT->SetVariable (
1058 &gEfiGlobalVariableGuid,
1059 0,
1060 0,
1061 NULL
1062 );
1063 //
1064 // Deleting NV variable shouldn't fail unless it doesn't exist.
1065 //
1066 ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);
1067
1068 //
1069 // Boot to "BootNext"
1070 //
1071 UnicodeSPrint (BootNextVariableName, sizeof (BootNextVariableName), L"Boot%04x", *BootNext);
1072 Status = EfiBootManagerVariableToLoadOption (BootNextVariableName, &LoadOption);
1073 if (!EFI_ERROR (Status)) {
1074 EfiBootManagerBoot (&LoadOption);
1075 EfiBootManagerFreeLoadOption (&LoadOption);
1076 if ((LoadOption.Status == EFI_SUCCESS) &&
1077 (BootManagerMenuStatus != EFI_NOT_FOUND) &&
1078 (LoadOption.OptionNumber != BootManagerMenu.OptionNumber))
1079 {
1080 //
1081 // Boot to Boot Manager Menu upon EFI_SUCCESS
1082 // Exception: Do not boot again when the BootNext points to Boot Manager Menu.
1083 //
1084 EfiBootManagerBoot (&BootManagerMenu);
1085 }
1086 }
1087 }
1088
1089 do {
1090 //
1091 // Retry to boot if any of the boot succeeds
1092 //
1093 LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypeBoot);
1094 BootSuccess = BootBootOptions (LoadOptions, LoadOptionCount, (BootManagerMenuStatus != EFI_NOT_FOUND) ? &BootManagerMenu : NULL);
1095 EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
1096 } while (BootSuccess);
1097 }
1098
1099 if (BootManagerMenuStatus != EFI_NOT_FOUND) {
1100 EfiBootManagerFreeLoadOption (&BootManagerMenu);
1101 }
1102
1103 if (!BootSuccess) {
1104 if (PcdGetBool (PcdPlatformRecoverySupport)) {
1105 LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypePlatformRecovery);
1106 ProcessLoadOptions (LoadOptions, LoadOptionCount);
1107 EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);
1108 } else if (PlatformDefaultBootOptionValid) {
1109 //
1110 // When platform recovery is not enabled, still boot to platform default file path.
1111 //
1112 PlatformDefaultBootOptionValid = EfiBootManagerProcessLoadOption (&PlatformDefaultBootOption) == EFI_SUCCESS;
1113 }
1114 }
1115
1116 if (PlatformDefaultBootOptionValid) {
1117 EfiBootManagerFreeLoadOption (&PlatformDefaultBootOption);
1118 }
1119
1120 DEBUG ((DEBUG_ERROR, "[Bds] Unable to boot!\n"));
1122 CpuDeadLoop ();
1123}
1124
1160 IN CHAR16 *VariableName,
1161 IN EFI_GUID *VendorGuid,
1162 IN UINT32 Attributes,
1163 IN UINTN DataSize,
1164 IN VOID *Data
1165 )
1166{
1167 EFI_STATUS Status;
1168 EDKII_SET_VARIABLE_STATUS *SetVariableStatus;
1169 UINTN NameSize;
1170
1171 Status = gRT->SetVariable (
1172 VariableName,
1173 VendorGuid,
1174 Attributes,
1175 DataSize,
1176 Data
1177 );
1178 if (EFI_ERROR (Status)) {
1179 NameSize = StrSize (VariableName);
1180 SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize);
1181 if (SetVariableStatus != NULL) {
1182 CopyGuid (&SetVariableStatus->Guid, VendorGuid);
1183 SetVariableStatus->NameSize = NameSize;
1184 SetVariableStatus->DataSize = DataSize;
1185 SetVariableStatus->SetStatus = Status;
1186 SetVariableStatus->Attributes = Attributes;
1187 CopyMem (SetVariableStatus + 1, VariableName, NameSize);
1188 CopyMem (((UINT8 *)(SetVariableStatus + 1)) + NameSize, Data, DataSize);
1189
1191 EFI_ERROR_CODE,
1192 PcdGet32 (PcdErrorCodeSetVariable),
1193 0,
1194 NULL,
1195 &gEdkiiStatusCodeDataTypeVariableGuid,
1196 SetVariableStatus,
1197 sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize
1198 );
1199
1200 FreePool (SetVariableStatus);
1201 }
1202 }
1203
1204 return Status;
1205}
UINT64 UINTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
VOID EFIAPI CpuDeadLoop(VOID)
Definition: CpuDeadLoop.c:25
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
VOID BdsFormalizeOSIndicationVariable(VOID)
Definition: BdsEntry.c:553
CHAR16 * mReadOnlyVariables[]
Definition: BdsEntry.c:39
VOID BdsWait(IN EFI_EVENT HotkeyTriggered)
Definition: BdsEntry.c:315
VOID EFIAPI CheckDeferredLoadImageOnReadyToBoot(IN EFI_EVENT Event, IN VOID *Context)
Definition: BdsEntry.c:95
BOOLEAN BootBootOptions(IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions, IN UINTN BootOptionCount, IN EFI_BOOT_MANAGER_LOAD_OPTION *BootManagerMenu OPTIONAL)
Definition: BdsEntry.c:375
VOID EFIAPI BdsEntry(IN EFI_BDS_ARCH_PROTOCOL *This)
Definition: BdsEntry.c:669
VOID BdsReadKeys(VOID)
Definition: BdsEntry.c:284
VOID EFIAPI BdsDxeOnConnectConInCallBack(IN EFI_EVENT Event, IN VOID *Context)
Definition: BdsEntry.c:64
VOID BdsFormalizeEfiGlobalVariable(VOID)
Definition: BdsEntry.c:642
EFI_BDS_ARCH_PROTOCOL gBds
Definition: BdsEntry.c:27
VOID ProcessLoadOptions(IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOptions, IN UINTN LoadOptionCount)
Definition: BdsEntry.c:438
EFI_STATUS BdsDxeSetVariableAndReportStatusCodeOnError(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data)
Definition: BdsEntry.c:1159
EFI_STATUS BdsWaitForSingleEvent(IN EFI_EVENT Event, IN UINT64 Timeout OPTIONAL)
Definition: BdsEntry.c:226
EFI_STATUS EFIAPI BdsInitialize(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: BdsEntry.c:177
VOID BdsFormalizeConsoleVariable(IN CHAR16 *VariableName)
Definition: BdsEntry.c:513
EFI_DEVICE_PATH_PROTOCOL *EFIAPI FileDevicePath(IN EFI_HANDLE Device OPTIONAL, IN CONST CHAR16 *FileName)
BOOLEAN EFIAPI IsDevicePathValid(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINTN MaxSize)
CHAR16 *EFIAPI ConvertDevicePathToText(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN BOOLEAN DisplayOnly, IN BOOLEAN AllowShortcuts)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateRuntimeCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define EFI_OS_INDICATIONS_VARIABLE_NAME
#define EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME
#define EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME
#define EFI_PLATFORM_LANG_CODES_VARIABLE_NAME
#define EFI_CON_IN_VARIABLE_NAME
#define EFI_LANG_CODES_VARIABLE_NAME
#define EFI_BOOT_NEXT_VARIABLE_NAME
#define EFI_TIME_OUT_VARIABLE_NAME
#define EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME
VOID InitializeHwErrRecSupport(VOID)
VOID InitializeLanguage(BOOLEAN LangCodesSettingRequired)
Definition: Language.c:155
VOID EFIAPI PlatformBootManagerBeforeConsole(VOID)
Definition: LinuxBootBm.c:114
VOID EFIAPI PlatformBootManagerWaitCallback(UINT16 TimeoutRemain)
Definition: LinuxBootBm.c:166
VOID EFIAPI PlatformBootManagerUnableToBoot(VOID)
Definition: LinuxBootBm.c:182
VOID EFIAPI PlatformBootManagerAfterConsole(VOID)
Definition: LinuxBootBm.c:136
UINTN EFIAPI UnicodeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
Definition: PrintLib.c:408
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:564
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define DEBUG_CODE_END()
Definition: DebugLib.h:578
#define DEBUG_CODE(Expression)
Definition: DebugLib.h:590
#define REPORT_STATUS_CODE_EX(Type, Value, Instance, CallerId, ExtendedDataGuid, ExtendedData, ExtendedDataSize)
#define REPORT_STATUS_CODE(Type, Value)
#define PcdGet16(TokenName)
Definition: PcdLib.h:349
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
#define PcdGetPtr(TokenName)
Definition: PcdLib.h:388
#define PERF_INMODULE_BEGIN(MeasurementString)
#define PERF_CROSSMODULE_BEGIN(MeasurementString)
#define PERF_INMODULE_END(MeasurementString)
#define PERF_CROSSMODULE_END(MeasurementString)
#define EFI_PROGRESS_CODE
Definition: PiStatusCode.h:43
#define EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS EFIAPI EfiBootManagerConnectConsoleVariable(IN CONSOLE_TYPE ConsoleType)
Definition: BmConsole.c:521
EFI_STATUS EFIAPI EfiBootManagerLoadOptionToVariable(IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption)
Definition: BmLoadOption.c:170
VOID EFIAPI EfiBootManagerBoot(IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption)
Definition: BmBoot.c:1846
EFI_STATUS EFIAPI EfiBootManagerStartHotkeyService(IN EFI_EVENT *HotkeyTriggered)
Definition: BmHotkey.c:882
EFI_STATUS EFIAPI EfiBootManagerFreeLoadOption(IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption)
VOID EFIAPI EfiBootManagerHotkeyBoot(VOID)
Definition: BmHotkey.c:328
EFI_STATUS EFIAPI EfiBootManagerConnectAllDefaultConsoles(VOID)
Definition: BmConsole.c:712
EFI_BOOT_MANAGER_LOAD_OPTION *EFIAPI EfiBootManagerGetLoadOptions(OUT UINTN *LoadOptionCount, IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType)
EFI_STATUS EFIAPI EfiBootManagerFreeLoadOptions(IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOptions, IN UINTN LoadOptionCount)
EFI_STATUS EFIAPI EfiBootManagerVariableToLoadOption(IN CHAR16 *VariableName, IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption)
Definition: BmLoadOption.c:998
INTN EFIAPI EfiBootManagerFindLoadOption(IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key, IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array, IN UINTN Count)
Definition: BmLoadOption.c:548
VOID EFIAPI EfiBootManagerConnectAll(VOID)
Definition: BmConnect.c:67
EFI_STATUS EFIAPI EfiBootManagerGetBootManagerMenu(EFI_BOOT_MANAGER_LOAD_OPTION *BootOption)
Definition: BmBoot.c:2608
EFI_STATUS EFIAPI EfiBootManagerInitializeLoadOption(IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option, IN UINTN OptionNumber, IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType, IN UINT32 Attributes, IN CHAR16 *Description, IN EFI_DEVICE_PATH_PROTOCOL *FilePath, IN UINT8 *OptionalData, IN UINT32 OptionalDataSize)
VOID EFIAPI EfiBootManagerDisconnectAll(VOID)
Definition: BmConnect.c:202
EFI_STATUS EFIAPI EfiBootManagerProcessLoadOption(EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption)
EFI_SYSTEM_TABLE * gST
EFI_BOOT_SERVICES * gBS
#define EFI_TIMER_PERIOD_SECONDS(Seconds)
Definition: UefiLib.h:98
EFI_STATUS EFIAPI GetEfiGlobalVariable2(IN CONST CHAR16 *Name, OUT VOID **Value, OUT UINTN *Size OPTIONAL)
Definition: UefiLib.c:1470
UINTN EFIAPI Print(IN CONST CHAR16 *Format,...)
Definition: UefiLibPrint.c:113
#define EFI_VARIABLE_NON_VOLATILE
@ TimerRelative
Definition: UefiSpec.h:539
@ ByProtocol
Definition: UefiSpec.h:1518
UINT32 FirmwareRevision
Definition: UefiSpec.h:2042
EFI_SIMPLE_TEXT_INPUT_PROTOCOL * ConIn
Definition: UefiSpec.h:2053
CHAR16 * FirmwareVendor
Definition: UefiSpec.h:2037
EFI_TABLE_HEADER Hdr
Definition: UefiSpec.h:2032
Definition: Base.h:213