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
43 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
51 (EFIAPI
*PROTOCOL_INSTANCE_CALLBACK
)(
58 @param[in] Handle - Handle of PCI device instance
59 @param[in] PciIo - PCI IO protocol instance
60 @param[in] Pci - PCI Header register block
64 (EFIAPI
*VISIT_PCI_INSTANCE_CALLBACK
)(
66 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
72 // Function prototypes
76 VisitAllInstancesOfProtocol (
78 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
83 VisitAllPciInstancesOfProtocol (
84 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
88 InstallDevicePathCallback (
93 PlatformRegisterFvBootOption (
101 EFI_BOOT_MANAGER_LOAD_OPTION NewOption
;
102 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
103 UINTN BootOptionCount
;
104 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode
;
105 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
106 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
108 Status
= gBS
->HandleProtocol (
110 &gEfiLoadedImageProtocolGuid
,
111 (VOID
**) &LoadedImage
113 ASSERT_EFI_ERROR (Status
);
115 EfiInitializeFwVolDevicepathNode (&FileNode
, FileGuid
);
116 DevicePath
= DevicePathFromHandle (LoadedImage
->DeviceHandle
);
117 ASSERT (DevicePath
!= NULL
);
118 DevicePath
= AppendDevicePathNode (
120 (EFI_DEVICE_PATH_PROTOCOL
*) &FileNode
122 ASSERT (DevicePath
!= NULL
);
124 Status
= EfiBootManagerInitializeLoadOption (
126 LoadOptionNumberUnassigned
,
134 ASSERT_EFI_ERROR (Status
);
135 FreePool (DevicePath
);
137 BootOptions
= EfiBootManagerGetLoadOptions (
138 &BootOptionCount
, LoadOptionTypeBoot
141 OptionIndex
= EfiBootManagerFindLoadOption (
142 &NewOption
, BootOptions
, BootOptionCount
145 if (OptionIndex
== -1) {
146 Status
= EfiBootManagerAddLoadOptionVariable (&NewOption
, MAX_UINTN
);
147 ASSERT_EFI_ERROR (Status
);
149 EfiBootManagerFreeLoadOption (&NewOption
);
150 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
154 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
155 whose device paths do not resolve exactly to an FvFile in the system.
157 This removes any boot options that point to binaries built into the firmware
158 and have become stale due to any of the following:
159 - DXEFV's base address or size changed (historical),
160 - DXEFV's FvNameGuid changed,
161 - the FILE_GUID of the pointed-to binary changed,
162 - the referenced binary is no longer built into the firmware.
164 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
165 avoids exact duplicates.
168 RemoveStaleFvFileOptions (
172 EFI_BOOT_MANAGER_LOAD_OPTION
*BootOptions
;
173 UINTN BootOptionCount
;
176 BootOptions
= EfiBootManagerGetLoadOptions (&BootOptionCount
,
179 for (Index
= 0; Index
< BootOptionCount
; ++Index
) {
180 EFI_DEVICE_PATH_PROTOCOL
*Node1
, *Node2
, *SearchNode
;
185 // If the device path starts with neither MemoryMapped(...) nor Fv(...),
186 // then keep the boot option.
188 Node1
= BootOptions
[Index
].FilePath
;
189 if (!(DevicePathType (Node1
) == HARDWARE_DEVICE_PATH
&&
190 DevicePathSubType (Node1
) == HW_MEMMAP_DP
) &&
191 !(DevicePathType (Node1
) == MEDIA_DEVICE_PATH
&&
192 DevicePathSubType (Node1
) == MEDIA_PIWG_FW_VOL_DP
)) {
197 // If the second device path node is not FvFile(...), then keep the boot
200 Node2
= NextDevicePathNode (Node1
);
201 if (DevicePathType (Node2
) != MEDIA_DEVICE_PATH
||
202 DevicePathSubType (Node2
) != MEDIA_PIWG_FW_FILE_DP
) {
207 // Locate the Firmware Volume2 protocol instance that is denoted by the
208 // boot option. If this lookup fails (i.e., the boot option references a
209 // firmware volume that doesn't exist), then we'll proceed to delete the
213 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
,
214 &SearchNode
, &FvHandle
);
216 if (!EFI_ERROR (Status
)) {
218 // The firmware volume was found; now let's see if it contains the FvFile
219 // identified by GUID.
221 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvProtocol
;
222 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFileNode
;
224 EFI_FV_FILETYPE FoundType
;
225 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
226 UINT32 AuthenticationStatus
;
228 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiFirmwareVolume2ProtocolGuid
,
229 (VOID
**)&FvProtocol
);
230 ASSERT_EFI_ERROR (Status
);
232 FvFileNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)Node2
;
234 // Buffer==NULL means we request metadata only: BufferSize, FoundType,
237 Status
= FvProtocol
->ReadFile (
239 &FvFileNode
->FvFileName
, // NameGuid
244 &AuthenticationStatus
246 if (!EFI_ERROR (Status
)) {
248 // The FvFile was found. Keep the boot option.
255 // Delete the boot option.
257 Status
= EfiBootManagerDeleteLoadOptionVariable (
258 BootOptions
[Index
].OptionNumber
, LoadOptionTypeBoot
);
260 CHAR16
*DevicePathString
;
262 DevicePathString
= ConvertDevicePathToText(BootOptions
[Index
].FilePath
,
265 EFI_ERROR (Status
) ? EFI_D_WARN
: EFI_D_VERBOSE
,
266 "%a: removing stale Boot#%04x %s: %r\n",
268 (UINT32
)BootOptions
[Index
].OptionNumber
,
269 DevicePathString
== NULL
? L
"<unavailable>" : DevicePathString
,
272 if (DevicePathString
!= NULL
) {
273 FreePool (DevicePathString
);
278 EfiBootManagerFreeLoadOptions (BootOptions
, BootOptionCount
);
282 PlatformRegisterOptionsAndKeys (
290 EFI_BOOT_MANAGER_LOAD_OPTION BootOption
;
293 // Register ENTER as CONTINUE key
295 Enter
.ScanCode
= SCAN_NULL
;
296 Enter
.UnicodeChar
= CHAR_CARRIAGE_RETURN
;
297 Status
= EfiBootManagerRegisterContinueKeyOption (0, &Enter
, NULL
);
298 ASSERT_EFI_ERROR (Status
);
301 // Map F2 to Boot Manager Menu
303 F2
.ScanCode
= SCAN_F2
;
304 F2
.UnicodeChar
= CHAR_NULL
;
305 Esc
.ScanCode
= SCAN_ESC
;
306 Esc
.UnicodeChar
= CHAR_NULL
;
307 Status
= EfiBootManagerGetBootManagerMenu (&BootOption
);
308 ASSERT_EFI_ERROR (Status
);
309 Status
= EfiBootManagerAddKeyOptionVariable (
310 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &F2
, NULL
312 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
313 Status
= EfiBootManagerAddKeyOptionVariable (
314 NULL
, (UINT16
) BootOption
.OptionNumber
, 0, &Esc
, NULL
316 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_ALREADY_STARTED
);
322 IN EFI_HANDLE RootBridgeHandle
,
334 // BDS Platform Functions
338 PlatformBootManagerBeforeConsole (
345 Platform Bds init. Include the platform firmware vendor, revision
358 RETURN_STATUS PcdStatus
;
360 DEBUG ((EFI_D_INFO
, "PlatformBootManagerBeforeConsole\n"));
361 InstallDevicePathCallback ();
363 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid
,
364 ConnectRootBridge
, NULL
);
367 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
369 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid
);
372 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
373 // the preparation of S3 system information. That logic has a hard dependency
374 // on the presence of the FACS ACPI table. Since our ACPI tables are only
375 // installed after PCI enumeration completes, we must not trigger the S3 save
376 // earlier, hence we can't signal End-of-Dxe earlier.
378 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid
);
380 if (QemuFwCfgS3Enabled ()) {
382 // Save the boot script too. Note that this will require us to emit the
383 // DxeSmmReadyToLock event just below, which in turn locks down SMM.
389 // Prevent further changes to LockBoxes or SMRAM.
392 Status
= gBS
->InstallProtocolInterface (&Handle
,
393 &gEfiDxeSmmReadyToLockProtocolGuid
, EFI_NATIVE_INTERFACE
,
395 ASSERT_EFI_ERROR (Status
);
397 PlatformInitializeConsole (gPlatformConsole
);
398 PcdStatus
= PcdSet16S (PcdPlatformBootTimeOut
,
399 GetFrontPageTimeoutFromQemu ());
400 ASSERT_RETURN_ERROR (PcdStatus
);
402 PlatformRegisterOptionsAndKeys ();
409 IN EFI_HANDLE RootBridgeHandle
,
417 // Make the PCI bus driver connect the root bridge, non-recursively. This
418 // will produce a number of child handles with PciIo on them.
420 Status
= gBS
->ConnectController (
421 RootBridgeHandle
, // ControllerHandle
422 NULL
, // DriverImageHandle
423 NULL
, // RemainingDevicePath -- produce all
432 PrepareLpcBridgeDevicePath (
433 IN EFI_HANDLE DeviceHandle
439 Add IsaKeyboard to ConIn,
440 add IsaSerial to ConOut, ConIn, ErrOut.
445 DeviceHandle - Handle of PCIIO protocol.
449 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
450 EFI_STATUS - No LPC bridge is added.
455 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
456 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
460 Status
= gBS
->HandleProtocol (
462 &gEfiDevicePathProtocolGuid
,
465 if (EFI_ERROR (Status
)) {
468 TempDevicePath
= DevicePath
;
473 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
475 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
480 DevicePath
= TempDevicePath
;
481 gPnp16550ComPortDeviceNode
.UID
= 0;
483 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
484 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
485 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
490 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
491 if (DevPathStr
!= NULL
) {
494 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
496 gPnp16550ComPortDeviceNode
.UID
+ 1,
499 FreePool(DevPathStr
);
502 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
503 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
504 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
509 DevicePath
= TempDevicePath
;
510 gPnp16550ComPortDeviceNode
.UID
= 1;
512 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
513 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
514 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
519 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
520 if (DevPathStr
!= NULL
) {
523 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
525 gPnp16550ComPortDeviceNode
.UID
+ 1,
528 FreePool(DevPathStr
);
531 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
532 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
533 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
540 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
541 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
546 EFI_HANDLE PciDeviceHandle
;
547 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
548 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
549 UINTN GopHandleCount
;
550 EFI_HANDLE
*GopHandleBuffer
;
552 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
553 return EFI_INVALID_PARAMETER
;
557 // Initialize the GopDevicePath to be PciDevicePath
559 *GopDevicePath
= PciDevicePath
;
560 TempPciDevicePath
= PciDevicePath
;
562 Status
= gBS
->LocateDevicePath (
563 &gEfiDevicePathProtocolGuid
,
567 if (EFI_ERROR (Status
)) {
572 // Try to connect this handle, so that GOP driver could start on this
573 // device and create child handles with GraphicsOutput Protocol installed
574 // on them, then we get device paths of these child handles and select
575 // them as possible console device.
577 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
579 Status
= gBS
->LocateHandleBuffer (
581 &gEfiGraphicsOutputProtocolGuid
,
586 if (!EFI_ERROR (Status
)) {
588 // Add all the child handles as possible Console Device
590 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
591 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
592 if (EFI_ERROR (Status
)) {
598 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
601 // In current implementation, we only enable one of the child handles
602 // as console device, i.e. sotre one of the child handle's device
603 // path to variable "ConOut"
604 // In future, we could select all child handles to be console device
607 *GopDevicePath
= TempDevicePath
;
610 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
611 // Add the integrity GOP device path.
613 EfiBootManagerUpdateConsoleVariable (ConOutDev
, NULL
, PciDevicePath
);
614 EfiBootManagerUpdateConsoleVariable (ConOutDev
, TempDevicePath
, NULL
);
617 gBS
->FreePool (GopHandleBuffer
);
624 PreparePciDisplayDevicePath (
625 IN EFI_HANDLE DeviceHandle
631 Add PCI VGA to ConOut.
636 DeviceHandle - Handle of PCIIO protocol.
640 EFI_SUCCESS - PCI VGA is added to ConOut.
641 EFI_STATUS - No PCI VGA device is added.
646 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
647 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
650 GopDevicePath
= NULL
;
651 Status
= gBS
->HandleProtocol (
653 &gEfiDevicePathProtocolGuid
,
656 if (EFI_ERROR (Status
)) {
660 GetGopDevicePath (DevicePath
, &GopDevicePath
);
661 DevicePath
= GopDevicePath
;
663 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
669 PreparePciSerialDevicePath (
670 IN EFI_HANDLE DeviceHandle
676 Add PCI Serial to ConOut, ConIn, ErrOut.
681 DeviceHandle - Handle of PCIIO protocol.
685 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
686 EFI_STATUS - No PCI Serial device is added.
691 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
694 Status
= gBS
->HandleProtocol (
696 &gEfiDevicePathProtocolGuid
,
699 if (EFI_ERROR (Status
)) {
703 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
704 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
706 EfiBootManagerUpdateConsoleVariable (ConOut
, DevicePath
, NULL
);
707 EfiBootManagerUpdateConsoleVariable (ConIn
, DevicePath
, NULL
);
708 EfiBootManagerUpdateConsoleVariable (ErrOut
, DevicePath
, NULL
);
714 VisitAllInstancesOfProtocol (
716 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
722 EFI_HANDLE
*HandleBuffer
;
727 // Start to check all the PciIo to find all possible device
731 Status
= gBS
->LocateHandleBuffer (
738 if (EFI_ERROR (Status
)) {
742 for (Index
= 0; Index
< HandleCount
; Index
++) {
743 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
744 if (EFI_ERROR (Status
)) {
748 Status
= (*CallBackFunction
) (
755 gBS
->FreePool (HandleBuffer
);
763 VisitingAPciInstance (
764 IN EFI_HANDLE Handle
,
770 EFI_PCI_IO_PROTOCOL
*PciIo
;
773 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
776 // Check for all PCI device
778 Status
= PciIo
->Pci
.Read (
782 sizeof (Pci
) / sizeof (UINT32
),
785 if (EFI_ERROR (Status
)) {
789 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
800 VisitAllPciInstances (
801 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
804 return VisitAllInstancesOfProtocol (
805 &gEfiPciIoProtocolGuid
,
806 VisitingAPciInstance
,
807 (VOID
*)(UINTN
) CallBackFunction
813 Do platform specific PCI Device check and add them to
814 ConOut, ConIn, ErrOut.
816 @param[in] Handle - Handle of PCI device instance
817 @param[in] PciIo - PCI IO protocol instance
818 @param[in] Pci - PCI Header register block
820 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
821 @retval EFI_STATUS - PCI Device check or Console variable update fail.
826 DetectAndPreparePlatformPciDevicePath (
827 IN EFI_HANDLE Handle
,
828 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
834 Status
= PciIo
->Attributes (
836 EfiPciIoAttributeOperationEnable
,
837 EFI_PCI_DEVICE_ENABLE
,
840 ASSERT_EFI_ERROR (Status
);
842 if (!mDetectVgaOnly
) {
844 // Here we decide whether it is LPC Bridge
846 if ((IS_PCI_LPC (Pci
)) ||
847 ((IS_PCI_ISA_PDECODE (Pci
)) &&
848 (Pci
->Hdr
.VendorId
== 0x8086) &&
849 (Pci
->Hdr
.DeviceId
== 0x7000)
853 // Add IsaKeyboard to ConIn,
854 // add IsaSerial to ConOut, ConIn, ErrOut
856 DEBUG ((EFI_D_INFO
, "Found LPC Bridge device\n"));
857 PrepareLpcBridgeDevicePath (Handle
);
861 // Here we decide which Serial device to enable in PCI bus
863 if (IS_PCI_16550SERIAL (Pci
)) {
865 // Add them to ConOut, ConIn, ErrOut.
867 DEBUG ((EFI_D_INFO
, "Found PCI 16550 SERIAL device\n"));
868 PreparePciSerialDevicePath (Handle
);
874 // Here we decide which display device to enable in PCI bus
876 if (IS_PCI_DISPLAY (Pci
)) {
878 // Add them to ConOut.
880 DEBUG ((EFI_D_INFO
, "Found PCI display device\n"));
881 PreparePciDisplayDevicePath (Handle
);
890 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
892 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
894 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
895 @retval EFI_STATUS - PCI Device check or Console variable update fail.
899 DetectAndPreparePlatformPciDevicePaths (
900 BOOLEAN DetectVgaOnly
903 mDetectVgaOnly
= DetectVgaOnly
;
904 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
909 PlatformInitializeConsole (
910 IN PLATFORM_CONSOLE_CONNECT_ENTRY
*PlatformConsole
916 Connect the predefined platform default console device. Always try to find
917 and enable the vga device if have.
921 PlatformConsole - Predefined platform default console device array.
925 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
926 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
929 // Connect RootBridge
931 GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME
, (VOID
**) &VarConout
, NULL
);
932 GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME
, (VOID
**) &VarConin
, NULL
);
934 if (VarConout
== NULL
|| VarConin
== NULL
) {
936 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
938 DetectAndPreparePlatformPciDevicePaths (FALSE
);
941 // Have chance to connect the platform default console,
942 // the platform default console is the minimum device group
943 // the platform should support
945 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
947 // Update the console variable with the connect type
949 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
950 EfiBootManagerUpdateConsoleVariable (ConIn
, PlatformConsole
[Index
].DevicePath
, NULL
);
952 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
953 EfiBootManagerUpdateConsoleVariable (ConOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
955 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
956 EfiBootManagerUpdateConsoleVariable (ErrOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
961 // Only detect VGA device and add them to ConOut
963 DetectAndPreparePlatformPciDevicePaths (TRUE
);
969 Configure PCI Interrupt Line register for applicable devices
970 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
972 @param[in] Handle - Handle of PCI device instance
973 @param[in] PciIo - PCI IO protocol instance
974 @param[in] PciHdr - PCI Header register block
976 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
982 IN EFI_HANDLE Handle
,
983 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
984 IN PCI_TYPE00
*PciHdr
987 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
988 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
993 UINT32 RootBusNumber
;
995 Status
= EFI_SUCCESS
;
997 if (PciHdr
->Device
.InterruptPin
!= 0) {
999 DevPathNode
= DevicePathFromHandle (Handle
);
1000 ASSERT (DevPathNode
!= NULL
);
1001 DevPath
= DevPathNode
;
1004 if (DevicePathType (DevPathNode
) == ACPI_DEVICE_PATH
&&
1005 DevicePathSubType (DevPathNode
) == ACPI_DP
&&
1006 ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->HID
== EISA_PNP_ID(0x0A03)) {
1007 RootBusNumber
= ((ACPI_HID_DEVICE_PATH
*)DevPathNode
)->UID
;
1011 // Compute index into PciHostIrqs[] table by walking
1012 // the device path and adding up all device numbers
1014 Status
= EFI_NOT_FOUND
;
1016 Idx
= PciHdr
->Device
.InterruptPin
- 1;
1017 while (!IsDevicePathEnd (DevPathNode
)) {
1018 if (DevicePathType (DevPathNode
) == HARDWARE_DEVICE_PATH
&&
1019 DevicePathSubType (DevPathNode
) == HW_PCI_DP
) {
1021 Idx
+= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1024 // Unlike SeaBIOS, which starts climbing from the leaf device
1025 // up toward the root, we traverse the device path starting at
1026 // the root moving toward the leaf node.
1027 // The slot number of the top-level parent bridge is needed for
1028 // Q35 cases with more than 24 slots on the root bus.
1030 if (Status
!= EFI_SUCCESS
) {
1031 Status
= EFI_SUCCESS
;
1032 RootSlot
= ((PCI_DEVICE_PATH
*)DevPathNode
)->Device
;
1036 DevPathNode
= NextDevicePathNode (DevPathNode
);
1038 if (EFI_ERROR (Status
)) {
1041 if (RootBusNumber
== 0 && RootSlot
== 0) {
1044 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
1051 // Final PciHostIrqs[] index calculation depends on the platform
1052 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
1054 switch (mHostBridgeDevId
) {
1055 case INTEL_82441_DEVICE_ID
:
1058 case INTEL_Q35_MCH_DEVICE_ID
:
1060 // SeaBIOS contains the following comment:
1061 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
1062 // with a different starting index - see q35-acpi-dsdt.dsl.
1064 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
1066 if (RootSlot
> 24) {
1068 // in this case, subtract back out RootSlot from Idx
1069 // (SeaBIOS never adds it to begin with, but that would make our
1070 // device path traversal loop above too awkward)
1076 ASSERT (FALSE
); // should never get here
1078 Idx
%= ARRAY_SIZE (PciHostIrqs
);
1079 IrqLine
= PciHostIrqs
[Idx
];
1081 DEBUG_CODE_BEGIN ();
1083 CHAR16
*DevPathString
;
1084 STATIC CHAR16 Fallback
[] = L
"<failed to convert>";
1085 UINTN Segment
, Bus
, Device
, Function
;
1087 DevPathString
= ConvertDevicePathToText (DevPath
, FALSE
, FALSE
);
1088 if (DevPathString
== NULL
) {
1089 DevPathString
= Fallback
;
1091 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
1092 ASSERT_EFI_ERROR (Status
);
1094 DEBUG ((EFI_D_VERBOSE
, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__
,
1095 (UINT32
)Bus
, (UINT32
)Device
, (UINT32
)Function
, DevPathString
,
1098 if (DevPathString
!= Fallback
) {
1099 FreePool (DevPathString
);
1105 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
1107 Status
= PciIo
->Pci
.Write (
1110 PCI_INT_LINE_OFFSET
,
1121 PciAcpiInitialization (
1127 // Query Host Bridge DID to determine platform type
1129 mHostBridgeDevId
= PcdGet16 (PcdOvmfHostBridgePciDevId
);
1130 switch (mHostBridgeDevId
) {
1131 case INTEL_82441_DEVICE_ID
:
1132 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
1134 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
1136 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
1137 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
1138 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
1139 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
1141 case INTEL_Q35_MCH_DEVICE_ID
:
1142 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
1144 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
1146 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
1147 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
1148 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
1149 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
1150 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
1151 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
1152 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
1153 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
1156 DEBUG ((EFI_D_ERROR
, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
1157 __FUNCTION__
, mHostBridgeDevId
));
1163 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
1165 VisitAllPciInstances (SetPciIntLine
);
1168 // Set ACPI SCI_EN bit in PMCNTRL
1170 IoOr16 ((PciRead32 (Pmba
) & ~BIT0
) + 4, BIT0
);
1174 This function detects if OVMF is running on Xen.
1183 EFI_HOB_GUID_TYPE
*GuidHob
;
1184 STATIC INTN FoundHob
= -1;
1186 if (FoundHob
== 0) {
1188 } else if (FoundHob
== 1) {
1193 // See if a XenInfo HOB is available
1195 GuidHob
= GetFirstGuidHob (&gEfiXenInfoGuid
);
1196 if (GuidHob
== NULL
) {
1207 ConnectRecursivelyIfPciMassStorage (
1208 IN EFI_HANDLE Handle
,
1209 IN EFI_PCI_IO_PROTOCOL
*Instance
,
1210 IN PCI_TYPE00
*PciHeader
1214 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1218 // Recognize PCI Mass Storage, and Xen PCI devices
1220 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
) ||
1221 (XenDetected() && IS_CLASS2 (PciHeader
, 0xFF, 0x80))) {
1223 Status
= gBS
->HandleProtocol (
1225 &gEfiDevicePathProtocolGuid
,
1228 if (EFI_ERROR (Status
)) {
1233 // Print Device Path
1235 DevPathStr
= ConvertDevicePathToText (DevicePath
, FALSE
, FALSE
);
1236 if (DevPathStr
!= NULL
) {
1239 "Found %s device: %s\n",
1240 IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
) ? L
"Mass Storage" : L
"Xen",
1243 FreePool(DevPathStr
);
1246 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
1247 if (EFI_ERROR (Status
)) {
1258 This notification function is invoked when the
1259 EMU Variable FVB has been changed.
1261 @param Event The event that occurred
1262 @param Context For EFI compatibility. Not used.
1267 EmuVariablesUpdatedCallback (
1272 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
1273 UpdateNvVarsOnFileSystem ();
1279 VisitingFileSystemInstance (
1280 IN EFI_HANDLE Handle
,
1286 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
1287 RETURN_STATUS PcdStatus
;
1289 if (ConnectedToFileSystem
) {
1290 return EFI_ALREADY_STARTED
;
1293 Status
= ConnectNvVarsToFileSystem (Handle
);
1294 if (EFI_ERROR (Status
)) {
1298 ConnectedToFileSystem
= TRUE
;
1300 EfiCreateProtocolNotifyEvent (
1301 &gEfiDevicePathProtocolGuid
,
1303 EmuVariablesUpdatedCallback
,
1305 &mEmuVariableEventReg
1307 PcdStatus
= PcdSet64S (PcdEmuVariableEvent
,
1308 (UINT64
)(UINTN
) mEmuVariableEvent
);
1309 ASSERT_RETURN_ERROR (PcdStatus
);
1316 PlatformBdsRestoreNvVarsFromHardDisk (
1319 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
1320 VisitAllInstancesOfProtocol (
1321 &gEfiSimpleFileSystemProtocolGuid
,
1322 VisitingFileSystemInstance
,
1329 PlatformBdsConnectSequence (
1334 Routine Description:
1336 Connect with predefined platform connect sequence,
1337 the OEM/IBV can customize with their own connect sequence.
1351 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
1356 // Here we can get the customized platform connect sequence
1357 // Notes: we can connect with new variable which record the
1358 // last time boots connect device path sequence
1360 while (gPlatformConnectSequence
[Index
] != NULL
) {
1362 // Build the platform boot option
1364 EfiBootManagerConnectDevicePath (gPlatformConnectSequence
[Index
], NULL
);
1369 // Just use the simple policy to connect all devices
1371 DEBUG ((EFI_D_INFO
, "EfiBootManagerConnectAll\n"));
1372 EfiBootManagerConnectAll ();
1374 PciAcpiInitialization ();
1378 Save the S3 boot script.
1380 Note that DxeSmmReadyToLock must be signaled after this function returns;
1381 otherwise the script wouldn't be saved actually.
1390 EFI_S3_SAVE_STATE_PROTOCOL
*BootScript
;
1391 STATIC CONST UINT8 Info
[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1393 Status
= gBS
->LocateProtocol (&gEfiS3SaveStateProtocolGuid
, NULL
,
1394 (VOID
**) &BootScript
);
1395 ASSERT_EFI_ERROR (Status
);
1398 // Despite the opcode documentation in the PI spec, the protocol
1399 // implementation embeds a deep copy of the info in the boot script, rather
1400 // than storing just a pointer to runtime or NVS storage.
1402 Status
= BootScript
->Write(BootScript
, EFI_BOOT_SCRIPT_INFORMATION_OPCODE
,
1403 (UINT32
) sizeof Info
,
1404 (EFI_PHYSICAL_ADDRESS
)(UINTN
) &Info
);
1405 ASSERT_EFI_ERROR (Status
);
1411 PlatformBootManagerAfterConsole (
1416 Routine Description:
1418 The function will execute with as the platform policy, current policy
1419 is driven by boot mode. IBV/OEM can customize this code for their specific
1424 EFI_BOOT_MODE BootMode
;
1426 DEBUG ((EFI_D_INFO
, "PlatformBootManagerAfterConsole\n"));
1428 if (PcdGetBool (PcdOvmfFlashVariablesEnable
)) {
1429 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior: not restoring NvVars "
1430 "from disk since flash variables appear to be supported.\n"));
1433 // Try to restore variables from the hard disk early so
1434 // they can be used for the other BDS connect operations.
1436 PlatformBdsRestoreNvVarsFromHardDisk ();
1440 // Get current Boot Mode
1442 BootMode
= GetBootModeHob ();
1443 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1446 // Go the different platform policy with different boot mode
1447 // Notes: this part code can be change with the table policy
1449 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1454 BootLogoEnableLogo ();
1457 // Perform some platform specific connect sequence
1459 PlatformBdsConnectSequence ();
1462 // Process QEMU's -kernel command line option
1464 TryRunningQemuKernel ();
1466 EfiBootManagerRefreshAllBootOption ();
1469 // Register UEFI Shell
1471 PlatformRegisterFvBootOption (
1472 PcdGetPtr (PcdShellFile
), L
"EFI Internal Shell", LOAD_OPTION_ACTIVE
1475 RemoveStaleFvFileOptions ();
1476 SetBootOrderFromQemu ();
1480 This notification function is invoked when an instance of the
1481 EFI_DEVICE_PATH_PROTOCOL is produced.
1483 @param Event The event that occurred
1484 @param Context For EFI compatibility. Not used.
1497 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1498 ATAPI_DEVICE_PATH
*Atapi
;
1501 // Examine all new handles
1505 // Get the next handle
1507 BufferSize
= sizeof (Handle
);
1508 Status
= gBS
->LocateHandle (
1511 mEfiDevPathNotifyReg
,
1517 // If not found, we're done
1519 if (EFI_NOT_FOUND
== Status
) {
1523 if (EFI_ERROR (Status
)) {
1528 // Get the DevicePath protocol on that handle
1530 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevPathNode
);
1531 ASSERT_EFI_ERROR (Status
);
1533 while (!IsDevicePathEnd (DevPathNode
)) {
1535 // Find the handler to dump this device path node
1538 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1539 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1541 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1547 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1554 // Next device path node
1556 DevPathNode
= NextDevicePathNode (DevPathNode
);
1565 InstallDevicePathCallback (
1569 DEBUG ((EFI_D_INFO
, "Registered NotifyDevPath Event\n"));
1570 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1571 &gEfiDevicePathProtocolGuid
,
1575 &mEfiDevPathNotifyReg
1580 This function is called each second during the boot manager waits the timeout.
1582 @param TimeoutRemain The remaining timeout.
1586 PlatformBootManagerWaitCallback (
1587 UINT16 TimeoutRemain
1590 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black
;
1591 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White
;
1594 Timeout
= PcdGet16 (PcdPlatformBootTimeOut
);
1596 Black
.Raw
= 0x00000000;
1597 White
.Raw
= 0x00FFFFFF;
1599 BootLogoUpdateProgress (
1602 L
"Start boot option",
1604 (Timeout
- TimeoutRemain
) * 100 / Timeout
,