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 (
94 IN EFI_HANDLE RootBridgeHandle
,
106 // BDS Platform Functions
110 PlatformBootManagerBeforeConsole (
117 Platform Bds init. Incude the platform firmware vendor, revision
131 DEBUG ((EFI_D_INFO
, "PlatformBootManagerBeforeConsole\n"));
132 InstallDevicePathCallback ();
134 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid
,
135 ConnectRootBridge
, NULL
);
138 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
140 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
143 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
144 // the preparation of S3 system information. That logic has a hard dependency
145 // on the presence of the FACS ACPI table. Since our ACPI tables are only
146 // installed after PCI enumeration completes, we must not trigger the S3 save
147 // earlier, hence we can't signal End-of-Dxe earlier.
149 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
151 if (QemuFwCfgS3Enabled ()) {
153 // Save the boot script too. Note that this will require us to emit the
154 // DxeSmmReadyToLock event just below, which in turn locks down SMM.
160 // Prevent further changes to LockBoxes or SMRAM.
163 Status
= gBS
->InstallProtocolInterface (&Handle
,
164 &gEfiDxeSmmReadyToLockProtocolGuid
, EFI_NATIVE_INTERFACE
,
166 ASSERT_EFI_ERROR (Status
);
168 PlatformInitializeConsole (gPlatformConsole
);
169 PcdSet16 (PcdPlatformBootTimeOut
, GetFrontPageTimeoutFromQemu ());
176 IN EFI_HANDLE RootBridgeHandle
,
184 // Make the PCI bus driver connect the root bridge, non-recursively. This
185 // will produce a number of child handles with PciIo on them.
187 Status
= gBS
->ConnectController (
188 RootBridgeHandle
, // ControllerHandle
189 NULL
, // DriverImageHandle
190 NULL
, // RemainingDevicePath -- produce all
199 PrepareLpcBridgeDevicePath (
200 IN EFI_HANDLE DeviceHandle
206 Add IsaKeyboard to ConIn,
207 add IsaSerial to ConOut, ConIn, ErrOut.
212 DeviceHandle - Handle of PCIIO protocol.
216 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
217 EFI_STATUS - No LPC bridge is added.
222 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
223 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
227 Status
= gBS
->HandleProtocol (
229 &gEfiDevicePathProtocolGuid
,
232 if (EFI_ERROR (Status
)) {
235 TempDevicePath
= DevicePath
;
240 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
242 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
247 DevicePath
= TempDevicePath
;
248 gPnp16550ComPortDeviceNode
.UID
= 0;
250 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
251 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
252 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
257 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
258 if (DevPathStr
!= NULL
) {
261 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
263 gPnp16550ComPortDeviceNode
.UID
+ 1,
266 FreePool(DevPathStr
);
269 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
270 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
271 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
276 DevicePath
= TempDevicePath
;
277 gPnp16550ComPortDeviceNode
.UID
= 1;
279 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
280 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
281 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
286 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
287 if (DevPathStr
!= NULL
) {
290 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
292 gPnp16550ComPortDeviceNode
.UID
+ 1,
295 FreePool(DevPathStr
);
298 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
299 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
300 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
307 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
308 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
313 EFI_HANDLE PciDeviceHandle
;
314 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
315 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
316 UINTN GopHandleCount
;
317 EFI_HANDLE
*GopHandleBuffer
;
319 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
320 return EFI_INVALID_PARAMETER
;
324 // Initialize the GopDevicePath to be PciDevicePath
326 *GopDevicePath
= PciDevicePath
;
327 TempPciDevicePath
= PciDevicePath
;
329 Status
= gBS
->LocateDevicePath (
330 &gEfiDevicePathProtocolGuid
,
334 if (EFI_ERROR (Status
)) {
339 // Try to connect this handle, so that GOP dirver could start on this
340 // device and create child handles with GraphicsOutput Protocol installed
341 // on them, then we get device paths of these child handles and select
342 // them as possible console device.
344 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
346 Status
= gBS
->LocateHandleBuffer (
348 &gEfiGraphicsOutputProtocolGuid
,
353 if (!EFI_ERROR (Status
)) {
355 // Add all the child handles as possible Console Device
357 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
358 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
359 if (EFI_ERROR (Status
)) {
365 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
368 // In current implementation, we only enable one of the child handles
369 // as console device, i.e. sotre one of the child handle's device
370 // path to variable "ConOut"
371 // In futhure, we could select all child handles to be console device
374 *GopDevicePath
= TempDevicePath
;
377 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
378 // Add the integrity GOP device path.
380 EfiBootManagerUpdateConsoleVariable (ConOutDev
, NULL
, PciDevicePath
);
381 EfiBootManagerUpdateConsoleVariable (ConOutDev
, TempDevicePath
, NULL
);
384 gBS
->FreePool (GopHandleBuffer
);
391 PreparePciVgaDevicePath (
392 IN EFI_HANDLE DeviceHandle
398 Add PCI VGA to ConOut.
403 DeviceHandle - Handle of PCIIO protocol.
407 EFI_SUCCESS - PCI VGA is added to ConOut.
408 EFI_STATUS - No PCI VGA device is added.
413 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
414 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
417 GopDevicePath
= NULL
;
418 Status
= gBS
->HandleProtocol (
420 &gEfiDevicePathProtocolGuid
,
423 if (EFI_ERROR (Status
)) {
427 GetGopDevicePath (DevicePath
, &GopDevicePath
);
428 DevicePath
= GopDevicePath
;
430 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
436 PreparePciSerialDevicePath (
437 IN EFI_HANDLE DeviceHandle
443 Add PCI Serial to ConOut, ConIn, ErrOut.
448 DeviceHandle - Handle of PCIIO protocol.
452 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
453 EFI_STATUS - No PCI Serial device is added.
458 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
461 Status
= gBS
->HandleProtocol (
463 &gEfiDevicePathProtocolGuid
,
466 if (EFI_ERROR (Status
)) {
470 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
471 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
473 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
474 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
475 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
481 VisitAllInstancesOfProtocol (
483 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
489 EFI_HANDLE
*HandleBuffer
;
494 // Start to check all the PciIo to find all possible device
498 Status
= gBS
->LocateHandleBuffer (
505 if (EFI_ERROR (Status
)) {
509 for (Index
= 0; Index
< HandleCount
; Index
++) {
510 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
511 if (EFI_ERROR (Status
)) {
515 Status
= (*CallBackFunction
) (
522 gBS
->FreePool (HandleBuffer
);
530 VisitingAPciInstance (
531 IN EFI_HANDLE Handle
,
537 EFI_PCI_IO_PROTOCOL
*PciIo
;
540 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
543 // Check for all PCI device
545 Status
= PciIo
->Pci
.Read (
549 sizeof (Pci
) / sizeof (UINT32
),
552 if (EFI_ERROR (Status
)) {
556 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
567 VisitAllPciInstances (
568 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
571 return VisitAllInstancesOfProtocol (
572 &gEfiPciIoProtocolGuid
,
573 VisitingAPciInstance
,
574 (VOID
*)(UINTN
) CallBackFunction
580 Do platform specific PCI Device check and add them to
581 ConOut, ConIn, ErrOut.
583 @param[in] Handle - Handle of PCI device instance
584 @param[in] PciIo - PCI IO protocol instance
585 @param[in] Pci - PCI Header register block
587 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
588 @retval EFI_STATUS - PCI Device check or Console variable update fail.
593 DetectAndPreparePlatformPciDevicePath (
594 IN EFI_HANDLE Handle
,
595 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
601 Status
= PciIo
->Attributes (
603 EfiPciIoAttributeOperationEnable
,
604 EFI_PCI_DEVICE_ENABLE
,
607 ASSERT_EFI_ERROR (Status
);
609 if (!mDetectVgaOnly
) {
611 // Here we decide whether it is LPC Bridge
613 if ((IS_PCI_LPC (Pci
)) ||
614 ((IS_PCI_ISA_PDECODE (Pci
)) &&
615 (Pci
->Hdr
.VendorId
== 0x8086) &&
616 (Pci
->Hdr
.DeviceId
== 0x7000)
620 // Add IsaKeyboard to ConIn,
621 // add IsaSerial to ConOut, ConIn, ErrOut
623 DEBUG ((EFI_D_INFO
, "Found LPC Bridge device\n"));
624 PrepareLpcBridgeDevicePath (Handle
);
628 // Here we decide which Serial device to enable in PCI bus
630 if (IS_PCI_16550SERIAL (Pci
)) {
632 // Add them to ConOut, ConIn, ErrOut.
634 DEBUG ((EFI_D_INFO
, "Found PCI 16550 SERIAL device\n"));
635 PreparePciSerialDevicePath (Handle
);
641 // Here we decide which VGA device to enable in PCI bus
643 if (IS_PCI_VGA (Pci
)) {
645 // Add them to ConOut.
647 DEBUG ((EFI_D_INFO
, "Found PCI VGA device\n"));
648 PreparePciVgaDevicePath (Handle
);
657 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
659 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
661 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
662 @retval EFI_STATUS - PCI Device check or Console variable update fail.
666 DetectAndPreparePlatformPciDevicePaths (
667 BOOLEAN DetectVgaOnly
670 mDetectVgaOnly
= DetectVgaOnly
;
671 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
676 PlatformInitializeConsole (
677 IN PLATFORM_CONSOLE_CONNECT_ENTRY
*PlatformConsole
683 Connect the predefined platform default console device. Always try to find
684 and enable the vga device if have.
688 PlatformConsole - Predfined platform default console device array.
692 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
693 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
696 // Connect RootBridge
698 GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME
, (VOID
**) &VarConout
, NULL
);
699 GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME
, (VOID
**) &VarConin
, NULL
);
701 if (VarConout
== NULL
|| VarConin
== NULL
) {
703 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
705 DetectAndPreparePlatformPciDevicePaths (FALSE
);
708 // Have chance to connect the platform default console,
709 // the platform default console is the minimue device group
710 // the platform should support
712 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
714 // Update the console variable with the connect type
716 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
717 EfiBootManagerUpdateConsoleVariable (ConIn
, PlatformConsole
[Index
].DevicePath
, NULL
);
719 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
720 EfiBootManagerUpdateConsoleVariable (ConOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
722 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
723 EfiBootManagerUpdateConsoleVariable (ErrOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
728 // Only detect VGA device and add them to ConOut
730 DetectAndPreparePlatformPciDevicePaths (TRUE
);
736 Configure PCI Interrupt Line register for applicable devices
737 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
739 @param[in] Handle - Handle of PCI device instance
740 @param[in] PciIo - PCI IO protocol instance
741 @param[in] PciHdr - PCI Header register block
743 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
749 IN EFI_HANDLE Handle
,
750 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
751 IN PCI_TYPE00
*PciHdr
754 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
755 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
760 UINT32 RootBusNumber
;
762 Status
= EFI_SUCCESS
;
764 if (PciHdr
->Device
.InterruptPin
!= 0) {
766 DevPathNode
= DevicePathFromHandle (Handle
);
767 ASSERT (DevPathNode
!= NULL
);
768 DevPath
= DevPathNode
;
771 if (DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
&&
772 DevicePathSubType (DevPathNode
) == ACPI_DP
&&
773 ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID(0x0A03)) {
774 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
778 // Compute index into PciHostIrqs[] table by walking
779 // the device path and adding up all device numbers
781 Status
= EFI_NOT_FOUND
;
783 Idx
= PciHdr
->Device
.InterruptPin
- 1;
784 while (!IsDevicePathEnd (DevPathNode
)) {
785 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
786 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
788 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
791 // Unlike SeaBIOS, which starts climbing from the leaf device
792 // up toward the root, we traverse the device path starting at
793 // the root moving toward the leaf node.
794 // The slot number of the top-level parent bridge is needed for
795 // Q35 cases with more than 24 slots on the root bus.
797 if (Status
!= EFI_SUCCESS
) {
798 Status
= EFI_SUCCESS
;
799 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
803 DevPathNode
= NextDevicePathNode (DevPathNode
);
805 if (EFI_ERROR (Status
)) {
808 if (RootBusNumber
== 0 && RootSlot
== 0) {
811 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
818 // Final PciHostIrqs[] index calculation depends on the platform
819 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
821 switch (mHostBridgeDevId
) {
822 case INTEL_82441_DEVICE_ID
:
825 case INTEL_Q35_MCH_DEVICE_ID
:
827 // SeaBIOS contains the following comment:
828 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
829 // with a different starting index - see q35-acpi-dsdt.dsl.
831 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
835 // in this case, subtract back out RootSlot from Idx
836 // (SeaBIOS never adds it to begin with, but that would make our
837 // device path traversal loop above too awkward)
843 ASSERT (FALSE
); // should never get here
845 Idx
%= ARRAY_SIZE (PciHostIrqs
);
846 IrqLine
= PciHostIrqs
[Idx
];
850 CHAR16
*DevPathString
;
851 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
852 UINTN Segment
, Bus
, Device
, Function
;
854 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
855 if (DevPathString
== NULL
) {
856 DevPathString
= Fallback
;
858 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
859 ASSERT_EFI_ERROR (Status
);
861 DEBUG ((EFI_D_VERBOSE
, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__
,
862 (UINT32
)Bus
, (UINT32
)Device
, (UINT32
)Function
, DevPathString
,
865 if (DevPathString
!= Fallback
) {
866 FreePool (DevPathString
);
872 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
874 Status
= PciIo
->Pci
.Write (
888 PciAcpiInitialization (
894 // Query Host Bridge DID to determine platform type
896 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
897 switch (mHostBridgeDevId
) {
898 case INTEL_82441_DEVICE_ID
:
899 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
901 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
903 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
904 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
905 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
906 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
908 case INTEL_Q35_MCH_DEVICE_ID
:
909 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
911 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
913 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
914 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
915 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
916 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
917 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
918 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
919 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
920 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
923 DEBUG ((EFI_D_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
924 __FUNCTION__
, mHostBridgeDevId
));
930 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
932 VisitAllPciInstances (SetPciIntLine
);
935 // Set ACPI SCI_EN bit in PMCNTRL
937 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
943 ConnectRecursivelyIfPciMassStorage (
944 IN EFI_HANDLE Handle
,
945 IN EFI_PCI_IO_PROTOCOL
*Instance
,
946 IN PCI_TYPE00
*PciHeader
950 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
953 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
)) {
955 Status
= gBS
->HandleProtocol (
957 &gEfiDevicePathProtocolGuid
,
960 if (EFI_ERROR (Status
)) {
967 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
968 if (DevPathStr
!= NULL
) {
971 "Found Mass Storage device: %s\n",
974 FreePool(DevPathStr
);
977 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
978 if (EFI_ERROR (Status
)) {
989 This notification function is invoked when the
990 EMU Variable FVB has been changed.
992 @param Event The event that occured
993 @param Context For EFI compatiblity. Not used.
998 EmuVariablesUpdatedCallback (
1003 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
1004 UpdateNvVarsOnFileSystem ();
1010 VisitingFileSystemInstance (
1011 IN EFI_HANDLE Handle
,
1017 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
1019 if (ConnectedToFileSystem
) {
1020 return EFI_ALREADY_STARTED
;
1023 Status
= ConnectNvVarsToFileSystem (Handle
);
1024 if (EFI_ERROR (Status
)) {
1028 ConnectedToFileSystem
= TRUE
;
1030 EfiCreateProtocolNotifyEvent (
1031 &gEfiDevicePathProtocolGuid
,
1033 EmuVariablesUpdatedCallback
,
1035 &mEmuVariableEventReg
1037 PcdSet64 (PcdEmuVariableEvent
, (UINT64
)(UINTN
) mEmuVariableEvent
);
1044 PlatformBdsRestoreNvVarsFromHardDisk (
1047 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1048 VisitAllInstancesOfProtocol (
1049 &gEfiSimpleFileSystemProtocolGuid
,
1050 VisitingFileSystemInstance
,
1058 PlatformBdsConnectSequence (
1063 Routine Description:
1065 Connect with predeined platform connect sequence,
1066 the OEM/IBV can customize with their own connect sequence.
1080 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
1085 // Here we can get the customized platform connect sequence
1086 // Notes: we can connect with new variable which record the
1087 // last time boots connect device path sequence
1089 while (gPlatformConnectSequence
[Index
] != NULL
) {
1091 // Build the platform boot option
1093 BdsLibConnectDevicePath (gPlatformConnectSequence
[Index
]);
1098 // Just use the simple policy to connect all devices
1100 BdsLibConnectAll ();
1102 PciAcpiInitialization ();
1105 // Clear the logo after all devices are connected.
1107 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1111 PlatformBdsGetDriverOption (
1112 IN OUT LIST_ENTRY
*BdsDriverLists
1116 Routine Description:
1118 Load the predefined driver option, OEM/IBV can customize this
1119 to load their own drivers
1123 BdsDriverLists - The header of the driver option link list.
1131 DEBUG ((EFI_D_INFO
, "PlatformBdsGetDriverOption\n"));
1136 PlatformBdsDiagnostics (
1137 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel
,
1138 IN BOOLEAN QuietBoot
,
1139 IN BASEM_MEMORY_TEST BaseMemoryTest
1143 Routine Description:
1145 Perform the platform diagnostic, such like test memory. OEM/IBV also
1146 can customize this fuction to support specific platform diagnostic.
1150 MemoryTestLevel - The memory test intensive level
1152 QuietBoot - Indicate if need to enable the quiet boot
1154 BaseMemoryTest - A pointer to BaseMemoryTest()
1164 DEBUG ((EFI_D_INFO
, "PlatformBdsDiagnostics\n"));
1167 // Here we can decide if we need to show
1168 // the diagnostics screen
1169 // Notes: this quiet boot code should be remove
1170 // from the graphic lib
1173 EnableQuietBoot (PcdGetPtr(PcdLogoFile
));
1175 // Perform system diagnostic
1177 Status
= BaseMemoryTest (MemoryTestLevel
);
1178 if (EFI_ERROR (Status
)) {
1179 DisableQuietBoot ();
1185 // Perform system diagnostic
1187 Status
= BaseMemoryTest (MemoryTestLevel
);
1192 Save the S3 boot script.
1194 Note that DxeSmmReadyToLock must be signaled after this function returns;
1195 otherwise the script wouldn't be saved actually.
1204 EFI_S3_SAVE_STATE_PROTOCOL
*BootScript
;
1205 STATIC CONST UINT8 Info
[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1207 Status
= gBS
->LocateProtocol (&gEfiS3SaveStateProtocolGuid
, NULL
,
1208 (VOID
**) &BootScript
);
1209 ASSERT_EFI_ERROR (Status
);
1212 // Despite the opcode documentation in the PI spec, the protocol
1213 // implementation embeds a deep copy of the info in the boot script, rather
1214 // than storing just a pointer to runtime or NVS storage.
1216 Status
= BootScript
->Write(BootScript
, EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
1217 (UINT32
) sizeof Info
,
1218 (EFI_PHYSICAL_ADDRESS
)(UINTN
) &Info
);
1219 ASSERT_EFI_ERROR (Status
);
1225 PlatformBootManagerAfterConsole (
1230 Routine Description:
1232 The function will excute with as the platform policy, current policy
1233 is driven by boot mode. IBV/OEM can customize this code for their specific
1239 EFI_BOOT_MODE BootMode
;
1241 DEBUG ((EFI_D_INFO
, "PlatformBootManagerAfterConsole\n"));
1243 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1244 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior: not restoring NvVars "
1245 "from disk since flash variables appear to be supported.\n"));
1248 // Try to restore variables from the hard disk early so
1249 // they can be used for the other BDS connect operations.
1251 PlatformBdsRestoreNvVarsFromHardDisk ();
1255 // Load the driver option as the driver option list
1257 PlatformBdsGetDriverOption (DriverOptionList
);
1260 // Get current Boot Mode
1262 Status
= BdsLibGetBootMode (&BootMode
);
1263 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1266 // Go the different platform policy with different boot mode
1267 // Notes: this part code can be change with the table policy
1269 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1272 // Memory test and Logo show
1274 PlatformBdsDiagnostics (IGNORE
, TRUE
, BaseMemoryTest
);
1277 // Perform some platform specific connect sequence
1279 PlatformBdsConnectSequence ();
1282 // Process QEMU's -kernel command line option
1284 TryRunningQemuKernel ();
1286 DEBUG ((EFI_D_INFO
, "BdsLibConnectAll\n"));
1287 BdsLibConnectAll ();
1288 BdsLibEnumerateAllBootOption (BootOptionList
);
1290 SetBootOrderFromQemu (BootOptionList
);
1292 // The BootOrder variable may have changed, reload the in-memory list with
1295 BdsLibBuildOptionFromVar (BootOptionList
, L
"BootOrder");
1300 PlatformBdsBootSuccess (
1301 IN BDS_COMMON_OPTION
*Option
1305 Routine Description:
1307 Hook point after a boot attempt succeeds. We don't expect a boot option to
1308 return, so the EFI 1.0 specification defines that you will default to an
1309 interactive mode and stop processing the BootOrder list in this case. This
1310 is alos a platform implementation and can be customized by IBV/OEM.
1314 Option - Pointer to Boot Option that succeeded to boot.
1324 DEBUG ((EFI_D_INFO
, "PlatformBdsBootSuccess\n"));
1326 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1327 // select loop then we need to pop up a UI and wait for user input.
1329 TmpStr
= Option
->StatusString
;
1330 if (TmpStr
!= NULL
) {
1331 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1338 PlatformBdsBootFail (
1339 IN BDS_COMMON_OPTION
*Option
,
1340 IN EFI_STATUS Status
,
1341 IN CHAR16
*ExitData
,
1342 IN UINTN ExitDataSize
1346 Routine Description:
1348 Hook point after a boot attempt fails.
1352 Option - Pointer to Boot Option that failed to boot.
1354 Status - Status returned from failed boot.
1356 ExitData - Exit data returned from failed boot.
1358 ExitDataSize - Exit data size returned from failed boot.
1368 DEBUG ((EFI_D_INFO
, "PlatformBdsBootFail\n"));
1371 // If Boot returned with failed status then we need to pop up a UI and wait
1374 TmpStr
= Option
->StatusString
;
1375 if (TmpStr
!= NULL
) {
1376 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1383 PlatformBdsLockNonUpdatableFlash (
1387 DEBUG ((EFI_D_INFO
, "PlatformBdsLockNonUpdatableFlash\n"));
1393 This notification function is invoked when an instance of the
1394 EFI_DEVICE_PATH_PROTOCOL is produced.
1396 @param Event The event that occured
1397 @param Context For EFI compatiblity. Not used.
1410 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1411 ATAPI_DEVICE_PATH
*Atapi
;
1414 // Examine all new handles
1418 // Get the next handle
1420 BufferSize
= sizeof (Handle
);
1421 Status
= gBS
->LocateHandle (
1424 mEfiDevPathNotifyReg
,
1430 // If not found, we're done
1432 if (EFI_NOT_FOUND
== Status
) {
1436 if (EFI_ERROR (Status
)) {
1441 // Get the DevicePath protocol on that handle
1443 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevPathNode
);
1444 ASSERT_EFI_ERROR (Status
);
1446 while (!IsDevicePathEnd (DevPathNode
)) {
1448 // Find the handler to dump this device path node
1451 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1452 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1454 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1460 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1467 // Next device path node
1469 DevPathNode
= NextDevicePathNode (DevPathNode
);
1478 InstallDevicePathCallback (
1482 DEBUG ((EFI_D_INFO
, "Registered NotifyDevPath Event\n"));
1483 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1484 &gEfiDevicePathProtocolGuid
,
1488 &mEfiDevPathNotifyReg
1493 This function is called each second during the boot manager waits the timeout.
1495 @param TimeoutRemain The remaining timeout.
1499 PlatformBootManagerWaitCallback (
1500 UINT16 TimeoutRemain