2 Platform BDS customizations.
4 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "BdsPlatform.h"
16 #include <Guid/RootBridgesConnectedEventGroup.h>
23 VOID
*mEfiDevPathNotifyReg
;
24 EFI_EVENT mEfiDevPathEvent
;
25 VOID
*mEmuVariableEventReg
;
26 EFI_EVENT mEmuVariableEvent
;
27 BOOLEAN mDetectVgaOnly
;
28 UINT16 mHostBridgeDevId
;
31 // Table of host IRQs matching PCI IRQs A-D
32 // (for configuring PCI Interrupt Line register)
34 CONST UINT8 PciHostIrqs
[] = {
35 0x0a, 0x0a, 0x0b, 0x0b
41 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
49 (EFIAPI
*PROTOCOL_INSTANCE_CALLBACK
)(
56 @param[in] Handle - Handle of PCI device instance
57 @param[in] PciIo - PCI IO protocol instance
58 @param[in] Pci - PCI Header register block
62 (EFIAPI
*VISIT_PCI_INSTANCE_CALLBACK
)(
64 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
70 // Function prototypes
74 VisitAllInstancesOfProtocol (
76 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
81 VisitAllPciInstancesOfProtocol (
82 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
86 InstallDevicePathCallback (
91 PlatformRegisterFvBootOption (
99 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
100 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
101 UINTN BootOptionCount
;
102 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
103 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
104 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
106 Status
= gBS
->HandleProtocol (
108 &gEfiLoadedImageProtocolGuid
,
109 (VOID
**) &LoadedImage
111 ASSERT_EFI_ERROR (Status
);
113 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
114 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
115 ASSERT (DevicePath
!= NULL
);
116 DevicePath
= AppendDevicePathNode (
118 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
120 ASSERT (DevicePath
!= NULL
);
122 Status
= EfiBootManagerInitializeLoadOption (
124 LoadOptionNumberUnassigned
,
132 ASSERT_EFI_ERROR (Status
);
133 FreePool (DevicePath
);
135 BootOptions
= EfiBootManagerGetLoadOptions (
136 &BootOptionCount
, LoadOptionTypeBoot
139 OptionIndex
= EfiBootManagerFindLoadOption (
140 &NewOption
, BootOptions
, BootOptionCount
143 if (OptionIndex
== -1) {
144 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
145 ASSERT_EFI_ERROR (Status
);
147 EfiBootManagerFreeLoadOption (&NewOption
);
148 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
152 PlatformRegisterOptionsAndKeys (
160 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
163 // Register ENTER as CONTINUE key
165 Enter
.ScanCode
= SCAN_NULL
;
166 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
167 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
168 ASSERT_EFI_ERROR (Status
);
171 // Map F2 to Boot Manager Menu
173 F2
.ScanCode
= SCAN_F2
;
174 F2
.UnicodeChar
= CHAR_NULL
;
175 Esc
.ScanCode
= SCAN_ESC
;
176 Esc
.UnicodeChar
= CHAR_NULL
;
177 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
178 ASSERT_EFI_ERROR (Status
);
179 Status
= EfiBootManagerAddKeyOptionVariable (
180 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
182 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
183 Status
= EfiBootManagerAddKeyOptionVariable (
184 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
186 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
192 IN EFI_HANDLE RootBridgeHandle
,
204 // BDS Platform Functions
208 PlatformBootManagerBeforeConsole (
215 Platform Bds init. Incude the platform firmware vendor, revision
229 DEBUG ((EFI_D_INFO
, "PlatformBootManagerBeforeConsole\n"));
230 InstallDevicePathCallback ();
232 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid
,
233 ConnectRootBridge
, NULL
);
236 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
238 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
241 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
242 // the preparation of S3 system information. That logic has a hard dependency
243 // on the presence of the FACS ACPI table. Since our ACPI tables are only
244 // installed after PCI enumeration completes, we must not trigger the S3 save
245 // earlier, hence we can't signal End-of-Dxe earlier.
247 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
249 if (QemuFwCfgS3Enabled ()) {
251 // Save the boot script too. Note that this will require us to emit the
252 // DxeSmmReadyToLock event just below, which in turn locks down SMM.
258 // Prevent further changes to LockBoxes or SMRAM.
261 Status
= gBS
->InstallProtocolInterface (&Handle
,
262 &gEfiDxeSmmReadyToLockProtocolGuid
, EFI_NATIVE_INTERFACE
,
264 ASSERT_EFI_ERROR (Status
);
266 PlatformInitializeConsole (gPlatformConsole
);
267 PcdSet16 (PcdPlatformBootTimeOut
, GetFrontPageTimeoutFromQemu ());
269 PlatformRegisterOptionsAndKeys ();
276 IN EFI_HANDLE RootBridgeHandle
,
284 // Make the PCI bus driver connect the root bridge, non-recursively. This
285 // will produce a number of child handles with PciIo on them.
287 Status
= gBS
->ConnectController (
288 RootBridgeHandle
, // ControllerHandle
289 NULL
, // DriverImageHandle
290 NULL
, // RemainingDevicePath -- produce all
299 PrepareLpcBridgeDevicePath (
300 IN EFI_HANDLE DeviceHandle
306 Add IsaKeyboard to ConIn,
307 add IsaSerial to ConOut, ConIn, ErrOut.
312 DeviceHandle - Handle of PCIIO protocol.
316 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
317 EFI_STATUS - No LPC bridge is added.
322 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
323 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
327 Status
= gBS
->HandleProtocol (
329 &gEfiDevicePathProtocolGuid
,
332 if (EFI_ERROR (Status
)) {
335 TempDevicePath
= DevicePath
;
340 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
342 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
347 DevicePath
= TempDevicePath
;
348 gPnp16550ComPortDeviceNode
.UID
= 0;
350 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
351 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
352 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
357 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
358 if (DevPathStr
!= NULL
) {
361 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
363 gPnp16550ComPortDeviceNode
.UID
+ 1,
366 FreePool(DevPathStr
);
369 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
370 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
371 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
376 DevicePath
= TempDevicePath
;
377 gPnp16550ComPortDeviceNode
.UID
= 1;
379 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
380 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
381 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
386 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
387 if (DevPathStr
!= NULL
) {
390 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
392 gPnp16550ComPortDeviceNode
.UID
+ 1,
395 FreePool(DevPathStr
);
398 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
399 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
400 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
407 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
408 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
413 EFI_HANDLE PciDeviceHandle
;
414 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
415 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
416 UINTN GopHandleCount
;
417 EFI_HANDLE
*GopHandleBuffer
;
419 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
420 return EFI_INVALID_PARAMETER
;
424 // Initialize the GopDevicePath to be PciDevicePath
426 *GopDevicePath
= PciDevicePath
;
427 TempPciDevicePath
= PciDevicePath
;
429 Status
= gBS
->LocateDevicePath (
430 &gEfiDevicePathProtocolGuid
,
434 if (EFI_ERROR (Status
)) {
439 // Try to connect this handle, so that GOP dirver could start on this
440 // device and create child handles with GraphicsOutput Protocol installed
441 // on them, then we get device paths of these child handles and select
442 // them as possible console device.
444 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
446 Status
= gBS
->LocateHandleBuffer (
448 &gEfiGraphicsOutputProtocolGuid
,
453 if (!EFI_ERROR (Status
)) {
455 // Add all the child handles as possible Console Device
457 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
458 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
459 if (EFI_ERROR (Status
)) {
465 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
468 // In current implementation, we only enable one of the child handles
469 // as console device, i.e. sotre one of the child handle's device
470 // path to variable "ConOut"
471 // In futhure, we could select all child handles to be console device
474 *GopDevicePath
= TempDevicePath
;
477 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
478 // Add the integrity GOP device path.
480 EfiBootManagerUpdateConsoleVariable (ConOutDev
, NULL
, PciDevicePath
);
481 EfiBootManagerUpdateConsoleVariable (ConOutDev
, TempDevicePath
, NULL
);
484 gBS
->FreePool (GopHandleBuffer
);
491 PreparePciVgaDevicePath (
492 IN EFI_HANDLE DeviceHandle
498 Add PCI VGA to ConOut.
503 DeviceHandle - Handle of PCIIO protocol.
507 EFI_SUCCESS - PCI VGA is added to ConOut.
508 EFI_STATUS - No PCI VGA device is added.
513 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
514 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
517 GopDevicePath
= NULL
;
518 Status
= gBS
->HandleProtocol (
520 &gEfiDevicePathProtocolGuid
,
523 if (EFI_ERROR (Status
)) {
527 GetGopDevicePath (DevicePath
, &GopDevicePath
);
528 DevicePath
= GopDevicePath
;
530 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
536 PreparePciSerialDevicePath (
537 IN EFI_HANDLE DeviceHandle
543 Add PCI Serial to ConOut, ConIn, ErrOut.
548 DeviceHandle - Handle of PCIIO protocol.
552 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
553 EFI_STATUS - No PCI Serial device is added.
558 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
561 Status
= gBS
->HandleProtocol (
563 &gEfiDevicePathProtocolGuid
,
566 if (EFI_ERROR (Status
)) {
570 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
571 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
573 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
574 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
575 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
581 VisitAllInstancesOfProtocol (
583 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
589 EFI_HANDLE
*HandleBuffer
;
594 // Start to check all the PciIo to find all possible device
598 Status
= gBS
->LocateHandleBuffer (
605 if (EFI_ERROR (Status
)) {
609 for (Index
= 0; Index
< HandleCount
; Index
++) {
610 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
611 if (EFI_ERROR (Status
)) {
615 Status
= (*CallBackFunction
) (
622 gBS
->FreePool (HandleBuffer
);
630 VisitingAPciInstance (
631 IN EFI_HANDLE Handle
,
637 EFI_PCI_IO_PROTOCOL
*PciIo
;
640 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
643 // Check for all PCI device
645 Status
= PciIo
->Pci
.Read (
649 sizeof (Pci
) / sizeof (UINT32
),
652 if (EFI_ERROR (Status
)) {
656 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
667 VisitAllPciInstances (
668 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
671 return VisitAllInstancesOfProtocol (
672 &gEfiPciIoProtocolGuid
,
673 VisitingAPciInstance
,
674 (VOID
*)(UINTN
) CallBackFunction
680 Do platform specific PCI Device check and add them to
681 ConOut, ConIn, ErrOut.
683 @param[in] Handle - Handle of PCI device instance
684 @param[in] PciIo - PCI IO protocol instance
685 @param[in] Pci - PCI Header register block
687 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
688 @retval EFI_STATUS - PCI Device check or Console variable update fail.
693 DetectAndPreparePlatformPciDevicePath (
694 IN EFI_HANDLE Handle
,
695 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
701 Status
= PciIo
->Attributes (
703 EfiPciIoAttributeOperationEnable
,
704 EFI_PCI_DEVICE_ENABLE
,
707 ASSERT_EFI_ERROR (Status
);
709 if (!mDetectVgaOnly
) {
711 // Here we decide whether it is LPC Bridge
713 if ((IS_PCI_LPC (Pci
)) ||
714 ((IS_PCI_ISA_PDECODE (Pci
)) &&
715 (Pci
->Hdr
.VendorId
== 0x8086) &&
716 (Pci
->Hdr
.DeviceId
== 0x7000)
720 // Add IsaKeyboard to ConIn,
721 // add IsaSerial to ConOut, ConIn, ErrOut
723 DEBUG ((EFI_D_INFO
, "Found LPC Bridge device\n"));
724 PrepareLpcBridgeDevicePath (Handle
);
728 // Here we decide which Serial device to enable in PCI bus
730 if (IS_PCI_16550SERIAL (Pci
)) {
732 // Add them to ConOut, ConIn, ErrOut.
734 DEBUG ((EFI_D_INFO
, "Found PCI 16550 SERIAL device\n"));
735 PreparePciSerialDevicePath (Handle
);
741 // Here we decide which VGA device to enable in PCI bus
743 if (IS_PCI_VGA (Pci
)) {
745 // Add them to ConOut.
747 DEBUG ((EFI_D_INFO
, "Found PCI VGA device\n"));
748 PreparePciVgaDevicePath (Handle
);
757 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
759 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
761 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
762 @retval EFI_STATUS - PCI Device check or Console variable update fail.
766 DetectAndPreparePlatformPciDevicePaths (
767 BOOLEAN DetectVgaOnly
770 mDetectVgaOnly
= DetectVgaOnly
;
771 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
776 PlatformInitializeConsole (
777 IN PLATFORM_CONSOLE_CONNECT_ENTRY
*PlatformConsole
783 Connect the predefined platform default console device. Always try to find
784 and enable the vga device if have.
788 PlatformConsole - Predfined platform default console device array.
792 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
793 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
796 // Connect RootBridge
798 GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME
, (VOID
**) &VarConout
, NULL
);
799 GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME
, (VOID
**) &VarConin
, NULL
);
801 if (VarConout
== NULL
|| VarConin
== NULL
) {
803 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
805 DetectAndPreparePlatformPciDevicePaths (FALSE
);
808 // Have chance to connect the platform default console,
809 // the platform default console is the minimue device group
810 // the platform should support
812 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
814 // Update the console variable with the connect type
816 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
817 EfiBootManagerUpdateConsoleVariable (ConIn
, PlatformConsole
[Index
].DevicePath
, NULL
);
819 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
820 EfiBootManagerUpdateConsoleVariable (ConOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
822 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
823 EfiBootManagerUpdateConsoleVariable (ErrOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
828 // Only detect VGA device and add them to ConOut
830 DetectAndPreparePlatformPciDevicePaths (TRUE
);
836 Configure PCI Interrupt Line register for applicable devices
837 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
839 @param[in] Handle - Handle of PCI device instance
840 @param[in] PciIo - PCI IO protocol instance
841 @param[in] PciHdr - PCI Header register block
843 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
849 IN EFI_HANDLE Handle
,
850 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
851 IN PCI_TYPE00
*PciHdr
854 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
855 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
860 UINT32 RootBusNumber
;
862 Status
= EFI_SUCCESS
;
864 if (PciHdr
->Device
.InterruptPin
!= 0) {
866 DevPathNode
= DevicePathFromHandle (Handle
);
867 ASSERT (DevPathNode
!= NULL
);
868 DevPath
= DevPathNode
;
871 if (DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
&&
872 DevicePathSubType (DevPathNode
) == ACPI_DP
&&
873 ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID(0x0A03)) {
874 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
878 // Compute index into PciHostIrqs[] table by walking
879 // the device path and adding up all device numbers
881 Status
= EFI_NOT_FOUND
;
883 Idx
= PciHdr
->Device
.InterruptPin
- 1;
884 while (!IsDevicePathEnd (DevPathNode
)) {
885 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
886 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
888 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
891 // Unlike SeaBIOS, which starts climbing from the leaf device
892 // up toward the root, we traverse the device path starting at
893 // the root moving toward the leaf node.
894 // The slot number of the top-level parent bridge is needed for
895 // Q35 cases with more than 24 slots on the root bus.
897 if (Status
!= EFI_SUCCESS
) {
898 Status
= EFI_SUCCESS
;
899 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
903 DevPathNode
= NextDevicePathNode (DevPathNode
);
905 if (EFI_ERROR (Status
)) {
908 if (RootBusNumber
== 0 && RootSlot
== 0) {
911 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
918 // Final PciHostIrqs[] index calculation depends on the platform
919 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
921 switch (mHostBridgeDevId
) {
922 case INTEL_82441_DEVICE_ID
:
925 case INTEL_Q35_MCH_DEVICE_ID
:
927 // SeaBIOS contains the following comment:
928 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
929 // with a different starting index - see q35-acpi-dsdt.dsl.
931 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
935 // in this case, subtract back out RootSlot from Idx
936 // (SeaBIOS never adds it to begin with, but that would make our
937 // device path traversal loop above too awkward)
943 ASSERT (FALSE
); // should never get here
945 Idx
%= ARRAY_SIZE (PciHostIrqs
);
946 IrqLine
= PciHostIrqs
[Idx
];
950 CHAR16
*DevPathString
;
951 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
952 UINTN Segment
, Bus
, Device
, Function
;
954 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
955 if (DevPathString
== NULL
) {
956 DevPathString
= Fallback
;
958 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
959 ASSERT_EFI_ERROR (Status
);
961 DEBUG ((EFI_D_VERBOSE
, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__
,
962 (UINT32
)Bus
, (UINT32
)Device
, (UINT32
)Function
, DevPathString
,
965 if (DevPathString
!= Fallback
) {
966 FreePool (DevPathString
);
972 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
974 Status
= PciIo
->Pci
.Write (
988 PciAcpiInitialization (
994 // Query Host Bridge DID to determine platform type
996 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
997 switch (mHostBridgeDevId
) {
998 case INTEL_82441_DEVICE_ID
:
999 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
1001 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
1003 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
1004 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
1005 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
1006 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
1008 case INTEL_Q35_MCH_DEVICE_ID
:
1009 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
1011 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
1013 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
1014 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
1015 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
1016 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
1017 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
1018 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
1019 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
1020 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
1023 DEBUG ((EFI_D_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
1024 __FUNCTION__
, mHostBridgeDevId
));
1030 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
1032 VisitAllPciInstances (SetPciIntLine
);
1035 // Set ACPI SCI_EN bit in PMCNTRL
1037 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
1043 ConnectRecursivelyIfPciMassStorage (
1044 IN EFI_HANDLE Handle
,
1045 IN EFI_PCI_IO_PROTOCOL
*Instance
,
1046 IN PCI_TYPE00
*PciHeader
1050 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1053 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
)) {
1055 Status
= gBS
->HandleProtocol (
1057 &gEfiDevicePathProtocolGuid
,
1060 if (EFI_ERROR (Status
)) {
1065 // Print Device Path
1067 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
1068 if (DevPathStr
!= NULL
) {
1071 "Found Mass Storage device: %s\n",
1074 FreePool(DevPathStr
);
1077 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
1078 if (EFI_ERROR (Status
)) {
1089 This notification function is invoked when the
1090 EMU Variable FVB has been changed.
1092 @param Event The event that occured
1093 @param Context For EFI compatiblity. Not used.
1098 EmuVariablesUpdatedCallback (
1103 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
1104 UpdateNvVarsOnFileSystem ();
1110 VisitingFileSystemInstance (
1111 IN EFI_HANDLE Handle
,
1117 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
1119 if (ConnectedToFileSystem
) {
1120 return EFI_ALREADY_STARTED
;
1123 Status
= ConnectNvVarsToFileSystem (Handle
);
1124 if (EFI_ERROR (Status
)) {
1128 ConnectedToFileSystem
= TRUE
;
1130 EfiCreateProtocolNotifyEvent (
1131 &gEfiDevicePathProtocolGuid
,
1133 EmuVariablesUpdatedCallback
,
1135 &mEmuVariableEventReg
1137 PcdSet64 (PcdEmuVariableEvent
, (UINT64
)(UINTN
) mEmuVariableEvent
);
1144 PlatformBdsRestoreNvVarsFromHardDisk (
1147 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1148 VisitAllInstancesOfProtocol (
1149 &gEfiSimpleFileSystemProtocolGuid
,
1150 VisitingFileSystemInstance
,
1157 PlatformBdsConnectSequence (
1162 Routine Description:
1164 Connect with predeined platform connect sequence,
1165 the OEM/IBV can customize with their own connect sequence.
1179 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
1184 // Here we can get the customized platform connect sequence
1185 // Notes: we can connect with new variable which record the
1186 // last time boots connect device path sequence
1188 while (gPlatformConnectSequence
[Index
] != NULL
) {
1190 // Build the platform boot option
1192 EfiBootManagerConnectDevicePath (gPlatformConnectSequence
[Index
], NULL
);
1197 // Just use the simple policy to connect all devices
1199 DEBUG ((EFI_D_INFO
, "EfiBootManagerConnectAll\n"));
1200 EfiBootManagerConnectAll ();
1202 PciAcpiInitialization ();
1205 // Clear the logo after all devices are connected.
1207 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1211 Save the S3 boot script.
1213 Note that DxeSmmReadyToLock must be signaled after this function returns;
1214 otherwise the script wouldn't be saved actually.
1223 EFI_S3_SAVE_STATE_PROTOCOL
*BootScript
;
1224 STATIC CONST UINT8 Info
[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1226 Status
= gBS
->LocateProtocol (&gEfiS3SaveStateProtocolGuid
, NULL
,
1227 (VOID
**) &BootScript
);
1228 ASSERT_EFI_ERROR (Status
);
1231 // Despite the opcode documentation in the PI spec, the protocol
1232 // implementation embeds a deep copy of the info in the boot script, rather
1233 // than storing just a pointer to runtime or NVS storage.
1235 Status
= BootScript
->Write(BootScript
, EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
1236 (UINT32
) sizeof Info
,
1237 (EFI_PHYSICAL_ADDRESS
)(UINTN
) &Info
);
1238 ASSERT_EFI_ERROR (Status
);
1244 PlatformBootManagerAfterConsole (
1249 Routine Description:
1251 The function will excute with as the platform policy, current policy
1252 is driven by boot mode. IBV/OEM can customize this code for their specific
1257 EFI_BOOT_MODE BootMode
;
1259 DEBUG ((EFI_D_INFO
, "PlatformBootManagerAfterConsole\n"));
1261 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1262 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior: not restoring NvVars "
1263 "from disk since flash variables appear to be supported.\n"));
1266 // Try to restore variables from the hard disk early so
1267 // they can be used for the other BDS connect operations.
1269 PlatformBdsRestoreNvVarsFromHardDisk ();
1273 // Get current Boot Mode
1275 BootMode
= GetBootModeHob ();
1276 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1279 // Go the different platform policy with different boot mode
1280 // Notes: this part code can be change with the table policy
1282 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1287 EnableQuietBoot (PcdGetPtr (PcdLogoFile
));
1290 // Perform some platform specific connect sequence
1292 PlatformBdsConnectSequence ();
1295 // Process QEMU's -kernel command line option
1297 TryRunningQemuKernel ();
1299 EfiBootManagerRefreshAllBootOption ();
1302 // Register UEFI Shell
1304 PlatformRegisterFvBootOption (
1305 PcdGetPtr (PcdShellFile
), L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
1308 SetBootOrderFromQemu ();
1312 This notification function is invoked when an instance of the
1313 EFI_DEVICE_PATH_PROTOCOL is produced.
1315 @param Event The event that occured
1316 @param Context For EFI compatiblity. Not used.
1329 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1330 ATAPI_DEVICE_PATH
*Atapi
;
1333 // Examine all new handles
1337 // Get the next handle
1339 BufferSize
= sizeof (Handle
);
1340 Status
= gBS
->LocateHandle (
1343 mEfiDevPathNotifyReg
,
1349 // If not found, we're done
1351 if (EFI_NOT_FOUND
== Status
) {
1355 if (EFI_ERROR (Status
)) {
1360 // Get the DevicePath protocol on that handle
1362 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevPathNode
);
1363 ASSERT_EFI_ERROR (Status
);
1365 while (!IsDevicePathEnd (DevPathNode
)) {
1367 // Find the handler to dump this device path node
1370 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1371 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1373 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1379 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1386 // Next device path node
1388 DevPathNode
= NextDevicePathNode (DevPathNode
);
1397 InstallDevicePathCallback (
1401 DEBUG ((EFI_D_INFO
, "Registered NotifyDevPath Event\n"));
1402 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1403 &gEfiDevicePathProtocolGuid
,
1407 &mEfiDevPathNotifyReg
1412 This function is called each second during the boot manager waits the timeout.
1414 @param TimeoutRemain The remaining timeout.
1418 PlatformBootManagerWaitCallback (
1419 UINT16 TimeoutRemain