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 <Library/QemuBootOrderLib.h>
23 VOID
*mEfiDevPathNotifyReg
;
24 EFI_EVENT mEfiDevPathEvent
;
25 VOID
*mEmuVariableEventReg
;
26 EFI_EVENT mEmuVariableEvent
;
27 BOOLEAN mDetectVgaOnly
;
28 UINT16 mHostBridgeDevId
;
31 // Table of host IRQs matching PCI IRQs A-D
32 // (for configuring PCI Interrupt Line register)
34 CONST UINT8 PciHostIrqs
[] = {
35 0x0a, 0x0a, 0x0b, 0x0b
41 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
49 (EFIAPI
*PROTOCOL_INSTANCE_CALLBACK
)(
56 @param[in] Handle - Handle of PCI device instance
57 @param[in] PciIo - PCI IO protocol instance
58 @param[in] Pci - PCI Header register block
62 (EFIAPI
*VISIT_PCI_INSTANCE_CALLBACK
)(
64 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
70 // Function prototypes
74 VisitAllInstancesOfProtocol (
76 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
81 VisitAllPciInstancesOfProtocol (
82 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
86 InstallDevicePathCallback (
91 // BDS Platform Functions
102 Platform Bds init. Incude the platform firmware vendor, revision
113 DEBUG ((EFI_D_INFO
, "PlatformBdsInit\n"));
114 InstallDevicePathCallback ();
134 EFI_SUCCESS - Connect RootBridge successfully.
135 EFI_STATUS - Connect RootBridge fail.
140 EFI_HANDLE RootHandle
;
143 // Make all the PCI_IO protocols on PCI Seg 0 show up
145 BdsLibConnectDevicePath (gPlatformRootBridges
[0]);
147 Status
= gBS
->LocateDevicePath (
148 &gEfiDevicePathProtocolGuid
,
149 &gPlatformRootBridges
[0],
152 if (EFI_ERROR (Status
)) {
156 Status
= gBS
->ConnectController (RootHandle
, NULL
, NULL
, FALSE
);
157 if (EFI_ERROR (Status
)) {
166 PrepareLpcBridgeDevicePath (
167 IN EFI_HANDLE DeviceHandle
173 Add IsaKeyboard to ConIn,
174 add IsaSerial to ConOut, ConIn, ErrOut.
179 DeviceHandle - Handle of PCIIO protocol.
183 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
184 EFI_STATUS - No LPC bridge is added.
189 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
190 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
194 Status
= gBS
->HandleProtocol (
196 &gEfiDevicePathProtocolGuid
,
199 if (EFI_ERROR (Status
)) {
202 TempDevicePath
= DevicePath
;
207 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
209 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
214 DevicePath
= TempDevicePath
;
215 gPnp16550ComPortDeviceNode
.UID
= 0;
217 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
218 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
219 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
224 DevPathStr
= DevicePathToStr(DevicePath
);
225 if (DevPathStr
!= NULL
) {
228 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
230 gPnp16550ComPortDeviceNode
.UID
+ 1,
233 FreePool(DevPathStr
);
236 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
237 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
238 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
243 DevicePath
= TempDevicePath
;
244 gPnp16550ComPortDeviceNode
.UID
= 1;
246 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
247 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
248 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
253 DevPathStr
= DevicePathToStr(DevicePath
);
254 if (DevPathStr
!= NULL
) {
257 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
259 gPnp16550ComPortDeviceNode
.UID
+ 1,
262 FreePool(DevPathStr
);
265 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
266 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
267 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
274 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
275 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
280 EFI_HANDLE PciDeviceHandle
;
281 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
282 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
283 UINTN GopHandleCount
;
284 EFI_HANDLE
*GopHandleBuffer
;
286 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
287 return EFI_INVALID_PARAMETER
;
291 // Initialize the GopDevicePath to be PciDevicePath
293 *GopDevicePath
= PciDevicePath
;
294 TempPciDevicePath
= PciDevicePath
;
296 Status
= gBS
->LocateDevicePath (
297 &gEfiDevicePathProtocolGuid
,
301 if (EFI_ERROR (Status
)) {
306 // Try to connect this handle, so that GOP dirver could start on this
307 // device and create child handles with GraphicsOutput Protocol installed
308 // on them, then we get device paths of these child handles and select
309 // them as possible console device.
311 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
313 Status
= gBS
->LocateHandleBuffer (
315 &gEfiGraphicsOutputProtocolGuid
,
320 if (!EFI_ERROR (Status
)) {
322 // Add all the child handles as possible Console Device
324 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
325 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
326 if (EFI_ERROR (Status
)) {
332 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
335 // In current implementation, we only enable one of the child handles
336 // as console device, i.e. sotre one of the child handle's device
337 // path to variable "ConOut"
338 // In futhure, we could select all child handles to be console device
341 *GopDevicePath
= TempDevicePath
;
344 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
345 // Add the integrity GOP device path.
347 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, NULL
, PciDevicePath
);
348 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, TempDevicePath
, NULL
);
351 gBS
->FreePool (GopHandleBuffer
);
358 PreparePciVgaDevicePath (
359 IN EFI_HANDLE DeviceHandle
365 Add PCI VGA to ConOut.
370 DeviceHandle - Handle of PCIIO protocol.
374 EFI_SUCCESS - PCI VGA is added to ConOut.
375 EFI_STATUS - No PCI VGA device is added.
380 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
381 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
384 GopDevicePath
= NULL
;
385 Status
= gBS
->HandleProtocol (
387 &gEfiDevicePathProtocolGuid
,
390 if (EFI_ERROR (Status
)) {
394 GetGopDevicePath (DevicePath
, &GopDevicePath
);
395 DevicePath
= GopDevicePath
;
397 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
403 PreparePciSerialDevicePath (
404 IN EFI_HANDLE DeviceHandle
410 Add PCI Serial to ConOut, ConIn, ErrOut.
415 DeviceHandle - Handle of PCIIO protocol.
419 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
420 EFI_STATUS - No PCI Serial device is added.
425 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
428 Status
= gBS
->HandleProtocol (
430 &gEfiDevicePathProtocolGuid
,
433 if (EFI_ERROR (Status
)) {
437 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
438 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
440 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
441 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
442 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
448 VisitAllInstancesOfProtocol (
450 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
456 EFI_HANDLE
*HandleBuffer
;
461 // Start to check all the PciIo to find all possible device
465 Status
= gBS
->LocateHandleBuffer (
472 if (EFI_ERROR (Status
)) {
476 for (Index
= 0; Index
< HandleCount
; Index
++) {
477 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
478 if (EFI_ERROR (Status
)) {
482 Status
= (*CallBackFunction
) (
489 gBS
->FreePool (HandleBuffer
);
497 VisitingAPciInstance (
498 IN EFI_HANDLE Handle
,
504 EFI_PCI_IO_PROTOCOL
*PciIo
;
507 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
510 // Check for all PCI device
512 Status
= PciIo
->Pci
.Read (
516 sizeof (Pci
) / sizeof (UINT32
),
519 if (EFI_ERROR (Status
)) {
523 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
534 VisitAllPciInstances (
535 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
538 return VisitAllInstancesOfProtocol (
539 &gEfiPciIoProtocolGuid
,
540 VisitingAPciInstance
,
541 (VOID
*)(UINTN
) CallBackFunction
547 Do platform specific PCI Device check and add them to
548 ConOut, ConIn, ErrOut.
550 @param[in] Handle - Handle of PCI device instance
551 @param[in] PciIo - PCI IO protocol instance
552 @param[in] Pci - PCI Header register block
554 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
555 @retval EFI_STATUS - PCI Device check or Console variable update fail.
560 DetectAndPreparePlatformPciDevicePath (
561 IN EFI_HANDLE Handle
,
562 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
568 Status
= PciIo
->Attributes (
570 EfiPciIoAttributeOperationEnable
,
571 EFI_PCI_DEVICE_ENABLE
,
574 ASSERT_EFI_ERROR (Status
);
576 if (!mDetectVgaOnly
) {
578 // Here we decide whether it is LPC Bridge
580 if ((IS_PCI_LPC (Pci
)) ||
581 ((IS_PCI_ISA_PDECODE (Pci
)) &&
582 (Pci
->Hdr
.VendorId
== 0x8086) &&
583 (Pci
->Hdr
.DeviceId
== 0x7000)
587 // Add IsaKeyboard to ConIn,
588 // add IsaSerial to ConOut, ConIn, ErrOut
590 DEBUG ((EFI_D_INFO
, "Found LPC Bridge device\n"));
591 PrepareLpcBridgeDevicePath (Handle
);
595 // Here we decide which Serial device to enable in PCI bus
597 if (IS_PCI_16550SERIAL (Pci
)) {
599 // Add them to ConOut, ConIn, ErrOut.
601 DEBUG ((EFI_D_INFO
, "Found PCI 16550 SERIAL device\n"));
602 PreparePciSerialDevicePath (Handle
);
608 // Here we decide which VGA device to enable in PCI bus
610 if (IS_PCI_VGA (Pci
)) {
612 // Add them to ConOut.
614 DEBUG ((EFI_D_INFO
, "Found PCI VGA device\n"));
615 PreparePciVgaDevicePath (Handle
);
624 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
626 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
628 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
629 @retval EFI_STATUS - PCI Device check or Console variable update fail.
633 DetectAndPreparePlatformPciDevicePaths (
634 BOOLEAN DetectVgaOnly
637 mDetectVgaOnly
= DetectVgaOnly
;
638 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
643 PlatformBdsConnectConsole (
644 IN BDS_CONSOLE_CONNECT_ENTRY
*PlatformConsole
650 Connect the predefined platform default console device. Always try to find
651 and enable the vga device if have.
655 PlatformConsole - Predfined platform default console device array.
659 EFI_SUCCESS - Success connect at least one ConIn and ConOut
660 device, there must have one ConOut device is
663 EFI_STATUS - Return the status of
664 BdsLibConnectAllDefaultConsoles ()
670 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
671 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
672 UINTN DevicePathSize
;
675 // Connect RootBridge
677 VarConout
= BdsLibGetVariableAndSize (
679 &gEfiGlobalVariableGuid
,
682 VarConin
= BdsLibGetVariableAndSize (
684 &gEfiGlobalVariableGuid
,
688 if (VarConout
== NULL
|| VarConin
== NULL
) {
690 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
692 DetectAndPreparePlatformPciDevicePaths (FALSE
);
695 // Have chance to connect the platform default console,
696 // the platform default console is the minimue device group
697 // the platform should support
699 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
701 // Update the console variable with the connect type
703 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
704 BdsLibUpdateConsoleVariable (VarConsoleInp
, PlatformConsole
[Index
].DevicePath
, NULL
);
706 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
707 BdsLibUpdateConsoleVariable (VarConsoleOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
709 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
710 BdsLibUpdateConsoleVariable (VarErrorOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
715 // Only detect VGA device and add them to ConOut
717 DetectAndPreparePlatformPciDevicePaths (TRUE
);
721 // Connect the all the default console with current cosole variable
723 Status
= BdsLibConnectAllDefaultConsoles ();
724 if (EFI_ERROR (Status
)) {
733 Configure PCI Interrupt Line register for applicable devices
734 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
736 @param[in] Handle - Handle of PCI device instance
737 @param[in] PciIo - PCI IO protocol instance
738 @param[in] PciHdr - PCI Header register block
740 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
746 IN EFI_HANDLE Handle
,
747 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
748 IN PCI_TYPE00
*PciHdr
751 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
752 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
758 Status
= EFI_SUCCESS
;
760 if (PciHdr
->Device
.InterruptPin
!= 0) {
762 DevPathNode
= DevicePathFromHandle (Handle
);
763 ASSERT (DevPathNode
!= NULL
);
764 DevPath
= DevPathNode
;
767 // Compute index into PciHostIrqs[] table by walking
768 // the device path and adding up all device numbers
770 Status
= EFI_NOT_FOUND
;
772 Idx
= PciHdr
->Device
.InterruptPin
- 1;
773 while (!IsDevicePathEnd (DevPathNode
)) {
774 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
775 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
777 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
780 // Unlike SeaBIOS, which starts climbing from the leaf device
781 // up toward the root, we traverse the device path starting at
782 // the root moving toward the leaf node.
783 // The slot number of the top-level parent bridge is needed for
784 // Q35 cases with more than 24 slots on the root bus.
786 if (Status
!= EFI_SUCCESS
) {
787 Status
= EFI_SUCCESS
;
788 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
792 DevPathNode
= NextDevicePathNode (DevPathNode
);
794 if (EFI_ERROR (Status
)) {
800 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
807 // Final PciHostIrqs[] index calculation depends on the platform
808 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
810 switch (mHostBridgeDevId
) {
811 case INTEL_82441_DEVICE_ID
:
814 case INTEL_Q35_MCH_DEVICE_ID
:
816 // SeaBIOS contains the following comment:
817 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
818 // with a different starting index - see q35-acpi-dsdt.dsl.
820 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
824 // in this case, subtract back out RootSlot from Idx
825 // (SeaBIOS never adds it to begin with, but that would make our
826 // device path traversal loop above too awkward)
832 ASSERT (FALSE
); // should never get here
834 Idx
%= ARRAY_SIZE (PciHostIrqs
);
835 IrqLine
= PciHostIrqs
[Idx
];
839 CHAR16
*DevPathString
;
840 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
841 UINTN Segment
, Bus
, Device
, Function
;
843 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
844 if (DevPathString
== NULL
) {
845 DevPathString
= Fallback
;
847 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
848 ASSERT_EFI_ERROR (Status
);
850 DEBUG ((EFI_D_VERBOSE
, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__
,
851 (UINT32
)Bus
, (UINT32
)Device
, (UINT32
)Function
, DevPathString
,
854 if (DevPathString
!= Fallback
) {
855 FreePool (DevPathString
);
861 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
863 Status
= PciIo
->Pci
.Write (
877 PciAcpiInitialization (
883 // Query Host Bridge DID to determine platform type
885 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
886 switch (mHostBridgeDevId
) {
887 case INTEL_82441_DEVICE_ID
:
888 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
890 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
892 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
893 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
894 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
895 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
897 case INTEL_Q35_MCH_DEVICE_ID
:
898 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
900 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
902 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
903 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
904 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
905 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
906 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
907 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
908 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
909 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
912 DEBUG ((EFI_D_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
913 __FUNCTION__
, mHostBridgeDevId
));
919 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
921 VisitAllPciInstances (SetPciIntLine
);
924 // Set ACPI SCI_EN bit in PMCNTRL
926 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
932 ConnectRecursivelyIfPciMassStorage (
933 IN EFI_HANDLE Handle
,
934 IN EFI_PCI_IO_PROTOCOL
*Instance
,
935 IN PCI_TYPE00
*PciHeader
939 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
942 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
)) {
944 Status
= gBS
->HandleProtocol (
946 &gEfiDevicePathProtocolGuid
,
949 if (EFI_ERROR (Status
)) {
956 DevPathStr
= DevicePathToStr (DevicePath
);
957 if (DevPathStr
!= NULL
) {
960 "Found Mass Storage device: %s\n",
963 FreePool(DevPathStr
);
966 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
967 if (EFI_ERROR (Status
)) {
978 This notification function is invoked when the
979 EMU Variable FVB has been changed.
981 @param Event The event that occured
982 @param Context For EFI compatiblity. Not used.
987 EmuVariablesUpdatedCallback (
992 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
993 UpdateNvVarsOnFileSystem ();
999 VisitingFileSystemInstance (
1000 IN EFI_HANDLE Handle
,
1006 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
1008 if (ConnectedToFileSystem
) {
1009 return EFI_ALREADY_STARTED
;
1012 Status
= ConnectNvVarsToFileSystem (Handle
);
1013 if (EFI_ERROR (Status
)) {
1017 ConnectedToFileSystem
= TRUE
;
1019 EfiCreateProtocolNotifyEvent (
1020 &gEfiDevicePathProtocolGuid
,
1022 EmuVariablesUpdatedCallback
,
1024 &mEmuVariableEventReg
1026 PcdSet64 (PcdEmuVariableEvent
, (UINT64
)(UINTN
) mEmuVariableEvent
);
1033 PlatformBdsRestoreNvVarsFromHardDisk (
1036 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1037 VisitAllInstancesOfProtocol (
1038 &gEfiSimpleFileSystemProtocolGuid
,
1039 VisitingFileSystemInstance
,
1047 PlatformBdsConnectSequence (
1052 Routine Description:
1054 Connect with predeined platform connect sequence,
1055 the OEM/IBV can customize with their own connect sequence.
1069 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
1074 // Here we can get the customized platform connect sequence
1075 // Notes: we can connect with new variable which record the
1076 // last time boots connect device path sequence
1078 while (gPlatformConnectSequence
[Index
] != NULL
) {
1080 // Build the platform boot option
1082 BdsLibConnectDevicePath (gPlatformConnectSequence
[Index
]);
1087 // Just use the simple policy to connect all devices
1089 BdsLibConnectAll ();
1091 PciAcpiInitialization ();
1094 // Clear the logo after all devices are connected.
1096 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1100 PlatformBdsGetDriverOption (
1101 IN OUT LIST_ENTRY
*BdsDriverLists
1105 Routine Description:
1107 Load the predefined driver option, OEM/IBV can customize this
1108 to load their own drivers
1112 BdsDriverLists - The header of the driver option link list.
1120 DEBUG ((EFI_D_INFO
, "PlatformBdsGetDriverOption\n"));
1125 PlatformBdsDiagnostics (
1126 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel
,
1127 IN BOOLEAN QuietBoot
,
1128 IN BASEM_MEMORY_TEST BaseMemoryTest
1132 Routine Description:
1134 Perform the platform diagnostic, such like test memory. OEM/IBV also
1135 can customize this fuction to support specific platform diagnostic.
1139 MemoryTestLevel - The memory test intensive level
1141 QuietBoot - Indicate if need to enable the quiet boot
1143 BaseMemoryTest - A pointer to BaseMemoryTest()
1153 DEBUG ((EFI_D_INFO
, "PlatformBdsDiagnostics\n"));
1156 // Here we can decide if we need to show
1157 // the diagnostics screen
1158 // Notes: this quiet boot code should be remove
1159 // from the graphic lib
1162 EnableQuietBoot (PcdGetPtr(PcdLogoFile
));
1164 // Perform system diagnostic
1166 Status
= BaseMemoryTest (MemoryTestLevel
);
1167 if (EFI_ERROR (Status
)) {
1168 DisableQuietBoot ();
1174 // Perform system diagnostic
1176 Status
= BaseMemoryTest (MemoryTestLevel
);
1182 PlatformBdsPolicyBehavior (
1183 IN OUT LIST_ENTRY
*DriverOptionList
,
1184 IN OUT LIST_ENTRY
*BootOptionList
,
1185 IN PROCESS_CAPSULES ProcessCapsules
,
1186 IN BASEM_MEMORY_TEST BaseMemoryTest
1190 Routine Description:
1192 The function will excute with as the platform policy, current policy
1193 is driven by boot mode. IBV/OEM can customize this code for their specific
1198 DriverOptionList - The header of the driver option link list
1200 BootOptionList - The header of the boot option link list
1202 ProcessCapsules - A pointer to ProcessCapsules()
1204 BaseMemoryTest - A pointer to BaseMemoryTest()
1213 EFI_BOOT_MODE BootMode
;
1215 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior\n"));
1217 ConnectRootBridge ();
1219 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1220 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior: not restoring NvVars "
1221 "from disk since flash variables appear to be supported.\n"));
1224 // Try to restore variables from the hard disk early so
1225 // they can be used for the other BDS connect operations.
1227 PlatformBdsRestoreNvVarsFromHardDisk ();
1231 // Load the driver option as the driver option list
1233 PlatformBdsGetDriverOption (DriverOptionList
);
1236 // Get current Boot Mode
1238 Status
= BdsLibGetBootMode (&BootMode
);
1239 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1242 // Go the different platform policy with different boot mode
1243 // Notes: this part code can be change with the table policy
1245 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1247 // Connect platform console
1249 Status
= PlatformBdsConnectConsole (gPlatformConsole
);
1250 if (EFI_ERROR (Status
)) {
1252 // Here OEM/IBV can customize with defined action
1254 PlatformBdsNoConsoleAction ();
1258 // Memory test and Logo show
1260 PlatformBdsDiagnostics (IGNORE
, TRUE
, BaseMemoryTest
);
1263 // Perform some platform specific connect sequence
1265 PlatformBdsConnectSequence ();
1268 // Process QEMU's -kernel command line option
1270 TryRunningQemuKernel ();
1272 DEBUG ((EFI_D_INFO
, "BdsLibConnectAll\n"));
1273 BdsLibConnectAll ();
1274 BdsLibEnumerateAllBootOption (BootOptionList
);
1276 SetBootOrderFromQemu (BootOptionList
);
1278 // The BootOrder variable may have changed, reload the in-memory list with
1281 BdsLibBuildOptionFromVar (BootOptionList
, L
"BootOrder");
1283 PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE
);
1288 PlatformBdsBootSuccess (
1289 IN BDS_COMMON_OPTION
*Option
1293 Routine Description:
1295 Hook point after a boot attempt succeeds. We don't expect a boot option to
1296 return, so the EFI 1.0 specification defines that you will default to an
1297 interactive mode and stop processing the BootOrder list in this case. This
1298 is alos a platform implementation and can be customized by IBV/OEM.
1302 Option - Pointer to Boot Option that succeeded to boot.
1312 DEBUG ((EFI_D_INFO
, "PlatformBdsBootSuccess\n"));
1314 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1315 // select loop then we need to pop up a UI and wait for user input.
1317 TmpStr
= Option
->StatusString
;
1318 if (TmpStr
!= NULL
) {
1319 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1326 PlatformBdsBootFail (
1327 IN BDS_COMMON_OPTION
*Option
,
1328 IN EFI_STATUS Status
,
1329 IN CHAR16
*ExitData
,
1330 IN UINTN ExitDataSize
1334 Routine Description:
1336 Hook point after a boot attempt fails.
1340 Option - Pointer to Boot Option that failed to boot.
1342 Status - Status returned from failed boot.
1344 ExitData - Exit data returned from failed boot.
1346 ExitDataSize - Exit data size returned from failed boot.
1356 DEBUG ((EFI_D_INFO
, "PlatformBdsBootFail\n"));
1359 // If Boot returned with failed status then we need to pop up a UI and wait
1362 TmpStr
= Option
->StatusString
;
1363 if (TmpStr
!= NULL
) {
1364 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1370 PlatformBdsNoConsoleAction (
1375 Routine Description:
1377 This function is remained for IBV/OEM to do some platform action,
1378 if there no console device can be connected.
1386 EFI_SUCCESS - Direct return success now.
1390 DEBUG ((EFI_D_INFO
, "PlatformBdsNoConsoleAction\n"));
1396 PlatformBdsLockNonUpdatableFlash (
1400 DEBUG ((EFI_D_INFO
, "PlatformBdsLockNonUpdatableFlash\n"));
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 Lock the ConsoleIn device in system table. All key
1507 presses will be ignored until the Password is typed in. The only way to
1508 disable the password is to type it in to a ConIn device.
1510 @param Password Password used to lock ConIn device.
1512 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1513 @retval EFI_UNSUPPORTED Password not found
1522 return EFI_UNSUPPORTED
;