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>
21 VOID
*mEfiDevPathNotifyReg
;
22 EFI_EVENT mEfiDevPathEvent
;
23 UINT16 mHostBridgeDevId
;
26 // Table of host IRQs matching PCI IRQs A-D
27 // (for configuring PCI Interrupt Line register)
29 CONST UINT8 PciHostIrqs
[] = {
30 0x0a, 0x0a, 0x0b, 0x0b
39 (EFIAPI
*PROTOCOL_INSTANCE_CALLBACK
)(
46 @param[in] Handle - Handle of PCI device instance
47 @param[in] PciIo - PCI IO protocol instance
48 @param[in] Pci - PCI Header register block
52 (EFIAPI
*VISIT_PCI_INSTANCE_CALLBACK
)(
54 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
60 // Function prototypes
64 VisitAllInstancesOfProtocol (
66 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
71 VisitAllPciInstancesOfProtocol (
72 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
76 InstallDevicePathCallback (
81 PlatformRegisterFvBootOption (
89 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
90 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
91 UINTN BootOptionCount
;
92 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
93 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
94 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
96 Status
= gBS
->HandleProtocol (
98 &gEfiLoadedImageProtocolGuid
,
99 (VOID
**) &LoadedImage
101 ASSERT_EFI_ERROR (Status
);
103 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
104 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
105 ASSERT (DevicePath
!= NULL
);
106 DevicePath
= AppendDevicePathNode (
108 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
110 ASSERT (DevicePath
!= NULL
);
112 Status
= EfiBootManagerInitializeLoadOption (
114 LoadOptionNumberUnassigned
,
122 ASSERT_EFI_ERROR (Status
);
123 FreePool (DevicePath
);
125 BootOptions
= EfiBootManagerGetLoadOptions (
126 &BootOptionCount
, LoadOptionTypeBoot
129 OptionIndex
= EfiBootManagerFindLoadOption (
130 &NewOption
, BootOptions
, BootOptionCount
133 if (OptionIndex
== -1) {
134 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
135 ASSERT_EFI_ERROR (Status
);
137 EfiBootManagerFreeLoadOption (&NewOption
);
138 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
142 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
143 whose device paths do not resolve exactly to an FvFile in the system.
145 Also strip out every boot option that is not an FvFile, meaning the system
146 can only boot either the Grub or (if built) the shell.
148 This removes any boot options that point to binaries built into the firmware
149 and have become stale due to any of the following:
150 - DXEFV's base address or size changed (historical),
151 - DXEFV's FvNameGuid changed,
152 - the FILE_GUID of the pointed-to binary changed,
153 - the referenced binary is no longer built into the firmware.
155 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
156 avoids exact duplicates.
159 RemoveStaleFvFileOptions (
163 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
164 UINTN BootOptionCount
;
167 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
,
170 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
171 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
176 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
177 // then delete the boot option.
179 Node1
= BootOptions
[Index
].FilePath
;
180 if (!(DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
&&
181 DevicePathSubType (Node1
) == HW_MEMMAP_DP
) &&
182 !(DevicePathType (Node1
) == MEDIA_DEVICE_PATH
&&
183 DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)) {
184 EfiBootManagerDeleteLoadOptionVariable (
185 BootOptions
[Index
].OptionNumber
, LoadOptionTypeBoot
);
190 // If the second device path node is not FvFile(...), then delete the boot
193 Node2
= NextDevicePathNode (Node1
);
194 if (DevicePathType (Node2
) != MEDIA_DEVICE_PATH
||
195 DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
) {
196 EfiBootManagerDeleteLoadOptionVariable (
197 BootOptions
[Index
].OptionNumber
, LoadOptionTypeBoot
);
202 // Locate the Firmware Volume2 protocol instance that is denoted by the
203 // boot option. If this lookup fails (i.e., the boot option references a
204 // firmware volume that doesn't exist), then we'll proceed to delete the
208 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
,
209 &SearchNode
, &FvHandle
);
211 if (!EFI_ERROR (Status
)) {
213 // The firmware volume was found; now let's see if it contains the FvFile
214 // identified by GUID.
216 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
217 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
219 EFI_FV_FILETYPE FoundType
;
220 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
221 UINT32 AuthenticationStatus
;
223 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiFirmwareVolume2ProtocolGuid
,
224 (VOID
**)&FvProtocol
);
225 ASSERT_EFI_ERROR (Status
);
227 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
229 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
232 Status
= FvProtocol
->ReadFile (
234 &FvFileNode
->FvFileName
, // NameGuid
239 &AuthenticationStatus
241 if (!EFI_ERROR (Status
)) {
243 // The FvFile was found. Keep the boot option.
250 // Delete the boot option.
252 Status
= EfiBootManagerDeleteLoadOptionVariable (
253 BootOptions
[Index
].OptionNumber
, LoadOptionTypeBoot
);
255 CHAR16
*DevicePathString
;
257 DevicePathString
= ConvertDevicePathToText(BootOptions
[Index
].FilePath
,
260 EFI_ERROR (Status
) ? DEBUG_WARN
: DEBUG_VERBOSE
,
261 "%a: removing stale Boot#%04x %s: %r\n",
263 (UINT32
)BootOptions
[Index
].OptionNumber
,
264 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
267 if (DevicePathString
!= NULL
) {
268 FreePool (DevicePathString
);
273 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
279 IN EFI_HANDLE RootBridgeHandle
,
287 ConnectVirtioPciRng (
288 IN EFI_HANDLE Handle
,
294 // BDS Platform Functions
297 Do the platform init, can be customized by OEM/IBV
299 Possible things that can be done in PlatformBootManagerBeforeConsole:
301 > Update console variable: 1. include hot-plug devices;
302 > 2. Clear ConIn and add SOL for AMT
303 > Register new Driver#### or Boot####
304 > Register new Key####: e.g.: F12
305 > Signal ReadyToLock event
306 > Authentication action: 1. connect Auth devices;
307 > 2. Identify auto logon user.
311 PlatformBootManagerBeforeConsole (
317 UINT16 FrontPageTimeout
;
319 FrontPageTimeout
= 0;
321 DEBUG ((DEBUG_INFO
, "PlatformBootManagerBeforeConsole\n"));
322 InstallDevicePathCallback ();
324 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid
,
325 ConnectRootBridge
, NULL
);
328 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
330 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
333 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
334 // the preparation of S3 system information. That logic has a hard dependency
335 // on the presence of the FACS ACPI table. Since our ACPI tables are only
336 // installed after PCI enumeration completes, we must not trigger the S3 save
337 // earlier, hence we can't signal End-of-Dxe earlier.
339 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
342 // Prevent further changes to LockBoxes or SMRAM.
345 Status
= gBS
->InstallProtocolInterface (&Handle
,
346 &gEfiDxeSmmReadyToLockProtocolGuid
, EFI_NATIVE_INTERFACE
,
348 ASSERT_EFI_ERROR (Status
);
351 // Dispatch deferred images after EndOfDxe event and ReadyToLock
354 EfiBootManagerDispatchDeferredImages ();
356 PlatformInitializeConsole (gPlatformConsole
);
358 Status
= gRT
->SetVariable (
359 EFI_TIME_OUT_VARIABLE_NAME
,
360 &gEfiGlobalVariableGuid
,
361 (EFI_VARIABLE_NON_VOLATILE
|
362 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
363 EFI_VARIABLE_RUNTIME_ACCESS
),
364 sizeof FrontPageTimeout
,
368 // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
369 // instances on Virtio PCI RNG devices.
371 VisitAllInstancesOfProtocol (&gEfiPciIoProtocolGuid
, ConnectVirtioPciRng
,
379 IN EFI_HANDLE RootBridgeHandle
,
387 // Make the PCI bus driver connect the root bridge, non-recursively. This
388 // will produce a number of child handles with PciIo on them.
390 Status
= gBS
->ConnectController (
391 RootBridgeHandle
, // ControllerHandle
392 NULL
, // DriverImageHandle
393 NULL
, // RemainingDevicePath -- produce all
404 ConnectVirtioPciRng (
405 IN EFI_HANDLE Handle
,
410 EFI_PCI_IO_PROTOCOL
*PciIo
;
421 // Read and check VendorId.
423 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_VENDOR_ID_OFFSET
,
425 if (EFI_ERROR (Status
)) {
428 if (VendorId
!= VIRTIO_VENDOR_ID
) {
433 // Read DeviceId and RevisionId.
435 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, PCI_DEVICE_ID_OFFSET
,
437 if (EFI_ERROR (Status
)) {
440 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, PCI_REVISION_ID_OFFSET
,
442 if (EFI_ERROR (Status
)) {
447 // From DeviceId and RevisionId, determine whether the device is a
448 // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
449 // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
450 // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
451 // only be sanity-checked, and SubsystemId will decide.
453 if (DeviceId
== 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
&&
454 RevisionId
>= 0x01) {
456 } else if (DeviceId
>= 0x1000 && DeviceId
<= 0x103F && RevisionId
== 0x00) {
463 // Read and check SubsystemId as dictated by Virtio10.
465 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
,
466 PCI_SUBSYSTEM_ID_OFFSET
, 1, &SubsystemId
);
467 if (EFI_ERROR (Status
)) {
470 if ((Virtio10
&& SubsystemId
>= 0x40) ||
471 (!Virtio10
&& SubsystemId
== VIRTIO_SUBSYSTEM_ENTROPY_SOURCE
)) {
472 Status
= gBS
->ConnectController (
473 Handle
, // ControllerHandle
474 NULL
, // DriverImageHandle -- connect all drivers
475 NULL
, // RemainingDevicePath -- produce all child handles
476 FALSE
// Recursive -- don't follow child handles
478 if (EFI_ERROR (Status
)) {
485 DEBUG ((DEBUG_ERROR
, "%a: %r\n", __FUNCTION__
, Status
));
491 Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
493 @param[in] DeviceHandle Handle of the LPC Bridge device.
495 @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
496 ConOut, ConIn, and ErrOut.
498 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
502 PrepareLpcBridgeDevicePath (
503 IN EFI_HANDLE DeviceHandle
507 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
508 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
512 Status
= gBS
->HandleProtocol (
514 &gEfiDevicePathProtocolGuid
,
517 if (EFI_ERROR (Status
)) {
520 TempDevicePath
= DevicePath
;
525 DevicePath
= AppendDevicePathNode (DevicePath
,
526 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
528 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
533 DevicePath
= TempDevicePath
;
534 gPnp16550ComPortDeviceNode
.UID
= 0;
536 DevicePath
= AppendDevicePathNode (DevicePath
,
537 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
538 DevicePath
= AppendDevicePathNode (DevicePath
,
539 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
540 DevicePath
= AppendDevicePathNode (DevicePath
,
541 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
546 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
547 if (DevPathStr
!= NULL
) {
550 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
552 gPnp16550ComPortDeviceNode
.UID
+ 1,
555 FreePool(DevPathStr
);
558 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
559 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
560 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
565 DevicePath
= TempDevicePath
;
566 gPnp16550ComPortDeviceNode
.UID
= 1;
568 DevicePath
= AppendDevicePathNode (DevicePath
,
569 (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
570 DevicePath
= AppendDevicePathNode (DevicePath
,
571 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
572 DevicePath
= AppendDevicePathNode (DevicePath
,
573 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
578 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
579 if (DevPathStr
!= NULL
) {
582 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
584 gPnp16550ComPortDeviceNode
.UID
+ 1,
587 FreePool(DevPathStr
);
590 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
591 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
592 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
599 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
600 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
605 EFI_HANDLE PciDeviceHandle
;
606 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
607 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
608 UINTN GopHandleCount
;
609 EFI_HANDLE
*GopHandleBuffer
;
611 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
612 return EFI_INVALID_PARAMETER
;
616 // Initialize the GopDevicePath to be PciDevicePath
618 *GopDevicePath
= PciDevicePath
;
619 TempPciDevicePath
= PciDevicePath
;
621 Status
= gBS
->LocateDevicePath (
622 &gEfiDevicePathProtocolGuid
,
626 if (EFI_ERROR (Status
)) {
631 // Try to connect this handle, so that GOP driver could start on this
632 // device and create child handles with GraphicsOutput Protocol installed
633 // on them, then we get device paths of these child handles and select
634 // them as possible console device.
636 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
638 Status
= gBS
->LocateHandleBuffer (
640 &gEfiGraphicsOutputProtocolGuid
,
645 if (!EFI_ERROR (Status
)) {
647 // Add all the child handles as possible Console Device
649 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
650 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
],
651 &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
652 if (EFI_ERROR (Status
)) {
658 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
661 // In current implementation, we only enable one of the child handles
662 // as console device, i.e. sotre one of the child handle's device
663 // path to variable "ConOut"
664 // In future, we could select all child handles to be console device
667 *GopDevicePath
= TempDevicePath
;
670 // Delete the PCI device's path that added by
671 // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
673 EfiBootManagerUpdateConsoleVariable (ConOutDev
, NULL
, PciDevicePath
);
674 EfiBootManagerUpdateConsoleVariable (ConOutDev
, TempDevicePath
, NULL
);
677 gBS
->FreePool (GopHandleBuffer
);
684 Add PCI display to ConOut.
686 @param[in] DeviceHandle Handle of the PCI display device.
688 @retval EFI_SUCCESS The PCI display device has been added to ConOut.
690 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
694 PreparePciDisplayDevicePath (
695 IN EFI_HANDLE DeviceHandle
699 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
700 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
703 GopDevicePath
= NULL
;
704 Status
= gBS
->HandleProtocol (
706 &gEfiDevicePathProtocolGuid
,
709 if (EFI_ERROR (Status
)) {
713 GetGopDevicePath (DevicePath
, &GopDevicePath
);
714 DevicePath
= GopDevicePath
;
716 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
722 Add PCI Serial to ConOut, ConIn, ErrOut.
724 @param[in] DeviceHandle Handle of the PCI serial device.
726 @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,
729 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
733 PreparePciSerialDevicePath (
734 IN EFI_HANDLE DeviceHandle
738 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
741 Status
= gBS
->HandleProtocol (
743 &gEfiDevicePathProtocolGuid
,
746 if (EFI_ERROR (Status
)) {
750 DevicePath
= AppendDevicePathNode (DevicePath
,
751 (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
752 DevicePath
= AppendDevicePathNode (DevicePath
,
753 (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
755 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
756 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
757 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
763 VisitAllInstancesOfProtocol (
765 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
771 EFI_HANDLE
*HandleBuffer
;
776 // Start to check all the PciIo to find all possible device
780 Status
= gBS
->LocateHandleBuffer (
787 if (EFI_ERROR (Status
)) {
791 for (Index
= 0; Index
< HandleCount
; Index
++) {
792 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
793 if (EFI_ERROR (Status
)) {
797 Status
= (*CallBackFunction
) (
804 gBS
->FreePool (HandleBuffer
);
812 VisitingAPciInstance (
813 IN EFI_HANDLE Handle
,
819 EFI_PCI_IO_PROTOCOL
*PciIo
;
822 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
825 // Check for all PCI device
827 Status
= PciIo
->Pci
.Read (
831 sizeof (Pci
) / sizeof (UINT32
),
834 if (EFI_ERROR (Status
)) {
838 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
849 VisitAllPciInstances (
850 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
853 return VisitAllInstancesOfProtocol (
854 &gEfiPciIoProtocolGuid
,
855 VisitingAPciInstance
,
856 (VOID
*)(UINTN
) CallBackFunction
862 Do platform specific PCI Device check and add them to
863 ConOut, ConIn, ErrOut.
865 @param[in] Handle - Handle of PCI device instance
866 @param[in] PciIo - PCI IO protocol instance
867 @param[in] Pci - PCI Header register block
869 @retval EFI_SUCCESS - PCI Device check and Console variable update
871 @retval EFI_STATUS - PCI Device check or Console variable update fail.
876 DetectAndPreparePlatformPciDevicePath (
877 IN EFI_HANDLE Handle
,
878 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
884 Status
= PciIo
->Attributes (
886 EfiPciIoAttributeOperationEnable
,
887 EFI_PCI_DEVICE_ENABLE
,
890 ASSERT_EFI_ERROR (Status
);
893 // Here we decide whether it is LPC Bridge
895 if ((IS_PCI_LPC (Pci
)) ||
896 ((IS_PCI_ISA_PDECODE (Pci
)) &&
897 (Pci
->Hdr
.VendorId
== 0x8086) &&
898 (Pci
->Hdr
.DeviceId
== 0x7000)
902 // Add IsaKeyboard to ConIn,
903 // add IsaSerial to ConOut, ConIn, ErrOut
905 DEBUG ((DEBUG_INFO
, "Found LPC Bridge device\n"));
906 PrepareLpcBridgeDevicePath (Handle
);
910 // Here we decide which Serial device to enable in PCI bus
912 if (IS_PCI_16550SERIAL (Pci
)) {
914 // Add them to ConOut, ConIn, ErrOut.
916 DEBUG ((DEBUG_INFO
, "Found PCI 16550 SERIAL device\n"));
917 PreparePciSerialDevicePath (Handle
);
922 // Here we decide which display device to enable in PCI bus
924 if (IS_PCI_DISPLAY (Pci
)) {
926 // Add them to ConOut.
928 DEBUG ((DEBUG_INFO
, "Found PCI display device\n"));
929 PreparePciDisplayDevicePath (Handle
);
938 Connect the predefined platform default console device.
940 Always try to find and enable PCI display devices.
942 @param[in] PlatformConsole Predefined platform default console device array.
945 PlatformInitializeConsole (
946 IN PLATFORM_CONSOLE_CONNECT_ENTRY
*PlatformConsole
952 // Do platform specific PCI Device check and add them to ConOut, ConIn,
955 VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
958 // Have chance to connect the platform default console,
959 // the platform default console is the minimum device group
960 // the platform should support
962 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
964 // Update the console variable with the connect type
966 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
967 EfiBootManagerUpdateConsoleVariable (ConIn
,
968 PlatformConsole
[Index
].DevicePath
, NULL
);
970 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
971 EfiBootManagerUpdateConsoleVariable (ConOut
,
972 PlatformConsole
[Index
].DevicePath
, NULL
);
974 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
975 EfiBootManagerUpdateConsoleVariable (ErrOut
,
976 PlatformConsole
[Index
].DevicePath
, NULL
);
983 Configure PCI Interrupt Line register for applicable devices
984 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
986 @param[in] Handle - Handle of PCI device instance
987 @param[in] PciIo - PCI IO protocol instance
988 @param[in] PciHdr - PCI Header register block
990 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
996 IN EFI_HANDLE Handle
,
997 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
998 IN PCI_TYPE00
*PciHdr
1001 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1002 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
1007 UINT32 RootBusNumber
;
1009 Status
= EFI_SUCCESS
;
1011 if (PciHdr
->Device
.InterruptPin
!= 0) {
1013 DevPathNode
= DevicePathFromHandle (Handle
);
1014 ASSERT (DevPathNode
!= NULL
);
1015 DevPath
= DevPathNode
;
1018 if (DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
&&
1019 DevicePathSubType (DevPathNode
) == ACPI_DP
&&
1020 ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID(0x0A03)) {
1021 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
1025 // Compute index into PciHostIrqs[] table by walking
1026 // the device path and adding up all device numbers
1028 Status
= EFI_NOT_FOUND
;
1030 Idx
= PciHdr
->Device
.InterruptPin
- 1;
1031 while (!IsDevicePathEnd (DevPathNode
)) {
1032 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
1033 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
1035 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1038 // Unlike SeaBIOS, which starts climbing from the leaf device
1039 // up toward the root, we traverse the device path starting at
1040 // the root moving toward the leaf node.
1041 // The slot number of the top-level parent bridge is needed for
1042 // Q35 cases with more than 24 slots on the root bus.
1044 if (Status
!= EFI_SUCCESS
) {
1045 Status
= EFI_SUCCESS
;
1046 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1050 DevPathNode
= NextDevicePathNode (DevPathNode
);
1052 if (EFI_ERROR (Status
)) {
1055 if (RootBusNumber
== 0 && RootSlot
== 0) {
1058 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
1065 // Final PciHostIrqs[] index calculation depends on the platform
1066 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
1068 switch (mHostBridgeDevId
) {
1069 case INTEL_82441_DEVICE_ID
:
1072 case INTEL_Q35_MCH_DEVICE_ID
:
1074 // SeaBIOS contains the following comment:
1075 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
1076 // with a different starting index - see q35-acpi-dsdt.dsl.
1078 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
1080 if (RootSlot
> 24) {
1082 // in this case, subtract back out RootSlot from Idx
1083 // (SeaBIOS never adds it to begin with, but that would make our
1084 // device path traversal loop above too awkward)
1090 ASSERT (FALSE
); // should never get here
1092 Idx
%= ARRAY_SIZE (PciHostIrqs
);
1093 IrqLine
= PciHostIrqs
[Idx
];
1095 DEBUG_CODE_BEGIN ();
1097 CHAR16
*DevPathString
;
1098 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
1099 UINTN Segment
, Bus
, Device
, Function
;
1101 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
1102 if (DevPathString
== NULL
) {
1103 DevPathString
= Fallback
;
1105 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
1106 ASSERT_EFI_ERROR (Status
);
1108 DEBUG ((DEBUG_VERBOSE
, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__
,
1109 (UINT32
)Bus
, (UINT32
)Device
, (UINT32
)Function
, DevPathString
,
1112 if (DevPathString
!= Fallback
) {
1113 FreePool (DevPathString
);
1119 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
1121 Status
= PciIo
->Pci
.Write (
1124 PCI_INT_LINE_OFFSET
,
1135 PciAcpiInitialization (
1141 // Query Host Bridge DID to determine platform type
1143 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
1144 switch (mHostBridgeDevId
) {
1145 case INTEL_82441_DEVICE_ID
:
1146 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
1148 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
1150 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
1151 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
1152 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
1153 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
1155 case INTEL_Q35_MCH_DEVICE_ID
:
1156 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
1158 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
1160 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
1161 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
1162 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
1163 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
1164 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
1165 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
1166 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
1167 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
1170 DEBUG ((DEBUG_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
1171 __FUNCTION__
, mHostBridgeDevId
));
1177 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
1179 VisitAllPciInstances (SetPciIntLine
);
1182 // Set ACPI SCI_EN bit in PMCNTRL
1184 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
1189 ConnectRecursivelyIfPciMassStorage (
1190 IN EFI_HANDLE Handle
,
1191 IN EFI_PCI_IO_PROTOCOL
*Instance
,
1192 IN PCI_TYPE00
*PciHeader
1196 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1200 // Recognize PCI Mass Storage
1202 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
)) {
1204 Status
= gBS
->HandleProtocol (
1206 &gEfiDevicePathProtocolGuid
,
1209 if (EFI_ERROR (Status
)) {
1214 // Print Device Path
1216 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
1217 if (DevPathStr
!= NULL
) {
1220 "Found Mass Storage device: %s\n",
1223 FreePool(DevPathStr
);
1226 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
1227 if (EFI_ERROR (Status
)) {
1238 Connect with predefined platform connect sequence.
1240 The OEM/IBV can customize with their own connect sequence.
1243 PlatformBdsConnectSequence (
1249 DEBUG ((DEBUG_INFO
, "PlatformBdsConnectSequence\n"));
1254 // Here we can get the customized platform connect sequence
1255 // Notes: we can connect with new variable which record the
1256 // last time boots connect device path sequence
1258 while (gPlatformConnectSequence
[Index
] != NULL
) {
1260 // Build the platform boot option
1262 EfiBootManagerConnectDevicePath (gPlatformConnectSequence
[Index
], NULL
);
1265 EfiBootManagerConnectAll ();
1269 Do the platform specific action after the console is ready
1271 Possible things that can be done in PlatformBootManagerAfterConsole:
1273 > Console post action:
1274 > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
1275 > Signal console ready platform customized event
1276 > Run diagnostics like memory testing
1277 > Connect certain devices
1278 > Dispatch aditional option roms
1279 > Special boot: e.g.: USB boot, enter UI
1283 PlatformBootManagerAfterConsole (
1287 EFI_BOOT_MODE BootMode
;
1289 DEBUG ((DEBUG_INFO
, "PlatformBootManagerAfterConsole\n"));
1292 // Get current Boot Mode
1294 BootMode
= GetBootModeHob ();
1295 DEBUG ((DEBUG_INFO
, "Boot Mode:%x\n", BootMode
));
1298 // Go the different platform policy with different boot mode
1299 // Notes: this part code can be change with the table policy
1301 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1306 BootLogoEnableLogo ();
1309 // Set PCI Interrupt Line registers and ACPI SCI_EN
1311 PciAcpiInitialization ();
1314 // Process TPM PPI request
1316 Tcg2PhysicalPresenceLibProcessRequest (NULL
);
1319 // Process QEMU's -kernel command line option
1321 TryRunningQemuKernel ();
1324 // Perform some platform specific connect sequence
1326 PlatformBdsConnectSequence ();
1328 EfiBootManagerRefreshAllBootOption ();
1331 // Register UEFI Shell (Will be removed if the Shell isn't built
1332 // which is the default)
1334 PlatformRegisterFvBootOption (
1335 &gUefiShellFileGuid
, L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
1341 PlatformRegisterFvBootOption (
1342 &gGrubFileGuid
, L
"Grub Bootloader", LOAD_OPTION_ACTIVE
1345 RemoveStaleFvFileOptions ();
1347 PlatformBmPrintScRegisterHandler ();
1351 This notification function is invoked when an instance of the
1352 EFI_DEVICE_PATH_PROTOCOL is produced.
1354 @param Event The event that occurred
1355 @param Context For EFI compatibility. Not used.
1368 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1369 ATAPI_DEVICE_PATH
*Atapi
;
1372 // Examine all new handles
1376 // Get the next handle
1378 BufferSize
= sizeof (Handle
);
1379 Status
= gBS
->LocateHandle (
1382 mEfiDevPathNotifyReg
,
1388 // If not found, we're done
1390 if (EFI_NOT_FOUND
== Status
) {
1394 if (EFI_ERROR (Status
)) {
1399 // Get the DevicePath protocol on that handle
1401 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
,
1402 (VOID
**)&DevPathNode
);
1403 ASSERT_EFI_ERROR (Status
);
1405 while (!IsDevicePathEnd (DevPathNode
)) {
1407 // Find the handler to dump this device path node
1410 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1411 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1413 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1419 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1426 // Next device path node
1428 DevPathNode
= NextDevicePathNode (DevPathNode
);
1437 InstallDevicePathCallback (
1441 DEBUG ((DEBUG_INFO
, "Registered NotifyDevPath Event\n"));
1442 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1443 &gEfiDevicePathProtocolGuid
,
1447 &mEfiDevPathNotifyReg
1452 This function is called each second during the boot manager waits the
1455 @param TimeoutRemain The remaining timeout.
1459 PlatformBootManagerWaitCallback (
1460 UINT16 TimeoutRemain
1464 // Since the timeout should be forced to zero we should never
1471 The function is called when no boot option could be launched,
1472 including platform recovery options and options pointing to applications
1473 built into firmware volumes.
1475 If this function returns, BDS attempts to enter an infinite loop.
1479 PlatformBootManagerUnableToBoot (
1484 // If we get here something failed about the grub boot but since
1485 // We're privy to the secret we must panic and not retry or loop