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
);
188 // Register UEFI Shell
190 PlatformRegisterFvBootOption (
191 PcdGetPtr (PcdShellFile
), L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
198 IN EFI_HANDLE RootBridgeHandle
,
210 // BDS Platform Functions
214 PlatformBootManagerBeforeConsole (
221 Platform Bds init. Incude the platform firmware vendor, revision
235 DEBUG ((EFI_D_INFO
, "PlatformBootManagerBeforeConsole\n"));
236 InstallDevicePathCallback ();
238 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid
,
239 ConnectRootBridge
, NULL
);
242 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
244 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
247 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
248 // the preparation of S3 system information. That logic has a hard dependency
249 // on the presence of the FACS ACPI table. Since our ACPI tables are only
250 // installed after PCI enumeration completes, we must not trigger the S3 save
251 // earlier, hence we can't signal End-of-Dxe earlier.
253 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
255 if (QemuFwCfgS3Enabled ()) {
257 // Save the boot script too. Note that this will require us to emit the
258 // DxeSmmReadyToLock event just below, which in turn locks down SMM.
264 // Prevent further changes to LockBoxes or SMRAM.
267 Status
= gBS
->InstallProtocolInterface (&Handle
,
268 &gEfiDxeSmmReadyToLockProtocolGuid
, EFI_NATIVE_INTERFACE
,
270 ASSERT_EFI_ERROR (Status
);
272 PlatformInitializeConsole (gPlatformConsole
);
273 PcdSet16 (PcdPlatformBootTimeOut
, GetFrontPageTimeoutFromQemu ());
275 PlatformRegisterOptionsAndKeys ();
282 IN EFI_HANDLE RootBridgeHandle
,
290 // Make the PCI bus driver connect the root bridge, non-recursively. This
291 // will produce a number of child handles with PciIo on them.
293 Status
= gBS
->ConnectController (
294 RootBridgeHandle
, // ControllerHandle
295 NULL
, // DriverImageHandle
296 NULL
, // RemainingDevicePath -- produce all
305 PrepareLpcBridgeDevicePath (
306 IN EFI_HANDLE DeviceHandle
312 Add IsaKeyboard to ConIn,
313 add IsaSerial to ConOut, ConIn, ErrOut.
318 DeviceHandle - Handle of PCIIO protocol.
322 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
323 EFI_STATUS - No LPC bridge is added.
328 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
329 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
333 Status
= gBS
->HandleProtocol (
335 &gEfiDevicePathProtocolGuid
,
338 if (EFI_ERROR (Status
)) {
341 TempDevicePath
= DevicePath
;
346 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
348 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
353 DevicePath
= TempDevicePath
;
354 gPnp16550ComPortDeviceNode
.UID
= 0;
356 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
357 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
358 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
363 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
364 if (DevPathStr
!= NULL
) {
367 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
369 gPnp16550ComPortDeviceNode
.UID
+ 1,
372 FreePool(DevPathStr
);
375 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
376 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
377 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
382 DevicePath
= TempDevicePath
;
383 gPnp16550ComPortDeviceNode
.UID
= 1;
385 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
386 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
387 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
392 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
393 if (DevPathStr
!= NULL
) {
396 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
398 gPnp16550ComPortDeviceNode
.UID
+ 1,
401 FreePool(DevPathStr
);
404 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
405 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
406 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
413 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
414 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
419 EFI_HANDLE PciDeviceHandle
;
420 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
421 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
422 UINTN GopHandleCount
;
423 EFI_HANDLE
*GopHandleBuffer
;
425 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
426 return EFI_INVALID_PARAMETER
;
430 // Initialize the GopDevicePath to be PciDevicePath
432 *GopDevicePath
= PciDevicePath
;
433 TempPciDevicePath
= PciDevicePath
;
435 Status
= gBS
->LocateDevicePath (
436 &gEfiDevicePathProtocolGuid
,
440 if (EFI_ERROR (Status
)) {
445 // Try to connect this handle, so that GOP dirver could start on this
446 // device and create child handles with GraphicsOutput Protocol installed
447 // on them, then we get device paths of these child handles and select
448 // them as possible console device.
450 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
452 Status
= gBS
->LocateHandleBuffer (
454 &gEfiGraphicsOutputProtocolGuid
,
459 if (!EFI_ERROR (Status
)) {
461 // Add all the child handles as possible Console Device
463 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
464 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
465 if (EFI_ERROR (Status
)) {
471 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
474 // In current implementation, we only enable one of the child handles
475 // as console device, i.e. sotre one of the child handle's device
476 // path to variable "ConOut"
477 // In futhure, we could select all child handles to be console device
480 *GopDevicePath
= TempDevicePath
;
483 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
484 // Add the integrity GOP device path.
486 EfiBootManagerUpdateConsoleVariable (ConOutDev
, NULL
, PciDevicePath
);
487 EfiBootManagerUpdateConsoleVariable (ConOutDev
, TempDevicePath
, NULL
);
490 gBS
->FreePool (GopHandleBuffer
);
497 PreparePciVgaDevicePath (
498 IN EFI_HANDLE DeviceHandle
504 Add PCI VGA to ConOut.
509 DeviceHandle - Handle of PCIIO protocol.
513 EFI_SUCCESS - PCI VGA is added to ConOut.
514 EFI_STATUS - No PCI VGA device is added.
519 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
520 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
523 GopDevicePath
= NULL
;
524 Status
= gBS
->HandleProtocol (
526 &gEfiDevicePathProtocolGuid
,
529 if (EFI_ERROR (Status
)) {
533 GetGopDevicePath (DevicePath
, &GopDevicePath
);
534 DevicePath
= GopDevicePath
;
536 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
542 PreparePciSerialDevicePath (
543 IN EFI_HANDLE DeviceHandle
549 Add PCI Serial to ConOut, ConIn, ErrOut.
554 DeviceHandle - Handle of PCIIO protocol.
558 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
559 EFI_STATUS - No PCI Serial device is added.
564 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
567 Status
= gBS
->HandleProtocol (
569 &gEfiDevicePathProtocolGuid
,
572 if (EFI_ERROR (Status
)) {
576 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
577 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
579 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
580 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
581 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
587 VisitAllInstancesOfProtocol (
589 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
595 EFI_HANDLE
*HandleBuffer
;
600 // Start to check all the PciIo to find all possible device
604 Status
= gBS
->LocateHandleBuffer (
611 if (EFI_ERROR (Status
)) {
615 for (Index
= 0; Index
< HandleCount
; Index
++) {
616 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
617 if (EFI_ERROR (Status
)) {
621 Status
= (*CallBackFunction
) (
628 gBS
->FreePool (HandleBuffer
);
636 VisitingAPciInstance (
637 IN EFI_HANDLE Handle
,
643 EFI_PCI_IO_PROTOCOL
*PciIo
;
646 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
649 // Check for all PCI device
651 Status
= PciIo
->Pci
.Read (
655 sizeof (Pci
) / sizeof (UINT32
),
658 if (EFI_ERROR (Status
)) {
662 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
673 VisitAllPciInstances (
674 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
677 return VisitAllInstancesOfProtocol (
678 &gEfiPciIoProtocolGuid
,
679 VisitingAPciInstance
,
680 (VOID
*)(UINTN
) CallBackFunction
686 Do platform specific PCI Device check and add them to
687 ConOut, ConIn, ErrOut.
689 @param[in] Handle - Handle of PCI device instance
690 @param[in] PciIo - PCI IO protocol instance
691 @param[in] Pci - PCI Header register block
693 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
694 @retval EFI_STATUS - PCI Device check or Console variable update fail.
699 DetectAndPreparePlatformPciDevicePath (
700 IN EFI_HANDLE Handle
,
701 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
707 Status
= PciIo
->Attributes (
709 EfiPciIoAttributeOperationEnable
,
710 EFI_PCI_DEVICE_ENABLE
,
713 ASSERT_EFI_ERROR (Status
);
715 if (!mDetectVgaOnly
) {
717 // Here we decide whether it is LPC Bridge
719 if ((IS_PCI_LPC (Pci
)) ||
720 ((IS_PCI_ISA_PDECODE (Pci
)) &&
721 (Pci
->Hdr
.VendorId
== 0x8086) &&
722 (Pci
->Hdr
.DeviceId
== 0x7000)
726 // Add IsaKeyboard to ConIn,
727 // add IsaSerial to ConOut, ConIn, ErrOut
729 DEBUG ((EFI_D_INFO
, "Found LPC Bridge device\n"));
730 PrepareLpcBridgeDevicePath (Handle
);
734 // Here we decide which Serial device to enable in PCI bus
736 if (IS_PCI_16550SERIAL (Pci
)) {
738 // Add them to ConOut, ConIn, ErrOut.
740 DEBUG ((EFI_D_INFO
, "Found PCI 16550 SERIAL device\n"));
741 PreparePciSerialDevicePath (Handle
);
747 // Here we decide which VGA device to enable in PCI bus
749 if (IS_PCI_VGA (Pci
)) {
751 // Add them to ConOut.
753 DEBUG ((EFI_D_INFO
, "Found PCI VGA device\n"));
754 PreparePciVgaDevicePath (Handle
);
763 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
765 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
767 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
768 @retval EFI_STATUS - PCI Device check or Console variable update fail.
772 DetectAndPreparePlatformPciDevicePaths (
773 BOOLEAN DetectVgaOnly
776 mDetectVgaOnly
= DetectVgaOnly
;
777 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
782 PlatformInitializeConsole (
783 IN PLATFORM_CONSOLE_CONNECT_ENTRY
*PlatformConsole
789 Connect the predefined platform default console device. Always try to find
790 and enable the vga device if have.
794 PlatformConsole - Predfined platform default console device array.
798 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
799 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
802 // Connect RootBridge
804 GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME
, (VOID
**) &VarConout
, NULL
);
805 GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME
, (VOID
**) &VarConin
, NULL
);
807 if (VarConout
== NULL
|| VarConin
== NULL
) {
809 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
811 DetectAndPreparePlatformPciDevicePaths (FALSE
);
814 // Have chance to connect the platform default console,
815 // the platform default console is the minimue device group
816 // the platform should support
818 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
820 // Update the console variable with the connect type
822 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
823 EfiBootManagerUpdateConsoleVariable (ConIn
, PlatformConsole
[Index
].DevicePath
, NULL
);
825 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
826 EfiBootManagerUpdateConsoleVariable (ConOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
828 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
829 EfiBootManagerUpdateConsoleVariable (ErrOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
834 // Only detect VGA device and add them to ConOut
836 DetectAndPreparePlatformPciDevicePaths (TRUE
);
842 Configure PCI Interrupt Line register for applicable devices
843 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
845 @param[in] Handle - Handle of PCI device instance
846 @param[in] PciIo - PCI IO protocol instance
847 @param[in] PciHdr - PCI Header register block
849 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
855 IN EFI_HANDLE Handle
,
856 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
857 IN PCI_TYPE00
*PciHdr
860 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
861 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
866 UINT32 RootBusNumber
;
868 Status
= EFI_SUCCESS
;
870 if (PciHdr
->Device
.InterruptPin
!= 0) {
872 DevPathNode
= DevicePathFromHandle (Handle
);
873 ASSERT (DevPathNode
!= NULL
);
874 DevPath
= DevPathNode
;
877 if (DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
&&
878 DevicePathSubType (DevPathNode
) == ACPI_DP
&&
879 ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID(0x0A03)) {
880 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
884 // Compute index into PciHostIrqs[] table by walking
885 // the device path and adding up all device numbers
887 Status
= EFI_NOT_FOUND
;
889 Idx
= PciHdr
->Device
.InterruptPin
- 1;
890 while (!IsDevicePathEnd (DevPathNode
)) {
891 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
892 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
894 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
897 // Unlike SeaBIOS, which starts climbing from the leaf device
898 // up toward the root, we traverse the device path starting at
899 // the root moving toward the leaf node.
900 // The slot number of the top-level parent bridge is needed for
901 // Q35 cases with more than 24 slots on the root bus.
903 if (Status
!= EFI_SUCCESS
) {
904 Status
= EFI_SUCCESS
;
905 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
909 DevPathNode
= NextDevicePathNode (DevPathNode
);
911 if (EFI_ERROR (Status
)) {
914 if (RootBusNumber
== 0 && RootSlot
== 0) {
917 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
924 // Final PciHostIrqs[] index calculation depends on the platform
925 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
927 switch (mHostBridgeDevId
) {
928 case INTEL_82441_DEVICE_ID
:
931 case INTEL_Q35_MCH_DEVICE_ID
:
933 // SeaBIOS contains the following comment:
934 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
935 // with a different starting index - see q35-acpi-dsdt.dsl.
937 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
941 // in this case, subtract back out RootSlot from Idx
942 // (SeaBIOS never adds it to begin with, but that would make our
943 // device path traversal loop above too awkward)
949 ASSERT (FALSE
); // should never get here
951 Idx
%= ARRAY_SIZE (PciHostIrqs
);
952 IrqLine
= PciHostIrqs
[Idx
];
956 CHAR16
*DevPathString
;
957 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
958 UINTN Segment
, Bus
, Device
, Function
;
960 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
961 if (DevPathString
== NULL
) {
962 DevPathString
= Fallback
;
964 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
965 ASSERT_EFI_ERROR (Status
);
967 DEBUG ((EFI_D_VERBOSE
, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__
,
968 (UINT32
)Bus
, (UINT32
)Device
, (UINT32
)Function
, DevPathString
,
971 if (DevPathString
!= Fallback
) {
972 FreePool (DevPathString
);
978 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
980 Status
= PciIo
->Pci
.Write (
994 PciAcpiInitialization (
1000 // Query Host Bridge DID to determine platform type
1002 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
1003 switch (mHostBridgeDevId
) {
1004 case INTEL_82441_DEVICE_ID
:
1005 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
1007 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
1009 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
1010 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
1011 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
1012 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
1014 case INTEL_Q35_MCH_DEVICE_ID
:
1015 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
1017 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
1019 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
1020 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
1021 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
1022 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
1023 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
1024 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
1025 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
1026 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
1029 DEBUG ((EFI_D_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
1030 __FUNCTION__
, mHostBridgeDevId
));
1036 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
1038 VisitAllPciInstances (SetPciIntLine
);
1041 // Set ACPI SCI_EN bit in PMCNTRL
1043 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
1049 ConnectRecursivelyIfPciMassStorage (
1050 IN EFI_HANDLE Handle
,
1051 IN EFI_PCI_IO_PROTOCOL
*Instance
,
1052 IN PCI_TYPE00
*PciHeader
1056 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1059 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
)) {
1061 Status
= gBS
->HandleProtocol (
1063 &gEfiDevicePathProtocolGuid
,
1066 if (EFI_ERROR (Status
)) {
1071 // Print Device Path
1073 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
1074 if (DevPathStr
!= NULL
) {
1077 "Found Mass Storage device: %s\n",
1080 FreePool(DevPathStr
);
1083 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
1084 if (EFI_ERROR (Status
)) {
1095 This notification function is invoked when the
1096 EMU Variable FVB has been changed.
1098 @param Event The event that occured
1099 @param Context For EFI compatiblity. Not used.
1104 EmuVariablesUpdatedCallback (
1109 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
1110 UpdateNvVarsOnFileSystem ();
1116 VisitingFileSystemInstance (
1117 IN EFI_HANDLE Handle
,
1123 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
1125 if (ConnectedToFileSystem
) {
1126 return EFI_ALREADY_STARTED
;
1129 Status
= ConnectNvVarsToFileSystem (Handle
);
1130 if (EFI_ERROR (Status
)) {
1134 ConnectedToFileSystem
= TRUE
;
1136 EfiCreateProtocolNotifyEvent (
1137 &gEfiDevicePathProtocolGuid
,
1139 EmuVariablesUpdatedCallback
,
1141 &mEmuVariableEventReg
1143 PcdSet64 (PcdEmuVariableEvent
, (UINT64
)(UINTN
) mEmuVariableEvent
);
1150 PlatformBdsRestoreNvVarsFromHardDisk (
1153 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1154 VisitAllInstancesOfProtocol (
1155 &gEfiSimpleFileSystemProtocolGuid
,
1156 VisitingFileSystemInstance
,
1163 PlatformBdsConnectSequence (
1168 Routine Description:
1170 Connect with predeined platform connect sequence,
1171 the OEM/IBV can customize with their own connect sequence.
1185 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
1190 // Here we can get the customized platform connect sequence
1191 // Notes: we can connect with new variable which record the
1192 // last time boots connect device path sequence
1194 while (gPlatformConnectSequence
[Index
] != NULL
) {
1196 // Build the platform boot option
1198 EfiBootManagerConnectDevicePath (gPlatformConnectSequence
[Index
], NULL
);
1203 // Just use the simple policy to connect all devices
1205 DEBUG ((EFI_D_INFO
, "EfiBootManagerConnectAll\n"));
1206 EfiBootManagerConnectAll ();
1208 PciAcpiInitialization ();
1211 // Clear the logo after all devices are connected.
1213 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1217 PlatformBdsDiagnostics (
1218 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel
,
1219 IN BOOLEAN QuietBoot
,
1220 IN BASEM_MEMORY_TEST BaseMemoryTest
1224 Routine Description:
1226 Perform the platform diagnostic, such like test memory. OEM/IBV also
1227 can customize this fuction to support specific platform diagnostic.
1231 MemoryTestLevel - The memory test intensive level
1233 QuietBoot - Indicate if need to enable the quiet boot
1235 BaseMemoryTest - A pointer to BaseMemoryTest()
1245 DEBUG ((EFI_D_INFO
, "PlatformBdsDiagnostics\n"));
1248 // Here we can decide if we need to show
1249 // the diagnostics screen
1250 // Notes: this quiet boot code should be remove
1251 // from the graphic lib
1254 EnableQuietBoot (PcdGetPtr(PcdLogoFile
));
1256 // Perform system diagnostic
1258 Status
= BaseMemoryTest (MemoryTestLevel
);
1259 if (EFI_ERROR (Status
)) {
1260 DisableQuietBoot ();
1266 // Perform system diagnostic
1268 Status
= BaseMemoryTest (MemoryTestLevel
);
1273 Save the S3 boot script.
1275 Note that DxeSmmReadyToLock must be signaled after this function returns;
1276 otherwise the script wouldn't be saved actually.
1285 EFI_S3_SAVE_STATE_PROTOCOL
*BootScript
;
1286 STATIC CONST UINT8 Info
[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1288 Status
= gBS
->LocateProtocol (&gEfiS3SaveStateProtocolGuid
, NULL
,
1289 (VOID
**) &BootScript
);
1290 ASSERT_EFI_ERROR (Status
);
1293 // Despite the opcode documentation in the PI spec, the protocol
1294 // implementation embeds a deep copy of the info in the boot script, rather
1295 // than storing just a pointer to runtime or NVS storage.
1297 Status
= BootScript
->Write(BootScript
, EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
1298 (UINT32
) sizeof Info
,
1299 (EFI_PHYSICAL_ADDRESS
)(UINTN
) &Info
);
1300 ASSERT_EFI_ERROR (Status
);
1306 PlatformBootManagerAfterConsole (
1311 Routine Description:
1313 The function will excute with as the platform policy, current policy
1314 is driven by boot mode. IBV/OEM can customize this code for their specific
1320 EFI_BOOT_MODE BootMode
;
1322 DEBUG ((EFI_D_INFO
, "PlatformBootManagerAfterConsole\n"));
1324 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1325 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior: not restoring NvVars "
1326 "from disk since flash variables appear to be supported.\n"));
1329 // Try to restore variables from the hard disk early so
1330 // they can be used for the other BDS connect operations.
1332 PlatformBdsRestoreNvVarsFromHardDisk ();
1336 // Get current Boot Mode
1338 Status
= BdsLibGetBootMode (&BootMode
);
1339 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1342 // Go the different platform policy with different boot mode
1343 // Notes: this part code can be change with the table policy
1345 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1348 // Memory test and Logo show
1350 PlatformBdsDiagnostics (IGNORE
, TRUE
, BaseMemoryTest
);
1353 // Perform some platform specific connect sequence
1355 PlatformBdsConnectSequence ();
1358 // Process QEMU's -kernel command line option
1360 TryRunningQemuKernel ();
1362 EfiBootManagerRefreshAllBootOption ();
1364 SetBootOrderFromQemu (NULL
);
1368 This notification function is invoked when an instance of the
1369 EFI_DEVICE_PATH_PROTOCOL is produced.
1371 @param Event The event that occured
1372 @param Context For EFI compatiblity. Not used.
1385 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1386 ATAPI_DEVICE_PATH
*Atapi
;
1389 // Examine all new handles
1393 // Get the next handle
1395 BufferSize
= sizeof (Handle
);
1396 Status
= gBS
->LocateHandle (
1399 mEfiDevPathNotifyReg
,
1405 // If not found, we're done
1407 if (EFI_NOT_FOUND
== Status
) {
1411 if (EFI_ERROR (Status
)) {
1416 // Get the DevicePath protocol on that handle
1418 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevPathNode
);
1419 ASSERT_EFI_ERROR (Status
);
1421 while (!IsDevicePathEnd (DevPathNode
)) {
1423 // Find the handler to dump this device path node
1426 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1427 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1429 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1435 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1442 // Next device path node
1444 DevPathNode
= NextDevicePathNode (DevPathNode
);
1453 InstallDevicePathCallback (
1457 DEBUG ((EFI_D_INFO
, "Registered NotifyDevPath Event\n"));
1458 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1459 &gEfiDevicePathProtocolGuid
,
1463 &mEfiDevPathNotifyReg
1468 This function is called each second during the boot manager waits the timeout.
1470 @param TimeoutRemain The remaining timeout.
1474 PlatformBootManagerWaitCallback (
1475 UINT16 TimeoutRemain