]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/RiscVVirt/Library/PlatformBootManagerLib/PlatformBm.c
OvmfPkg/RiscVVirt: Add PlatformBootManagerLib library
[mirror_edk2.git] / OvmfPkg / RiscVVirt / Library / PlatformBootManagerLib / PlatformBm.c
1 /** @file
2 Implementation for PlatformBootManagerLib library class interfaces.
3
4 Copyright (C) 2015-2016, Red Hat, Inc.
5 Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
6 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include <IndustryStandard/Pci22.h>
13 #include <IndustryStandard/Virtio095.h>
14 #include <Library/BootLogoLib.h>
15 #include <Library/DevicePathLib.h>
16 #include <Library/PcdLib.h>
17 #include <Library/PlatformBmPrintScLib.h>
18 #include <Library/QemuBootOrderLib.h>
19 #include <Library/TpmPlatformHierarchyLib.h>
20 #include <Library/UefiBootManagerLib.h>
21 #include <Protocol/DevicePath.h>
22 #include <Protocol/FirmwareVolume2.h>
23 #include <Protocol/GraphicsOutput.h>
24 #include <Protocol/LoadedImage.h>
25 #include <Protocol/PciIo.h>
26 #include <Protocol/PciRootBridgeIo.h>
27 #include <Protocol/VirtioDevice.h>
28 #include <Guid/EventGroup.h>
29 #include <Guid/GlobalVariable.h>
30 #include <Guid/RootBridgesConnectedEventGroup.h>
31 #include <Guid/SerialPortLibVendor.h>
32 #include <Guid/TtyTerm.h>
33
34 #include "PlatformBm.h"
35
36 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
37
38 #define VERSION_STRING_PREFIX L"RISC-V EDK2 firmware version "
39
40 #pragma pack (1)
41 typedef struct {
42 VENDOR_DEVICE_PATH SerialDxe;
43 UART_DEVICE_PATH Uart;
44 VENDOR_DEFINED_DEVICE_PATH TermType;
45 EFI_DEVICE_PATH_PROTOCOL End;
46 } PLATFORM_SERIAL_CONSOLE;
47 #pragma pack ()
48
49 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {
50 //
51 // VENDOR_DEVICE_PATH SerialDxe
52 //
53 {
54 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },
55 EDKII_SERIAL_PORT_LIB_VENDOR_GUID
56 },
57
58 //
59 // UART_DEVICE_PATH Uart
60 //
61 {
62 { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) },
63 0, // Reserved
64 FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
65 FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits
66 FixedPcdGet8 (PcdUartDefaultParity), // Parity
67 FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits
68 },
69
70 //
71 // VENDOR_DEFINED_DEVICE_PATH TermType
72 //
73 {
74 {
75 MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,
76 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)
77 }
78 //
79 // Guid to be filled in dynamically
80 //
81 },
82
83 //
84 // EFI_DEVICE_PATH_PROTOCOL End
85 //
86 {
87 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
88 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
89 }
90 };
91
92 #pragma pack (1)
93 typedef struct {
94 USB_CLASS_DEVICE_PATH Keyboard;
95 EFI_DEVICE_PATH_PROTOCOL End;
96 } PLATFORM_USB_KEYBOARD;
97 #pragma pack ()
98
99 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {
100 //
101 // USB_CLASS_DEVICE_PATH Keyboard
102 //
103 {
104 {
105 MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,
106 DP_NODE_LEN (USB_CLASS_DEVICE_PATH)
107 },
108 0xFFFF, // VendorId: any
109 0xFFFF, // ProductId: any
110 3, // DeviceClass: HID
111 1, // DeviceSubClass: boot
112 1 // DeviceProtocol: keyboard
113 },
114
115 //
116 // EFI_DEVICE_PATH_PROTOCOL End
117 //
118 {
119 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
120 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
121 }
122 };
123
124 /**
125 Check if the handle satisfies a particular condition.
126
127 @param[in] Handle The handle to check.
128 @param[in] ReportText A caller-allocated string passed in for reporting
129 purposes. It must never be NULL.
130
131 @retval TRUE The condition is satisfied.
132 @retval FALSE Otherwise. This includes the case when the condition could not
133 be fully evaluated due to an error.
134 **/
135 typedef
136 BOOLEAN
137 (EFIAPI *FILTER_FUNCTION)(
138 IN EFI_HANDLE Handle,
139 IN CONST CHAR16 *ReportText
140 );
141
142 /**
143 Process a handle.
144
145 @param[in] Handle The handle to process.
146 @param[in] ReportText A caller-allocated string passed in for reporting
147 purposes. It must never be NULL.
148 **/
149 typedef
150 VOID
151 (EFIAPI *CALLBACK_FUNCTION)(
152 IN EFI_HANDLE Handle,
153 IN CONST CHAR16 *ReportText
154 );
155
156 /**
157 Locate all handles that carry the specified protocol, filter them with a
158 callback function, and pass each handle that passes the filter to another
159 callback.
160
161 @param[in] ProtocolGuid The protocol to look for.
162
163 @param[in] Filter The filter function to pass each handle to. If this
164 parameter is NULL, then all handles are processed.
165
166 @param[in] Process The callback function to pass each handle to that
167 clears the filter.
168 **/
169 STATIC
170 VOID
171 FilterAndProcess (
172 IN EFI_GUID *ProtocolGuid,
173 IN FILTER_FUNCTION Filter OPTIONAL,
174 IN CALLBACK_FUNCTION Process
175 )
176 {
177 EFI_STATUS Status;
178 EFI_HANDLE *Handles;
179 UINTN NoHandles;
180 UINTN Idx;
181
182 Status = gBS->LocateHandleBuffer (
183 ByProtocol,
184 ProtocolGuid,
185 NULL /* SearchKey */,
186 &NoHandles,
187 &Handles
188 );
189 if (EFI_ERROR (Status)) {
190 //
191 // This is not an error, just an informative condition.
192 //
193 DEBUG ((
194 DEBUG_VERBOSE,
195 "%a: %g: %r\n",
196 __FUNCTION__,
197 ProtocolGuid,
198 Status
199 ));
200 return;
201 }
202
203 ASSERT (NoHandles > 0);
204 for (Idx = 0; Idx < NoHandles; ++Idx) {
205 CHAR16 *DevicePathText;
206 STATIC CHAR16 Fallback[] = L"<device path unavailable>";
207
208 //
209 // The ConvertDevicePathToText() function handles NULL input transparently.
210 //
211 DevicePathText = ConvertDevicePathToText (
212 DevicePathFromHandle (Handles[Idx]),
213 FALSE, // DisplayOnly
214 FALSE // AllowShortcuts
215 );
216 if (DevicePathText == NULL) {
217 DevicePathText = Fallback;
218 }
219
220 if ((Filter == NULL) || Filter (Handles[Idx], DevicePathText)) {
221 Process (Handles[Idx], DevicePathText);
222 }
223
224 if (DevicePathText != Fallback) {
225 FreePool (DevicePathText);
226 }
227 }
228
229 gBS->FreePool (Handles);
230 }
231
232 /**
233 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
234 **/
235 STATIC
236 BOOLEAN
237 EFIAPI
238 IsPciDisplay (
239 IN EFI_HANDLE Handle,
240 IN CONST CHAR16 *ReportText
241 )
242 {
243 EFI_STATUS Status;
244 EFI_PCI_IO_PROTOCOL *PciIo;
245 PCI_TYPE00 Pci;
246
247 Status = gBS->HandleProtocol (
248 Handle,
249 &gEfiPciIoProtocolGuid,
250 (VOID **)&PciIo
251 );
252 if (EFI_ERROR (Status)) {
253 //
254 // This is not an error worth reporting.
255 //
256 return FALSE;
257 }
258
259 Status = PciIo->Pci.Read (
260 PciIo,
261 EfiPciIoWidthUint32,
262 0 /* Offset */,
263 sizeof Pci / sizeof (UINT32),
264 &Pci
265 );
266 if (EFI_ERROR (Status)) {
267 DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));
268 return FALSE;
269 }
270
271 return IS_PCI_DISPLAY (&Pci);
272 }
273
274 /**
275 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
276 the VIRTIO_DEVICE_PROTOCOL level.
277 **/
278 STATIC
279 BOOLEAN
280 EFIAPI
281 IsVirtioRng (
282 IN EFI_HANDLE Handle,
283 IN CONST CHAR16 *ReportText
284 )
285 {
286 EFI_STATUS Status;
287 VIRTIO_DEVICE_PROTOCOL *VirtIo;
288
289 Status = gBS->HandleProtocol (
290 Handle,
291 &gVirtioDeviceProtocolGuid,
292 (VOID **)&VirtIo
293 );
294 if (EFI_ERROR (Status)) {
295 return FALSE;
296 }
297
298 return (BOOLEAN)(VirtIo->SubSystemDeviceId ==
299 VIRTIO_SUBSYSTEM_ENTROPY_SOURCE);
300 }
301
302 /**
303 This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
304 the EFI_PCI_IO_PROTOCOL level.
305 **/
306 STATIC
307 BOOLEAN
308 EFIAPI
309 IsVirtioPciRng (
310 IN EFI_HANDLE Handle,
311 IN CONST CHAR16 *ReportText
312 )
313 {
314 EFI_STATUS Status;
315 EFI_PCI_IO_PROTOCOL *PciIo;
316 UINT16 VendorId;
317 UINT16 DeviceId;
318 UINT8 RevisionId;
319 BOOLEAN Virtio10;
320 UINT16 SubsystemId;
321
322 Status = gBS->HandleProtocol (
323 Handle,
324 &gEfiPciIoProtocolGuid,
325 (VOID **)&PciIo
326 );
327 if (EFI_ERROR (Status)) {
328 return FALSE;
329 }
330
331 //
332 // Read and check VendorId.
333 //
334 Status = PciIo->Pci.Read (
335 PciIo,
336 EfiPciIoWidthUint16,
337 PCI_VENDOR_ID_OFFSET,
338 1,
339 &VendorId
340 );
341 if (EFI_ERROR (Status)) {
342 goto PciError;
343 }
344
345 if (VendorId != VIRTIO_VENDOR_ID) {
346 return FALSE;
347 }
348
349 //
350 // Read DeviceId and RevisionId.
351 //
352 Status = PciIo->Pci.Read (
353 PciIo,
354 EfiPciIoWidthUint16,
355 PCI_DEVICE_ID_OFFSET,
356 1,
357 &DeviceId
358 );
359 if (EFI_ERROR (Status)) {
360 goto PciError;
361 }
362
363 Status = PciIo->Pci.Read (
364 PciIo,
365 EfiPciIoWidthUint8,
366 PCI_REVISION_ID_OFFSET,
367 1,
368 &RevisionId
369 );
370 if (EFI_ERROR (Status)) {
371 goto PciError;
372 }
373
374 //
375 // From DeviceId and RevisionId, determine whether the device is a
376 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
377 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
378 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
379 // only be sanity-checked, and SubsystemId will decide.
380 //
381 if ((DeviceId == 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE) &&
382 (RevisionId >= 0x01))
383 {
384 Virtio10 = TRUE;
385 } else if ((DeviceId >= 0x1000) && (DeviceId <= 0x103F) && (RevisionId == 0x00)) {
386 Virtio10 = FALSE;
387 } else {
388 return FALSE;
389 }
390
391 //
392 // Read and check SubsystemId as dictated by Virtio10.
393 //
394 Status = PciIo->Pci.Read (
395 PciIo,
396 EfiPciIoWidthUint16,
397 PCI_SUBSYSTEM_ID_OFFSET,
398 1,
399 &SubsystemId
400 );
401 if (EFI_ERROR (Status)) {
402 goto PciError;
403 }
404
405 if (Virtio10 && (SubsystemId >= 0x40)) {
406 return TRUE;
407 }
408
409 if (!Virtio10 && (SubsystemId == VIRTIO_SUBSYSTEM_ENTROPY_SOURCE)) {
410 return TRUE;
411 }
412
413 return FALSE;
414
415 PciError:
416 DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));
417 return FALSE;
418 }
419
420 /**
421 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
422 the matching driver to produce all first-level child handles.
423 **/
424 STATIC
425 VOID
426 EFIAPI
427 Connect (
428 IN EFI_HANDLE Handle,
429 IN CONST CHAR16 *ReportText
430 )
431 {
432 EFI_STATUS Status;
433
434 Status = gBS->ConnectController (
435 Handle, // ControllerHandle
436 NULL, // DriverImageHandle
437 NULL, // RemainingDevicePath -- produce all children
438 FALSE // Recursive
439 );
440 DEBUG ((
441 EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
442 "%a: %s: %r\n",
443 __FUNCTION__,
444 ReportText,
445 Status
446 ));
447 }
448
449 /**
450 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
451 handle, and adds it to ConOut and ErrOut.
452 **/
453 STATIC
454 VOID
455 EFIAPI
456 AddOutput (
457 IN EFI_HANDLE Handle,
458 IN CONST CHAR16 *ReportText
459 )
460 {
461 EFI_STATUS Status;
462 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
463
464 DevicePath = DevicePathFromHandle (Handle);
465 if (DevicePath == NULL) {
466 DEBUG ((
467 DEBUG_ERROR,
468 "%a: %s: handle %p: device path not found\n",
469 __FUNCTION__,
470 ReportText,
471 Handle
472 ));
473 return;
474 }
475
476 Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
477 if (EFI_ERROR (Status)) {
478 DEBUG ((
479 DEBUG_ERROR,
480 "%a: %s: adding to ConOut: %r\n",
481 __FUNCTION__,
482 ReportText,
483 Status
484 ));
485 return;
486 }
487
488 Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
489 if (EFI_ERROR (Status)) {
490 DEBUG ((
491 DEBUG_ERROR,
492 "%a: %s: adding to ErrOut: %r\n",
493 __FUNCTION__,
494 ReportText,
495 Status
496 ));
497 return;
498 }
499
500 DEBUG ((
501 DEBUG_VERBOSE,
502 "%a: %s: added to ConOut and ErrOut\n",
503 __FUNCTION__,
504 ReportText
505 ));
506 }
507
508 STATIC
509 VOID
510 PlatformRegisterFvBootOption (
511 EFI_GUID *FileGuid,
512 CHAR16 *Description,
513 UINT32 Attributes
514 )
515 {
516 EFI_STATUS Status;
517 INTN OptionIndex;
518 EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
519 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
520 UINTN BootOptionCount;
521 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
522 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
523 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
524
525 Status = gBS->HandleProtocol (
526 gImageHandle,
527 &gEfiLoadedImageProtocolGuid,
528 (VOID **)&LoadedImage
529 );
530 ASSERT_EFI_ERROR (Status);
531
532 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
533 DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
534 ASSERT (DevicePath != NULL);
535 DevicePath = AppendDevicePathNode (
536 DevicePath,
537 (EFI_DEVICE_PATH_PROTOCOL *)&FileNode
538 );
539 ASSERT (DevicePath != NULL);
540
541 Status = EfiBootManagerInitializeLoadOption (
542 &NewOption,
543 LoadOptionNumberUnassigned,
544 LoadOptionTypeBoot,
545 Attributes,
546 Description,
547 DevicePath,
548 NULL,
549 0
550 );
551 ASSERT_EFI_ERROR (Status);
552 FreePool (DevicePath);
553
554 BootOptions = EfiBootManagerGetLoadOptions (
555 &BootOptionCount,
556 LoadOptionTypeBoot
557 );
558
559 OptionIndex = EfiBootManagerFindLoadOption (
560 &NewOption,
561 BootOptions,
562 BootOptionCount
563 );
564
565 if (OptionIndex == -1) {
566 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
567 ASSERT_EFI_ERROR (Status);
568 }
569
570 EfiBootManagerFreeLoadOption (&NewOption);
571 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
572 }
573
574 /**
575 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
576 whose device paths do not resolve exactly to an FvFile in the system.
577
578 This removes any boot options that point to binaries built into the firmware
579 and have become stale due to any of the following:
580 - FvMain's base address or size changed (historical),
581 - FvMain's FvNameGuid changed,
582 - the FILE_GUID of the pointed-to binary changed,
583 - the referenced binary is no longer built into the firmware.
584
585 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
586 avoids exact duplicates.
587 **/
588 STATIC
589 VOID
590 RemoveStaleFvFileOptions (
591 VOID
592 )
593 {
594 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
595 UINTN BootOptionCount;
596 UINTN Index;
597
598 BootOptions = EfiBootManagerGetLoadOptions (
599 &BootOptionCount,
600 LoadOptionTypeBoot
601 );
602
603 for (Index = 0; Index < BootOptionCount; ++Index) {
604 EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
605 EFI_STATUS Status;
606 EFI_HANDLE FvHandle;
607
608 //
609 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
610 // then keep the boot option.
611 //
612 Node1 = BootOptions[Index].FilePath;
613 if (!((DevicePathType (Node1) == HARDWARE_DEVICE_PATH) &&
614 (DevicePathSubType (Node1) == HW_MEMMAP_DP)) &&
615 !((DevicePathType (Node1) == MEDIA_DEVICE_PATH) &&
616 (DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)))
617 {
618 continue;
619 }
620
621 //
622 // If the second device path node is not FvFile(...), then keep the boot
623 // option.
624 //
625 Node2 = NextDevicePathNode (Node1);
626 if ((DevicePathType (Node2) != MEDIA_DEVICE_PATH) ||
627 (DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP))
628 {
629 continue;
630 }
631
632 //
633 // Locate the Firmware Volume2 protocol instance that is denoted by the
634 // boot option. If this lookup fails (i.e., the boot option references a
635 // firmware volume that doesn't exist), then we'll proceed to delete the
636 // boot option.
637 //
638 SearchNode = Node1;
639 Status = gBS->LocateDevicePath (
640 &gEfiFirmwareVolume2ProtocolGuid,
641 &SearchNode,
642 &FvHandle
643 );
644
645 if (!EFI_ERROR (Status)) {
646 //
647 // The firmware volume was found; now let's see if it contains the FvFile
648 // identified by GUID.
649 //
650 EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
651 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
652 UINTN BufferSize;
653 EFI_FV_FILETYPE FoundType;
654 EFI_FV_FILE_ATTRIBUTES FileAttributes;
655 UINT32 AuthenticationStatus;
656
657 Status = gBS->HandleProtocol (
658 FvHandle,
659 &gEfiFirmwareVolume2ProtocolGuid,
660 (VOID **)&FvProtocol
661 );
662 ASSERT_EFI_ERROR (Status);
663
664 FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
665 //
666 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
667 // FileAttributes.
668 //
669 Status = FvProtocol->ReadFile (
670 FvProtocol,
671 &FvFileNode->FvFileName, // NameGuid
672 NULL, // Buffer
673 &BufferSize,
674 &FoundType,
675 &FileAttributes,
676 &AuthenticationStatus
677 );
678 if (!EFI_ERROR (Status)) {
679 //
680 // The FvFile was found. Keep the boot option.
681 //
682 continue;
683 }
684 }
685
686 //
687 // Delete the boot option.
688 //
689 Status = EfiBootManagerDeleteLoadOptionVariable (
690 BootOptions[Index].OptionNumber,
691 LoadOptionTypeBoot
692 );
693 DEBUG_CODE_BEGIN ();
694 CHAR16 *DevicePathString;
695
696 DevicePathString = ConvertDevicePathToText (
697 BootOptions[Index].FilePath,
698 FALSE,
699 FALSE
700 );
701 DEBUG ((
702 EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_VERBOSE,
703 "%a: removing stale Boot#%04x %s: %r\n",
704 __FUNCTION__,
705 (UINT32)BootOptions[Index].OptionNumber,
706 DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
707 Status
708 ));
709 if (DevicePathString != NULL) {
710 FreePool (DevicePathString);
711 }
712
713 DEBUG_CODE_END ();
714 }
715
716 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
717 }
718
719 STATIC
720 VOID
721 PlatformRegisterOptionsAndKeys (
722 VOID
723 )
724 {
725 EFI_STATUS Status;
726 EFI_INPUT_KEY Enter;
727 EFI_INPUT_KEY F2;
728 EFI_INPUT_KEY Esc;
729 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
730
731 //
732 // Register ENTER as CONTINUE key
733 //
734 Enter.ScanCode = SCAN_NULL;
735 Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
736 Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
737 ASSERT_EFI_ERROR (Status);
738
739 //
740 // Map F2 and ESC to Boot Manager Menu
741 //
742 F2.ScanCode = SCAN_F2;
743 F2.UnicodeChar = CHAR_NULL;
744 Esc.ScanCode = SCAN_ESC;
745 Esc.UnicodeChar = CHAR_NULL;
746 Status = EfiBootManagerGetBootManagerMenu (&BootOption);
747 ASSERT_EFI_ERROR (Status);
748 Status = EfiBootManagerAddKeyOptionVariable (
749 NULL,
750 (UINT16)BootOption.OptionNumber,
751 0,
752 &F2,
753 NULL
754 );
755 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
756 Status = EfiBootManagerAddKeyOptionVariable (
757 NULL,
758 (UINT16)BootOption.OptionNumber,
759 0,
760 &Esc,
761 NULL
762 );
763 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
764 }
765
766 //
767 // BDS Platform Functions
768 //
769
770 /**
771 Do the platform init, can be customized by OEM/IBV
772 Possible things that can be done in PlatformBootManagerBeforeConsole:
773 > Update console variable: 1. include hot-plug devices;
774 > 2. Clear ConIn and add SOL for AMT
775 > Register new Driver#### or Boot####
776 > Register new Key####: e.g.: F12
777 > Signal ReadyToLock event
778 > Authentication action: 1. connect Auth devices;
779 > 2. Identify auto logon user.
780 **/
781 VOID
782 EFIAPI
783 PlatformBootManagerBeforeConsole (
784 VOID
785 )
786 {
787 UINT16 FrontPageTimeout;
788 RETURN_STATUS PcdStatus;
789 EFI_STATUS Status;
790
791 //
792 // Signal EndOfDxe PI Event
793 //
794 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
795
796 //
797 // Disable the TPM 2 platform hierarchy
798 //
799 ConfigureTpmPlatformHierarchy ();
800
801 //
802 // Dispatch deferred images after EndOfDxe event.
803 //
804 EfiBootManagerDispatchDeferredImages ();
805
806 //
807 // Locate the PCI root bridges and make the PCI bus driver connect each,
808 // non-recursively. This will produce a number of child handles with PciIo on
809 // them.
810 //
811 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);
812
813 //
814 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
815 //
816 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);
817
818 //
819 // Find all display class PCI devices (using the handles from the previous
820 // step), and connect them non-recursively. This should produce a number of
821 // child handles with GOPs on them.
822 //
823 FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);
824
825 //
826 // Now add the device path of all handles with GOP on them to ConOut and
827 // ErrOut.
828 //
829 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);
830
831 //
832 // Add the hardcoded short-form USB keyboard device path to ConIn.
833 //
834 EfiBootManagerUpdateConsoleVariable (
835 ConIn,
836 (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard,
837 NULL
838 );
839
840 //
841 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
842 //
843 CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid);
844
845 EfiBootManagerUpdateConsoleVariable (
846 ConIn,
847 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,
848 NULL
849 );
850 EfiBootManagerUpdateConsoleVariable (
851 ConOut,
852 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,
853 NULL
854 );
855 EfiBootManagerUpdateConsoleVariable (
856 ErrOut,
857 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,
858 NULL
859 );
860
861 //
862 // Set the front page timeout from the QEMU configuration.
863 //
864 FrontPageTimeout = GetFrontPageTimeoutFromQemu ();
865 PcdStatus = PcdSet16S (PcdPlatformBootTimeOut, FrontPageTimeout);
866 ASSERT_RETURN_ERROR (PcdStatus);
867 //
868 // Reflect the PCD in the standard Timeout variable.
869 //
870 Status = gRT->SetVariable (
871 EFI_TIME_OUT_VARIABLE_NAME,
872 &gEfiGlobalVariableGuid,
873 (EFI_VARIABLE_NON_VOLATILE |
874 EFI_VARIABLE_BOOTSERVICE_ACCESS |
875 EFI_VARIABLE_RUNTIME_ACCESS),
876 sizeof FrontPageTimeout,
877 &FrontPageTimeout
878 );
879 DEBUG ((
880 EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
881 "%a: SetVariable(%s, %u): %r\n",
882 __FUNCTION__,
883 EFI_TIME_OUT_VARIABLE_NAME,
884 FrontPageTimeout,
885 Status
886 ));
887
888 //
889 // Register platform-specific boot options and keyboard shortcuts.
890 //
891 PlatformRegisterOptionsAndKeys ();
892
893 //
894 // At this point, VIRTIO_DEVICE_PROTOCOL instances exist only for Virtio MMIO
895 // transports. Install EFI_RNG_PROTOCOL instances on Virtio MMIO RNG devices.
896 //
897 FilterAndProcess (&gVirtioDeviceProtocolGuid, IsVirtioRng, Connect);
898
899 //
900 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
901 // instances on Virtio PCI RNG devices.
902 //
903 FilterAndProcess (&gEfiPciIoProtocolGuid, IsVirtioPciRng, Connect);
904 }
905
906 /**
907 Do the platform specific action after the console is ready
908 Possible things that can be done in PlatformBootManagerAfterConsole:
909 > Console post action:
910 > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
911 > Signal console ready platform customized event
912 > Run diagnostics like memory testing
913 > Connect certain devices
914 > Dispatch additional option roms
915 > Special boot: e.g.: USB boot, enter UI
916 **/
917 VOID
918 EFIAPI
919 PlatformBootManagerAfterConsole (
920 VOID
921 )
922 {
923 RETURN_STATUS Status;
924 UINTN FirmwareVerLength;
925
926 FirmwareVerLength = StrLen (PcdGetPtr (PcdFirmwareVersionString));
927 //
928 // Show the splash screen.
929 //
930 BootLogoEnableLogo ();
931
932 if (FirmwareVerLength > 0) {
933 Print (
934 VERSION_STRING_PREFIX L"%s\n",
935 PcdGetPtr (PcdFirmwareVersionString)
936 );
937 }
938
939 Print (L"Press ESCAPE within 10 seconds for boot options ");
940 //
941 // Process QEMU's -kernel command line option. The kernel booted this way
942 // will receive ACPI tables: in PlatformBootManagerBeforeConsole(), we
943 // connected any and all PCI root bridges, and then signaled the ACPI
944 // platform driver.
945 //
946 TryRunningQemuKernel ();
947
948 //
949 // Connect the purported boot devices.
950 //
951 Status = ConnectDevicesFromQemu ();
952 if (RETURN_ERROR (Status)) {
953 //
954 // Connect the rest of the devices.
955 //
956 EfiBootManagerConnectAll ();
957 }
958
959 //
960 // Enumerate all possible boot options, then filter and reorder them based on
961 // the QEMU configuration.
962 //
963 EfiBootManagerRefreshAllBootOption ();
964
965 //
966 // Register UEFI Shell
967 //
968 PlatformRegisterFvBootOption (
969 &gUefiShellFileGuid,
970 L"EFI Internal Shell",
971 LOAD_OPTION_ACTIVE
972 );
973
974 RemoveStaleFvFileOptions ();
975 SetBootOrderFromQemu ();
976
977 PlatformBmPrintScRegisterHandler ();
978 }
979
980 /**
981 This function is called each second during the boot manager waits the
982 timeout.
983
984 @param TimeoutRemain The remaining timeout.
985 **/
986 VOID
987 EFIAPI
988 PlatformBootManagerWaitCallback (
989 UINT16 TimeoutRemain
990 )
991 {
992 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;
993 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;
994 UINT16 TimeoutInitial;
995
996 TimeoutInitial = PcdGet16 (PcdPlatformBootTimeOut);
997
998 //
999 // If PcdPlatformBootTimeOut is set to zero, then we consider
1000 // that no progress update should be enacted.
1001 //
1002 if (TimeoutInitial == 0) {
1003 return;
1004 }
1005
1006 Black.Raw = 0x00000000;
1007 White.Raw = 0x00FFFFFF;
1008
1009 BootLogoUpdateProgress (
1010 White.Pixel,
1011 Black.Pixel,
1012 L"Start boot option",
1013 White.Pixel,
1014 (TimeoutInitial - TimeoutRemain) * 100 / TimeoutInitial,
1015 0
1016 );
1017 }
1018
1019 /**
1020 The function is called when no boot option could be launched,
1021 including platform recovery options and options pointing to applications
1022 built into firmware volumes.
1023
1024 If this function returns, BDS attempts to enter an infinite loop.
1025 **/
1026 VOID
1027 EFIAPI
1028 PlatformBootManagerUnableToBoot (
1029 VOID
1030 )
1031 {
1032 EFI_STATUS Status;
1033 EFI_INPUT_KEY Key;
1034 EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
1035 UINTN Index;
1036
1037 //
1038 // BootManagerMenu doesn't contain the correct information when return status
1039 // is EFI_NOT_FOUND.
1040 //
1041 Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
1042 if (EFI_ERROR (Status)) {
1043 return;
1044 }
1045
1046 //
1047 // Normally BdsDxe does not print anything to the system console, but this is
1048 // a last resort -- the end-user will likely not see any DEBUG messages
1049 // logged in this situation.
1050 //
1051 // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
1052 // here to see if it makes sense to request and wait for a keypress.
1053 //
1054 if (gST->ConIn != NULL) {
1055 AsciiPrint (
1056 "%a: No bootable option or device was found.\n"
1057 "%a: Press any key to enter the Boot Manager Menu.\n",
1058 gEfiCallerBaseName,
1059 gEfiCallerBaseName
1060 );
1061 Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
1062 ASSERT_EFI_ERROR (Status);
1063 ASSERT (Index == 0);
1064
1065 //
1066 // Drain any queued keys.
1067 //
1068 while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {
1069 //
1070 // just throw away Key
1071 //
1072 }
1073 }
1074
1075 for ( ; ;) {
1076 EfiBootManagerBoot (&BootManagerMenu);
1077 }
1078 }