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/XenInfo.h>
17 #include <Guid/RootBridgesConnectedEventGroup.h>
18 #include <Protocol/FirmwareVolume2.h>
25 VOID
*mEfiDevPathNotifyReg
;
26 EFI_EVENT mEfiDevPathEvent
;
27 VOID
*mEmuVariableEventReg
;
28 EFI_EVENT mEmuVariableEvent
;
29 BOOLEAN mDetectVgaOnly
;
30 UINT16 mHostBridgeDevId
;
33 // Table of host IRQs matching PCI IRQs A-D
34 // (for configuring PCI Interrupt Line register)
36 CONST UINT8 PciHostIrqs
[] = {
37 0x0a, 0x0a, 0x0b, 0x0b
46 (EFIAPI
*PROTOCOL_INSTANCE_CALLBACK
)(
53 @param[in] Handle - Handle of PCI device instance
54 @param[in] PciIo - PCI IO protocol instance
55 @param[in] Pci - PCI Header register block
59 (EFIAPI
*VISIT_PCI_INSTANCE_CALLBACK
)(
61 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
67 // Function prototypes
71 VisitAllInstancesOfProtocol (
73 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
78 VisitAllPciInstancesOfProtocol (
79 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
83 InstallDevicePathCallback (
88 PlatformRegisterFvBootOption (
96 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
97 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
98 UINTN BootOptionCount
;
99 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
100 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
101 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
103 Status
= gBS
->HandleProtocol (
105 &gEfiLoadedImageProtocolGuid
,
106 (VOID
**) &LoadedImage
108 ASSERT_EFI_ERROR (Status
);
110 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
111 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
112 ASSERT (DevicePath
!= NULL
);
113 DevicePath
= AppendDevicePathNode (
115 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
117 ASSERT (DevicePath
!= NULL
);
119 Status
= EfiBootManagerInitializeLoadOption (
121 LoadOptionNumberUnassigned
,
129 ASSERT_EFI_ERROR (Status
);
130 FreePool (DevicePath
);
132 BootOptions
= EfiBootManagerGetLoadOptions (
133 &BootOptionCount
, LoadOptionTypeBoot
136 OptionIndex
= EfiBootManagerFindLoadOption (
137 &NewOption
, BootOptions
, BootOptionCount
140 if (OptionIndex
== -1) {
141 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
142 ASSERT_EFI_ERROR (Status
);
144 EfiBootManagerFreeLoadOption (&NewOption
);
145 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
149 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
150 whose device paths do not resolve exactly to an FvFile in the system.
152 This removes any boot options that point to binaries built into the firmware
153 and have become stale due to any of the following:
154 - DXEFV's base address or size changed (historical),
155 - DXEFV's FvNameGuid changed,
156 - the FILE_GUID of the pointed-to binary changed,
157 - the referenced binary is no longer built into the firmware.
159 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
160 avoids exact duplicates.
163 RemoveStaleFvFileOptions (
167 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
168 UINTN BootOptionCount
;
171 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
,
174 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
175 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
180 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
181 // then keep the boot option.
183 Node1
= BootOptions
[Index
].FilePath
;
184 if (!(DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
&&
185 DevicePathSubType (Node1
) == HW_MEMMAP_DP
) &&
186 !(DevicePathType (Node1
) == MEDIA_DEVICE_PATH
&&
187 DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)) {
192 // If the second device path node is not FvFile(...), then keep the boot
195 Node2
= NextDevicePathNode (Node1
);
196 if (DevicePathType (Node2
) != MEDIA_DEVICE_PATH
||
197 DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
) {
202 // Locate the Firmware Volume2 protocol instance that is denoted by the
203 // boot option. If this lookup fails (i.e., the boot option references a
204 // firmware volume that doesn't exist), then we'll proceed to delete the
208 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
,
209 &SearchNode
, &FvHandle
);
211 if (!EFI_ERROR (Status
)) {
213 // The firmware volume was found; now let's see if it contains the FvFile
214 // identified by GUID.
216 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
217 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
219 EFI_FV_FILETYPE FoundType
;
220 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
221 UINT32 AuthenticationStatus
;
223 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiFirmwareVolume2ProtocolGuid
,
224 (VOID
**)&FvProtocol
);
225 ASSERT_EFI_ERROR (Status
);
227 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
229 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
232 Status
= FvProtocol
->ReadFile (
234 &FvFileNode
->FvFileName
, // NameGuid
239 &AuthenticationStatus
241 if (!EFI_ERROR (Status
)) {
243 // The FvFile was found. Keep the boot option.
250 // Delete the boot option.
252 Status
= EfiBootManagerDeleteLoadOptionVariable (
253 BootOptions
[Index
].OptionNumber
, LoadOptionTypeBoot
);
255 CHAR16
*DevicePathString
;
257 DevicePathString
= ConvertDevicePathToText(BootOptions
[Index
].FilePath
,
260 EFI_ERROR (Status
) ? EFI_D_WARN
: EFI_D_VERBOSE
,
261 "%a: removing stale Boot#%04x %s: %r\n",
263 (UINT32
)BootOptions
[Index
].OptionNumber
,
264 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
267 if (DevicePathString
!= NULL
) {
268 FreePool (DevicePathString
);
273 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
277 PlatformRegisterOptionsAndKeys (
285 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
288 // Register ENTER as CONTINUE key
290 Enter
.ScanCode
= SCAN_NULL
;
291 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
292 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
293 ASSERT_EFI_ERROR (Status
);
296 // Map F2 to Boot Manager Menu
298 F2
.ScanCode
= SCAN_F2
;
299 F2
.UnicodeChar
= CHAR_NULL
;
300 Esc
.ScanCode
= SCAN_ESC
;
301 Esc
.UnicodeChar
= CHAR_NULL
;
302 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
303 ASSERT_EFI_ERROR (Status
);
304 Status
= EfiBootManagerAddKeyOptionVariable (
305 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
307 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
308 Status
= EfiBootManagerAddKeyOptionVariable (
309 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
311 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
317 IN EFI_HANDLE RootBridgeHandle
,
329 // BDS Platform Functions
333 PlatformBootManagerBeforeConsole (
340 Platform Bds init. Include the platform firmware vendor, revision
353 RETURN_STATUS PcdStatus
;
355 DEBUG ((EFI_D_INFO
, "PlatformBootManagerBeforeConsole\n"));
356 InstallDevicePathCallback ();
358 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid
,
359 ConnectRootBridge
, NULL
);
362 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
364 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
367 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
368 // the preparation of S3 system information. That logic has a hard dependency
369 // on the presence of the FACS ACPI table. Since our ACPI tables are only
370 // installed after PCI enumeration completes, we must not trigger the S3 save
371 // earlier, hence we can't signal End-of-Dxe earlier.
373 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
375 if (QemuFwCfgS3Enabled ()) {
377 // Save the boot script too. Note that this will require us to emit the
378 // DxeSmmReadyToLock event just below, which in turn locks down SMM.
384 // Prevent further changes to LockBoxes or SMRAM.
387 Status
= gBS
->InstallProtocolInterface (&Handle
,
388 &gEfiDxeSmmReadyToLockProtocolGuid
, EFI_NATIVE_INTERFACE
,
390 ASSERT_EFI_ERROR (Status
);
392 PlatformInitializeConsole (gPlatformConsole
);
393 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
,
394 GetFrontPageTimeoutFromQemu ());
395 ASSERT_RETURN_ERROR (PcdStatus
);
397 PlatformRegisterOptionsAndKeys ();
404 IN EFI_HANDLE RootBridgeHandle
,
412 // Make the PCI bus driver connect the root bridge, non-recursively. This
413 // will produce a number of child handles with PciIo on them.
415 Status
= gBS
->ConnectController (
416 RootBridgeHandle
, // ControllerHandle
417 NULL
, // DriverImageHandle
418 NULL
, // RemainingDevicePath -- produce all
427 PrepareLpcBridgeDevicePath (
428 IN EFI_HANDLE DeviceHandle
434 Add IsaKeyboard to ConIn,
435 add IsaSerial to ConOut, ConIn, ErrOut.
440 DeviceHandle - Handle of PCIIO protocol.
444 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
445 EFI_STATUS - No LPC bridge is added.
450 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
451 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
455 Status
= gBS
->HandleProtocol (
457 &gEfiDevicePathProtocolGuid
,
460 if (EFI_ERROR (Status
)) {
463 TempDevicePath
= DevicePath
;
468 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
470 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
475 DevicePath
= TempDevicePath
;
476 gPnp16550ComPortDeviceNode
.UID
= 0;
478 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
479 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
480 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
485 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
486 if (DevPathStr
!= NULL
) {
489 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
491 gPnp16550ComPortDeviceNode
.UID
+ 1,
494 FreePool(DevPathStr
);
497 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
498 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
499 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
504 DevicePath
= TempDevicePath
;
505 gPnp16550ComPortDeviceNode
.UID
= 1;
507 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
508 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
509 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
514 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
515 if (DevPathStr
!= NULL
) {
518 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
520 gPnp16550ComPortDeviceNode
.UID
+ 1,
523 FreePool(DevPathStr
);
526 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
527 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
528 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
535 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
536 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
541 EFI_HANDLE PciDeviceHandle
;
542 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
543 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
544 UINTN GopHandleCount
;
545 EFI_HANDLE
*GopHandleBuffer
;
547 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
548 return EFI_INVALID_PARAMETER
;
552 // Initialize the GopDevicePath to be PciDevicePath
554 *GopDevicePath
= PciDevicePath
;
555 TempPciDevicePath
= PciDevicePath
;
557 Status
= gBS
->LocateDevicePath (
558 &gEfiDevicePathProtocolGuid
,
562 if (EFI_ERROR (Status
)) {
567 // Try to connect this handle, so that GOP driver could start on this
568 // device and create child handles with GraphicsOutput Protocol installed
569 // on them, then we get device paths of these child handles and select
570 // them as possible console device.
572 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
574 Status
= gBS
->LocateHandleBuffer (
576 &gEfiGraphicsOutputProtocolGuid
,
581 if (!EFI_ERROR (Status
)) {
583 // Add all the child handles as possible Console Device
585 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
586 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
587 if (EFI_ERROR (Status
)) {
593 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
596 // In current implementation, we only enable one of the child handles
597 // as console device, i.e. sotre one of the child handle's device
598 // path to variable "ConOut"
599 // In future, we could select all child handles to be console device
602 *GopDevicePath
= TempDevicePath
;
605 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
606 // Add the integrity GOP device path.
608 EfiBootManagerUpdateConsoleVariable (ConOutDev
, NULL
, PciDevicePath
);
609 EfiBootManagerUpdateConsoleVariable (ConOutDev
, TempDevicePath
, NULL
);
612 gBS
->FreePool (GopHandleBuffer
);
619 PreparePciDisplayDevicePath (
620 IN EFI_HANDLE DeviceHandle
626 Add PCI VGA to ConOut.
631 DeviceHandle - Handle of PCIIO protocol.
635 EFI_SUCCESS - PCI VGA is added to ConOut.
636 EFI_STATUS - No PCI VGA device is added.
641 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
642 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
645 GopDevicePath
= NULL
;
646 Status
= gBS
->HandleProtocol (
648 &gEfiDevicePathProtocolGuid
,
651 if (EFI_ERROR (Status
)) {
655 GetGopDevicePath (DevicePath
, &GopDevicePath
);
656 DevicePath
= GopDevicePath
;
658 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
664 PreparePciSerialDevicePath (
665 IN EFI_HANDLE DeviceHandle
671 Add PCI Serial to ConOut, ConIn, ErrOut.
676 DeviceHandle - Handle of PCIIO protocol.
680 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
681 EFI_STATUS - No PCI Serial device is added.
686 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
689 Status
= gBS
->HandleProtocol (
691 &gEfiDevicePathProtocolGuid
,
694 if (EFI_ERROR (Status
)) {
698 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
699 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
701 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
702 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
703 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
709 VisitAllInstancesOfProtocol (
711 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
717 EFI_HANDLE
*HandleBuffer
;
722 // Start to check all the PciIo to find all possible device
726 Status
= gBS
->LocateHandleBuffer (
733 if (EFI_ERROR (Status
)) {
737 for (Index
= 0; Index
< HandleCount
; Index
++) {
738 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
739 if (EFI_ERROR (Status
)) {
743 Status
= (*CallBackFunction
) (
750 gBS
->FreePool (HandleBuffer
);
758 VisitingAPciInstance (
759 IN EFI_HANDLE Handle
,
765 EFI_PCI_IO_PROTOCOL
*PciIo
;
768 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
771 // Check for all PCI device
773 Status
= PciIo
->Pci
.Read (
777 sizeof (Pci
) / sizeof (UINT32
),
780 if (EFI_ERROR (Status
)) {
784 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
795 VisitAllPciInstances (
796 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
799 return VisitAllInstancesOfProtocol (
800 &gEfiPciIoProtocolGuid
,
801 VisitingAPciInstance
,
802 (VOID
*)(UINTN
) CallBackFunction
808 Do platform specific PCI Device check and add them to
809 ConOut, ConIn, ErrOut.
811 @param[in] Handle - Handle of PCI device instance
812 @param[in] PciIo - PCI IO protocol instance
813 @param[in] Pci - PCI Header register block
815 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
816 @retval EFI_STATUS - PCI Device check or Console variable update fail.
821 DetectAndPreparePlatformPciDevicePath (
822 IN EFI_HANDLE Handle
,
823 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
829 Status
= PciIo
->Attributes (
831 EfiPciIoAttributeOperationEnable
,
832 EFI_PCI_DEVICE_ENABLE
,
835 ASSERT_EFI_ERROR (Status
);
837 if (!mDetectVgaOnly
) {
839 // Here we decide whether it is LPC Bridge
841 if ((IS_PCI_LPC (Pci
)) ||
842 ((IS_PCI_ISA_PDECODE (Pci
)) &&
843 (Pci
->Hdr
.VendorId
== 0x8086) &&
844 (Pci
->Hdr
.DeviceId
== 0x7000)
848 // Add IsaKeyboard to ConIn,
849 // add IsaSerial to ConOut, ConIn, ErrOut
851 DEBUG ((EFI_D_INFO
, "Found LPC Bridge device\n"));
852 PrepareLpcBridgeDevicePath (Handle
);
856 // Here we decide which Serial device to enable in PCI bus
858 if (IS_PCI_16550SERIAL (Pci
)) {
860 // Add them to ConOut, ConIn, ErrOut.
862 DEBUG ((EFI_D_INFO
, "Found PCI 16550 SERIAL device\n"));
863 PreparePciSerialDevicePath (Handle
);
869 // Here we decide which display device to enable in PCI bus
871 if (IS_PCI_DISPLAY (Pci
)) {
873 // Add them to ConOut.
875 DEBUG ((EFI_D_INFO
, "Found PCI display device\n"));
876 PreparePciDisplayDevicePath (Handle
);
885 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
887 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
889 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
890 @retval EFI_STATUS - PCI Device check or Console variable update fail.
894 DetectAndPreparePlatformPciDevicePaths (
895 BOOLEAN DetectVgaOnly
898 mDetectVgaOnly
= DetectVgaOnly
;
899 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
904 PlatformInitializeConsole (
905 IN PLATFORM_CONSOLE_CONNECT_ENTRY
*PlatformConsole
911 Connect the predefined platform default console device. Always try to find
912 and enable the vga device if have.
916 PlatformConsole - Predefined platform default console device array.
920 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
921 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
924 // Connect RootBridge
926 GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME
, (VOID
**) &VarConout
, NULL
);
927 GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME
, (VOID
**) &VarConin
, NULL
);
929 if (VarConout
== NULL
|| VarConin
== NULL
) {
931 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
933 DetectAndPreparePlatformPciDevicePaths (FALSE
);
936 // Have chance to connect the platform default console,
937 // the platform default console is the minimum device group
938 // the platform should support
940 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
942 // Update the console variable with the connect type
944 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
945 EfiBootManagerUpdateConsoleVariable (ConIn
, PlatformConsole
[Index
].DevicePath
, NULL
);
947 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
948 EfiBootManagerUpdateConsoleVariable (ConOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
950 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
951 EfiBootManagerUpdateConsoleVariable (ErrOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
956 // Only detect VGA device and add them to ConOut
958 DetectAndPreparePlatformPciDevicePaths (TRUE
);
964 Configure PCI Interrupt Line register for applicable devices
965 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
967 @param[in] Handle - Handle of PCI device instance
968 @param[in] PciIo - PCI IO protocol instance
969 @param[in] PciHdr - PCI Header register block
971 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
977 IN EFI_HANDLE Handle
,
978 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
979 IN PCI_TYPE00
*PciHdr
982 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
983 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
988 UINT32 RootBusNumber
;
990 Status
= EFI_SUCCESS
;
992 if (PciHdr
->Device
.InterruptPin
!= 0) {
994 DevPathNode
= DevicePathFromHandle (Handle
);
995 ASSERT (DevPathNode
!= NULL
);
996 DevPath
= DevPathNode
;
999 if (DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
&&
1000 DevicePathSubType (DevPathNode
) == ACPI_DP
&&
1001 ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID(0x0A03)) {
1002 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
1006 // Compute index into PciHostIrqs[] table by walking
1007 // the device path and adding up all device numbers
1009 Status
= EFI_NOT_FOUND
;
1011 Idx
= PciHdr
->Device
.InterruptPin
- 1;
1012 while (!IsDevicePathEnd (DevPathNode
)) {
1013 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
1014 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
1016 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1019 // Unlike SeaBIOS, which starts climbing from the leaf device
1020 // up toward the root, we traverse the device path starting at
1021 // the root moving toward the leaf node.
1022 // The slot number of the top-level parent bridge is needed for
1023 // Q35 cases with more than 24 slots on the root bus.
1025 if (Status
!= EFI_SUCCESS
) {
1026 Status
= EFI_SUCCESS
;
1027 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1031 DevPathNode
= NextDevicePathNode (DevPathNode
);
1033 if (EFI_ERROR (Status
)) {
1036 if (RootBusNumber
== 0 && RootSlot
== 0) {
1039 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
1046 // Final PciHostIrqs[] index calculation depends on the platform
1047 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
1049 switch (mHostBridgeDevId
) {
1050 case INTEL_82441_DEVICE_ID
:
1053 case INTEL_Q35_MCH_DEVICE_ID
:
1055 // SeaBIOS contains the following comment:
1056 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
1057 // with a different starting index - see q35-acpi-dsdt.dsl.
1059 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
1061 if (RootSlot
> 24) {
1063 // in this case, subtract back out RootSlot from Idx
1064 // (SeaBIOS never adds it to begin with, but that would make our
1065 // device path traversal loop above too awkward)
1071 ASSERT (FALSE
); // should never get here
1073 Idx
%= ARRAY_SIZE (PciHostIrqs
);
1074 IrqLine
= PciHostIrqs
[Idx
];
1076 DEBUG_CODE_BEGIN ();
1078 CHAR16
*DevPathString
;
1079 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
1080 UINTN Segment
, Bus
, Device
, Function
;
1082 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
1083 if (DevPathString
== NULL
) {
1084 DevPathString
= Fallback
;
1086 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
1087 ASSERT_EFI_ERROR (Status
);
1089 DEBUG ((EFI_D_VERBOSE
, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__
,
1090 (UINT32
)Bus
, (UINT32
)Device
, (UINT32
)Function
, DevPathString
,
1093 if (DevPathString
!= Fallback
) {
1094 FreePool (DevPathString
);
1100 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
1102 Status
= PciIo
->Pci
.Write (
1105 PCI_INT_LINE_OFFSET
,
1116 PciAcpiInitialization (
1122 // Query Host Bridge DID to determine platform type
1124 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
1125 switch (mHostBridgeDevId
) {
1126 case INTEL_82441_DEVICE_ID
:
1127 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
1129 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
1131 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
1132 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
1133 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
1134 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
1136 case INTEL_Q35_MCH_DEVICE_ID
:
1137 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
1139 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
1141 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
1142 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
1143 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
1144 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
1145 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
1146 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
1147 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
1148 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
1151 DEBUG ((EFI_D_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
1152 __FUNCTION__
, mHostBridgeDevId
));
1158 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
1160 VisitAllPciInstances (SetPciIntLine
);
1163 // Set ACPI SCI_EN bit in PMCNTRL
1165 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
1169 This function detects if OVMF is running on Xen.
1178 EFI_HOB_GUID_TYPE
*GuidHob
;
1179 STATIC INTN FoundHob
= -1;
1181 if (FoundHob
== 0) {
1183 } else if (FoundHob
== 1) {
1188 // See if a XenInfo HOB is available
1190 GuidHob
= GetFirstGuidHob (&gEfiXenInfoGuid
);
1191 if (GuidHob
== NULL
) {
1202 ConnectRecursivelyIfPciMassStorage (
1203 IN EFI_HANDLE Handle
,
1204 IN EFI_PCI_IO_PROTOCOL
*Instance
,
1205 IN PCI_TYPE00
*PciHeader
1209 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1213 // Recognize PCI Mass Storage, and Xen PCI devices
1215 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
) ||
1216 (XenDetected() && IS_CLASS2 (PciHeader
, 0xFF, 0x80))) {
1218 Status
= gBS
->HandleProtocol (
1220 &gEfiDevicePathProtocolGuid
,
1223 if (EFI_ERROR (Status
)) {
1228 // Print Device Path
1230 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
1231 if (DevPathStr
!= NULL
) {
1234 "Found %s device: %s\n",
1235 IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
) ? L
"Mass Storage" : L
"Xen",
1238 FreePool(DevPathStr
);
1241 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
1242 if (EFI_ERROR (Status
)) {
1253 This notification function is invoked when the
1254 EMU Variable FVB has been changed.
1256 @param Event The event that occurred
1257 @param Context For EFI compatibility. Not used.
1262 EmuVariablesUpdatedCallback (
1267 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
1268 UpdateNvVarsOnFileSystem ();
1274 VisitingFileSystemInstance (
1275 IN EFI_HANDLE Handle
,
1281 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
1282 RETURN_STATUS PcdStatus
;
1284 if (ConnectedToFileSystem
) {
1285 return EFI_ALREADY_STARTED
;
1288 Status
= ConnectNvVarsToFileSystem (Handle
);
1289 if (EFI_ERROR (Status
)) {
1293 ConnectedToFileSystem
= TRUE
;
1295 EfiCreateProtocolNotifyEvent (
1296 &gEfiDevicePathProtocolGuid
,
1298 EmuVariablesUpdatedCallback
,
1300 &mEmuVariableEventReg
1302 PcdStatus
= PcdSet64S (PcdEmuVariableEvent
,
1303 (UINT64
)(UINTN
) mEmuVariableEvent
);
1304 ASSERT_RETURN_ERROR (PcdStatus
);
1311 PlatformBdsRestoreNvVarsFromHardDisk (
1314 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1315 VisitAllInstancesOfProtocol (
1316 &gEfiSimpleFileSystemProtocolGuid
,
1317 VisitingFileSystemInstance
,
1324 PlatformBdsConnectSequence (
1329 Routine Description:
1331 Connect with predefined platform connect sequence,
1332 the OEM/IBV can customize with their own connect sequence.
1346 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
1351 // Here we can get the customized platform connect sequence
1352 // Notes: we can connect with new variable which record the
1353 // last time boots connect device path sequence
1355 while (gPlatformConnectSequence
[Index
] != NULL
) {
1357 // Build the platform boot option
1359 EfiBootManagerConnectDevicePath (gPlatformConnectSequence
[Index
], NULL
);
1364 // Just use the simple policy to connect all devices
1366 DEBUG ((EFI_D_INFO
, "EfiBootManagerConnectAll\n"));
1367 EfiBootManagerConnectAll ();
1369 PciAcpiInitialization ();
1373 Save the S3 boot script.
1375 Note that DxeSmmReadyToLock must be signaled after this function returns;
1376 otherwise the script wouldn't be saved actually.
1385 EFI_S3_SAVE_STATE_PROTOCOL
*BootScript
;
1386 STATIC CONST UINT8 Info
[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1388 Status
= gBS
->LocateProtocol (&gEfiS3SaveStateProtocolGuid
, NULL
,
1389 (VOID
**) &BootScript
);
1390 ASSERT_EFI_ERROR (Status
);
1393 // Despite the opcode documentation in the PI spec, the protocol
1394 // implementation embeds a deep copy of the info in the boot script, rather
1395 // than storing just a pointer to runtime or NVS storage.
1397 Status
= BootScript
->Write(BootScript
, EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
1398 (UINT32
) sizeof Info
,
1399 (EFI_PHYSICAL_ADDRESS
)(UINTN
) &Info
);
1400 ASSERT_EFI_ERROR (Status
);
1406 PlatformBootManagerAfterConsole (
1411 Routine Description:
1413 The function will execute with as the platform policy, current policy
1414 is driven by boot mode. IBV/OEM can customize this code for their specific
1419 EFI_BOOT_MODE BootMode
;
1421 DEBUG ((EFI_D_INFO
, "PlatformBootManagerAfterConsole\n"));
1423 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1424 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior: not restoring NvVars "
1425 "from disk since flash variables appear to be supported.\n"));
1428 // Try to restore variables from the hard disk early so
1429 // they can be used for the other BDS connect operations.
1431 PlatformBdsRestoreNvVarsFromHardDisk ();
1435 // Get current Boot Mode
1437 BootMode
= GetBootModeHob ();
1438 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1441 // Go the different platform policy with different boot mode
1442 // Notes: this part code can be change with the table policy
1444 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1449 BootLogoEnableLogo ();
1452 // Perform some platform specific connect sequence
1454 PlatformBdsConnectSequence ();
1457 // Process QEMU's -kernel command line option
1459 TryRunningQemuKernel ();
1461 EfiBootManagerRefreshAllBootOption ();
1464 // Register UEFI Shell
1466 PlatformRegisterFvBootOption (
1467 PcdGetPtr (PcdShellFile
), L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
1470 RemoveStaleFvFileOptions ();
1471 SetBootOrderFromQemu ();
1475 This notification function is invoked when an instance of the
1476 EFI_DEVICE_PATH_PROTOCOL is produced.
1478 @param Event The event that occurred
1479 @param Context For EFI compatibility. Not used.
1492 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1493 ATAPI_DEVICE_PATH
*Atapi
;
1496 // Examine all new handles
1500 // Get the next handle
1502 BufferSize
= sizeof (Handle
);
1503 Status
= gBS
->LocateHandle (
1506 mEfiDevPathNotifyReg
,
1512 // If not found, we're done
1514 if (EFI_NOT_FOUND
== Status
) {
1518 if (EFI_ERROR (Status
)) {
1523 // Get the DevicePath protocol on that handle
1525 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevPathNode
);
1526 ASSERT_EFI_ERROR (Status
);
1528 while (!IsDevicePathEnd (DevPathNode
)) {
1530 // Find the handler to dump this device path node
1533 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1534 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1536 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1542 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1549 // Next device path node
1551 DevPathNode
= NextDevicePathNode (DevPathNode
);
1560 InstallDevicePathCallback (
1564 DEBUG ((EFI_D_INFO
, "Registered NotifyDevPath Event\n"));
1565 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1566 &gEfiDevicePathProtocolGuid
,
1570 &mEfiDevPathNotifyReg
1575 This function is called each second during the boot manager waits the timeout.
1577 @param TimeoutRemain The remaining timeout.
1581 PlatformBootManagerWaitCallback (
1582 UINT16 TimeoutRemain
1585 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
1586 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
1589 Timeout
= PcdGet16 (PcdPlatformBootTimeOut
);
1591 Black
.Raw
= 0x00000000;
1592 White
.Raw
= 0x00FFFFFF;
1594 BootLogoUpdateProgress (
1597 L
"Start boot option",
1599 (Timeout
- TimeoutRemain
) * 100 / Timeout
,