TianoCore EDK2 master
Loading...
Searching...
No Matches
PlatformBm.c
Go to the documentation of this file.
1
15#include <Library/BootLogoLib.h>
16#include <Library/CapsuleLib.h>
18#include <Library/HobLib.h>
19#include <Library/PcdLib.h>
21#include <Library/UefiLib.h>
24#include <Protocol/DevicePath.h>
29#include <Protocol/PciIo.h>
31#include <Protocol/PlatformBootManager.h>
33#include <Guid/EventGroup.h>
35#include <Guid/TtyTerm.h>
37
38#include "PlatformBm.h"
39
40#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
41
42#pragma pack (1)
43typedef struct {
44 VENDOR_DEVICE_PATH SerialDxe;
49#pragma pack ()
50
51STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {
52 //
53 // VENDOR_DEVICE_PATH SerialDxe
54 //
55 {
57 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
58 },
59
60 //
61 // UART_DEVICE_PATH Uart
62 //
63 {
65 0, // Reserved
66 FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
67 FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits
68 FixedPcdGet8 (PcdUartDefaultParity), // Parity
69 FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits
70 },
71
72 //
73 // VENDOR_DEFINED_DEVICE_PATH TermType
74 //
75 {
76 {
77 MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,
78 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)
79 }
80 //
81 // Guid to be filled in dynamically
82 //
83 },
84
85 //
86 // EFI_DEVICE_PATH_PROTOCOL End
87 //
88 {
89 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
90 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
91 }
92};
93
94#pragma pack (1)
95typedef struct {
96 USB_CLASS_DEVICE_PATH Keyboard;
99#pragma pack ()
100
101STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {
102 //
103 // USB_CLASS_DEVICE_PATH Keyboard
104 //
105 {
106 {
108 DP_NODE_LEN (USB_CLASS_DEVICE_PATH)
109 },
110 0xFFFF, // VendorId: any
111 0xFFFF, // ProductId: any
112 3, // DeviceClass: HID
113 1, // DeviceSubClass: boot
114 1 // DeviceProtocol: keyboard
115 },
116
117 //
118 // EFI_DEVICE_PATH_PROTOCOL End
119 //
120 {
121 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
122 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
123 }
124};
125
137typedef
138BOOLEAN
139(EFIAPI *FILTER_FUNCTION)(
140 IN EFI_HANDLE Handle,
141 IN CONST CHAR16 *ReportText
142 );
143
151typedef
153(EFIAPI *CALLBACK_FUNCTION)(
154 IN EFI_HANDLE Handle,
155 IN CONST CHAR16 *ReportText
156 );
157
171STATIC
172VOID
174 IN EFI_GUID *ProtocolGuid,
175 IN FILTER_FUNCTION Filter OPTIONAL,
176 IN CALLBACK_FUNCTION Process
177 )
178{
179 EFI_STATUS Status;
180 EFI_HANDLE *Handles;
181 UINTN NoHandles;
182 UINTN Idx;
183
184 Status = gBS->LocateHandleBuffer (
186 ProtocolGuid,
187 NULL /* SearchKey */,
188 &NoHandles,
189 &Handles
190 );
191 if (EFI_ERROR (Status)) {
192 //
193 // This is not an error, just an informative condition.
194 //
195 DEBUG ((
196 DEBUG_VERBOSE,
197 "%a: %g: %r\n",
198 __func__,
199 ProtocolGuid,
200 Status
201 ));
202 return;
203 }
204
205 ASSERT (NoHandles > 0);
206 for (Idx = 0; Idx < NoHandles; ++Idx) {
207 CHAR16 *DevicePathText;
208 STATIC CHAR16 Fallback[] = L"<device path unavailable>";
209
210 //
211 // The ConvertDevicePathToText() function handles NULL input transparently.
212 //
213 DevicePathText = ConvertDevicePathToText (
214 DevicePathFromHandle (Handles[Idx]),
215 FALSE, // DisplayOnly
216 FALSE // AllowShortcuts
217 );
218 if (DevicePathText == NULL) {
219 DevicePathText = Fallback;
220 }
221
222 if ((Filter == NULL) || Filter (Handles[Idx], DevicePathText)) {
223 Process (Handles[Idx], DevicePathText);
224 }
225
226 if (DevicePathText != Fallback) {
227 FreePool (DevicePathText);
228 }
229 }
230
231 gBS->FreePool (Handles);
232}
233
237STATIC
238BOOLEAN
239EFIAPI
241 IN EFI_HANDLE Handle,
242 IN CONST CHAR16 *ReportText
243 )
244{
245 EFI_STATUS Status;
246 EFI_PCI_IO_PROTOCOL *PciIo;
247 PCI_TYPE00 Pci;
248
249 Status = gBS->HandleProtocol (
250 Handle,
251 &gEfiPciIoProtocolGuid,
252 (VOID **)&PciIo
253 );
254 if (EFI_ERROR (Status)) {
255 //
256 // This is not an error worth reporting.
257 //
258 return FALSE;
259 }
260
261 Status = PciIo->Pci.Read (
262 PciIo,
263 EfiPciIoWidthUint32,
264 0 /* Offset */,
265 sizeof Pci / sizeof (UINT32),
266 &Pci
267 );
268 if (EFI_ERROR (Status)) {
269 DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __func__, ReportText, Status));
270 return FALSE;
271 }
272
273 return IS_PCI_DISPLAY (&Pci);
274}
275
280STATIC
281BOOLEAN
282EFIAPI
284 IN EFI_HANDLE Handle,
285 IN CONST CHAR16 *ReportText
286 )
287{
289 EFI_STATUS Status;
290
291 Status = gBS->HandleProtocol (
292 Handle,
293 &gEdkiiNonDiscoverableDeviceProtocolGuid,
294 (VOID **)&Device
295 );
296 if (EFI_ERROR (Status)) {
297 return FALSE;
298 }
299
300 if (CompareGuid (Device->Type, &gEdkiiNonDiscoverableUhciDeviceGuid) ||
301 CompareGuid (Device->Type, &gEdkiiNonDiscoverableEhciDeviceGuid) ||
302 CompareGuid (Device->Type, &gEdkiiNonDiscoverableXhciDeviceGuid))
303 {
304 return TRUE;
305 }
306
307 return FALSE;
308}
309
314STATIC
315VOID
316EFIAPI
318 IN EFI_HANDLE Handle,
319 IN CONST CHAR16 *ReportText
320 )
321{
322 EFI_STATUS Status;
323
324 Status = gBS->ConnectController (
325 Handle, // ControllerHandle
326 NULL, // DriverImageHandle
327 NULL, // RemainingDevicePath -- produce all children
328 FALSE // Recursive
329 );
330 DEBUG ((
331 EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
332 "%a: %s: %r\n",
333 __func__,
334 ReportText,
335 Status
336 ));
337}
338
343STATIC
344VOID
345EFIAPI
347 IN EFI_HANDLE Handle,
348 IN CONST CHAR16 *ReportText
349 )
350{
351 EFI_STATUS Status;
352 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
353
354 DevicePath = DevicePathFromHandle (Handle);
355 if (DevicePath == NULL) {
356 DEBUG ((
357 DEBUG_ERROR,
358 "%a: %s: handle %p: device path not found\n",
359 __func__,
360 ReportText,
361 Handle
362 ));
363 return;
364 }
365
366 Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
367 if (EFI_ERROR (Status)) {
368 DEBUG ((
369 DEBUG_ERROR,
370 "%a: %s: adding to ConOut: %r\n",
371 __func__,
372 ReportText,
373 Status
374 ));
375 return;
376 }
377
378 Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
379 if (EFI_ERROR (Status)) {
380 DEBUG ((
381 DEBUG_ERROR,
382 "%a: %s: adding to ErrOut: %r\n",
383 __func__,
384 ReportText,
385 Status
386 ));
387 return;
388 }
389
390 DEBUG ((
391 DEBUG_VERBOSE,
392 "%a: %s: added to ConOut and ErrOut\n",
393 __func__,
394 ReportText
395 ));
396}
397
398STATIC
399VOID
401 CONST EFI_GUID *FileGuid,
402 CHAR16 *Description,
403 UINT32 Attributes,
404 EFI_INPUT_KEY *Key
405 )
406{
407 EFI_STATUS Status;
408 INTN OptionIndex;
410 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
411 UINTN BootOptionCount;
413 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
414 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
415
416 Status = gBS->HandleProtocol (
418 &gEfiLoadedImageProtocolGuid,
419 (VOID **)&LoadedImage
420 );
421 ASSERT_EFI_ERROR (Status);
422
423 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
424 DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
425 ASSERT (DevicePath != NULL);
426 DevicePath = AppendDevicePathNode (
427 DevicePath,
428 (EFI_DEVICE_PATH_PROTOCOL *)&FileNode
429 );
430 ASSERT (DevicePath != NULL);
431
433 &NewOption,
434 LoadOptionNumberUnassigned,
435 LoadOptionTypeBoot,
436 Attributes,
437 Description,
438 DevicePath,
439 NULL,
440 0
441 );
442 ASSERT_EFI_ERROR (Status);
443 FreePool (DevicePath);
444
445 BootOptions = EfiBootManagerGetLoadOptions (
446 &BootOptionCount,
447 LoadOptionTypeBoot
448 );
449
450 OptionIndex = EfiBootManagerFindLoadOption (
451 &NewOption,
452 BootOptions,
453 BootOptionCount
454 );
455
456 if (OptionIndex == -1) {
457 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
458 ASSERT_EFI_ERROR (Status);
460 NULL,
461 (UINT16)NewOption.OptionNumber,
462 0,
463 Key,
464 NULL
465 );
466 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
467 }
468
469 EfiBootManagerFreeLoadOption (&NewOption);
470 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
471}
472
482STATIC
483VOID
485 IN CONST EFI_GUID *FileGuid,
486 IN CHAR16 *Description
487 )
488{
489 EFI_STATUS Status;
492 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
493 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
494
495 Status = gBS->HandleProtocol (
497 &gEfiLoadedImageProtocolGuid,
498 (VOID **)&LoadedImage
499 );
500 ASSERT_EFI_ERROR (Status);
501
502 //
503 // The UEFI Shell was registered in PlatformRegisterFvBootOption ()
504 // previously, thus it must still be available in this FV.
505 //
506 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
507 DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
508 ASSERT (DevicePath != NULL);
509 DevicePath = AppendDevicePathNode (
510 DevicePath,
511 (EFI_DEVICE_PATH_PROTOCOL *)&FileNode
512 );
513 ASSERT (DevicePath != NULL);
514
516 &NewOption,
517 LoadOptionNumberUnassigned,
518 LoadOptionTypeBoot,
519 LOAD_OPTION_ACTIVE,
520 Description,
521 DevicePath,
522 NULL,
523 0
524 );
525 ASSERT_EFI_ERROR (Status);
526 FreePool (DevicePath);
527
528 EfiBootManagerBoot (&NewOption);
529}
530
531STATIC
532VOID
533GetPlatformOptions (
534 VOID
535 )
536{
537 EFI_STATUS Status;
538 EFI_BOOT_MANAGER_LOAD_OPTION *CurrentBootOptions;
539 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
540 EFI_INPUT_KEY *BootKeys;
541 PLATFORM_BOOT_MANAGER_PROTOCOL *PlatformBootManager;
542 UINTN CurrentBootOptionCount;
543 UINTN Index;
544 UINTN BootCount;
545
546 Status = gBS->LocateProtocol (
547 &gPlatformBootManagerProtocolGuid,
548 NULL,
549 (VOID **)&PlatformBootManager
550 );
551 if (EFI_ERROR (Status)) {
552 return;
553 }
554
555 Status = PlatformBootManager->GetPlatformBootOptionsAndKeys (
556 &BootCount,
557 &BootOptions,
558 &BootKeys
559 );
560 if (EFI_ERROR (Status)) {
561 return;
562 }
563
564 //
565 // Fetch the existent boot options. If there are none, CurrentBootCount
566 // will be zeroed.
567 //
568 CurrentBootOptions = EfiBootManagerGetLoadOptions (
569 &CurrentBootOptionCount,
570 LoadOptionTypeBoot
571 );
572 //
573 // Process the platform boot options.
574 //
575 for (Index = 0; Index < BootCount; Index++) {
576 INTN Match;
577 UINTN BootOptionNumber;
578
579 //
580 // If there are any preexistent boot options, and the subject platform boot
581 // option is already among them, then don't try to add it. Just get its
582 // assigned boot option number so we can associate a hotkey with it. Note
583 // that EfiBootManagerFindLoadOption() deals fine with (CurrentBootOptions
584 // == NULL) if (CurrentBootCount == 0).
585 //
587 &BootOptions[Index],
588 CurrentBootOptions,
589 CurrentBootOptionCount
590 );
591 if (Match >= 0) {
592 BootOptionNumber = CurrentBootOptions[Match].OptionNumber;
593 } else {
594 //
595 // Add the platform boot options as a new one, at the end of the boot
596 // order. Note that if the platform provided this boot option with an
597 // unassigned option number, then the below function call will assign a
598 // number.
599 //
601 &BootOptions[Index],
602 MAX_UINTN
603 );
604 if (EFI_ERROR (Status)) {
605 DEBUG ((
606 DEBUG_ERROR,
607 "%a: failed to register \"%s\": %r\n",
608 __func__,
609 BootOptions[Index].Description,
610 Status
611 ));
612 continue;
613 }
614
615 BootOptionNumber = BootOptions[Index].OptionNumber;
616 }
617
618 //
619 // Register a hotkey with the boot option, if requested.
620 //
621 if (BootKeys[Index].UnicodeChar == L'\0') {
622 continue;
623 }
624
626 NULL,
627 BootOptionNumber,
628 0,
629 &BootKeys[Index],
630 NULL
631 );
632 if (EFI_ERROR (Status)) {
633 DEBUG ((
634 DEBUG_ERROR,
635 "%a: failed to register hotkey for \"%s\": %r\n",
636 __func__,
637 BootOptions[Index].Description,
638 Status
639 ));
640 }
641 }
642
643 EfiBootManagerFreeLoadOptions (CurrentBootOptions, CurrentBootOptionCount);
644 EfiBootManagerFreeLoadOptions (BootOptions, BootCount);
645 FreePool (BootKeys);
646}
647
648STATIC
649VOID
650PlatformRegisterOptionsAndKeys (
651 VOID
652 )
653{
654 EFI_STATUS Status;
655 EFI_INPUT_KEY Enter;
656 EFI_INPUT_KEY F2;
657 EFI_INPUT_KEY Esc;
659
660 GetPlatformOptions ();
661
662 //
663 // Register ENTER as CONTINUE key
664 //
665 Enter.ScanCode = SCAN_NULL;
666 Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
667 Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
668 ASSERT_EFI_ERROR (Status);
669
670 //
671 // Map F2 and ESC to Boot Manager Menu
672 //
673 F2.ScanCode = SCAN_F2;
674 F2.UnicodeChar = CHAR_NULL;
675 Esc.ScanCode = SCAN_ESC;
676 Esc.UnicodeChar = CHAR_NULL;
677 Status = EfiBootManagerGetBootManagerMenu (&BootOption);
678 ASSERT_EFI_ERROR (Status);
680 NULL,
681 (UINT16)BootOption.OptionNumber,
682 0,
683 &F2,
684 NULL
685 );
686 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
688 NULL,
689 (UINT16)BootOption.OptionNumber,
690 0,
691 &Esc,
692 NULL
693 );
694 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
695}
696
697//
698// BDS Platform Functions
699//
700
712VOID
713EFIAPI
715 VOID
716 )
717{
718 //
719 // Signal EndOfDxe PI Event
720 //
721 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
722
723 //
724 // Dispatch deferred images after EndOfDxe event.
725 //
727
728 //
729 // Locate the PCI root bridges and make the PCI bus driver connect each,
730 // non-recursively. This will produce a number of child handles with PciIo on
731 // them.
732 //
733 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);
734
735 //
736 // Find all display class PCI devices (using the handles from the previous
737 // step), and connect them non-recursively. This should produce a number of
738 // child handles with GOPs on them.
739 //
740 FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);
741
742 //
743 // Now add the device path of all handles with GOP on them to ConOut and
744 // ErrOut.
745 //
746 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);
747
748 //
749 // The core BDS code connects short-form USB device paths by explicitly
750 // looking for handles with PCI I/O installed, and checking the PCI class
751 // code whether it matches the one for a USB host controller. This means
752 // non-discoverable USB host controllers need to have the non-discoverable
753 // PCI driver attached first.
754 //
755 FilterAndProcess (&gEdkiiNonDiscoverableDeviceProtocolGuid, IsUsbHost, Connect);
756
757 //
758 // Add the hardcoded short-form USB keyboard device path to ConIn.
759 //
761 ConIn,
762 (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard,
763 NULL
764 );
765
766 //
767 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
768 //
769 STATIC_ASSERT (
770 FixedPcdGet8 (PcdDefaultTerminalType) == 4,
771 "PcdDefaultTerminalType must be TTYTERM"
772 );
773 STATIC_ASSERT (
774 FixedPcdGet8 (PcdUartDefaultParity) != 0,
775 "PcdUartDefaultParity must be set to an actual value, not 'default'"
776 );
777 STATIC_ASSERT (
778 FixedPcdGet8 (PcdUartDefaultStopBits) != 0,
779 "PcdUartDefaultStopBits must be set to an actual value, not 'default'"
780 );
781
782 CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid);
783
785 ConIn,
786 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,
787 NULL
788 );
790 ConOut,
791 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,
792 NULL
793 );
795 ErrOut,
796 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,
797 NULL
798 );
799
800 //
801 // Register platform-specific boot options and keyboard shortcuts.
802 //
803 PlatformRegisterOptionsAndKeys ();
804}
805
806STATIC
807VOID
808HandleCapsules (
809 VOID
810 )
811{
812 ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
813 EFI_PEI_HOB_POINTERS HobPointer;
814 EFI_CAPSULE_HEADER *CapsuleHeader;
815 BOOLEAN NeedReset;
816 EFI_STATUS Status;
817
818 DEBUG ((DEBUG_INFO, "%a: processing capsules ...\n", __func__));
819
820 Status = gBS->LocateProtocol (
821 &gEsrtManagementProtocolGuid,
822 NULL,
823 (VOID **)&EsrtManagement
824 );
825 if (!EFI_ERROR (Status)) {
826 EsrtManagement->SyncEsrtFmp ();
827 }
828
829 //
830 // Find all capsule images from hob
831 //
832 HobPointer.Raw = GetHobList ();
833 NeedReset = FALSE;
834 while ((HobPointer.Raw = GetNextHob (
835 EFI_HOB_TYPE_UEFI_CAPSULE,
836 HobPointer.Raw
837 )) != NULL)
838 {
839 CapsuleHeader = (VOID *)(UINTN)HobPointer.Capsule->BaseAddress;
840
841 Status = ProcessCapsuleImage (CapsuleHeader);
842 if (EFI_ERROR (Status)) {
843 DEBUG ((
844 DEBUG_ERROR,
845 "%a: failed to process capsule %p - %r\n",
846 __func__,
847 CapsuleHeader,
848 Status
849 ));
850 return;
851 }
852
853 NeedReset = TRUE;
854 HobPointer.Raw = GET_NEXT_HOB (HobPointer);
855 }
856
857 if (NeedReset) {
858 DEBUG ((
859 DEBUG_WARN,
860 "%a: capsule update successful, resetting ...\n",
861 __func__
862 ));
863
864 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
865 CpuDeadLoop ();
866 }
867}
868
869#define VERSION_STRING_PREFIX L"Tianocore/EDK2 firmware version "
870
881STATIC
884 VOID
885 )
886{
887 EFI_STATUS Status;
888 UINT32 DiscoveryPolicy;
889 UINT32 DiscoveryPolicyOld;
890 UINTN Size;
892 EFI_GUID *Class;
893
894 Size = sizeof (DiscoveryPolicy);
895 Status = gRT->GetVariable (
896 BOOT_DISCOVERY_POLICY_VAR,
897 &gBootDiscoveryPolicyMgrFormsetGuid,
898 NULL,
899 &Size,
900 &DiscoveryPolicy
901 );
902 if (Status == EFI_NOT_FOUND) {
903 DiscoveryPolicy = PcdGet32 (PcdBootDiscoveryPolicy);
904 Status = PcdSet32S (PcdBootDiscoveryPolicy, DiscoveryPolicy);
905 if (Status == EFI_NOT_FOUND) {
906 return EFI_SUCCESS;
907 } else if (EFI_ERROR (Status)) {
908 return Status;
909 }
910 } else if (EFI_ERROR (Status)) {
911 return Status;
912 }
913
914 if (DiscoveryPolicy == BDP_CONNECT_MINIMAL) {
915 return EFI_SUCCESS;
916 }
917
918 switch (DiscoveryPolicy) {
919 case BDP_CONNECT_NET:
920 Class = &gEfiBootManagerPolicyNetworkGuid;
921 break;
922 case BDP_CONNECT_ALL:
923 Class = &gEfiBootManagerPolicyConnectAllGuid;
924 break;
925 default:
926 DEBUG ((
927 DEBUG_INFO,
928 "%a - Unexpected DiscoveryPolicy (0x%x). Run Minimal Discovery Policy\n",
929 __func__,
930 DiscoveryPolicy
931 ));
932 return EFI_SUCCESS;
933 }
934
935 Status = gBS->LocateProtocol (
936 &gEfiBootManagerPolicyProtocolGuid,
937 NULL,
938 (VOID **)&BMPolicy
939 );
940 if (EFI_ERROR (Status)) {
941 DEBUG ((
942 DEBUG_INFO,
943 "%a - Failed to locate gEfiBootManagerPolicyProtocolGuid."
944 "Driver connect will be skipped.\n",
945 __func__
946 ));
947 return Status;
948 }
949
950 Status = BMPolicy->ConnectDeviceClass (BMPolicy, Class);
951 if (EFI_ERROR (Status)) {
952 DEBUG ((DEBUG_ERROR, "%a - ConnectDeviceClass returns - %r\n", __func__, Status));
953 return Status;
954 }
955
956 //
957 // Refresh Boot Options if Boot Discovery Policy has been changed
958 //
959 Size = sizeof (DiscoveryPolicyOld);
960 Status = gRT->GetVariable (
961 BOOT_DISCOVERY_POLICY_OLD_VAR,
962 &gBootDiscoveryPolicyMgrFormsetGuid,
963 NULL,
964 &Size,
965 &DiscoveryPolicyOld
966 );
967 if ((Status == EFI_NOT_FOUND) || (DiscoveryPolicyOld != DiscoveryPolicy)) {
969
970 Status = gRT->SetVariable (
971 BOOT_DISCOVERY_POLICY_OLD_VAR,
972 &gBootDiscoveryPolicyMgrFormsetGuid,
973 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
974 sizeof (DiscoveryPolicyOld),
975 &DiscoveryPolicy
976 );
977 }
978
979 return EFI_SUCCESS;
980}
981
993VOID
994EFIAPI
996 VOID
997 )
998{
999 EFI_STATUS Status;
1000 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
1001 UINTN FirmwareVerLength;
1002 UINTN PosX;
1003 UINTN PosY;
1004 EFI_INPUT_KEY Key;
1005
1006 FirmwareVerLength = StrLen (PcdGetPtr (PcdFirmwareVersionString));
1007
1008 //
1009 // Show the splash screen.
1010 //
1011 Status = BootLogoEnableLogo ();
1012 if (EFI_ERROR (Status)) {
1013 if (FirmwareVerLength > 0) {
1014 Print (
1015 VERSION_STRING_PREFIX L"%s\n",
1016 PcdGetPtr (PcdFirmwareVersionString)
1017 );
1018 }
1019
1020 Print (L"Press ESCAPE for boot options ");
1021 } else if (FirmwareVerLength > 0) {
1022 Status = gBS->HandleProtocol (
1024 &gEfiGraphicsOutputProtocolGuid,
1025 (VOID **)&GraphicsOutput
1026 );
1027 if (!EFI_ERROR (Status)) {
1028 PosX = (GraphicsOutput->Mode->Info->HorizontalResolution -
1029 (StrLen (VERSION_STRING_PREFIX) + FirmwareVerLength) *
1030 EFI_GLYPH_WIDTH) / 2;
1031 PosY = 0;
1032
1033 PrintXY (
1034 PosX,
1035 PosY,
1036 NULL,
1037 NULL,
1038 VERSION_STRING_PREFIX L"%s",
1039 PcdGetPtr (PcdFirmwareVersionString)
1040 );
1041 }
1042 }
1043
1044 //
1045 // Connect device specified by BootDiscoverPolicy variable and
1046 // refresh Boot order for newly discovered boot devices
1047 //
1049
1050 //
1051 // On ARM, there is currently no reason to use the phased capsule
1052 // update approach where some capsules are dispatched before EndOfDxe
1053 // and some are dispatched after. So just handle all capsules here,
1054 // when the console is up and we can actually give the user some
1055 // feedback about what is going on.
1056 //
1057 HandleCapsules ();
1058
1059 //
1060 // Register UEFI Shell
1061 //
1062 Key.ScanCode = SCAN_NULL;
1063 Key.UnicodeChar = L's';
1064 PlatformRegisterFvBootOption (&gUefiShellFileGuid, L"UEFI Shell", 0, &Key);
1065}
1066
1073VOID
1074EFIAPI
1076 UINT16 TimeoutRemain
1077 )
1078{
1081 UINT16 Timeout;
1082 EFI_STATUS Status;
1083
1084 Timeout = PcdGet16 (PcdPlatformBootTimeOut);
1085
1086 Black.Raw = 0x00000000;
1087 White.Raw = 0x00FFFFFF;
1088
1089 Status = BootLogoUpdateProgress (
1090 White.Pixel,
1091 Black.Pixel,
1092 L"Press ESCAPE for boot options",
1093 White.Pixel,
1094 (Timeout - TimeoutRemain) * 100 / Timeout,
1095 0
1096 );
1097 if (EFI_ERROR (Status)) {
1098 Print (L".");
1099 }
1100}
1101
1109VOID
1110EFIAPI
1112 VOID
1113 )
1114{
1115 EFI_STATUS Status;
1116 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
1117 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
1118 UINTN OldBootOptionCount;
1119 UINTN NewBootOptionCount;
1120
1121 //
1122 // Record the total number of boot configured boot options
1123 //
1124 BootOptions = EfiBootManagerGetLoadOptions (
1125 &OldBootOptionCount,
1126 LoadOptionTypeBoot
1127 );
1128 EfiBootManagerFreeLoadOptions (BootOptions, OldBootOptionCount);
1129
1130 //
1131 // Connect all devices, and regenerate all boot options
1132 //
1135
1136 //
1137 // Boot the 'UEFI Shell'. If the Pcd is not set, the UEFI Shell is not
1138 // an active boot option and must be manually selected through UiApp
1139 // (at least during the fist boot).
1140 //
1141 if (FixedPcdGetBool (PcdUefiShellDefaultBootEnable)) {
1143 &gUefiShellFileGuid,
1144 L"UEFI Shell (default)"
1145 );
1146 }
1147
1148 //
1149 // Record the updated number of boot configured boot options
1150 //
1151 BootOptions = EfiBootManagerGetLoadOptions (
1152 &NewBootOptionCount,
1153 LoadOptionTypeBoot
1154 );
1155 EfiBootManagerFreeLoadOptions (BootOptions, NewBootOptionCount);
1156
1157 //
1158 // If the number of configured boot options has changed, reboot
1159 // the system so the new boot options will be taken into account
1160 // while executing the ordinary BDS bootflow sequence.
1161 // *Unless* persistent varstore is being emulated, since we would
1162 // then end up in an endless reboot loop.
1163 //
1164 if (!PcdGetBool (PcdEmuVariableNvModeEnable)) {
1165 if (NewBootOptionCount != OldBootOptionCount) {
1166 DEBUG ((
1167 DEBUG_WARN,
1168 "%a: rebooting after refreshing all boot options\n",
1169 __func__
1170 ));
1171 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
1172 }
1173 }
1174
1175 Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
1176 if (EFI_ERROR (Status)) {
1177 return;
1178 }
1179
1180 for ( ; ;) {
1181 EfiBootManagerBoot (&BootManagerMenu);
1182 }
1183}
UINT64 UINTN
INT64 INTN
VOID EFIAPI PlatformBootManagerBeforeConsole(VOID)
Definition: PlatformBm.c:714
VOID EFIAPI PlatformBootManagerWaitCallback(UINT16 TimeoutRemain)
Definition: PlatformBm.c:1075
VOID(EFIAPI * CALLBACK_FUNCTION)(IN EFI_HANDLE Handle, IN CONST CHAR16 *ReportText)
Definition: PlatformBm.c:153
STATIC VOID EFIAPI Connect(IN EFI_HANDLE Handle, IN CONST CHAR16 *ReportText)
Definition: PlatformBm.c:317
VOID EFIAPI PlatformBootManagerUnableToBoot(VOID)
Definition: PlatformBm.c:1111
VOID EFIAPI PlatformBootManagerAfterConsole(VOID)
Definition: PlatformBm.c:995
STATIC VOID PlatformBootFvBootOption(IN CONST EFI_GUID *FileGuid, IN CHAR16 *Description)
Definition: PlatformBm.c:484
STATIC VOID EFIAPI AddOutput(IN EFI_HANDLE Handle, IN CONST CHAR16 *ReportText)
Definition: PlatformBm.c:346
STATIC BOOLEAN EFIAPI IsPciDisplay(IN EFI_HANDLE Handle, IN CONST CHAR16 *ReportText)
Definition: PlatformBm.c:240
STATIC EFI_STATUS BootDiscoveryPolicyHandler(VOID)
Definition: PlatformBm.c:883
BOOLEAN(EFIAPI * FILTER_FUNCTION)(IN EFI_HANDLE Handle, IN CONST CHAR16 *ReportText)
Definition: PlatformBm.c:139
STATIC VOID FilterAndProcess(IN EFI_GUID *ProtocolGuid, IN FILTER_FUNCTION Filter OPTIONAL, IN CALLBACK_FUNCTION Process)
Definition: PlatformBm.c:173
STATIC BOOLEAN EFIAPI IsUsbHost(IN EFI_HANDLE Handle, IN CONST CHAR16 *ReportText)
Definition: PlatformBm.c:283
VOID *EFIAPI GetNextHob(IN UINT16 Type, IN CONST VOID *HobStart)
Definition: HobLib.c:103
VOID *EFIAPI GetHobList(VOID)
Definition: HobLib.c:76
VOID EFIAPI CpuDeadLoop(VOID)
Definition: CpuDeadLoop.c:25
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
EFI_STATUS EFIAPI BootLogoUpdateProgress(IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground, IN CHAR16 *Title, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor, IN UINTN Progress, IN UINTN PreviousValue)
Definition: BootLogoLib.c:348
EFI_STATUS EFIAPI BootLogoEnableLogo(VOID)
Definition: BootLogoLib.c:33
EFI_STATUS EFIAPI ProcessCapsuleImage(IN EFI_CAPSULE_HEADER *CapsuleHeader)
#define HARDWARE_DEVICE_PATH
Definition: DevicePath.h:68
#define HW_VENDOR_DP
Definition: DevicePath.h:133
#define MSG_UART_DP
Definition: DevicePath.h:692
#define MSG_USB_CLASS_DP
Definition: DevicePath.h:434
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:321
EFI_DEVICE_PATH_PROTOCOL *EFIAPI AppendDevicePathNode(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
CHAR16 *EFIAPI ConvertDevicePathToText(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN BOOLEAN DisplayOnly, IN BOOLEAN AllowShortcuts)
VOID EFIAPI FreePool(IN VOID *Buffer)
STATIC VOID PlatformRegisterFvBootOption(CONST EFI_GUID *FileGuid, CHAR16 *Description, UINT32 Attributes)
Definition: LinuxBootBm.c:40
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define VOID
Definition: Base.h:269
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:463
#define DEBUG(Expression)
Definition: DebugLib.h:435
#define PcdGet16(TokenName)
Definition: PcdLib.h:349
#define FixedPcdGet64(TokenName)
Definition: PcdLib.h:106
#define FixedPcdGetBool(TokenName)
Definition: PcdLib.h:120
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
#define FixedPcdGet8(TokenName)
Definition: PcdLib.h:64
#define PcdSet32S(TokenName, Value)
Definition: PcdLib.h:497
#define PcdGetPtr(TokenName)
Definition: PcdLib.h:388
#define IS_PCI_DISPLAY(_p)
Definition: Pci22.h:349
STATIC BOOLEAN Match(IN CONST CHAR16 *Translated, IN UINTN TranslatedLength, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS EFIAPI EfiBootManagerDispatchDeferredImages(VOID)
Definition: BmMisc.c:428
VOID EFIAPI EfiBootManagerBoot(IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption)
Definition: BmBoot.c:1894
EFI_STATUS EFIAPI EfiBootManagerFreeLoadOption(IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption)
EFI_STATUS EFIAPI EfiBootManagerRegisterContinueKeyOption(IN UINT32 Modifier,...)
Definition: BmHotkey.c:813
EFI_STATUS EFIAPI EfiBootManagerUpdateConsoleVariable(IN CONSOLE_TYPE ConsoleType, IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath, IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath)
Definition: BmConsole.c:418
EFI_BOOT_MANAGER_LOAD_OPTION *EFIAPI EfiBootManagerGetLoadOptions(OUT UINTN *LoadOptionCount, IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType)
VOID EFIAPI EfiBootManagerRefreshAllBootOption(VOID)
Definition: BmBoot.c:2436
EFI_STATUS EFIAPI EfiBootManagerAddLoadOptionVariable(IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option, IN UINTN Position)
Definition: BmLoadOption.c:365
EFI_STATUS EFIAPI EfiBootManagerFreeLoadOptions(IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOptions, IN UINTN LoadOptionCount)
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:550
VOID EFIAPI EfiBootManagerConnectAll(VOID)
Definition: BmConnect.c:67
EFI_STATUS EFIAPI EfiBootManagerGetBootManagerMenu(EFI_BOOT_MANAGER_LOAD_OPTION *BootOption)
Definition: BmBoot.c:2656
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)
EFI_STATUS EFIAPI EfiBootManagerAddKeyOptionVariable(OUT EFI_BOOT_MANAGER_KEY_OPTION *AddedOption OPTIONAL, IN UINT16 BootOptionNumber, IN UINT32 Modifier,...)
Definition: BmHotkey.c:972
EFI_SYSTEM_TABLE * gST
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
UINTN EFIAPI PrintXY(IN UINTN PointX, IN UINTN PointY, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ForeGround OPTIONAL, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackGround OPTIONAL, IN CONST CHAR16 *Format,...)
Definition: UefiLibPrint.c:527
EFI_STATUS EFIAPI EfiEventGroupSignal(IN CONST EFI_GUID *EventGroup)
Definition: UefiLib.c:310
VOID EFIAPI EfiInitializeFwVolDevicepathNode(IN OUT MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode, IN CONST EFI_GUID *NameGuid)
Definition: UefiNotTiano.c:325
UINTN EFIAPI Print(IN CONST CHAR16 *Format,...)
Definition: UefiLibPrint.c:113
@ EfiResetCold
#define EFI_VARIABLE_NON_VOLATILE
@ ByProtocol
Definition: UefiSpec.h:1528
EFI_PHYSICAL_ADDRESS BaseAddress
Definition: PiHob.h:487
EFI_HANDLE DeviceHandle
The device handle that the EFI Image was loaded from.
Definition: LoadedImage.h:53
EFI_PCI_IO_PROTOCOL_CONFIG Read
Definition: PciIo.h:232
EFI_HANDLE ConsoleOutHandle
Definition: UefiSpec.h:2072
Definition: Base.h:213