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
);
173 IN EFI_HANDLE RootBridgeHandle
,
181 // Make the PCI bus driver connect the root bridge, non-recursively. This
182 // will produce a number of child handles with PciIo on them.
184 Status
= gBS
->ConnectController (
185 RootBridgeHandle
, // ControllerHandle
186 NULL
, // DriverImageHandle
187 NULL
, // RemainingDevicePath -- produce all
196 PrepareLpcBridgeDevicePath (
197 IN EFI_HANDLE DeviceHandle
203 Add IsaKeyboard to ConIn,
204 add IsaSerial to ConOut, ConIn, ErrOut.
209 DeviceHandle - Handle of PCIIO protocol.
213 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
214 EFI_STATUS - No LPC bridge is added.
219 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
220 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
224 Status
= gBS
->HandleProtocol (
226 &gEfiDevicePathProtocolGuid
,
229 if (EFI_ERROR (Status
)) {
232 TempDevicePath
= DevicePath
;
237 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
239 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
244 DevicePath
= TempDevicePath
;
245 gPnp16550ComPortDeviceNode
.UID
= 0;
247 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
248 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
249 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
254 DevPathStr
= DevicePathToStr(DevicePath
);
255 if (DevPathStr
!= NULL
) {
258 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
260 gPnp16550ComPortDeviceNode
.UID
+ 1,
263 FreePool(DevPathStr
);
266 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
267 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
268 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
273 DevicePath
= TempDevicePath
;
274 gPnp16550ComPortDeviceNode
.UID
= 1;
276 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
277 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
278 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
283 DevPathStr
= DevicePathToStr(DevicePath
);
284 if (DevPathStr
!= NULL
) {
287 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
289 gPnp16550ComPortDeviceNode
.UID
+ 1,
292 FreePool(DevPathStr
);
295 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
296 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
297 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
304 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
305 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
310 EFI_HANDLE PciDeviceHandle
;
311 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
312 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
313 UINTN GopHandleCount
;
314 EFI_HANDLE
*GopHandleBuffer
;
316 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
317 return EFI_INVALID_PARAMETER
;
321 // Initialize the GopDevicePath to be PciDevicePath
323 *GopDevicePath
= PciDevicePath
;
324 TempPciDevicePath
= PciDevicePath
;
326 Status
= gBS
->LocateDevicePath (
327 &gEfiDevicePathProtocolGuid
,
331 if (EFI_ERROR (Status
)) {
336 // Try to connect this handle, so that GOP dirver could start on this
337 // device and create child handles with GraphicsOutput Protocol installed
338 // on them, then we get device paths of these child handles and select
339 // them as possible console device.
341 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
343 Status
= gBS
->LocateHandleBuffer (
345 &gEfiGraphicsOutputProtocolGuid
,
350 if (!EFI_ERROR (Status
)) {
352 // Add all the child handles as possible Console Device
354 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
355 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
356 if (EFI_ERROR (Status
)) {
362 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
365 // In current implementation, we only enable one of the child handles
366 // as console device, i.e. sotre one of the child handle's device
367 // path to variable "ConOut"
368 // In futhure, we could select all child handles to be console device
371 *GopDevicePath
= TempDevicePath
;
374 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
375 // Add the integrity GOP device path.
377 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, NULL
, PciDevicePath
);
378 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, TempDevicePath
, NULL
);
381 gBS
->FreePool (GopHandleBuffer
);
388 PreparePciVgaDevicePath (
389 IN EFI_HANDLE DeviceHandle
395 Add PCI VGA to ConOut.
400 DeviceHandle - Handle of PCIIO protocol.
404 EFI_SUCCESS - PCI VGA is added to ConOut.
405 EFI_STATUS - No PCI VGA device is added.
410 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
411 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
414 GopDevicePath
= NULL
;
415 Status
= gBS
->HandleProtocol (
417 &gEfiDevicePathProtocolGuid
,
420 if (EFI_ERROR (Status
)) {
424 GetGopDevicePath (DevicePath
, &GopDevicePath
);
425 DevicePath
= GopDevicePath
;
427 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
433 PreparePciSerialDevicePath (
434 IN EFI_HANDLE DeviceHandle
440 Add PCI Serial to ConOut, ConIn, ErrOut.
445 DeviceHandle - Handle of PCIIO protocol.
449 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
450 EFI_STATUS - No PCI Serial device is added.
455 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
458 Status
= gBS
->HandleProtocol (
460 &gEfiDevicePathProtocolGuid
,
463 if (EFI_ERROR (Status
)) {
467 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
468 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
470 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
471 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
472 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
478 VisitAllInstancesOfProtocol (
480 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
486 EFI_HANDLE
*HandleBuffer
;
491 // Start to check all the PciIo to find all possible device
495 Status
= gBS
->LocateHandleBuffer (
502 if (EFI_ERROR (Status
)) {
506 for (Index
= 0; Index
< HandleCount
; Index
++) {
507 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
508 if (EFI_ERROR (Status
)) {
512 Status
= (*CallBackFunction
) (
519 gBS
->FreePool (HandleBuffer
);
527 VisitingAPciInstance (
528 IN EFI_HANDLE Handle
,
534 EFI_PCI_IO_PROTOCOL
*PciIo
;
537 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
540 // Check for all PCI device
542 Status
= PciIo
->Pci
.Read (
546 sizeof (Pci
) / sizeof (UINT32
),
549 if (EFI_ERROR (Status
)) {
553 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
564 VisitAllPciInstances (
565 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
568 return VisitAllInstancesOfProtocol (
569 &gEfiPciIoProtocolGuid
,
570 VisitingAPciInstance
,
571 (VOID
*)(UINTN
) CallBackFunction
577 Do platform specific PCI Device check and add them to
578 ConOut, ConIn, ErrOut.
580 @param[in] Handle - Handle of PCI device instance
581 @param[in] PciIo - PCI IO protocol instance
582 @param[in] Pci - PCI Header register block
584 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
585 @retval EFI_STATUS - PCI Device check or Console variable update fail.
590 DetectAndPreparePlatformPciDevicePath (
591 IN EFI_HANDLE Handle
,
592 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
598 Status
= PciIo
->Attributes (
600 EfiPciIoAttributeOperationEnable
,
601 EFI_PCI_DEVICE_ENABLE
,
604 ASSERT_EFI_ERROR (Status
);
606 if (!mDetectVgaOnly
) {
608 // Here we decide whether it is LPC Bridge
610 if ((IS_PCI_LPC (Pci
)) ||
611 ((IS_PCI_ISA_PDECODE (Pci
)) &&
612 (Pci
->Hdr
.VendorId
== 0x8086) &&
613 (Pci
->Hdr
.DeviceId
== 0x7000)
617 // Add IsaKeyboard to ConIn,
618 // add IsaSerial to ConOut, ConIn, ErrOut
620 DEBUG ((EFI_D_INFO
, "Found LPC Bridge device\n"));
621 PrepareLpcBridgeDevicePath (Handle
);
625 // Here we decide which Serial device to enable in PCI bus
627 if (IS_PCI_16550SERIAL (Pci
)) {
629 // Add them to ConOut, ConIn, ErrOut.
631 DEBUG ((EFI_D_INFO
, "Found PCI 16550 SERIAL device\n"));
632 PreparePciSerialDevicePath (Handle
);
638 // Here we decide which VGA device to enable in PCI bus
640 if (IS_PCI_VGA (Pci
)) {
642 // Add them to ConOut.
644 DEBUG ((EFI_D_INFO
, "Found PCI VGA device\n"));
645 PreparePciVgaDevicePath (Handle
);
654 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
656 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
658 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
659 @retval EFI_STATUS - PCI Device check or Console variable update fail.
663 DetectAndPreparePlatformPciDevicePaths (
664 BOOLEAN DetectVgaOnly
667 mDetectVgaOnly
= DetectVgaOnly
;
668 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
673 PlatformBdsConnectConsole (
674 IN BDS_CONSOLE_CONNECT_ENTRY
*PlatformConsole
680 Connect the predefined platform default console device. Always try to find
681 and enable the vga device if have.
685 PlatformConsole - Predfined platform default console device array.
689 EFI_SUCCESS - Success connect at least one ConIn and ConOut
690 device, there must have one ConOut device is
693 EFI_STATUS - Return the status of
694 BdsLibConnectAllDefaultConsoles ()
700 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
701 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
702 UINTN DevicePathSize
;
705 // Connect RootBridge
707 VarConout
= BdsLibGetVariableAndSize (
709 &gEfiGlobalVariableGuid
,
712 VarConin
= BdsLibGetVariableAndSize (
714 &gEfiGlobalVariableGuid
,
718 if (VarConout
== NULL
|| VarConin
== NULL
) {
720 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
722 DetectAndPreparePlatformPciDevicePaths (FALSE
);
725 // Have chance to connect the platform default console,
726 // the platform default console is the minimue device group
727 // the platform should support
729 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
731 // Update the console variable with the connect type
733 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
734 BdsLibUpdateConsoleVariable (VarConsoleInp
, PlatformConsole
[Index
].DevicePath
, NULL
);
736 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
737 BdsLibUpdateConsoleVariable (VarConsoleOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
739 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
740 BdsLibUpdateConsoleVariable (VarErrorOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
745 // Only detect VGA device and add them to ConOut
747 DetectAndPreparePlatformPciDevicePaths (TRUE
);
751 // Connect the all the default console with current cosole variable
753 Status
= BdsLibConnectAllDefaultConsoles ();
754 if (EFI_ERROR (Status
)) {
763 Configure PCI Interrupt Line register for applicable devices
764 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
766 @param[in] Handle - Handle of PCI device instance
767 @param[in] PciIo - PCI IO protocol instance
768 @param[in] PciHdr - PCI Header register block
770 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
776 IN EFI_HANDLE Handle
,
777 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
778 IN PCI_TYPE00
*PciHdr
781 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
782 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
787 UINT32 RootBusNumber
;
789 Status
= EFI_SUCCESS
;
791 if (PciHdr
->Device
.InterruptPin
!= 0) {
793 DevPathNode
= DevicePathFromHandle (Handle
);
794 ASSERT (DevPathNode
!= NULL
);
795 DevPath
= DevPathNode
;
798 if (DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
&&
799 DevicePathSubType (DevPathNode
) == ACPI_DP
&&
800 ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID(0x0A03)) {
801 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
805 // Compute index into PciHostIrqs[] table by walking
806 // the device path and adding up all device numbers
808 Status
= EFI_NOT_FOUND
;
810 Idx
= PciHdr
->Device
.InterruptPin
- 1;
811 while (!IsDevicePathEnd (DevPathNode
)) {
812 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
813 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
815 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
818 // Unlike SeaBIOS, which starts climbing from the leaf device
819 // up toward the root, we traverse the device path starting at
820 // the root moving toward the leaf node.
821 // The slot number of the top-level parent bridge is needed for
822 // Q35 cases with more than 24 slots on the root bus.
824 if (Status
!= EFI_SUCCESS
) {
825 Status
= EFI_SUCCESS
;
826 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
830 DevPathNode
= NextDevicePathNode (DevPathNode
);
832 if (EFI_ERROR (Status
)) {
835 if (RootBusNumber
== 0 && RootSlot
== 0) {
838 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
845 // Final PciHostIrqs[] index calculation depends on the platform
846 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
848 switch (mHostBridgeDevId
) {
849 case INTEL_82441_DEVICE_ID
:
852 case INTEL_Q35_MCH_DEVICE_ID
:
854 // SeaBIOS contains the following comment:
855 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
856 // with a different starting index - see q35-acpi-dsdt.dsl.
858 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
862 // in this case, subtract back out RootSlot from Idx
863 // (SeaBIOS never adds it to begin with, but that would make our
864 // device path traversal loop above too awkward)
870 ASSERT (FALSE
); // should never get here
872 Idx
%= ARRAY_SIZE (PciHostIrqs
);
873 IrqLine
= PciHostIrqs
[Idx
];
877 CHAR16
*DevPathString
;
878 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
879 UINTN Segment
, Bus
, Device
, Function
;
881 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
882 if (DevPathString
== NULL
) {
883 DevPathString
= Fallback
;
885 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
886 ASSERT_EFI_ERROR (Status
);
888 DEBUG ((EFI_D_VERBOSE
, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__
,
889 (UINT32
)Bus
, (UINT32
)Device
, (UINT32
)Function
, DevPathString
,
892 if (DevPathString
!= Fallback
) {
893 FreePool (DevPathString
);
899 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
901 Status
= PciIo
->Pci
.Write (
915 PciAcpiInitialization (
921 // Query Host Bridge DID to determine platform type
923 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
924 switch (mHostBridgeDevId
) {
925 case INTEL_82441_DEVICE_ID
:
926 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
928 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
930 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
931 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
932 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
933 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
935 case INTEL_Q35_MCH_DEVICE_ID
:
936 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
938 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
940 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
941 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
942 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
943 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
944 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
945 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
946 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
947 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
950 DEBUG ((EFI_D_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
951 __FUNCTION__
, mHostBridgeDevId
));
957 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
959 VisitAllPciInstances (SetPciIntLine
);
962 // Set ACPI SCI_EN bit in PMCNTRL
964 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
970 ConnectRecursivelyIfPciMassStorage (
971 IN EFI_HANDLE Handle
,
972 IN EFI_PCI_IO_PROTOCOL
*Instance
,
973 IN PCI_TYPE00
*PciHeader
977 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
980 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
)) {
982 Status
= gBS
->HandleProtocol (
984 &gEfiDevicePathProtocolGuid
,
987 if (EFI_ERROR (Status
)) {
994 DevPathStr
= DevicePathToStr (DevicePath
);
995 if (DevPathStr
!= NULL
) {
998 "Found Mass Storage device: %s\n",
1001 FreePool(DevPathStr
);
1004 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
1005 if (EFI_ERROR (Status
)) {
1016 This notification function is invoked when the
1017 EMU Variable FVB has been changed.
1019 @param Event The event that occured
1020 @param Context For EFI compatiblity. Not used.
1025 EmuVariablesUpdatedCallback (
1030 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
1031 UpdateNvVarsOnFileSystem ();
1037 VisitingFileSystemInstance (
1038 IN EFI_HANDLE Handle
,
1044 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
1046 if (ConnectedToFileSystem
) {
1047 return EFI_ALREADY_STARTED
;
1050 Status
= ConnectNvVarsToFileSystem (Handle
);
1051 if (EFI_ERROR (Status
)) {
1055 ConnectedToFileSystem
= TRUE
;
1057 EfiCreateProtocolNotifyEvent (
1058 &gEfiDevicePathProtocolGuid
,
1060 EmuVariablesUpdatedCallback
,
1062 &mEmuVariableEventReg
1064 PcdSet64 (PcdEmuVariableEvent
, (UINT64
)(UINTN
) mEmuVariableEvent
);
1071 PlatformBdsRestoreNvVarsFromHardDisk (
1074 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1075 VisitAllInstancesOfProtocol (
1076 &gEfiSimpleFileSystemProtocolGuid
,
1077 VisitingFileSystemInstance
,
1085 PlatformBdsConnectSequence (
1090 Routine Description:
1092 Connect with predeined platform connect sequence,
1093 the OEM/IBV can customize with their own connect sequence.
1107 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
1112 // Here we can get the customized platform connect sequence
1113 // Notes: we can connect with new variable which record the
1114 // last time boots connect device path sequence
1116 while (gPlatformConnectSequence
[Index
] != NULL
) {
1118 // Build the platform boot option
1120 BdsLibConnectDevicePath (gPlatformConnectSequence
[Index
]);
1125 // Just use the simple policy to connect all devices
1127 BdsLibConnectAll ();
1129 PciAcpiInitialization ();
1132 // Clear the logo after all devices are connected.
1134 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1138 PlatformBdsGetDriverOption (
1139 IN OUT LIST_ENTRY
*BdsDriverLists
1143 Routine Description:
1145 Load the predefined driver option, OEM/IBV can customize this
1146 to load their own drivers
1150 BdsDriverLists - The header of the driver option link list.
1158 DEBUG ((EFI_D_INFO
, "PlatformBdsGetDriverOption\n"));
1163 PlatformBdsDiagnostics (
1164 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel
,
1165 IN BOOLEAN QuietBoot
,
1166 IN BASEM_MEMORY_TEST BaseMemoryTest
1170 Routine Description:
1172 Perform the platform diagnostic, such like test memory. OEM/IBV also
1173 can customize this fuction to support specific platform diagnostic.
1177 MemoryTestLevel - The memory test intensive level
1179 QuietBoot - Indicate if need to enable the quiet boot
1181 BaseMemoryTest - A pointer to BaseMemoryTest()
1191 DEBUG ((EFI_D_INFO
, "PlatformBdsDiagnostics\n"));
1194 // Here we can decide if we need to show
1195 // the diagnostics screen
1196 // Notes: this quiet boot code should be remove
1197 // from the graphic lib
1200 EnableQuietBoot (PcdGetPtr(PcdLogoFile
));
1202 // Perform system diagnostic
1204 Status
= BaseMemoryTest (MemoryTestLevel
);
1205 if (EFI_ERROR (Status
)) {
1206 DisableQuietBoot ();
1212 // Perform system diagnostic
1214 Status
= BaseMemoryTest (MemoryTestLevel
);
1219 Save the S3 boot script.
1221 Note that DxeSmmReadyToLock must be signaled after this function returns;
1222 otherwise the script wouldn't be saved actually.
1231 EFI_S3_SAVE_STATE_PROTOCOL
*BootScript
;
1232 STATIC CONST UINT8 Info
[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1234 Status
= gBS
->LocateProtocol (&gEfiS3SaveStateProtocolGuid
, NULL
,
1235 (VOID
**) &BootScript
);
1236 ASSERT_EFI_ERROR (Status
);
1239 // Despite the opcode documentation in the PI spec, the protocol
1240 // implementation embeds a deep copy of the info in the boot script, rather
1241 // than storing just a pointer to runtime or NVS storage.
1243 Status
= BootScript
->Write(BootScript
, EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
1244 (UINT32
) sizeof Info
,
1245 (EFI_PHYSICAL_ADDRESS
)(UINTN
) &Info
);
1246 ASSERT_EFI_ERROR (Status
);
1252 PlatformBootManagerAfterConsole (
1257 Routine Description:
1259 The function will excute with as the platform policy, current policy
1260 is driven by boot mode. IBV/OEM can customize this code for their specific
1266 EFI_BOOT_MODE BootMode
;
1268 DEBUG ((EFI_D_INFO
, "PlatformBootManagerAfterConsole\n"));
1270 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1271 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior: not restoring NvVars "
1272 "from disk since flash variables appear to be supported.\n"));
1275 // Try to restore variables from the hard disk early so
1276 // they can be used for the other BDS connect operations.
1278 PlatformBdsRestoreNvVarsFromHardDisk ();
1282 // Load the driver option as the driver option list
1284 PlatformBdsGetDriverOption (DriverOptionList
);
1287 // Get current Boot Mode
1289 Status
= BdsLibGetBootMode (&BootMode
);
1290 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1293 // Go the different platform policy with different boot mode
1294 // Notes: this part code can be change with the table policy
1296 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1298 // Connect platform console
1300 Status
= PlatformBdsConnectConsole (gPlatformConsole
);
1301 if (EFI_ERROR (Status
)) {
1303 // Here OEM/IBV can customize with defined action
1305 PlatformBdsNoConsoleAction ();
1309 // Memory test and Logo show
1311 PlatformBdsDiagnostics (IGNORE
, TRUE
, BaseMemoryTest
);
1314 // Perform some platform specific connect sequence
1316 PlatformBdsConnectSequence ();
1319 // Process QEMU's -kernel command line option
1321 TryRunningQemuKernel ();
1323 DEBUG ((EFI_D_INFO
, "BdsLibConnectAll\n"));
1324 BdsLibConnectAll ();
1325 BdsLibEnumerateAllBootOption (BootOptionList
);
1327 SetBootOrderFromQemu (BootOptionList
);
1329 // The BootOrder variable may have changed, reload the in-memory list with
1332 BdsLibBuildOptionFromVar (BootOptionList
, L
"BootOrder");
1334 PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE
);
1339 PlatformBdsBootSuccess (
1340 IN BDS_COMMON_OPTION
*Option
1344 Routine Description:
1346 Hook point after a boot attempt succeeds. We don't expect a boot option to
1347 return, so the EFI 1.0 specification defines that you will default to an
1348 interactive mode and stop processing the BootOrder list in this case. This
1349 is alos a platform implementation and can be customized by IBV/OEM.
1353 Option - Pointer to Boot Option that succeeded to boot.
1363 DEBUG ((EFI_D_INFO
, "PlatformBdsBootSuccess\n"));
1365 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1366 // select loop then we need to pop up a UI and wait for user input.
1368 TmpStr
= Option
->StatusString
;
1369 if (TmpStr
!= NULL
) {
1370 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1377 PlatformBdsBootFail (
1378 IN BDS_COMMON_OPTION
*Option
,
1379 IN EFI_STATUS Status
,
1380 IN CHAR16
*ExitData
,
1381 IN UINTN ExitDataSize
1385 Routine Description:
1387 Hook point after a boot attempt fails.
1391 Option - Pointer to Boot Option that failed to boot.
1393 Status - Status returned from failed boot.
1395 ExitData - Exit data returned from failed boot.
1397 ExitDataSize - Exit data size returned from failed boot.
1407 DEBUG ((EFI_D_INFO
, "PlatformBdsBootFail\n"));
1410 // If Boot returned with failed status then we need to pop up a UI and wait
1413 TmpStr
= Option
->StatusString
;
1414 if (TmpStr
!= NULL
) {
1415 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1421 PlatformBdsNoConsoleAction (
1426 Routine Description:
1428 This function is remained for IBV/OEM to do some platform action,
1429 if there no console device can be connected.
1437 EFI_SUCCESS - Direct return success now.
1441 DEBUG ((EFI_D_INFO
, "PlatformBdsNoConsoleAction\n"));
1447 PlatformBdsLockNonUpdatableFlash (
1451 DEBUG ((EFI_D_INFO
, "PlatformBdsLockNonUpdatableFlash\n"));
1457 This notification function is invoked when an instance of the
1458 EFI_DEVICE_PATH_PROTOCOL is produced.
1460 @param Event The event that occured
1461 @param Context For EFI compatiblity. Not used.
1474 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1475 ATAPI_DEVICE_PATH
*Atapi
;
1478 // Examine all new handles
1482 // Get the next handle
1484 BufferSize
= sizeof (Handle
);
1485 Status
= gBS
->LocateHandle (
1488 mEfiDevPathNotifyReg
,
1494 // If not found, we're done
1496 if (EFI_NOT_FOUND
== Status
) {
1500 if (EFI_ERROR (Status
)) {
1505 // Get the DevicePath protocol on that handle
1507 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevPathNode
);
1508 ASSERT_EFI_ERROR (Status
);
1510 while (!IsDevicePathEnd (DevPathNode
)) {
1512 // Find the handler to dump this device path node
1515 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1516 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1518 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1524 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1531 // Next device path node
1533 DevPathNode
= NextDevicePathNode (DevPathNode
);
1542 InstallDevicePathCallback (
1546 DEBUG ((EFI_D_INFO
, "Registered NotifyDevPath Event\n"));
1547 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1548 &gEfiDevicePathProtocolGuid
,
1552 &mEfiDevPathNotifyReg
1557 This function is called each second during the boot manager waits the timeout.
1559 @param TimeoutRemain The remaining timeout.
1563 PlatformBootManagerWaitCallback (
1564 UINT16 TimeoutRemain
1570 Lock the ConsoleIn device in system table. All key
1571 presses will be ignored until the Password is typed in. The only way to
1572 disable the password is to type it in to a ConIn device.
1574 @param Password Password used to lock ConIn device.
1576 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1577 @retval EFI_UNSUPPORTED Password not found
1586 return EFI_UNSUPPORTED
;