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
;
757 Status
= EFI_SUCCESS
;
759 if (PciHdr
->Device
.InterruptPin
!= 0) {
761 DevPathNode
= DevicePathFromHandle (Handle
);
762 ASSERT (DevPathNode
!= NULL
);
765 // Compute index into PciHostIrqs[] table by walking
766 // the device path and adding up all device numbers
768 Status
= EFI_NOT_FOUND
;
770 Idx
= PciHdr
->Device
.InterruptPin
- 1;
771 while (!IsDevicePathEnd (DevPathNode
)) {
772 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
773 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
775 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
778 // Unlike SeaBIOS, which starts climbing from the leaf device
779 // up toward the root, we traverse the device path starting at
780 // the root moving toward the leaf node.
781 // The slot number of the top-level parent bridge is needed for
782 // Q35 cases with more than 24 slots on the root bus.
784 if (Status
!= EFI_SUCCESS
) {
785 Status
= EFI_SUCCESS
;
786 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
790 DevPathNode
= NextDevicePathNode (DevPathNode
);
792 if (EFI_ERROR (Status
)) {
798 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
805 // Final PciHostIrqs[] index calculation depends on the platform
806 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
808 switch (mHostBridgeDevId
) {
809 case INTEL_82441_DEVICE_ID
:
812 case INTEL_Q35_MCH_DEVICE_ID
:
814 // SeaBIOS contains the following comment:
815 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
816 // with a different starting index - see q35-acpi-dsdt.dsl.
818 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
822 // in this case, subtract back out RootSlot from Idx
823 // (SeaBIOS never adds it to begin with, but that would make our
824 // device path traversal loop above too awkward)
830 ASSERT (FALSE
); // should never get here
832 Idx
%= ARRAY_SIZE (PciHostIrqs
);
833 IrqLine
= PciHostIrqs
[Idx
];
836 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
838 Status
= PciIo
->Pci
.Write (
852 PciAcpiInitialization (
858 // Query Host Bridge DID to determine platform type
860 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
861 switch (mHostBridgeDevId
) {
862 case INTEL_82441_DEVICE_ID
:
863 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
865 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
867 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
868 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
869 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
870 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
872 case INTEL_Q35_MCH_DEVICE_ID
:
873 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
875 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
877 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
878 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
879 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
880 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
881 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
882 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
883 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
884 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
887 DEBUG ((EFI_D_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
888 __FUNCTION__
, mHostBridgeDevId
));
894 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
896 VisitAllPciInstances (SetPciIntLine
);
899 // Set ACPI SCI_EN bit in PMCNTRL
901 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
907 ConnectRecursivelyIfPciMassStorage (
908 IN EFI_HANDLE Handle
,
909 IN EFI_PCI_IO_PROTOCOL
*Instance
,
910 IN PCI_TYPE00
*PciHeader
914 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
917 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
)) {
919 Status
= gBS
->HandleProtocol (
921 &gEfiDevicePathProtocolGuid
,
924 if (EFI_ERROR (Status
)) {
931 DevPathStr
= DevicePathToStr (DevicePath
);
932 if (DevPathStr
!= NULL
) {
935 "Found Mass Storage device: %s\n",
938 FreePool(DevPathStr
);
941 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
942 if (EFI_ERROR (Status
)) {
953 This notification function is invoked when the
954 EMU Variable FVB has been changed.
956 @param Event The event that occured
957 @param Context For EFI compatiblity. Not used.
962 EmuVariablesUpdatedCallback (
967 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
968 UpdateNvVarsOnFileSystem ();
974 VisitingFileSystemInstance (
975 IN EFI_HANDLE Handle
,
981 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
983 if (ConnectedToFileSystem
) {
984 return EFI_ALREADY_STARTED
;
987 Status
= ConnectNvVarsToFileSystem (Handle
);
988 if (EFI_ERROR (Status
)) {
992 ConnectedToFileSystem
= TRUE
;
994 EfiCreateProtocolNotifyEvent (
995 &gEfiDevicePathProtocolGuid
,
997 EmuVariablesUpdatedCallback
,
999 &mEmuVariableEventReg
1001 PcdSet64 (PcdEmuVariableEvent
, (UINT64
)(UINTN
) mEmuVariableEvent
);
1008 PlatformBdsRestoreNvVarsFromHardDisk (
1011 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1012 VisitAllInstancesOfProtocol (
1013 &gEfiSimpleFileSystemProtocolGuid
,
1014 VisitingFileSystemInstance
,
1022 PlatformBdsConnectSequence (
1027 Routine Description:
1029 Connect with predeined platform connect sequence,
1030 the OEM/IBV can customize with their own connect sequence.
1044 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
1049 // Here we can get the customized platform connect sequence
1050 // Notes: we can connect with new variable which record the
1051 // last time boots connect device path sequence
1053 while (gPlatformConnectSequence
[Index
] != NULL
) {
1055 // Build the platform boot option
1057 BdsLibConnectDevicePath (gPlatformConnectSequence
[Index
]);
1062 // Just use the simple policy to connect all devices
1064 BdsLibConnectAll ();
1066 PciAcpiInitialization ();
1069 // Clear the logo after all devices are connected.
1071 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1075 PlatformBdsGetDriverOption (
1076 IN OUT LIST_ENTRY
*BdsDriverLists
1080 Routine Description:
1082 Load the predefined driver option, OEM/IBV can customize this
1083 to load their own drivers
1087 BdsDriverLists - The header of the driver option link list.
1095 DEBUG ((EFI_D_INFO
, "PlatformBdsGetDriverOption\n"));
1100 PlatformBdsDiagnostics (
1101 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel
,
1102 IN BOOLEAN QuietBoot
,
1103 IN BASEM_MEMORY_TEST BaseMemoryTest
1107 Routine Description:
1109 Perform the platform diagnostic, such like test memory. OEM/IBV also
1110 can customize this fuction to support specific platform diagnostic.
1114 MemoryTestLevel - The memory test intensive level
1116 QuietBoot - Indicate if need to enable the quiet boot
1118 BaseMemoryTest - A pointer to BaseMemoryTest()
1128 DEBUG ((EFI_D_INFO
, "PlatformBdsDiagnostics\n"));
1131 // Here we can decide if we need to show
1132 // the diagnostics screen
1133 // Notes: this quiet boot code should be remove
1134 // from the graphic lib
1137 EnableQuietBoot (PcdGetPtr(PcdLogoFile
));
1139 // Perform system diagnostic
1141 Status
= BaseMemoryTest (MemoryTestLevel
);
1142 if (EFI_ERROR (Status
)) {
1143 DisableQuietBoot ();
1149 // Perform system diagnostic
1151 Status
= BaseMemoryTest (MemoryTestLevel
);
1157 PlatformBdsPolicyBehavior (
1158 IN OUT LIST_ENTRY
*DriverOptionList
,
1159 IN OUT LIST_ENTRY
*BootOptionList
,
1160 IN PROCESS_CAPSULES ProcessCapsules
,
1161 IN BASEM_MEMORY_TEST BaseMemoryTest
1165 Routine Description:
1167 The function will excute with as the platform policy, current policy
1168 is driven by boot mode. IBV/OEM can customize this code for their specific
1173 DriverOptionList - The header of the driver option link list
1175 BootOptionList - The header of the boot option link list
1177 ProcessCapsules - A pointer to ProcessCapsules()
1179 BaseMemoryTest - A pointer to BaseMemoryTest()
1188 EFI_BOOT_MODE BootMode
;
1190 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior\n"));
1192 ConnectRootBridge ();
1194 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1195 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior: not restoring NvVars "
1196 "from disk since flash variables appear to be supported.\n"));
1199 // Try to restore variables from the hard disk early so
1200 // they can be used for the other BDS connect operations.
1202 PlatformBdsRestoreNvVarsFromHardDisk ();
1206 // Load the driver option as the driver option list
1208 PlatformBdsGetDriverOption (DriverOptionList
);
1211 // Get current Boot Mode
1213 Status
= BdsLibGetBootMode (&BootMode
);
1214 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1217 // Go the different platform policy with different boot mode
1218 // Notes: this part code can be change with the table policy
1220 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1222 // Connect platform console
1224 Status
= PlatformBdsConnectConsole (gPlatformConsole
);
1225 if (EFI_ERROR (Status
)) {
1227 // Here OEM/IBV can customize with defined action
1229 PlatformBdsNoConsoleAction ();
1233 // Memory test and Logo show
1235 PlatformBdsDiagnostics (IGNORE
, TRUE
, BaseMemoryTest
);
1238 // Perform some platform specific connect sequence
1240 PlatformBdsConnectSequence ();
1243 // Process QEMU's -kernel command line option
1245 TryRunningQemuKernel ();
1247 DEBUG ((EFI_D_INFO
, "BdsLibConnectAll\n"));
1248 BdsLibConnectAll ();
1249 BdsLibEnumerateAllBootOption (BootOptionList
);
1251 SetBootOrderFromQemu (BootOptionList
);
1253 // The BootOrder variable may have changed, reload the in-memory list with
1256 BdsLibBuildOptionFromVar (BootOptionList
, L
"BootOrder");
1258 PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE
);
1263 PlatformBdsBootSuccess (
1264 IN BDS_COMMON_OPTION
*Option
1268 Routine Description:
1270 Hook point after a boot attempt succeeds. We don't expect a boot option to
1271 return, so the EFI 1.0 specification defines that you will default to an
1272 interactive mode and stop processing the BootOrder list in this case. This
1273 is alos a platform implementation and can be customized by IBV/OEM.
1277 Option - Pointer to Boot Option that succeeded to boot.
1287 DEBUG ((EFI_D_INFO
, "PlatformBdsBootSuccess\n"));
1289 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1290 // select loop then we need to pop up a UI and wait for user input.
1292 TmpStr
= Option
->StatusString
;
1293 if (TmpStr
!= NULL
) {
1294 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1301 PlatformBdsBootFail (
1302 IN BDS_COMMON_OPTION
*Option
,
1303 IN EFI_STATUS Status
,
1304 IN CHAR16
*ExitData
,
1305 IN UINTN ExitDataSize
1309 Routine Description:
1311 Hook point after a boot attempt fails.
1315 Option - Pointer to Boot Option that failed to boot.
1317 Status - Status returned from failed boot.
1319 ExitData - Exit data returned from failed boot.
1321 ExitDataSize - Exit data size returned from failed boot.
1331 DEBUG ((EFI_D_INFO
, "PlatformBdsBootFail\n"));
1334 // If Boot returned with failed status then we need to pop up a UI and wait
1337 TmpStr
= Option
->StatusString
;
1338 if (TmpStr
!= NULL
) {
1339 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1345 PlatformBdsNoConsoleAction (
1350 Routine Description:
1352 This function is remained for IBV/OEM to do some platform action,
1353 if there no console device can be connected.
1361 EFI_SUCCESS - Direct return success now.
1365 DEBUG ((EFI_D_INFO
, "PlatformBdsNoConsoleAction\n"));
1371 PlatformBdsLockNonUpdatableFlash (
1375 DEBUG ((EFI_D_INFO
, "PlatformBdsLockNonUpdatableFlash\n"));
1381 This notification function is invoked when an instance of the
1382 EFI_DEVICE_PATH_PROTOCOL is produced.
1384 @param Event The event that occured
1385 @param Context For EFI compatiblity. Not used.
1398 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1399 ATAPI_DEVICE_PATH
*Atapi
;
1402 // Examine all new handles
1406 // Get the next handle
1408 BufferSize
= sizeof (Handle
);
1409 Status
= gBS
->LocateHandle (
1412 mEfiDevPathNotifyReg
,
1418 // If not found, we're done
1420 if (EFI_NOT_FOUND
== Status
) {
1424 if (EFI_ERROR (Status
)) {
1429 // Get the DevicePath protocol on that handle
1431 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevPathNode
);
1432 ASSERT_EFI_ERROR (Status
);
1434 while (!IsDevicePathEnd (DevPathNode
)) {
1436 // Find the handler to dump this device path node
1439 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1440 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1442 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1448 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1455 // Next device path node
1457 DevPathNode
= NextDevicePathNode (DevPathNode
);
1466 InstallDevicePathCallback (
1470 DEBUG ((EFI_D_INFO
, "Registered NotifyDevPath Event\n"));
1471 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1472 &gEfiDevicePathProtocolGuid
,
1476 &mEfiDevPathNotifyReg
1481 Lock the ConsoleIn device in system table. All key
1482 presses will be ignored until the Password is typed in. The only way to
1483 disable the password is to type it in to a ConIn device.
1485 @param Password Password used to lock ConIn device.
1487 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1488 @retval EFI_UNSUPPORTED Password not found
1497 return EFI_UNSUPPORTED
;