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>
17 #include <Library/QemuBootOrderLib.h>
24 VOID
*mEfiDevPathNotifyReg
;
25 EFI_EVENT mEfiDevPathEvent
;
26 VOID
*mEmuVariableEventReg
;
27 EFI_EVENT mEmuVariableEvent
;
28 BOOLEAN mDetectVgaOnly
;
29 UINT16 mHostBridgeDevId
;
32 // Table of host IRQs matching PCI IRQs A-D
33 // (for configuring PCI Interrupt Line register)
35 CONST UINT8 PciHostIrqs
[] = {
36 0x0a, 0x0a, 0x0b, 0x0b
42 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
50 (EFIAPI
*PROTOCOL_INSTANCE_CALLBACK
)(
57 @param[in] Handle - Handle of PCI device instance
58 @param[in] PciIo - PCI IO protocol instance
59 @param[in] Pci - PCI Header register block
63 (EFIAPI
*VISIT_PCI_INSTANCE_CALLBACK
)(
65 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
71 // Function prototypes
75 VisitAllInstancesOfProtocol (
77 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
82 VisitAllPciInstancesOfProtocol (
83 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
87 InstallDevicePathCallback (
92 PlatformRegisterFvBootOption (
100 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
101 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
102 UINTN BootOptionCount
;
103 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
104 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
105 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
107 Status
= gBS
->HandleProtocol (
109 &gEfiLoadedImageProtocolGuid
,
110 (VOID
**) &LoadedImage
112 ASSERT_EFI_ERROR (Status
);
114 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
115 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
116 ASSERT (DevicePath
!= NULL
);
117 DevicePath
= AppendDevicePathNode (
119 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
121 ASSERT (DevicePath
!= NULL
);
123 Status
= EfiBootManagerInitializeLoadOption (
125 LoadOptionNumberUnassigned
,
133 ASSERT_EFI_ERROR (Status
);
134 FreePool (DevicePath
);
136 BootOptions
= EfiBootManagerGetLoadOptions (
137 &BootOptionCount
, LoadOptionTypeBoot
140 OptionIndex
= EfiBootManagerFindLoadOption (
141 &NewOption
, BootOptions
, BootOptionCount
144 if (OptionIndex
== -1) {
145 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
146 ASSERT_EFI_ERROR (Status
);
148 EfiBootManagerFreeLoadOption (&NewOption
);
149 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
153 PlatformRegisterOptionsAndKeys (
161 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
164 // Register ENTER as CONTINUE key
166 Enter
.ScanCode
= SCAN_NULL
;
167 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
168 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
169 ASSERT_EFI_ERROR (Status
);
172 // Map F2 to Boot Manager Menu
174 F2
.ScanCode
= SCAN_F2
;
175 F2
.UnicodeChar
= CHAR_NULL
;
176 Esc
.ScanCode
= SCAN_ESC
;
177 Esc
.UnicodeChar
= CHAR_NULL
;
178 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
179 ASSERT_EFI_ERROR (Status
);
180 Status
= EfiBootManagerAddKeyOptionVariable (
181 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
183 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
184 Status
= EfiBootManagerAddKeyOptionVariable (
185 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
187 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
189 // Register UEFI Shell
191 PlatformRegisterFvBootOption (
192 PcdGetPtr (PcdShellFile
), L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
199 IN EFI_HANDLE RootBridgeHandle
,
211 // BDS Platform Functions
215 PlatformBootManagerBeforeConsole (
222 Platform Bds init. Incude the platform firmware vendor, revision
236 DEBUG ((EFI_D_INFO
, "PlatformBootManagerBeforeConsole\n"));
237 InstallDevicePathCallback ();
239 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid
,
240 ConnectRootBridge
, NULL
);
243 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
245 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
248 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
249 // the preparation of S3 system information. That logic has a hard dependency
250 // on the presence of the FACS ACPI table. Since our ACPI tables are only
251 // installed after PCI enumeration completes, we must not trigger the S3 save
252 // earlier, hence we can't signal End-of-Dxe earlier.
254 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
256 if (QemuFwCfgS3Enabled ()) {
258 // Save the boot script too. Note that this will require us to emit the
259 // DxeSmmReadyToLock event just below, which in turn locks down SMM.
265 // Prevent further changes to LockBoxes or SMRAM.
268 Status
= gBS
->InstallProtocolInterface (&Handle
,
269 &gEfiDxeSmmReadyToLockProtocolGuid
, EFI_NATIVE_INTERFACE
,
271 ASSERT_EFI_ERROR (Status
);
273 PlatformInitializeConsole (gPlatformConsole
);
274 PcdSet16 (PcdPlatformBootTimeOut
, GetFrontPageTimeoutFromQemu ());
276 PlatformRegisterOptionsAndKeys ();
283 IN EFI_HANDLE RootBridgeHandle
,
291 // Make the PCI bus driver connect the root bridge, non-recursively. This
292 // will produce a number of child handles with PciIo on them.
294 Status
= gBS
->ConnectController (
295 RootBridgeHandle
, // ControllerHandle
296 NULL
, // DriverImageHandle
297 NULL
, // RemainingDevicePath -- produce all
306 PrepareLpcBridgeDevicePath (
307 IN EFI_HANDLE DeviceHandle
313 Add IsaKeyboard to ConIn,
314 add IsaSerial to ConOut, ConIn, ErrOut.
319 DeviceHandle - Handle of PCIIO protocol.
323 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
324 EFI_STATUS - No LPC bridge is added.
329 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
330 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
334 Status
= gBS
->HandleProtocol (
336 &gEfiDevicePathProtocolGuid
,
339 if (EFI_ERROR (Status
)) {
342 TempDevicePath
= DevicePath
;
347 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
349 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
354 DevicePath
= TempDevicePath
;
355 gPnp16550ComPortDeviceNode
.UID
= 0;
357 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
358 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
359 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
364 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
365 if (DevPathStr
!= NULL
) {
368 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
370 gPnp16550ComPortDeviceNode
.UID
+ 1,
373 FreePool(DevPathStr
);
376 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
377 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
378 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
383 DevicePath
= TempDevicePath
;
384 gPnp16550ComPortDeviceNode
.UID
= 1;
386 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
387 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
388 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
393 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
394 if (DevPathStr
!= NULL
) {
397 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
399 gPnp16550ComPortDeviceNode
.UID
+ 1,
402 FreePool(DevPathStr
);
405 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
406 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
407 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
414 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
415 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
420 EFI_HANDLE PciDeviceHandle
;
421 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
422 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
423 UINTN GopHandleCount
;
424 EFI_HANDLE
*GopHandleBuffer
;
426 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
427 return EFI_INVALID_PARAMETER
;
431 // Initialize the GopDevicePath to be PciDevicePath
433 *GopDevicePath
= PciDevicePath
;
434 TempPciDevicePath
= PciDevicePath
;
436 Status
= gBS
->LocateDevicePath (
437 &gEfiDevicePathProtocolGuid
,
441 if (EFI_ERROR (Status
)) {
446 // Try to connect this handle, so that GOP dirver could start on this
447 // device and create child handles with GraphicsOutput Protocol installed
448 // on them, then we get device paths of these child handles and select
449 // them as possible console device.
451 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
453 Status
= gBS
->LocateHandleBuffer (
455 &gEfiGraphicsOutputProtocolGuid
,
460 if (!EFI_ERROR (Status
)) {
462 // Add all the child handles as possible Console Device
464 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
465 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
466 if (EFI_ERROR (Status
)) {
472 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
475 // In current implementation, we only enable one of the child handles
476 // as console device, i.e. sotre one of the child handle's device
477 // path to variable "ConOut"
478 // In futhure, we could select all child handles to be console device
481 *GopDevicePath
= TempDevicePath
;
484 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
485 // Add the integrity GOP device path.
487 EfiBootManagerUpdateConsoleVariable (ConOutDev
, NULL
, PciDevicePath
);
488 EfiBootManagerUpdateConsoleVariable (ConOutDev
, TempDevicePath
, NULL
);
491 gBS
->FreePool (GopHandleBuffer
);
498 PreparePciVgaDevicePath (
499 IN EFI_HANDLE DeviceHandle
505 Add PCI VGA to ConOut.
510 DeviceHandle - Handle of PCIIO protocol.
514 EFI_SUCCESS - PCI VGA is added to ConOut.
515 EFI_STATUS - No PCI VGA device is added.
520 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
521 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
524 GopDevicePath
= NULL
;
525 Status
= gBS
->HandleProtocol (
527 &gEfiDevicePathProtocolGuid
,
530 if (EFI_ERROR (Status
)) {
534 GetGopDevicePath (DevicePath
, &GopDevicePath
);
535 DevicePath
= GopDevicePath
;
537 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
543 PreparePciSerialDevicePath (
544 IN EFI_HANDLE DeviceHandle
550 Add PCI Serial to ConOut, ConIn, ErrOut.
555 DeviceHandle - Handle of PCIIO protocol.
559 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
560 EFI_STATUS - No PCI Serial device is added.
565 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
568 Status
= gBS
->HandleProtocol (
570 &gEfiDevicePathProtocolGuid
,
573 if (EFI_ERROR (Status
)) {
577 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
578 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
580 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
581 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
582 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
588 VisitAllInstancesOfProtocol (
590 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
596 EFI_HANDLE
*HandleBuffer
;
601 // Start to check all the PciIo to find all possible device
605 Status
= gBS
->LocateHandleBuffer (
612 if (EFI_ERROR (Status
)) {
616 for (Index
= 0; Index
< HandleCount
; Index
++) {
617 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
618 if (EFI_ERROR (Status
)) {
622 Status
= (*CallBackFunction
) (
629 gBS
->FreePool (HandleBuffer
);
637 VisitingAPciInstance (
638 IN EFI_HANDLE Handle
,
644 EFI_PCI_IO_PROTOCOL
*PciIo
;
647 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
650 // Check for all PCI device
652 Status
= PciIo
->Pci
.Read (
656 sizeof (Pci
) / sizeof (UINT32
),
659 if (EFI_ERROR (Status
)) {
663 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
674 VisitAllPciInstances (
675 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
678 return VisitAllInstancesOfProtocol (
679 &gEfiPciIoProtocolGuid
,
680 VisitingAPciInstance
,
681 (VOID
*)(UINTN
) CallBackFunction
687 Do platform specific PCI Device check and add them to
688 ConOut, ConIn, ErrOut.
690 @param[in] Handle - Handle of PCI device instance
691 @param[in] PciIo - PCI IO protocol instance
692 @param[in] Pci - PCI Header register block
694 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
695 @retval EFI_STATUS - PCI Device check or Console variable update fail.
700 DetectAndPreparePlatformPciDevicePath (
701 IN EFI_HANDLE Handle
,
702 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
708 Status
= PciIo
->Attributes (
710 EfiPciIoAttributeOperationEnable
,
711 EFI_PCI_DEVICE_ENABLE
,
714 ASSERT_EFI_ERROR (Status
);
716 if (!mDetectVgaOnly
) {
718 // Here we decide whether it is LPC Bridge
720 if ((IS_PCI_LPC (Pci
)) ||
721 ((IS_PCI_ISA_PDECODE (Pci
)) &&
722 (Pci
->Hdr
.VendorId
== 0x8086) &&
723 (Pci
->Hdr
.DeviceId
== 0x7000)
727 // Add IsaKeyboard to ConIn,
728 // add IsaSerial to ConOut, ConIn, ErrOut
730 DEBUG ((EFI_D_INFO
, "Found LPC Bridge device\n"));
731 PrepareLpcBridgeDevicePath (Handle
);
735 // Here we decide which Serial device to enable in PCI bus
737 if (IS_PCI_16550SERIAL (Pci
)) {
739 // Add them to ConOut, ConIn, ErrOut.
741 DEBUG ((EFI_D_INFO
, "Found PCI 16550 SERIAL device\n"));
742 PreparePciSerialDevicePath (Handle
);
748 // Here we decide which VGA device to enable in PCI bus
750 if (IS_PCI_VGA (Pci
)) {
752 // Add them to ConOut.
754 DEBUG ((EFI_D_INFO
, "Found PCI VGA device\n"));
755 PreparePciVgaDevicePath (Handle
);
764 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
766 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
768 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
769 @retval EFI_STATUS - PCI Device check or Console variable update fail.
773 DetectAndPreparePlatformPciDevicePaths (
774 BOOLEAN DetectVgaOnly
777 mDetectVgaOnly
= DetectVgaOnly
;
778 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
783 PlatformInitializeConsole (
784 IN PLATFORM_CONSOLE_CONNECT_ENTRY
*PlatformConsole
790 Connect the predefined platform default console device. Always try to find
791 and enable the vga device if have.
795 PlatformConsole - Predfined platform default console device array.
799 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
800 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
803 // Connect RootBridge
805 GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME
, (VOID
**) &VarConout
, NULL
);
806 GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME
, (VOID
**) &VarConin
, NULL
);
808 if (VarConout
== NULL
|| VarConin
== NULL
) {
810 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
812 DetectAndPreparePlatformPciDevicePaths (FALSE
);
815 // Have chance to connect the platform default console,
816 // the platform default console is the minimue device group
817 // the platform should support
819 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
821 // Update the console variable with the connect type
823 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
824 EfiBootManagerUpdateConsoleVariable (ConIn
, PlatformConsole
[Index
].DevicePath
, NULL
);
826 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
827 EfiBootManagerUpdateConsoleVariable (ConOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
829 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
830 EfiBootManagerUpdateConsoleVariable (ErrOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
835 // Only detect VGA device and add them to ConOut
837 DetectAndPreparePlatformPciDevicePaths (TRUE
);
843 Configure PCI Interrupt Line register for applicable devices
844 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
846 @param[in] Handle - Handle of PCI device instance
847 @param[in] PciIo - PCI IO protocol instance
848 @param[in] PciHdr - PCI Header register block
850 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
856 IN EFI_HANDLE Handle
,
857 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
858 IN PCI_TYPE00
*PciHdr
861 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
862 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
867 UINT32 RootBusNumber
;
869 Status
= EFI_SUCCESS
;
871 if (PciHdr
->Device
.InterruptPin
!= 0) {
873 DevPathNode
= DevicePathFromHandle (Handle
);
874 ASSERT (DevPathNode
!= NULL
);
875 DevPath
= DevPathNode
;
878 if (DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
&&
879 DevicePathSubType (DevPathNode
) == ACPI_DP
&&
880 ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID(0x0A03)) {
881 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
885 // Compute index into PciHostIrqs[] table by walking
886 // the device path and adding up all device numbers
888 Status
= EFI_NOT_FOUND
;
890 Idx
= PciHdr
->Device
.InterruptPin
- 1;
891 while (!IsDevicePathEnd (DevPathNode
)) {
892 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
893 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
895 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
898 // Unlike SeaBIOS, which starts climbing from the leaf device
899 // up toward the root, we traverse the device path starting at
900 // the root moving toward the leaf node.
901 // The slot number of the top-level parent bridge is needed for
902 // Q35 cases with more than 24 slots on the root bus.
904 if (Status
!= EFI_SUCCESS
) {
905 Status
= EFI_SUCCESS
;
906 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
910 DevPathNode
= NextDevicePathNode (DevPathNode
);
912 if (EFI_ERROR (Status
)) {
915 if (RootBusNumber
== 0 && RootSlot
== 0) {
918 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
925 // Final PciHostIrqs[] index calculation depends on the platform
926 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
928 switch (mHostBridgeDevId
) {
929 case INTEL_82441_DEVICE_ID
:
932 case INTEL_Q35_MCH_DEVICE_ID
:
934 // SeaBIOS contains the following comment:
935 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
936 // with a different starting index - see q35-acpi-dsdt.dsl.
938 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
942 // in this case, subtract back out RootSlot from Idx
943 // (SeaBIOS never adds it to begin with, but that would make our
944 // device path traversal loop above too awkward)
950 ASSERT (FALSE
); // should never get here
952 Idx
%= ARRAY_SIZE (PciHostIrqs
);
953 IrqLine
= PciHostIrqs
[Idx
];
957 CHAR16
*DevPathString
;
958 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
959 UINTN Segment
, Bus
, Device
, Function
;
961 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
962 if (DevPathString
== NULL
) {
963 DevPathString
= Fallback
;
965 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
966 ASSERT_EFI_ERROR (Status
);
968 DEBUG ((EFI_D_VERBOSE
, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__
,
969 (UINT32
)Bus
, (UINT32
)Device
, (UINT32
)Function
, DevPathString
,
972 if (DevPathString
!= Fallback
) {
973 FreePool (DevPathString
);
979 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
981 Status
= PciIo
->Pci
.Write (
995 PciAcpiInitialization (
1001 // Query Host Bridge DID to determine platform type
1003 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
1004 switch (mHostBridgeDevId
) {
1005 case INTEL_82441_DEVICE_ID
:
1006 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
1008 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
1010 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
1011 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
1012 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
1013 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
1015 case INTEL_Q35_MCH_DEVICE_ID
:
1016 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
1018 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
1020 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
1021 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
1022 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
1023 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
1024 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
1025 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
1026 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
1027 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
1030 DEBUG ((EFI_D_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
1031 __FUNCTION__
, mHostBridgeDevId
));
1037 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
1039 VisitAllPciInstances (SetPciIntLine
);
1042 // Set ACPI SCI_EN bit in PMCNTRL
1044 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
1050 ConnectRecursivelyIfPciMassStorage (
1051 IN EFI_HANDLE Handle
,
1052 IN EFI_PCI_IO_PROTOCOL
*Instance
,
1053 IN PCI_TYPE00
*PciHeader
1057 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1060 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
)) {
1062 Status
= gBS
->HandleProtocol (
1064 &gEfiDevicePathProtocolGuid
,
1067 if (EFI_ERROR (Status
)) {
1072 // Print Device Path
1074 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
1075 if (DevPathStr
!= NULL
) {
1078 "Found Mass Storage device: %s\n",
1081 FreePool(DevPathStr
);
1084 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
1085 if (EFI_ERROR (Status
)) {
1096 This notification function is invoked when the
1097 EMU Variable FVB has been changed.
1099 @param Event The event that occured
1100 @param Context For EFI compatiblity. Not used.
1105 EmuVariablesUpdatedCallback (
1110 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
1111 UpdateNvVarsOnFileSystem ();
1117 VisitingFileSystemInstance (
1118 IN EFI_HANDLE Handle
,
1124 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
1126 if (ConnectedToFileSystem
) {
1127 return EFI_ALREADY_STARTED
;
1130 Status
= ConnectNvVarsToFileSystem (Handle
);
1131 if (EFI_ERROR (Status
)) {
1135 ConnectedToFileSystem
= TRUE
;
1137 EfiCreateProtocolNotifyEvent (
1138 &gEfiDevicePathProtocolGuid
,
1140 EmuVariablesUpdatedCallback
,
1142 &mEmuVariableEventReg
1144 PcdSet64 (PcdEmuVariableEvent
, (UINT64
)(UINTN
) mEmuVariableEvent
);
1151 PlatformBdsRestoreNvVarsFromHardDisk (
1154 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1155 VisitAllInstancesOfProtocol (
1156 &gEfiSimpleFileSystemProtocolGuid
,
1157 VisitingFileSystemInstance
,
1165 PlatformBdsConnectSequence (
1170 Routine Description:
1172 Connect with predeined platform connect sequence,
1173 the OEM/IBV can customize with their own connect sequence.
1187 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
1192 // Here we can get the customized platform connect sequence
1193 // Notes: we can connect with new variable which record the
1194 // last time boots connect device path sequence
1196 while (gPlatformConnectSequence
[Index
] != NULL
) {
1198 // Build the platform boot option
1200 BdsLibConnectDevicePath (gPlatformConnectSequence
[Index
]);
1205 // Just use the simple policy to connect all devices
1207 BdsLibConnectAll ();
1209 PciAcpiInitialization ();
1212 // Clear the logo after all devices are connected.
1214 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1218 PlatformBdsGetDriverOption (
1219 IN OUT LIST_ENTRY
*BdsDriverLists
1223 Routine Description:
1225 Load the predefined driver option, OEM/IBV can customize this
1226 to load their own drivers
1230 BdsDriverLists - The header of the driver option link list.
1238 DEBUG ((EFI_D_INFO
, "PlatformBdsGetDriverOption\n"));
1243 PlatformBdsDiagnostics (
1244 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel
,
1245 IN BOOLEAN QuietBoot
,
1246 IN BASEM_MEMORY_TEST BaseMemoryTest
1250 Routine Description:
1252 Perform the platform diagnostic, such like test memory. OEM/IBV also
1253 can customize this fuction to support specific platform diagnostic.
1257 MemoryTestLevel - The memory test intensive level
1259 QuietBoot - Indicate if need to enable the quiet boot
1261 BaseMemoryTest - A pointer to BaseMemoryTest()
1271 DEBUG ((EFI_D_INFO
, "PlatformBdsDiagnostics\n"));
1274 // Here we can decide if we need to show
1275 // the diagnostics screen
1276 // Notes: this quiet boot code should be remove
1277 // from the graphic lib
1280 EnableQuietBoot (PcdGetPtr(PcdLogoFile
));
1282 // Perform system diagnostic
1284 Status
= BaseMemoryTest (MemoryTestLevel
);
1285 if (EFI_ERROR (Status
)) {
1286 DisableQuietBoot ();
1292 // Perform system diagnostic
1294 Status
= BaseMemoryTest (MemoryTestLevel
);
1299 Save the S3 boot script.
1301 Note that DxeSmmReadyToLock must be signaled after this function returns;
1302 otherwise the script wouldn't be saved actually.
1311 EFI_S3_SAVE_STATE_PROTOCOL
*BootScript
;
1312 STATIC CONST UINT8 Info
[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1314 Status
= gBS
->LocateProtocol (&gEfiS3SaveStateProtocolGuid
, NULL
,
1315 (VOID
**) &BootScript
);
1316 ASSERT_EFI_ERROR (Status
);
1319 // Despite the opcode documentation in the PI spec, the protocol
1320 // implementation embeds a deep copy of the info in the boot script, rather
1321 // than storing just a pointer to runtime or NVS storage.
1323 Status
= BootScript
->Write(BootScript
, EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
1324 (UINT32
) sizeof Info
,
1325 (EFI_PHYSICAL_ADDRESS
)(UINTN
) &Info
);
1326 ASSERT_EFI_ERROR (Status
);
1332 PlatformBootManagerAfterConsole (
1337 Routine Description:
1339 The function will excute with as the platform policy, current policy
1340 is driven by boot mode. IBV/OEM can customize this code for their specific
1346 EFI_BOOT_MODE BootMode
;
1348 DEBUG ((EFI_D_INFO
, "PlatformBootManagerAfterConsole\n"));
1350 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1351 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior: not restoring NvVars "
1352 "from disk since flash variables appear to be supported.\n"));
1355 // Try to restore variables from the hard disk early so
1356 // they can be used for the other BDS connect operations.
1358 PlatformBdsRestoreNvVarsFromHardDisk ();
1362 // Load the driver option as the driver option list
1364 PlatformBdsGetDriverOption (DriverOptionList
);
1367 // Get current Boot Mode
1369 Status
= BdsLibGetBootMode (&BootMode
);
1370 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1373 // Go the different platform policy with different boot mode
1374 // Notes: this part code can be change with the table policy
1376 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1379 // Memory test and Logo show
1381 PlatformBdsDiagnostics (IGNORE
, TRUE
, BaseMemoryTest
);
1384 // Perform some platform specific connect sequence
1386 PlatformBdsConnectSequence ();
1389 // Process QEMU's -kernel command line option
1391 TryRunningQemuKernel ();
1393 DEBUG ((EFI_D_INFO
, "BdsLibConnectAll\n"));
1394 BdsLibConnectAll ();
1395 BdsLibEnumerateAllBootOption (BootOptionList
);
1397 SetBootOrderFromQemu (BootOptionList
);
1399 // The BootOrder variable may have changed, reload the in-memory list with
1402 BdsLibBuildOptionFromVar (BootOptionList
, L
"BootOrder");
1406 This notification function is invoked when an instance of the
1407 EFI_DEVICE_PATH_PROTOCOL is produced.
1409 @param Event The event that occured
1410 @param Context For EFI compatiblity. Not used.
1423 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1424 ATAPI_DEVICE_PATH
*Atapi
;
1427 // Examine all new handles
1431 // Get the next handle
1433 BufferSize
= sizeof (Handle
);
1434 Status
= gBS
->LocateHandle (
1437 mEfiDevPathNotifyReg
,
1443 // If not found, we're done
1445 if (EFI_NOT_FOUND
== Status
) {
1449 if (EFI_ERROR (Status
)) {
1454 // Get the DevicePath protocol on that handle
1456 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevPathNode
);
1457 ASSERT_EFI_ERROR (Status
);
1459 while (!IsDevicePathEnd (DevPathNode
)) {
1461 // Find the handler to dump this device path node
1464 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1465 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1467 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1473 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1480 // Next device path node
1482 DevPathNode
= NextDevicePathNode (DevPathNode
);
1491 InstallDevicePathCallback (
1495 DEBUG ((EFI_D_INFO
, "Registered NotifyDevPath Event\n"));
1496 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1497 &gEfiDevicePathProtocolGuid
,
1501 &mEfiDevPathNotifyReg
1506 This function is called each second during the boot manager waits the timeout.
1508 @param TimeoutRemain The remaining timeout.
1512 PlatformBootManagerWaitCallback (
1513 UINT16 TimeoutRemain