2 Platform BDS customizations.
4 Copyright (C) 2020 James Bottomley, IBM Corporation.
5 Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "BdsPlatform.h"
11 #include <Guid/RootBridgesConnectedEventGroup.h>
12 #include <Protocol/FirmwareVolume2.h>
13 #include <Library/PlatformBmPrintScLib.h>
14 #include <Library/Tcg2PhysicalPresenceLib.h>
20 VOID
*mEfiDevPathNotifyReg
;
21 EFI_EVENT mEfiDevPathEvent
;
22 UINT16 mHostBridgeDevId
;
25 // Table of host IRQs matching PCI IRQs A-D
26 // (for configuring PCI Interrupt Line register)
28 CONST UINT8 PciHostIrqs
[] = {
29 0x0a, 0x0a, 0x0b, 0x0b
38 (EFIAPI
*PROTOCOL_INSTANCE_CALLBACK
)(
45 @param[in] Handle - Handle of PCI device instance
46 @param[in] PciIo - PCI IO protocol instance
47 @param[in] Pci - PCI Header register block
51 (EFIAPI
*VISIT_PCI_INSTANCE_CALLBACK
)(
53 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
58 // Function prototypes
62 VisitAllInstancesOfProtocol (
64 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
69 VisitAllPciInstancesOfProtocol (
70 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
74 InstallDevicePathCallback (
79 PlatformRegisterFvBootOption (
87 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
88 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
89 UINTN BootOptionCount
;
90 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
91 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
92 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
94 Status
= gBS
->HandleProtocol (
96 &gEfiLoadedImageProtocolGuid
,
99 ASSERT_EFI_ERROR (Status
);
101 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
102 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
103 ASSERT (DevicePath
!= NULL
);
104 DevicePath
= AppendDevicePathNode (
106 (EFI_DEVICE_PATH_PROTOCOL
*)&FileNode
108 ASSERT (DevicePath
!= NULL
);
110 Status
= EfiBootManagerInitializeLoadOption (
112 LoadOptionNumberUnassigned
,
120 ASSERT_EFI_ERROR (Status
);
121 FreePool (DevicePath
);
123 BootOptions
= EfiBootManagerGetLoadOptions (
128 OptionIndex
= EfiBootManagerFindLoadOption (
134 if (OptionIndex
== -1) {
135 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
136 ASSERT_EFI_ERROR (Status
);
139 EfiBootManagerFreeLoadOption (&NewOption
);
140 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
144 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
145 whose device paths do not resolve exactly to an FvFile in the system.
147 Also strip out every boot option that is not an FvFile, meaning the system
148 can only boot either the Grub or (if built) the shell.
150 This removes any boot options that point to binaries built into the firmware
151 and have become stale due to any of the following:
152 - DXEFV's base address or size changed (historical),
153 - DXEFV's FvNameGuid changed,
154 - the FILE_GUID of the pointed-to binary changed,
155 - the referenced binary is no longer built into the firmware.
157 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
158 avoids exact duplicates.
161 RemoveStaleFvFileOptions (
165 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
166 UINTN BootOptionCount
;
169 BootOptions
= EfiBootManagerGetLoadOptions (
174 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
175 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
180 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
181 // then delete the boot option.
183 Node1
= BootOptions
[Index
].FilePath
;
184 if (!((DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
) &&
185 (DevicePathSubType (Node1
) == HW_MEMMAP_DP
)) &&
186 !((DevicePathType (Node1
) == MEDIA_DEVICE_PATH
) &&
187 (DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)))
189 EfiBootManagerDeleteLoadOptionVariable (
190 BootOptions
[Index
].OptionNumber
,
197 // If the second device path node is not FvFile(...), then delete the boot
200 Node2
= NextDevicePathNode (Node1
);
201 if ((DevicePathType (Node2
) != MEDIA_DEVICE_PATH
) ||
202 (DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
))
204 EfiBootManagerDeleteLoadOptionVariable (
205 BootOptions
[Index
].OptionNumber
,
212 // Locate the Firmware Volume2 protocol instance that is denoted by the
213 // boot option. If this lookup fails (i.e., the boot option references a
214 // firmware volume that doesn't exist), then we'll proceed to delete the
218 Status
= gBS
->LocateDevicePath (
219 &gEfiFirmwareVolume2ProtocolGuid
,
224 if (!EFI_ERROR (Status
)) {
226 // The firmware volume was found; now let's see if it contains the FvFile
227 // identified by GUID.
229 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
230 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
232 EFI_FV_FILETYPE FoundType
;
233 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
234 UINT32 AuthenticationStatus
;
236 Status
= gBS
->HandleProtocol (
238 &gEfiFirmwareVolume2ProtocolGuid
,
241 ASSERT_EFI_ERROR (Status
);
243 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
245 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
248 Status
= FvProtocol
->ReadFile (
250 &FvFileNode
->FvFileName
, // NameGuid
255 &AuthenticationStatus
257 if (!EFI_ERROR (Status
)) {
259 // The FvFile was found. Keep the boot option.
266 // Delete the boot option.
268 Status
= EfiBootManagerDeleteLoadOptionVariable (
269 BootOptions
[Index
].OptionNumber
,
273 CHAR16
*DevicePathString
;
275 DevicePathString
= ConvertDevicePathToText (
276 BootOptions
[Index
].FilePath
,
281 EFI_ERROR (Status
) ? DEBUG_WARN
: DEBUG_VERBOSE
,
282 "%a: removing stale Boot#%04x %s: %r\n",
284 (UINT32
)BootOptions
[Index
].OptionNumber
,
285 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
288 if (DevicePathString
!= NULL
) {
289 FreePool (DevicePathString
);
295 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
301 IN EFI_HANDLE RootBridgeHandle
,
309 ConnectVirtioPciRng (
310 IN EFI_HANDLE Handle
,
316 // BDS Platform Functions
320 Do the platform init, can be customized by OEM/IBV
322 Possible things that can be done in PlatformBootManagerBeforeConsole:
324 > Update console variable: 1. include hot-plug devices;
325 > 2. Clear ConIn and add SOL for AMT
326 > Register new Driver#### or Boot####
327 > Register new Key####: e.g.: F12
328 > Signal ReadyToLock event
329 > Authentication action: 1. connect Auth devices;
330 > 2. Identify auto logon user.
334 PlatformBootManagerBeforeConsole (
340 UINT16 FrontPageTimeout
;
342 FrontPageTimeout
= 0;
344 DEBUG ((DEBUG_INFO
, "PlatformBootManagerBeforeConsole\n"));
345 InstallDevicePathCallback ();
347 VisitAllInstancesOfProtocol (
348 &gEfiPciRootBridgeIoProtocolGuid
,
354 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
356 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
359 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
360 // the preparation of S3 system information. That logic has a hard dependency
361 // on the presence of the FACS ACPI table. Since our ACPI tables are only
362 // installed after PCI enumeration completes, we must not trigger the S3 save
363 // earlier, hence we can't signal End-of-Dxe earlier.
365 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
367 // We need to connect all trusted consoles for TCG PP. Here we treat all
368 // consoles in OVMF to be trusted consoles.
369 PlatformInitializeConsole (gPlatformConsole
);
372 // Process TPM PPI request
374 Tcg2PhysicalPresenceLibProcessRequest (NULL
);
377 // Prevent further changes to LockBoxes or SMRAM.
378 // Any TPM 2 Physical Presence Interface opcode must be handled before.
381 Status
= gBS
->InstallProtocolInterface (
383 &gEfiDxeSmmReadyToLockProtocolGuid
,
384 EFI_NATIVE_INTERFACE
,
387 ASSERT_EFI_ERROR (Status
);
390 // Dispatch deferred images after EndOfDxe event and ReadyToLock
393 EfiBootManagerDispatchDeferredImages ();
395 Status
= gRT
->SetVariable (
396 EFI_TIME_OUT_VARIABLE_NAME
,
397 &gEfiGlobalVariableGuid
,
398 (EFI_VARIABLE_NON_VOLATILE
|
399 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
400 EFI_VARIABLE_RUNTIME_ACCESS
),
401 sizeof FrontPageTimeout
,
405 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
406 // instances on Virtio PCI RNG devices.
408 VisitAllInstancesOfProtocol (
409 &gEfiPciIoProtocolGuid
,
418 IN EFI_HANDLE RootBridgeHandle
,
426 // Make the PCI bus driver connect the root bridge, non-recursively. This
427 // will produce a number of child handles with PciIo on them.
429 Status
= gBS
->ConnectController (
430 RootBridgeHandle
, // ControllerHandle
431 NULL
, // DriverImageHandle
432 NULL
, // RemainingDevicePath -- produce all
442 ConnectVirtioPciRng (
443 IN EFI_HANDLE Handle
,
448 EFI_PCI_IO_PROTOCOL
*PciIo
;
459 // Read and check VendorId.
461 Status
= PciIo
->Pci
.Read (
464 PCI_VENDOR_ID_OFFSET
,
468 if (EFI_ERROR (Status
)) {
472 if (VendorId
!= VIRTIO_VENDOR_ID
) {
477 // Read DeviceId and RevisionId.
479 Status
= PciIo
->Pci
.Read (
482 PCI_DEVICE_ID_OFFSET
,
486 if (EFI_ERROR (Status
)) {
490 Status
= PciIo
->Pci
.Read (
493 PCI_REVISION_ID_OFFSET
,
497 if (EFI_ERROR (Status
)) {
502 // From DeviceId and RevisionId, determine whether the device is a
503 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
504 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
505 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
506 // only be sanity-checked, and SubsystemId will decide.
508 if ((DeviceId
== 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
) &&
509 (RevisionId
>= 0x01))
512 } else if ((DeviceId
>= 0x1000) && (DeviceId
<= 0x103F) && (RevisionId
== 0x00)) {
519 // Read and check SubsystemId as dictated by Virtio10.
521 Status
= PciIo
->Pci
.Read (
524 PCI_SUBSYSTEM_ID_OFFSET
,
528 if (EFI_ERROR (Status
)) {
532 if ((Virtio10
&& (SubsystemId
>= 0x40)) ||
533 (!Virtio10
&& (SubsystemId
== VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
)))
535 Status
= gBS
->ConnectController (
536 Handle
, // ControllerHandle
537 NULL
, // DriverImageHandle -- connect all drivers
538 NULL
, // RemainingDevicePath -- produce all child handles
539 FALSE
// Recursive -- don't follow child handles
541 if (EFI_ERROR (Status
)) {
549 DEBUG ((DEBUG_ERROR
, "%a: %r\n", __FUNCTION__
, Status
));
554 Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
556 @param[in] DeviceHandle Handle of the LPC Bridge device.
558 @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
559 ConOut, ConIn, and ErrOut.
561 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
565 PrepareLpcBridgeDevicePath (
566 IN EFI_HANDLE DeviceHandle
570 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
571 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
575 Status
= gBS
->HandleProtocol (
577 &gEfiDevicePathProtocolGuid
,
580 if (EFI_ERROR (Status
)) {
584 TempDevicePath
= DevicePath
;
589 DevicePath
= AppendDevicePathNode (
591 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
594 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
599 DevicePath
= TempDevicePath
;
600 gPnp16550ComPortDeviceNode
.UID
= 0;
602 DevicePath
= AppendDevicePathNode (
604 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
606 DevicePath
= AppendDevicePathNode (
608 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
610 DevicePath
= AppendDevicePathNode (
612 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
618 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
619 if (DevPathStr
!= NULL
) {
622 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
624 gPnp16550ComPortDeviceNode
.UID
+ 1,
627 FreePool (DevPathStr
);
630 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
631 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
632 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
637 DevicePath
= TempDevicePath
;
638 gPnp16550ComPortDeviceNode
.UID
= 1;
640 DevicePath
= AppendDevicePathNode (
642 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
644 DevicePath
= AppendDevicePathNode (
646 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
648 DevicePath
= AppendDevicePathNode (
650 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
656 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
657 if (DevPathStr
!= NULL
) {
660 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
662 gPnp16550ComPortDeviceNode
.UID
+ 1,
665 FreePool (DevPathStr
);
668 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
669 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
670 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
677 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
678 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
683 EFI_HANDLE PciDeviceHandle
;
684 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
685 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
686 UINTN GopHandleCount
;
687 EFI_HANDLE
*GopHandleBuffer
;
689 if ((PciDevicePath
== NULL
) || (GopDevicePath
== NULL
)) {
690 return EFI_INVALID_PARAMETER
;
694 // Initialize the GopDevicePath to be PciDevicePath
696 *GopDevicePath
= PciDevicePath
;
697 TempPciDevicePath
= PciDevicePath
;
699 Status
= gBS
->LocateDevicePath (
700 &gEfiDevicePathProtocolGuid
,
704 if (EFI_ERROR (Status
)) {
709 // Try to connect this handle, so that GOP driver could start on this
710 // device and create child handles with GraphicsOutput Protocol installed
711 // on them, then we get device paths of these child handles and select
712 // them as possible console device.
714 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
716 Status
= gBS
->LocateHandleBuffer (
718 &gEfiGraphicsOutputProtocolGuid
,
723 if (!EFI_ERROR (Status
)) {
725 // Add all the child handles as possible Console Device
727 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
728 Status
= gBS
->HandleProtocol (
729 GopHandleBuffer
[Index
],
730 &gEfiDevicePathProtocolGuid
,
731 (VOID
*)&TempDevicePath
733 if (EFI_ERROR (Status
)) {
740 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
744 // In current implementation, we only enable one of the child handles
745 // as console device, i.e. sotre one of the child handle's device
746 // path to variable "ConOut"
747 // In future, we could select all child handles to be console device
750 *GopDevicePath
= TempDevicePath
;
753 // Delete the PCI device's path that added by
754 // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
756 EfiBootManagerUpdateConsoleVariable (ConOutDev
, NULL
, PciDevicePath
);
757 EfiBootManagerUpdateConsoleVariable (ConOutDev
, TempDevicePath
, NULL
);
761 gBS
->FreePool (GopHandleBuffer
);
768 Add PCI display to ConOut.
770 @param[in] DeviceHandle Handle of the PCI display device.
772 @retval EFI_SUCCESS The PCI display device has been added to ConOut.
774 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
778 PreparePciDisplayDevicePath (
779 IN EFI_HANDLE DeviceHandle
783 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
784 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
787 GopDevicePath
= NULL
;
788 Status
= gBS
->HandleProtocol (
790 &gEfiDevicePathProtocolGuid
,
793 if (EFI_ERROR (Status
)) {
797 GetGopDevicePath (DevicePath
, &GopDevicePath
);
798 DevicePath
= GopDevicePath
;
800 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
806 Add PCI Serial to ConOut, ConIn, ErrOut.
808 @param[in] DeviceHandle Handle of the PCI serial device.
810 @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,
813 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
817 PreparePciSerialDevicePath (
818 IN EFI_HANDLE DeviceHandle
822 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
825 Status
= gBS
->HandleProtocol (
827 &gEfiDevicePathProtocolGuid
,
830 if (EFI_ERROR (Status
)) {
834 DevicePath
= AppendDevicePathNode (
836 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
838 DevicePath
= AppendDevicePathNode (
840 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
843 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
844 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
845 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
851 VisitAllInstancesOfProtocol (
853 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
859 EFI_HANDLE
*HandleBuffer
;
864 // Start to check all the PciIo to find all possible device
868 Status
= gBS
->LocateHandleBuffer (
875 if (EFI_ERROR (Status
)) {
879 for (Index
= 0; Index
< HandleCount
; Index
++) {
880 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
881 if (EFI_ERROR (Status
)) {
885 Status
= (*CallBackFunction
)(
892 gBS
->FreePool (HandleBuffer
);
899 VisitingAPciInstance (
900 IN EFI_HANDLE Handle
,
906 EFI_PCI_IO_PROTOCOL
*PciIo
;
909 PciIo
= (EFI_PCI_IO_PROTOCOL
*)Instance
;
912 // Check for all PCI device
914 Status
= PciIo
->Pci
.Read (
918 sizeof (Pci
) / sizeof (UINT32
),
921 if (EFI_ERROR (Status
)) {
925 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
)Context
)(
933 VisitAllPciInstances (
934 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
937 return VisitAllInstancesOfProtocol (
938 &gEfiPciIoProtocolGuid
,
939 VisitingAPciInstance
,
940 (VOID
*)(UINTN
)CallBackFunction
945 Do platform specific PCI Device check and add them to
946 ConOut, ConIn, ErrOut.
948 @param[in] Handle - Handle of PCI device instance
949 @param[in] PciIo - PCI IO protocol instance
950 @param[in] Pci - PCI Header register block
952 @retval EFI_SUCCESS - PCI Device check and Console variable update
954 @retval EFI_STATUS - PCI Device check or Console variable update fail.
959 DetectAndPreparePlatformPciDevicePath (
960 IN EFI_HANDLE Handle
,
961 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
967 Status
= PciIo
->Attributes (
969 EfiPciIoAttributeOperationEnable
,
970 EFI_PCI_DEVICE_ENABLE
,
973 ASSERT_EFI_ERROR (Status
);
976 // Here we decide whether it is LPC Bridge
978 if ((IS_PCI_LPC (Pci
)) ||
979 ((IS_PCI_ISA_PDECODE (Pci
)) &&
980 (Pci
->Hdr
.VendorId
== 0x8086) &&
981 (Pci
->Hdr
.DeviceId
== 0x7000)
986 // Add IsaKeyboard to ConIn,
987 // add IsaSerial to ConOut, ConIn, ErrOut
989 DEBUG ((DEBUG_INFO
, "Found LPC Bridge device\n"));
990 PrepareLpcBridgeDevicePath (Handle
);
995 // Here we decide which Serial device to enable in PCI bus
997 if (IS_PCI_16550SERIAL (Pci
)) {
999 // Add them to ConOut, ConIn, ErrOut.
1001 DEBUG ((DEBUG_INFO
, "Found PCI 16550 SERIAL device\n"));
1002 PreparePciSerialDevicePath (Handle
);
1007 // Here we decide which display device to enable in PCI bus
1009 if (IS_PCI_DISPLAY (Pci
)) {
1011 // Add them to ConOut.
1013 DEBUG ((DEBUG_INFO
, "Found PCI display device\n"));
1014 PreparePciDisplayDevicePath (Handle
);
1022 Connect the predefined platform default console device.
1024 Always try to find and enable PCI display devices.
1026 @param[in] PlatformConsole Predefined platform default console device array.
1029 PlatformInitializeConsole (
1030 IN PLATFORM_CONSOLE_CONNECT_ENTRY
*PlatformConsole
1036 // Do platform specific PCI Device check and add them to ConOut, ConIn,
1039 VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
1042 // Have chance to connect the platform default console,
1043 // the platform default console is the minimum device group
1044 // the platform should support
1046 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
1048 // Update the console variable with the connect type
1050 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
1051 EfiBootManagerUpdateConsoleVariable (
1053 PlatformConsole
[Index
].DevicePath
,
1058 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
1059 EfiBootManagerUpdateConsoleVariable (
1061 PlatformConsole
[Index
].DevicePath
,
1066 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
1067 EfiBootManagerUpdateConsoleVariable (
1069 PlatformConsole
[Index
].DevicePath
,
1077 Configure PCI Interrupt Line register for applicable devices
1078 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
1080 @param[in] Handle - Handle of PCI device instance
1081 @param[in] PciIo - PCI IO protocol instance
1082 @param[in] PciHdr - PCI Header register block
1084 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
1090 IN EFI_HANDLE Handle
,
1091 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1092 IN PCI_TYPE00
*PciHdr
1095 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1096 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1101 UINT32 RootBusNumber
;
1103 Status
= EFI_SUCCESS
;
1105 if (PciHdr
->Device
.InterruptPin
!= 0) {
1106 DevPathNode
= DevicePathFromHandle (Handle
);
1107 ASSERT (DevPathNode
!= NULL
);
1108 DevPath
= DevPathNode
;
1111 if ((DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
) &&
1112 (DevicePathSubType (DevPathNode
) == ACPI_DP
) &&
1113 (((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID (0x0A03)))
1115 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
1119 // Compute index into PciHostIrqs[] table by walking
1120 // the device path and adding up all device numbers
1122 Status
= EFI_NOT_FOUND
;
1124 Idx
= PciHdr
->Device
.InterruptPin
- 1;
1125 while (!IsDevicePathEnd (DevPathNode
)) {
1126 if ((DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
) &&
1127 (DevicePathSubType (DevPathNode
) == HW_PCI_DP
))
1129 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1132 // Unlike SeaBIOS, which starts climbing from the leaf device
1133 // up toward the root, we traverse the device path starting at
1134 // the root moving toward the leaf node.
1135 // The slot number of the top-level parent bridge is needed for
1136 // Q35 cases with more than 24 slots on the root bus.
1138 if (Status
!= EFI_SUCCESS
) {
1139 Status
= EFI_SUCCESS
;
1140 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1144 DevPathNode
= NextDevicePathNode (DevPathNode
);
1147 if (EFI_ERROR (Status
)) {
1151 if ((RootBusNumber
== 0) && (RootSlot
== 0)) {
1154 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
1161 // Final PciHostIrqs[] index calculation depends on the platform
1162 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
1164 switch (mHostBridgeDevId
) {
1165 case INTEL_82441_DEVICE_ID
:
1168 case INTEL_Q35_MCH_DEVICE_ID
:
1170 // SeaBIOS contains the following comment:
1171 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
1172 // with a different starting index - see q35-acpi-dsdt.dsl.
1174 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
1176 if (RootSlot
> 24) {
1178 // in this case, subtract back out RootSlot from Idx
1179 // (SeaBIOS never adds it to begin with, but that would make our
1180 // device path traversal loop above too awkward)
1187 ASSERT (FALSE
); // should never get here
1190 Idx
%= ARRAY_SIZE (PciHostIrqs
);
1191 IrqLine
= PciHostIrqs
[Idx
];
1193 DEBUG_CODE_BEGIN ();
1195 CHAR16
*DevPathString
;
1196 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
1197 UINTN Segment
, Bus
, Device
, Function
;
1199 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
1200 if (DevPathString
== NULL
) {
1201 DevPathString
= Fallback
;
1204 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
1205 ASSERT_EFI_ERROR (Status
);
1209 "%a: [%02x:%02x.%x] %s -> 0x%02x\n",
1218 if (DevPathString
!= Fallback
) {
1219 FreePool (DevPathString
);
1225 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
1227 Status
= PciIo
->Pci
.Write (
1230 PCI_INT_LINE_OFFSET
,
1240 PciAcpiInitialization (
1246 // Query Host Bridge DID to determine platform type
1248 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
1249 switch (mHostBridgeDevId
) {
1250 case INTEL_82441_DEVICE_ID
:
1251 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
1253 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
1255 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
1256 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
1257 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
1258 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
1260 case INTEL_Q35_MCH_DEVICE_ID
:
1261 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
1263 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
1265 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
1266 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
1267 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
1268 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
1269 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
1270 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
1271 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
1272 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
1277 "%a: Unknown Host Bridge Device ID: 0x%04x\n",
1286 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
1288 VisitAllPciInstances (SetPciIntLine
);
1291 // Set ACPI SCI_EN bit in PMCNTRL
1293 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
1298 ConnectRecursivelyIfPciMassStorage (
1299 IN EFI_HANDLE Handle
,
1300 IN EFI_PCI_IO_PROTOCOL
*Instance
,
1301 IN PCI_TYPE00
*PciHeader
1305 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1309 // Recognize PCI Mass Storage
1311 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
)) {
1313 Status
= gBS
->HandleProtocol (
1315 &gEfiDevicePathProtocolGuid
,
1318 if (EFI_ERROR (Status
)) {
1323 // Print Device Path
1325 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
1326 if (DevPathStr
!= NULL
) {
1329 "Found Mass Storage device: %s\n",
1332 FreePool (DevPathStr
);
1335 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
1336 if (EFI_ERROR (Status
)) {
1345 Connect with predefined platform connect sequence.
1347 The OEM/IBV can customize with their own connect sequence.
1350 PlatformBdsConnectSequence (
1356 DEBUG ((DEBUG_INFO
, "PlatformBdsConnectSequence\n"));
1361 // Here we can get the customized platform connect sequence
1362 // Notes: we can connect with new variable which record the
1363 // last time boots connect device path sequence
1365 while (gPlatformConnectSequence
[Index
] != NULL
) {
1367 // Build the platform boot option
1369 EfiBootManagerConnectDevicePath (gPlatformConnectSequence
[Index
], NULL
);
1373 EfiBootManagerConnectAll ();
1377 Do the platform specific action after the console is ready
1379 Possible things that can be done in PlatformBootManagerAfterConsole:
1381 > Console post action:
1382 > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
1383 > Signal console ready platform customized event
1384 > Run diagnostics like memory testing
1385 > Connect certain devices
1386 > Dispatch aditional option roms
1387 > Special boot: e.g.: USB boot, enter UI
1391 PlatformBootManagerAfterConsole (
1395 EFI_BOOT_MODE BootMode
;
1397 DEBUG ((DEBUG_INFO
, "PlatformBootManagerAfterConsole\n"));
1400 // Get current Boot Mode
1402 BootMode
= GetBootModeHob ();
1403 DEBUG ((DEBUG_INFO
, "Boot Mode:%x\n", BootMode
));
1406 // Go the different platform policy with different boot mode
1407 // Notes: this part code can be change with the table policy
1409 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1414 BootLogoEnableLogo ();
1417 // Set PCI Interrupt Line registers and ACPI SCI_EN
1419 PciAcpiInitialization ();
1422 // Process QEMU's -kernel command line option
1424 TryRunningQemuKernel ();
1427 // Perform some platform specific connect sequence
1429 PlatformBdsConnectSequence ();
1431 EfiBootManagerRefreshAllBootOption ();
1434 // Register UEFI Shell (Will be removed if the Shell isn't built
1435 // which is the default)
1437 PlatformRegisterFvBootOption (
1438 &gUefiShellFileGuid
,
1439 L
"EFI Internal Shell",
1446 PlatformRegisterFvBootOption (
1452 RemoveStaleFvFileOptions ();
1454 PlatformBmPrintScRegisterHandler ();
1458 This notification function is invoked when an instance of the
1459 EFI_DEVICE_PATH_PROTOCOL is produced.
1461 @param Event The event that occurred
1462 @param Context For EFI compatibility. Not used.
1475 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1476 ATAPI_DEVICE_PATH
*Atapi
;
1479 // Examine all new handles
1483 // Get the next handle
1485 BufferSize
= sizeof (Handle
);
1486 Status
= gBS
->LocateHandle (
1489 mEfiDevPathNotifyReg
,
1495 // If not found, we're done
1497 if (EFI_NOT_FOUND
== Status
) {
1501 if (EFI_ERROR (Status
)) {
1506 // Get the DevicePath protocol on that handle
1508 Status
= gBS
->HandleProtocol (
1510 &gEfiDevicePathProtocolGuid
,
1511 (VOID
**)&DevPathNode
1513 ASSERT_EFI_ERROR (Status
);
1515 while (!IsDevicePathEnd (DevPathNode
)) {
1517 // Find the handler to dump this device path node
1520 (DevicePathType (DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1521 (DevicePathSubType (DevPathNode
) == MSG_ATAPI_DP
)
1524 Atapi
= (ATAPI_DEVICE_PATH
*)DevPathNode
;
1530 (Atapi
->PrimarySecondary
== 1) ? 0x42 : 0x40
1537 // Next device path node
1539 DevPathNode
= NextDevicePathNode (DevPathNode
);
1547 InstallDevicePathCallback (
1551 DEBUG ((DEBUG_INFO
, "Registered NotifyDevPath Event\n"));
1552 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1553 &gEfiDevicePathProtocolGuid
,
1557 &mEfiDevPathNotifyReg
1562 This function is called each second during the boot manager waits the
1565 @param TimeoutRemain The remaining timeout.
1569 PlatformBootManagerWaitCallback (
1570 UINT16 TimeoutRemain
1574 // Since the timeout should be forced to zero we should never
1581 The function is called when no boot option could be launched,
1582 including platform recovery options and options pointing to applications
1583 built into firmware volumes.
1585 If this function returns, BDS attempts to enter an infinite loop.
1589 PlatformBootManagerUnableToBoot (
1594 // If we get here something failed about the grub boot but since
1595 // We're privy to the secret we must panic and not retry or loop