2 Platform BDS customizations.
4 Copyright (c) 2004 - 2014, 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 // BDS Platform Functions
103 Platform Bds init. Incude the platform firmware vendor, revision
114 DEBUG ((EFI_D_INFO
, "PlatformBdsInit\n"));
115 InstallDevicePathCallback ();
122 IN EFI_HANDLE RootBridgeHandle
,
130 // Make the PCI bus driver connect the root bridge, non-recursively. This
131 // will produce a number of child handles with PciIo on them.
133 Status
= gBS
->ConnectController (
134 RootBridgeHandle
, // ControllerHandle
135 NULL
, // DriverImageHandle
136 NULL
, // RemainingDevicePath -- produce all
145 PrepareLpcBridgeDevicePath (
146 IN EFI_HANDLE DeviceHandle
152 Add IsaKeyboard to ConIn,
153 add IsaSerial to ConOut, ConIn, ErrOut.
158 DeviceHandle - Handle of PCIIO protocol.
162 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
163 EFI_STATUS - No LPC bridge is added.
168 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
169 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
173 Status
= gBS
->HandleProtocol (
175 &gEfiDevicePathProtocolGuid
,
178 if (EFI_ERROR (Status
)) {
181 TempDevicePath
= DevicePath
;
186 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
188 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
193 DevicePath
= TempDevicePath
;
194 gPnp16550ComPortDeviceNode
.UID
= 0;
196 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
197 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
198 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
203 DevPathStr
= DevicePathToStr(DevicePath
);
204 if (DevPathStr
!= NULL
) {
207 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
209 gPnp16550ComPortDeviceNode
.UID
+ 1,
212 FreePool(DevPathStr
);
215 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
216 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
217 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
222 DevicePath
= TempDevicePath
;
223 gPnp16550ComPortDeviceNode
.UID
= 1;
225 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
226 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
227 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
232 DevPathStr
= DevicePathToStr(DevicePath
);
233 if (DevPathStr
!= NULL
) {
236 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
238 gPnp16550ComPortDeviceNode
.UID
+ 1,
241 FreePool(DevPathStr
);
244 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
245 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
246 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
253 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
254 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
259 EFI_HANDLE PciDeviceHandle
;
260 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
261 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
262 UINTN GopHandleCount
;
263 EFI_HANDLE
*GopHandleBuffer
;
265 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
266 return EFI_INVALID_PARAMETER
;
270 // Initialize the GopDevicePath to be PciDevicePath
272 *GopDevicePath
= PciDevicePath
;
273 TempPciDevicePath
= PciDevicePath
;
275 Status
= gBS
->LocateDevicePath (
276 &gEfiDevicePathProtocolGuid
,
280 if (EFI_ERROR (Status
)) {
285 // Try to connect this handle, so that GOP dirver could start on this
286 // device and create child handles with GraphicsOutput Protocol installed
287 // on them, then we get device paths of these child handles and select
288 // them as possible console device.
290 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
292 Status
= gBS
->LocateHandleBuffer (
294 &gEfiGraphicsOutputProtocolGuid
,
299 if (!EFI_ERROR (Status
)) {
301 // Add all the child handles as possible Console Device
303 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
304 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
305 if (EFI_ERROR (Status
)) {
311 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
314 // In current implementation, we only enable one of the child handles
315 // as console device, i.e. sotre one of the child handle's device
316 // path to variable "ConOut"
317 // In futhure, we could select all child handles to be console device
320 *GopDevicePath
= TempDevicePath
;
323 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
324 // Add the integrity GOP device path.
326 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, NULL
, PciDevicePath
);
327 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, TempDevicePath
, NULL
);
330 gBS
->FreePool (GopHandleBuffer
);
337 PreparePciVgaDevicePath (
338 IN EFI_HANDLE DeviceHandle
344 Add PCI VGA to ConOut.
349 DeviceHandle - Handle of PCIIO protocol.
353 EFI_SUCCESS - PCI VGA is added to ConOut.
354 EFI_STATUS - No PCI VGA device is added.
359 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
360 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
363 GopDevicePath
= NULL
;
364 Status
= gBS
->HandleProtocol (
366 &gEfiDevicePathProtocolGuid
,
369 if (EFI_ERROR (Status
)) {
373 GetGopDevicePath (DevicePath
, &GopDevicePath
);
374 DevicePath
= GopDevicePath
;
376 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
382 PreparePciSerialDevicePath (
383 IN EFI_HANDLE DeviceHandle
389 Add PCI Serial to ConOut, ConIn, ErrOut.
394 DeviceHandle - Handle of PCIIO protocol.
398 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
399 EFI_STATUS - No PCI Serial device is added.
404 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
407 Status
= gBS
->HandleProtocol (
409 &gEfiDevicePathProtocolGuid
,
412 if (EFI_ERROR (Status
)) {
416 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
417 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
419 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
420 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
421 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
427 VisitAllInstancesOfProtocol (
429 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
435 EFI_HANDLE
*HandleBuffer
;
440 // Start to check all the PciIo to find all possible device
444 Status
= gBS
->LocateHandleBuffer (
451 if (EFI_ERROR (Status
)) {
455 for (Index
= 0; Index
< HandleCount
; Index
++) {
456 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
457 if (EFI_ERROR (Status
)) {
461 Status
= (*CallBackFunction
) (
468 gBS
->FreePool (HandleBuffer
);
476 VisitingAPciInstance (
477 IN EFI_HANDLE Handle
,
483 EFI_PCI_IO_PROTOCOL
*PciIo
;
486 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
489 // Check for all PCI device
491 Status
= PciIo
->Pci
.Read (
495 sizeof (Pci
) / sizeof (UINT32
),
498 if (EFI_ERROR (Status
)) {
502 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
513 VisitAllPciInstances (
514 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
517 return VisitAllInstancesOfProtocol (
518 &gEfiPciIoProtocolGuid
,
519 VisitingAPciInstance
,
520 (VOID
*)(UINTN
) CallBackFunction
526 Do platform specific PCI Device check and add them to
527 ConOut, ConIn, ErrOut.
529 @param[in] Handle - Handle of PCI device instance
530 @param[in] PciIo - PCI IO protocol instance
531 @param[in] Pci - PCI Header register block
533 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
534 @retval EFI_STATUS - PCI Device check or Console variable update fail.
539 DetectAndPreparePlatformPciDevicePath (
540 IN EFI_HANDLE Handle
,
541 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
547 Status
= PciIo
->Attributes (
549 EfiPciIoAttributeOperationEnable
,
550 EFI_PCI_DEVICE_ENABLE
,
553 ASSERT_EFI_ERROR (Status
);
555 if (!mDetectVgaOnly
) {
557 // Here we decide whether it is LPC Bridge
559 if ((IS_PCI_LPC (Pci
)) ||
560 ((IS_PCI_ISA_PDECODE (Pci
)) &&
561 (Pci
->Hdr
.VendorId
== 0x8086) &&
562 (Pci
->Hdr
.DeviceId
== 0x7000)
566 // Add IsaKeyboard to ConIn,
567 // add IsaSerial to ConOut, ConIn, ErrOut
569 DEBUG ((EFI_D_INFO
, "Found LPC Bridge device\n"));
570 PrepareLpcBridgeDevicePath (Handle
);
574 // Here we decide which Serial device to enable in PCI bus
576 if (IS_PCI_16550SERIAL (Pci
)) {
578 // Add them to ConOut, ConIn, ErrOut.
580 DEBUG ((EFI_D_INFO
, "Found PCI 16550 SERIAL device\n"));
581 PreparePciSerialDevicePath (Handle
);
587 // Here we decide which VGA device to enable in PCI bus
589 if (IS_PCI_VGA (Pci
)) {
591 // Add them to ConOut.
593 DEBUG ((EFI_D_INFO
, "Found PCI VGA device\n"));
594 PreparePciVgaDevicePath (Handle
);
603 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
605 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
607 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
608 @retval EFI_STATUS - PCI Device check or Console variable update fail.
612 DetectAndPreparePlatformPciDevicePaths (
613 BOOLEAN DetectVgaOnly
616 mDetectVgaOnly
= DetectVgaOnly
;
617 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
622 PlatformBdsConnectConsole (
623 IN BDS_CONSOLE_CONNECT_ENTRY
*PlatformConsole
629 Connect the predefined platform default console device. Always try to find
630 and enable the vga device if have.
634 PlatformConsole - Predfined platform default console device array.
638 EFI_SUCCESS - Success connect at least one ConIn and ConOut
639 device, there must have one ConOut device is
642 EFI_STATUS - Return the status of
643 BdsLibConnectAllDefaultConsoles ()
649 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
650 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
651 UINTN DevicePathSize
;
654 // Connect RootBridge
656 VarConout
= BdsLibGetVariableAndSize (
658 &gEfiGlobalVariableGuid
,
661 VarConin
= BdsLibGetVariableAndSize (
663 &gEfiGlobalVariableGuid
,
667 if (VarConout
== NULL
|| VarConin
== NULL
) {
669 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
671 DetectAndPreparePlatformPciDevicePaths (FALSE
);
674 // Have chance to connect the platform default console,
675 // the platform default console is the minimue device group
676 // the platform should support
678 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
680 // Update the console variable with the connect type
682 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
683 BdsLibUpdateConsoleVariable (VarConsoleInp
, PlatformConsole
[Index
].DevicePath
, NULL
);
685 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
686 BdsLibUpdateConsoleVariable (VarConsoleOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
688 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
689 BdsLibUpdateConsoleVariable (VarErrorOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
694 // Only detect VGA device and add them to ConOut
696 DetectAndPreparePlatformPciDevicePaths (TRUE
);
700 // Connect the all the default console with current cosole variable
702 Status
= BdsLibConnectAllDefaultConsoles ();
703 if (EFI_ERROR (Status
)) {
712 Configure PCI Interrupt Line register for applicable devices
713 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
715 @param[in] Handle - Handle of PCI device instance
716 @param[in] PciIo - PCI IO protocol instance
717 @param[in] PciHdr - PCI Header register block
719 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
725 IN EFI_HANDLE Handle
,
726 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
727 IN PCI_TYPE00
*PciHdr
730 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
731 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
736 UINT32 RootBusNumber
;
738 Status
= EFI_SUCCESS
;
740 if (PciHdr
->Device
.InterruptPin
!= 0) {
742 DevPathNode
= DevicePathFromHandle (Handle
);
743 ASSERT (DevPathNode
!= NULL
);
744 DevPath
= DevPathNode
;
747 if (DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
&&
748 DevicePathSubType (DevPathNode
) == ACPI_DP
&&
749 ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID(0x0A03)) {
750 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
754 // Compute index into PciHostIrqs[] table by walking
755 // the device path and adding up all device numbers
757 Status
= EFI_NOT_FOUND
;
759 Idx
= PciHdr
->Device
.InterruptPin
- 1;
760 while (!IsDevicePathEnd (DevPathNode
)) {
761 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
762 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
764 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
767 // Unlike SeaBIOS, which starts climbing from the leaf device
768 // up toward the root, we traverse the device path starting at
769 // the root moving toward the leaf node.
770 // The slot number of the top-level parent bridge is needed for
771 // Q35 cases with more than 24 slots on the root bus.
773 if (Status
!= EFI_SUCCESS
) {
774 Status
= EFI_SUCCESS
;
775 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
779 DevPathNode
= NextDevicePathNode (DevPathNode
);
781 if (EFI_ERROR (Status
)) {
784 if (RootBusNumber
== 0 && RootSlot
== 0) {
787 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
794 // Final PciHostIrqs[] index calculation depends on the platform
795 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
797 switch (mHostBridgeDevId
) {
798 case INTEL_82441_DEVICE_ID
:
801 case INTEL_Q35_MCH_DEVICE_ID
:
803 // SeaBIOS contains the following comment:
804 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
805 // with a different starting index - see q35-acpi-dsdt.dsl.
807 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
811 // in this case, subtract back out RootSlot from Idx
812 // (SeaBIOS never adds it to begin with, but that would make our
813 // device path traversal loop above too awkward)
819 ASSERT (FALSE
); // should never get here
821 Idx
%= ARRAY_SIZE (PciHostIrqs
);
822 IrqLine
= PciHostIrqs
[Idx
];
826 CHAR16
*DevPathString
;
827 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
828 UINTN Segment
, Bus
, Device
, Function
;
830 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
831 if (DevPathString
== NULL
) {
832 DevPathString
= Fallback
;
834 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
835 ASSERT_EFI_ERROR (Status
);
837 DEBUG ((EFI_D_VERBOSE
, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__
,
838 (UINT32
)Bus
, (UINT32
)Device
, (UINT32
)Function
, DevPathString
,
841 if (DevPathString
!= Fallback
) {
842 FreePool (DevPathString
);
848 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
850 Status
= PciIo
->Pci
.Write (
864 PciAcpiInitialization (
870 // Query Host Bridge DID to determine platform type
872 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
873 switch (mHostBridgeDevId
) {
874 case INTEL_82441_DEVICE_ID
:
875 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
877 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
879 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
880 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
881 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
882 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
884 case INTEL_Q35_MCH_DEVICE_ID
:
885 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
887 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
889 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
890 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
891 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
892 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
893 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
894 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
895 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
896 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
899 DEBUG ((EFI_D_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
900 __FUNCTION__
, mHostBridgeDevId
));
906 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
908 VisitAllPciInstances (SetPciIntLine
);
911 // Set ACPI SCI_EN bit in PMCNTRL
913 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
919 ConnectRecursivelyIfPciMassStorage (
920 IN EFI_HANDLE Handle
,
921 IN EFI_PCI_IO_PROTOCOL
*Instance
,
922 IN PCI_TYPE00
*PciHeader
926 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
929 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
)) {
931 Status
= gBS
->HandleProtocol (
933 &gEfiDevicePathProtocolGuid
,
936 if (EFI_ERROR (Status
)) {
943 DevPathStr
= DevicePathToStr (DevicePath
);
944 if (DevPathStr
!= NULL
) {
947 "Found Mass Storage device: %s\n",
950 FreePool(DevPathStr
);
953 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
954 if (EFI_ERROR (Status
)) {
965 This notification function is invoked when the
966 EMU Variable FVB has been changed.
968 @param Event The event that occured
969 @param Context For EFI compatiblity. Not used.
974 EmuVariablesUpdatedCallback (
979 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
980 UpdateNvVarsOnFileSystem ();
986 VisitingFileSystemInstance (
987 IN EFI_HANDLE Handle
,
993 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
995 if (ConnectedToFileSystem
) {
996 return EFI_ALREADY_STARTED
;
999 Status
= ConnectNvVarsToFileSystem (Handle
);
1000 if (EFI_ERROR (Status
)) {
1004 ConnectedToFileSystem
= TRUE
;
1006 EfiCreateProtocolNotifyEvent (
1007 &gEfiDevicePathProtocolGuid
,
1009 EmuVariablesUpdatedCallback
,
1011 &mEmuVariableEventReg
1013 PcdSet64 (PcdEmuVariableEvent
, (UINT64
)(UINTN
) mEmuVariableEvent
);
1020 PlatformBdsRestoreNvVarsFromHardDisk (
1023 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1024 VisitAllInstancesOfProtocol (
1025 &gEfiSimpleFileSystemProtocolGuid
,
1026 VisitingFileSystemInstance
,
1034 PlatformBdsConnectSequence (
1039 Routine Description:
1041 Connect with predeined platform connect sequence,
1042 the OEM/IBV can customize with their own connect sequence.
1056 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
1061 // Here we can get the customized platform connect sequence
1062 // Notes: we can connect with new variable which record the
1063 // last time boots connect device path sequence
1065 while (gPlatformConnectSequence
[Index
] != NULL
) {
1067 // Build the platform boot option
1069 BdsLibConnectDevicePath (gPlatformConnectSequence
[Index
]);
1074 // Just use the simple policy to connect all devices
1076 BdsLibConnectAll ();
1078 PciAcpiInitialization ();
1081 // Clear the logo after all devices are connected.
1083 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1087 PlatformBdsGetDriverOption (
1088 IN OUT LIST_ENTRY
*BdsDriverLists
1092 Routine Description:
1094 Load the predefined driver option, OEM/IBV can customize this
1095 to load their own drivers
1099 BdsDriverLists - The header of the driver option link list.
1107 DEBUG ((EFI_D_INFO
, "PlatformBdsGetDriverOption\n"));
1112 PlatformBdsDiagnostics (
1113 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel
,
1114 IN BOOLEAN QuietBoot
,
1115 IN BASEM_MEMORY_TEST BaseMemoryTest
1119 Routine Description:
1121 Perform the platform diagnostic, such like test memory. OEM/IBV also
1122 can customize this fuction to support specific platform diagnostic.
1126 MemoryTestLevel - The memory test intensive level
1128 QuietBoot - Indicate if need to enable the quiet boot
1130 BaseMemoryTest - A pointer to BaseMemoryTest()
1140 DEBUG ((EFI_D_INFO
, "PlatformBdsDiagnostics\n"));
1143 // Here we can decide if we need to show
1144 // the diagnostics screen
1145 // Notes: this quiet boot code should be remove
1146 // from the graphic lib
1149 EnableQuietBoot (PcdGetPtr(PcdLogoFile
));
1151 // Perform system diagnostic
1153 Status
= BaseMemoryTest (MemoryTestLevel
);
1154 if (EFI_ERROR (Status
)) {
1155 DisableQuietBoot ();
1161 // Perform system diagnostic
1163 Status
= BaseMemoryTest (MemoryTestLevel
);
1168 Save the S3 boot script.
1170 Note that we trigger DxeSmmReadyToLock here -- otherwise the script wouldn't
1171 be saved actually. Triggering this protocol installation event in turn locks
1172 down SMM, so no further changes to LockBoxes or SMRAM are possible
1182 EFI_S3_SAVE_STATE_PROTOCOL
*BootScript
;
1184 STATIC CONST UINT8 Info
[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1186 Status
= gBS
->LocateProtocol (&gEfiS3SaveStateProtocolGuid
, NULL
,
1187 (VOID
**) &BootScript
);
1188 ASSERT_EFI_ERROR (Status
);
1191 // Despite the opcode documentation in the PI spec, the protocol
1192 // implementation embeds a deep copy of the info in the boot script, rather
1193 // than storing just a pointer to runtime or NVS storage.
1195 Status
= BootScript
->Write(BootScript
, EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
1196 (UINT32
) sizeof Info
,
1197 (EFI_PHYSICAL_ADDRESS
)(UINTN
) &Info
);
1198 ASSERT_EFI_ERROR (Status
);
1201 Status
= gBS
->InstallProtocolInterface (&Handle
,
1202 &gEfiDxeSmmReadyToLockProtocolGuid
, EFI_NATIVE_INTERFACE
,
1204 ASSERT_EFI_ERROR (Status
);
1210 PlatformBdsPolicyBehavior (
1211 IN OUT LIST_ENTRY
*DriverOptionList
,
1212 IN OUT LIST_ENTRY
*BootOptionList
,
1213 IN PROCESS_CAPSULES ProcessCapsules
,
1214 IN BASEM_MEMORY_TEST BaseMemoryTest
1218 Routine Description:
1220 The function will excute with as the platform policy, current policy
1221 is driven by boot mode. IBV/OEM can customize this code for their specific
1226 DriverOptionList - The header of the driver option link list
1228 BootOptionList - The header of the boot option link list
1230 ProcessCapsules - A pointer to ProcessCapsules()
1232 BaseMemoryTest - A pointer to BaseMemoryTest()
1241 EFI_BOOT_MODE BootMode
;
1243 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior\n"));
1245 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid
,
1246 ConnectRootBridge
, NULL
);
1249 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
1251 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
1254 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
1255 // the preparation of S3 system information. That logic has a hard dependency
1256 // on the presence of the FACS ACPI table. Since our ACPI tables are only
1257 // installed after PCI enumeration completes, we must not trigger the S3 save
1258 // earlier, hence we can't signal End-of-Dxe earlier.
1260 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
1262 if (QemuFwCfgS3Enabled ()) {
1264 // Save the boot script too. Note that this requires/includes emitting the
1265 // DxeSmmReadyToLock event, which in turn locks down SMM.
1267 SaveS3BootScript ();
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 Lock the ConsoleIn device in system table. All key
1558 presses will be ignored until the Password is typed in. The only way to
1559 disable the password is to type it in to a ConIn device.
1561 @param Password Password used to lock ConIn device.
1563 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1564 @retval EFI_UNSUPPORTED Password not found
1573 return EFI_UNSUPPORTED
;