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
44 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
53 (EFIAPI
*PROTOCOL_INSTANCE_CALLBACK
)(
60 @param[in] Handle - Handle of PCI device instance
61 @param[in] PciIo - PCI IO protocol instance
62 @param[in] Pci - PCI Header register block
66 (EFIAPI
*VISIT_PCI_INSTANCE_CALLBACK
)(
68 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
74 // Function prototypes
78 VisitAllInstancesOfProtocol (
80 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
85 VisitAllPciInstancesOfProtocol (
86 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
90 InstallDevicePathCallback (
95 PlatformRegisterFvBootOption (
103 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
104 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
105 UINTN BootOptionCount
;
106 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
107 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
108 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
110 Status
= gBS
->HandleProtocol (
112 &gEfiLoadedImageProtocolGuid
,
113 (VOID
**) &LoadedImage
115 ASSERT_EFI_ERROR (Status
);
117 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
118 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
119 ASSERT (DevicePath
!= NULL
);
120 DevicePath
= AppendDevicePathNode (
122 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
124 ASSERT (DevicePath
!= NULL
);
126 Status
= EfiBootManagerInitializeLoadOption (
128 LoadOptionNumberUnassigned
,
136 ASSERT_EFI_ERROR (Status
);
137 FreePool (DevicePath
);
139 BootOptions
= EfiBootManagerGetLoadOptions (
140 &BootOptionCount
, LoadOptionTypeBoot
143 OptionIndex
= EfiBootManagerFindLoadOption (
144 &NewOption
, BootOptions
, BootOptionCount
147 if (OptionIndex
== -1) {
148 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
149 ASSERT_EFI_ERROR (Status
);
151 EfiBootManagerFreeLoadOption (&NewOption
);
152 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
156 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
157 whose device paths do not resolve exactly to an FvFile in the system.
159 This removes any boot options that point to binaries built into the firmware
160 and have become stale due to any of the following:
161 - DXEFV's base address or size changed (historical),
162 - DXEFV's FvNameGuid changed,
163 - the FILE_GUID of the pointed-to binary changed,
164 - the referenced binary is no longer built into the firmware.
166 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
167 avoids exact duplicates.
170 RemoveStaleFvFileOptions (
174 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
175 UINTN BootOptionCount
;
178 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
,
181 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
182 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
187 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
188 // then keep the boot option.
190 Node1
= BootOptions
[Index
].FilePath
;
191 if (!(DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
&&
192 DevicePathSubType (Node1
) == HW_MEMMAP_DP
) &&
193 !(DevicePathType (Node1
) == MEDIA_DEVICE_PATH
&&
194 DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)) {
199 // If the second device path node is not FvFile(...), then keep the boot
202 Node2
= NextDevicePathNode (Node1
);
203 if (DevicePathType (Node2
) != MEDIA_DEVICE_PATH
||
204 DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
) {
209 // Locate the Firmware Volume2 protocol instance that is denoted by the
210 // boot option. If this lookup fails (i.e., the boot option references a
211 // firmware volume that doesn't exist), then we'll proceed to delete the
215 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
,
216 &SearchNode
, &FvHandle
);
218 if (!EFI_ERROR (Status
)) {
220 // The firmware volume was found; now let's see if it contains the FvFile
221 // identified by GUID.
223 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
224 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
226 EFI_FV_FILETYPE FoundType
;
227 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
228 UINT32 AuthenticationStatus
;
230 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiFirmwareVolume2ProtocolGuid
,
231 (VOID
**)&FvProtocol
);
232 ASSERT_EFI_ERROR (Status
);
234 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
236 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
239 Status
= FvProtocol
->ReadFile (
241 &FvFileNode
->FvFileName
, // NameGuid
246 &AuthenticationStatus
248 if (!EFI_ERROR (Status
)) {
250 // The FvFile was found. Keep the boot option.
257 // Delete the boot option.
259 Status
= EfiBootManagerDeleteLoadOptionVariable (
260 BootOptions
[Index
].OptionNumber
, LoadOptionTypeBoot
);
262 CHAR16
*DevicePathString
;
264 DevicePathString
= ConvertDevicePathToText(BootOptions
[Index
].FilePath
,
267 EFI_ERROR (Status
) ? EFI_D_WARN
: EFI_D_VERBOSE
,
268 "%a: removing stale Boot#%04x %s: %r\n",
270 (UINT32
)BootOptions
[Index
].OptionNumber
,
271 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
274 if (DevicePathString
!= NULL
) {
275 FreePool (DevicePathString
);
280 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
284 PlatformRegisterOptionsAndKeys (
292 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
295 // Register ENTER as CONTINUE key
297 Enter
.ScanCode
= SCAN_NULL
;
298 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
299 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
300 ASSERT_EFI_ERROR (Status
);
303 // Map F2 to Boot Manager Menu
305 F2
.ScanCode
= SCAN_F2
;
306 F2
.UnicodeChar
= CHAR_NULL
;
307 Esc
.ScanCode
= SCAN_ESC
;
308 Esc
.UnicodeChar
= CHAR_NULL
;
309 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
310 ASSERT_EFI_ERROR (Status
);
311 Status
= EfiBootManagerAddKeyOptionVariable (
312 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
314 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
315 Status
= EfiBootManagerAddKeyOptionVariable (
316 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
318 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
324 IN EFI_HANDLE RootBridgeHandle
,
336 // BDS Platform Functions
340 PlatformBootManagerBeforeConsole (
347 Platform Bds init. Include the platform firmware vendor, revision
360 RETURN_STATUS PcdStatus
;
362 DEBUG ((EFI_D_INFO
, "PlatformBootManagerBeforeConsole\n"));
363 InstallDevicePathCallback ();
365 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid
,
366 ConnectRootBridge
, NULL
);
369 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
371 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
374 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
375 // the preparation of S3 system information. That logic has a hard dependency
376 // on the presence of the FACS ACPI table. Since our ACPI tables are only
377 // installed after PCI enumeration completes, we must not trigger the S3 save
378 // earlier, hence we can't signal End-of-Dxe earlier.
380 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
382 if (QemuFwCfgS3Enabled ()) {
384 // Save the boot script too. Note that this will require us to emit the
385 // DxeSmmReadyToLock event just below, which in turn locks down SMM.
391 // Prevent further changes to LockBoxes or SMRAM.
394 Status
= gBS
->InstallProtocolInterface (&Handle
,
395 &gEfiDxeSmmReadyToLockProtocolGuid
, EFI_NATIVE_INTERFACE
,
397 ASSERT_EFI_ERROR (Status
);
399 PlatformInitializeConsole (gPlatformConsole
);
400 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
,
401 GetFrontPageTimeoutFromQemu ());
402 ASSERT_RETURN_ERROR (PcdStatus
);
404 PlatformRegisterOptionsAndKeys ();
411 IN EFI_HANDLE RootBridgeHandle
,
419 // Make the PCI bus driver connect the root bridge, non-recursively. This
420 // will produce a number of child handles with PciIo on them.
422 Status
= gBS
->ConnectController (
423 RootBridgeHandle
, // ControllerHandle
424 NULL
, // DriverImageHandle
425 NULL
, // RemainingDevicePath -- produce all
434 PrepareLpcBridgeDevicePath (
435 IN EFI_HANDLE DeviceHandle
441 Add IsaKeyboard to ConIn,
442 add IsaSerial to ConOut, ConIn, ErrOut.
447 DeviceHandle - Handle of PCIIO protocol.
451 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
452 EFI_STATUS - No LPC bridge is added.
457 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
458 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
462 Status
= gBS
->HandleProtocol (
464 &gEfiDevicePathProtocolGuid
,
467 if (EFI_ERROR (Status
)) {
470 TempDevicePath
= DevicePath
;
475 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
477 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
482 DevicePath
= TempDevicePath
;
483 gPnp16550ComPortDeviceNode
.UID
= 0;
485 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
486 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
487 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
492 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
493 if (DevPathStr
!= NULL
) {
496 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
498 gPnp16550ComPortDeviceNode
.UID
+ 1,
501 FreePool(DevPathStr
);
504 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
505 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
506 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
511 DevicePath
= TempDevicePath
;
512 gPnp16550ComPortDeviceNode
.UID
= 1;
514 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
515 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
516 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
521 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
522 if (DevPathStr
!= NULL
) {
525 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
527 gPnp16550ComPortDeviceNode
.UID
+ 1,
530 FreePool(DevPathStr
);
533 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
534 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
535 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
542 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
543 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
548 EFI_HANDLE PciDeviceHandle
;
549 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
550 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
551 UINTN GopHandleCount
;
552 EFI_HANDLE
*GopHandleBuffer
;
554 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
555 return EFI_INVALID_PARAMETER
;
559 // Initialize the GopDevicePath to be PciDevicePath
561 *GopDevicePath
= PciDevicePath
;
562 TempPciDevicePath
= PciDevicePath
;
564 Status
= gBS
->LocateDevicePath (
565 &gEfiDevicePathProtocolGuid
,
569 if (EFI_ERROR (Status
)) {
574 // Try to connect this handle, so that GOP driver could start on this
575 // device and create child handles with GraphicsOutput Protocol installed
576 // on them, then we get device paths of these child handles and select
577 // them as possible console device.
579 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
581 Status
= gBS
->LocateHandleBuffer (
583 &gEfiGraphicsOutputProtocolGuid
,
588 if (!EFI_ERROR (Status
)) {
590 // Add all the child handles as possible Console Device
592 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
593 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
594 if (EFI_ERROR (Status
)) {
600 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
603 // In current implementation, we only enable one of the child handles
604 // as console device, i.e. sotre one of the child handle's device
605 // path to variable "ConOut"
606 // In future, we could select all child handles to be console device
609 *GopDevicePath
= TempDevicePath
;
612 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
613 // Add the integrity GOP device path.
615 EfiBootManagerUpdateConsoleVariable (ConOutDev
, NULL
, PciDevicePath
);
616 EfiBootManagerUpdateConsoleVariable (ConOutDev
, TempDevicePath
, NULL
);
619 gBS
->FreePool (GopHandleBuffer
);
626 PreparePciDisplayDevicePath (
627 IN EFI_HANDLE DeviceHandle
633 Add PCI VGA to ConOut.
638 DeviceHandle - Handle of PCIIO protocol.
642 EFI_SUCCESS - PCI VGA is added to ConOut.
643 EFI_STATUS - No PCI VGA device is added.
648 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
649 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
652 GopDevicePath
= NULL
;
653 Status
= gBS
->HandleProtocol (
655 &gEfiDevicePathProtocolGuid
,
658 if (EFI_ERROR (Status
)) {
662 GetGopDevicePath (DevicePath
, &GopDevicePath
);
663 DevicePath
= GopDevicePath
;
665 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
671 PreparePciSerialDevicePath (
672 IN EFI_HANDLE DeviceHandle
678 Add PCI Serial to ConOut, ConIn, ErrOut.
683 DeviceHandle - Handle of PCIIO protocol.
687 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
688 EFI_STATUS - No PCI Serial device is added.
693 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
696 Status
= gBS
->HandleProtocol (
698 &gEfiDevicePathProtocolGuid
,
701 if (EFI_ERROR (Status
)) {
705 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
706 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
708 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
709 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
710 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
716 VisitAllInstancesOfProtocol (
718 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
724 EFI_HANDLE
*HandleBuffer
;
729 // Start to check all the PciIo to find all possible device
733 Status
= gBS
->LocateHandleBuffer (
740 if (EFI_ERROR (Status
)) {
744 for (Index
= 0; Index
< HandleCount
; Index
++) {
745 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
746 if (EFI_ERROR (Status
)) {
750 Status
= (*CallBackFunction
) (
757 gBS
->FreePool (HandleBuffer
);
765 VisitingAPciInstance (
766 IN EFI_HANDLE Handle
,
772 EFI_PCI_IO_PROTOCOL
*PciIo
;
775 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
778 // Check for all PCI device
780 Status
= PciIo
->Pci
.Read (
784 sizeof (Pci
) / sizeof (UINT32
),
787 if (EFI_ERROR (Status
)) {
791 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
802 VisitAllPciInstances (
803 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
806 return VisitAllInstancesOfProtocol (
807 &gEfiPciIoProtocolGuid
,
808 VisitingAPciInstance
,
809 (VOID
*)(UINTN
) CallBackFunction
815 Do platform specific PCI Device check and add them to
816 ConOut, ConIn, ErrOut.
818 @param[in] Handle - Handle of PCI device instance
819 @param[in] PciIo - PCI IO protocol instance
820 @param[in] Pci - PCI Header register block
822 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
823 @retval EFI_STATUS - PCI Device check or Console variable update fail.
828 DetectAndPreparePlatformPciDevicePath (
829 IN EFI_HANDLE Handle
,
830 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
836 Status
= PciIo
->Attributes (
838 EfiPciIoAttributeOperationEnable
,
839 EFI_PCI_DEVICE_ENABLE
,
842 ASSERT_EFI_ERROR (Status
);
844 if (!mDetectVgaOnly
) {
846 // Here we decide whether it is LPC Bridge
848 if ((IS_PCI_LPC (Pci
)) ||
849 ((IS_PCI_ISA_PDECODE (Pci
)) &&
850 (Pci
->Hdr
.VendorId
== 0x8086) &&
851 (Pci
->Hdr
.DeviceId
== 0x7000)
855 // Add IsaKeyboard to ConIn,
856 // add IsaSerial to ConOut, ConIn, ErrOut
858 DEBUG ((EFI_D_INFO
, "Found LPC Bridge device\n"));
859 PrepareLpcBridgeDevicePath (Handle
);
863 // Here we decide which Serial device to enable in PCI bus
865 if (IS_PCI_16550SERIAL (Pci
)) {
867 // Add them to ConOut, ConIn, ErrOut.
869 DEBUG ((EFI_D_INFO
, "Found PCI 16550 SERIAL device\n"));
870 PreparePciSerialDevicePath (Handle
);
876 // Here we decide which display device to enable in PCI bus
878 if (IS_PCI_DISPLAY (Pci
)) {
880 // Add them to ConOut.
882 DEBUG ((EFI_D_INFO
, "Found PCI display device\n"));
883 PreparePciDisplayDevicePath (Handle
);
892 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
894 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
896 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
897 @retval EFI_STATUS - PCI Device check or Console variable update fail.
901 DetectAndPreparePlatformPciDevicePaths (
902 BOOLEAN DetectVgaOnly
905 mDetectVgaOnly
= DetectVgaOnly
;
906 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
911 PlatformInitializeConsole (
912 IN PLATFORM_CONSOLE_CONNECT_ENTRY
*PlatformConsole
918 Connect the predefined platform default console device. Always try to find
919 and enable the vga device if have.
923 PlatformConsole - Predefined platform default console device array.
927 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
928 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
931 // Connect RootBridge
933 GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME
, (VOID
**) &VarConout
, NULL
);
934 GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME
, (VOID
**) &VarConin
, NULL
);
936 if (VarConout
== NULL
|| VarConin
== NULL
) {
938 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
940 DetectAndPreparePlatformPciDevicePaths (FALSE
);
943 // Have chance to connect the platform default console,
944 // the platform default console is the minimum device group
945 // the platform should support
947 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
949 // Update the console variable with the connect type
951 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
952 EfiBootManagerUpdateConsoleVariable (ConIn
, PlatformConsole
[Index
].DevicePath
, NULL
);
954 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
955 EfiBootManagerUpdateConsoleVariable (ConOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
957 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
958 EfiBootManagerUpdateConsoleVariable (ErrOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
963 // Only detect VGA device and add them to ConOut
965 DetectAndPreparePlatformPciDevicePaths (TRUE
);
971 Configure PCI Interrupt Line register for applicable devices
972 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
974 @param[in] Handle - Handle of PCI device instance
975 @param[in] PciIo - PCI IO protocol instance
976 @param[in] PciHdr - PCI Header register block
978 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
984 IN EFI_HANDLE Handle
,
985 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
986 IN PCI_TYPE00
*PciHdr
989 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
990 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
995 UINT32 RootBusNumber
;
997 Status
= EFI_SUCCESS
;
999 if (PciHdr
->Device
.InterruptPin
!= 0) {
1001 DevPathNode
= DevicePathFromHandle (Handle
);
1002 ASSERT (DevPathNode
!= NULL
);
1003 DevPath
= DevPathNode
;
1006 if (DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
&&
1007 DevicePathSubType (DevPathNode
) == ACPI_DP
&&
1008 ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID(0x0A03)) {
1009 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
1013 // Compute index into PciHostIrqs[] table by walking
1014 // the device path and adding up all device numbers
1016 Status
= EFI_NOT_FOUND
;
1018 Idx
= PciHdr
->Device
.InterruptPin
- 1;
1019 while (!IsDevicePathEnd (DevPathNode
)) {
1020 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
1021 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
1023 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1026 // Unlike SeaBIOS, which starts climbing from the leaf device
1027 // up toward the root, we traverse the device path starting at
1028 // the root moving toward the leaf node.
1029 // The slot number of the top-level parent bridge is needed for
1030 // Q35 cases with more than 24 slots on the root bus.
1032 if (Status
!= EFI_SUCCESS
) {
1033 Status
= EFI_SUCCESS
;
1034 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1038 DevPathNode
= NextDevicePathNode (DevPathNode
);
1040 if (EFI_ERROR (Status
)) {
1043 if (RootBusNumber
== 0 && RootSlot
== 0) {
1046 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
1053 // Final PciHostIrqs[] index calculation depends on the platform
1054 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
1056 switch (mHostBridgeDevId
) {
1057 case INTEL_82441_DEVICE_ID
:
1060 case INTEL_Q35_MCH_DEVICE_ID
:
1062 // SeaBIOS contains the following comment:
1063 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
1064 // with a different starting index - see q35-acpi-dsdt.dsl.
1066 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
1068 if (RootSlot
> 24) {
1070 // in this case, subtract back out RootSlot from Idx
1071 // (SeaBIOS never adds it to begin with, but that would make our
1072 // device path traversal loop above too awkward)
1078 ASSERT (FALSE
); // should never get here
1080 Idx
%= ARRAY_SIZE (PciHostIrqs
);
1081 IrqLine
= PciHostIrqs
[Idx
];
1083 DEBUG_CODE_BEGIN ();
1085 CHAR16
*DevPathString
;
1086 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
1087 UINTN Segment
, Bus
, Device
, Function
;
1089 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
1090 if (DevPathString
== NULL
) {
1091 DevPathString
= Fallback
;
1093 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
1094 ASSERT_EFI_ERROR (Status
);
1096 DEBUG ((EFI_D_VERBOSE
, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__
,
1097 (UINT32
)Bus
, (UINT32
)Device
, (UINT32
)Function
, DevPathString
,
1100 if (DevPathString
!= Fallback
) {
1101 FreePool (DevPathString
);
1107 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
1109 Status
= PciIo
->Pci
.Write (
1112 PCI_INT_LINE_OFFSET
,
1123 PciAcpiInitialization (
1129 // Query Host Bridge DID to determine platform type
1131 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
1132 switch (mHostBridgeDevId
) {
1133 case INTEL_82441_DEVICE_ID
:
1134 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
1136 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
1138 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
1139 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
1140 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
1141 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
1143 case INTEL_Q35_MCH_DEVICE_ID
:
1144 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
1146 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
1148 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
1149 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
1150 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
1151 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
1152 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
1153 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
1154 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
1155 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
1158 DEBUG ((EFI_D_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
1159 __FUNCTION__
, mHostBridgeDevId
));
1165 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
1167 VisitAllPciInstances (SetPciIntLine
);
1170 // Set ACPI SCI_EN bit in PMCNTRL
1172 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
1176 This function detects if OVMF is running on Xen.
1185 EFI_HOB_GUID_TYPE
*GuidHob
;
1186 STATIC INTN FoundHob
= -1;
1188 if (FoundHob
== 0) {
1190 } else if (FoundHob
== 1) {
1195 // See if a XenInfo HOB is available
1197 GuidHob
= GetFirstGuidHob (&gEfiXenInfoGuid
);
1198 if (GuidHob
== NULL
) {
1209 ConnectRecursivelyIfPciMassStorage (
1210 IN EFI_HANDLE Handle
,
1211 IN EFI_PCI_IO_PROTOCOL
*Instance
,
1212 IN PCI_TYPE00
*PciHeader
1216 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1220 // Recognize PCI Mass Storage, and Xen PCI devices
1222 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
) ||
1223 (XenDetected() && IS_CLASS2 (PciHeader
, 0xFF, 0x80))) {
1225 Status
= gBS
->HandleProtocol (
1227 &gEfiDevicePathProtocolGuid
,
1230 if (EFI_ERROR (Status
)) {
1235 // Print Device Path
1237 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
1238 if (DevPathStr
!= NULL
) {
1241 "Found %s device: %s\n",
1242 IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
) ? L
"Mass Storage" : L
"Xen",
1245 FreePool(DevPathStr
);
1248 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
1249 if (EFI_ERROR (Status
)) {
1260 This notification function is invoked when the
1261 EMU Variable FVB has been changed.
1263 @param Event The event that occurred
1264 @param Context For EFI compatibility. Not used.
1269 EmuVariablesUpdatedCallback (
1274 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
1275 UpdateNvVarsOnFileSystem ();
1281 VisitingFileSystemInstance (
1282 IN EFI_HANDLE Handle
,
1288 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
1289 RETURN_STATUS PcdStatus
;
1291 if (ConnectedToFileSystem
) {
1292 return EFI_ALREADY_STARTED
;
1295 Status
= ConnectNvVarsToFileSystem (Handle
);
1296 if (EFI_ERROR (Status
)) {
1300 ConnectedToFileSystem
= TRUE
;
1302 EfiCreateProtocolNotifyEvent (
1303 &gEfiDevicePathProtocolGuid
,
1305 EmuVariablesUpdatedCallback
,
1307 &mEmuVariableEventReg
1309 PcdStatus
= PcdSet64S (PcdEmuVariableEvent
,
1310 (UINT64
)(UINTN
) mEmuVariableEvent
);
1311 ASSERT_RETURN_ERROR (PcdStatus
);
1318 PlatformBdsRestoreNvVarsFromHardDisk (
1321 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1322 VisitAllInstancesOfProtocol (
1323 &gEfiSimpleFileSystemProtocolGuid
,
1324 VisitingFileSystemInstance
,
1331 PlatformBdsConnectSequence (
1336 Routine Description:
1338 Connect with predefined platform connect sequence,
1339 the OEM/IBV can customize with their own connect sequence.
1353 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
1358 // Here we can get the customized platform connect sequence
1359 // Notes: we can connect with new variable which record the
1360 // last time boots connect device path sequence
1362 while (gPlatformConnectSequence
[Index
] != NULL
) {
1364 // Build the platform boot option
1366 EfiBootManagerConnectDevicePath (gPlatformConnectSequence
[Index
], NULL
);
1371 // Just use the simple policy to connect all devices
1373 DEBUG ((EFI_D_INFO
, "EfiBootManagerConnectAll\n"));
1374 EfiBootManagerConnectAll ();
1376 PciAcpiInitialization ();
1380 Save the S3 boot script.
1382 Note that DxeSmmReadyToLock must be signaled after this function returns;
1383 otherwise the script wouldn't be saved actually.
1392 EFI_S3_SAVE_STATE_PROTOCOL
*BootScript
;
1393 STATIC CONST UINT8 Info
[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1395 Status
= gBS
->LocateProtocol (&gEfiS3SaveStateProtocolGuid
, NULL
,
1396 (VOID
**) &BootScript
);
1397 ASSERT_EFI_ERROR (Status
);
1400 // Despite the opcode documentation in the PI spec, the protocol
1401 // implementation embeds a deep copy of the info in the boot script, rather
1402 // than storing just a pointer to runtime or NVS storage.
1404 Status
= BootScript
->Write(BootScript
, EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
1405 (UINT32
) sizeof Info
,
1406 (EFI_PHYSICAL_ADDRESS
)(UINTN
) &Info
);
1407 ASSERT_EFI_ERROR (Status
);
1413 PlatformBootManagerAfterConsole (
1418 Routine Description:
1420 The function will execute with as the platform policy, current policy
1421 is driven by boot mode. IBV/OEM can customize this code for their specific
1426 EFI_BOOT_MODE BootMode
;
1428 DEBUG ((EFI_D_INFO
, "PlatformBootManagerAfterConsole\n"));
1430 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1431 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior: not restoring NvVars "
1432 "from disk since flash variables appear to be supported.\n"));
1435 // Try to restore variables from the hard disk early so
1436 // they can be used for the other BDS connect operations.
1438 PlatformBdsRestoreNvVarsFromHardDisk ();
1442 // Get current Boot Mode
1444 BootMode
= GetBootModeHob ();
1445 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1448 // Go the different platform policy with different boot mode
1449 // Notes: this part code can be change with the table policy
1451 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1456 BootLogoEnableLogo ();
1459 // Perform some platform specific connect sequence
1461 PlatformBdsConnectSequence ();
1464 // Process QEMU's -kernel command line option
1466 TryRunningQemuKernel ();
1468 EfiBootManagerRefreshAllBootOption ();
1471 // Register UEFI Shell
1473 PlatformRegisterFvBootOption (
1474 PcdGetPtr (PcdShellFile
), L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
1477 RemoveStaleFvFileOptions ();
1478 SetBootOrderFromQemu ();
1482 This notification function is invoked when an instance of the
1483 EFI_DEVICE_PATH_PROTOCOL is produced.
1485 @param Event The event that occurred
1486 @param Context For EFI compatibility. Not used.
1499 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1500 ATAPI_DEVICE_PATH
*Atapi
;
1503 // Examine all new handles
1507 // Get the next handle
1509 BufferSize
= sizeof (Handle
);
1510 Status
= gBS
->LocateHandle (
1513 mEfiDevPathNotifyReg
,
1519 // If not found, we're done
1521 if (EFI_NOT_FOUND
== Status
) {
1525 if (EFI_ERROR (Status
)) {
1530 // Get the DevicePath protocol on that handle
1532 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevPathNode
);
1533 ASSERT_EFI_ERROR (Status
);
1535 while (!IsDevicePathEnd (DevPathNode
)) {
1537 // Find the handler to dump this device path node
1540 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1541 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1543 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1549 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1556 // Next device path node
1558 DevPathNode
= NextDevicePathNode (DevPathNode
);
1567 InstallDevicePathCallback (
1571 DEBUG ((EFI_D_INFO
, "Registered NotifyDevPath Event\n"));
1572 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1573 &gEfiDevicePathProtocolGuid
,
1577 &mEfiDevPathNotifyReg
1582 This function is called each second during the boot manager waits the timeout.
1584 @param TimeoutRemain The remaining timeout.
1588 PlatformBootManagerWaitCallback (
1589 UINT16 TimeoutRemain
1592 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
1593 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
1596 Timeout
= PcdGet16 (PcdPlatformBootTimeOut
);
1598 Black
.Raw
= 0x00000000;
1599 White
.Raw
= 0x00FFFFFF;
1601 BootLogoUpdateProgress (
1604 L
"Start boot option",
1606 (Timeout
- TimeoutRemain
) * 100 / Timeout
,