+++ /dev/null
-/** @file\r
- Platform BDS customizations.\r
-\r
- Copyright (C) 2020 James Bottomley, IBM Corporation.\r
- Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "BdsPlatform.h"\r
-#include <Guid/RootBridgesConnectedEventGroup.h>\r
-#include <Protocol/FirmwareVolume2.h>\r
-#include <Library/PlatformBmPrintScLib.h>\r
-#include <Library/Tcg2PhysicalPresenceLib.h>\r
-\r
-//\r
-// Global data\r
-//\r
-\r
-VOID *mEfiDevPathNotifyReg;\r
-EFI_EVENT mEfiDevPathEvent;\r
-UINT16 mHostBridgeDevId;\r
-\r
-//\r
-// Table of host IRQs matching PCI IRQs A-D\r
-// (for configuring PCI Interrupt Line register)\r
-//\r
-CONST UINT8 PciHostIrqs[] = {\r
- 0x0a, 0x0a, 0x0b, 0x0b\r
-};\r
-\r
-//\r
-// Type definitions\r
-//\r
-\r
-typedef\r
-EFI_STATUS\r
-(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(\r
- IN EFI_HANDLE Handle,\r
- IN VOID *Instance,\r
- IN VOID *Context\r
- );\r
-\r
-/**\r
- @param[in] Handle - Handle of PCI device instance\r
- @param[in] PciIo - PCI IO protocol instance\r
- @param[in] Pci - PCI Header register block\r
-**/\r
-typedef\r
-EFI_STATUS\r
-(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(\r
- IN EFI_HANDLE Handle,\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN PCI_TYPE00 *Pci\r
- );\r
-\r
-//\r
-// Function prototypes\r
-//\r
-\r
-EFI_STATUS\r
-VisitAllInstancesOfProtocol (\r
- IN EFI_GUID *Id,\r
- IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,\r
- IN VOID *Context\r
- );\r
-\r
-EFI_STATUS\r
-VisitAllPciInstancesOfProtocol (\r
- IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
- );\r
-\r
-VOID\r
-InstallDevicePathCallback (\r
- VOID\r
- );\r
-\r
-VOID\r
-PlatformRegisterFvBootOption (\r
- EFI_GUID *FileGuid,\r
- CHAR16 *Description,\r
- UINT32 Attributes\r
- )\r
-{\r
- EFI_STATUS Status;\r
- INTN OptionIndex;\r
- EFI_BOOT_MANAGER_LOAD_OPTION NewOption;\r
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
- UINTN BootOptionCount;\r
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;\r
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
-\r
- Status = gBS->HandleProtocol (\r
- gImageHandle,\r
- &gEfiLoadedImageProtocolGuid,\r
- (VOID **)&LoadedImage\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);\r
- DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);\r
- ASSERT (DevicePath != NULL);\r
- DevicePath = AppendDevicePathNode (\r
- DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&FileNode\r
- );\r
- ASSERT (DevicePath != NULL);\r
-\r
- Status = EfiBootManagerInitializeLoadOption (\r
- &NewOption,\r
- LoadOptionNumberUnassigned,\r
- LoadOptionTypeBoot,\r
- Attributes,\r
- Description,\r
- DevicePath,\r
- NULL,\r
- 0\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- FreePool (DevicePath);\r
-\r
- BootOptions = EfiBootManagerGetLoadOptions (\r
- &BootOptionCount,\r
- LoadOptionTypeBoot\r
- );\r
-\r
- OptionIndex = EfiBootManagerFindLoadOption (\r
- &NewOption,\r
- BootOptions,\r
- BootOptionCount\r
- );\r
-\r
- if (OptionIndex == -1) {\r
- Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
-\r
- EfiBootManagerFreeLoadOption (&NewOption);\r
- EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
-}\r
-\r
-/**\r
- Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options\r
- whose device paths do not resolve exactly to an FvFile in the system.\r
-\r
- Also strip out every boot option that is not an FvFile, meaning the system\r
- can only boot either the Grub or (if built) the shell.\r
-\r
- This removes any boot options that point to binaries built into the firmware\r
- and have become stale due to any of the following:\r
- - DXEFV's base address or size changed (historical),\r
- - DXEFV's FvNameGuid changed,\r
- - the FILE_GUID of the pointed-to binary changed,\r
- - the referenced binary is no longer built into the firmware.\r
-\r
- EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only\r
- avoids exact duplicates.\r
-**/\r
-VOID\r
-RemoveStaleFvFileOptions (\r
- VOID\r
- )\r
-{\r
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
- UINTN BootOptionCount;\r
- UINTN Index;\r
-\r
- BootOptions = EfiBootManagerGetLoadOptions (\r
- &BootOptionCount,\r
- LoadOptionTypeBoot\r
- );\r
-\r
- for (Index = 0; Index < BootOptionCount; ++Index) {\r
- EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;\r
- EFI_STATUS Status;\r
- EFI_HANDLE FvHandle;\r
-\r
- //\r
- // If the device path starts with neither MemoryMapped(...) nor Fv(...),\r
- // then delete the boot option.\r
- //\r
- Node1 = BootOptions[Index].FilePath;\r
- if (!((DevicePathType (Node1) == HARDWARE_DEVICE_PATH) &&\r
- (DevicePathSubType (Node1) == HW_MEMMAP_DP)) &&\r
- !((DevicePathType (Node1) == MEDIA_DEVICE_PATH) &&\r
- (DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)))\r
- {\r
- EfiBootManagerDeleteLoadOptionVariable (\r
- BootOptions[Index].OptionNumber,\r
- LoadOptionTypeBoot\r
- );\r
- continue;\r
- }\r
-\r
- //\r
- // If the second device path node is not FvFile(...), then delete the boot\r
- // option.\r
- //\r
- Node2 = NextDevicePathNode (Node1);\r
- if ((DevicePathType (Node2) != MEDIA_DEVICE_PATH) ||\r
- (DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP))\r
- {\r
- EfiBootManagerDeleteLoadOptionVariable (\r
- BootOptions[Index].OptionNumber,\r
- LoadOptionTypeBoot\r
- );\r
- continue;\r
- }\r
-\r
- //\r
- // Locate the Firmware Volume2 protocol instance that is denoted by the\r
- // boot option. If this lookup fails (i.e., the boot option references a\r
- // firmware volume that doesn't exist), then we'll proceed to delete the\r
- // boot option.\r
- //\r
- SearchNode = Node1;\r
- Status = gBS->LocateDevicePath (\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- &SearchNode,\r
- &FvHandle\r
- );\r
-\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // The firmware volume was found; now let's see if it contains the FvFile\r
- // identified by GUID.\r
- //\r
- EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;\r
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;\r
- UINTN BufferSize;\r
- EFI_FV_FILETYPE FoundType;\r
- EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
- UINT32 AuthenticationStatus;\r
-\r
- Status = gBS->HandleProtocol (\r
- FvHandle,\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- (VOID **)&FvProtocol\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;\r
- //\r
- // Buffer==NULL means we request metadata only: BufferSize, FoundType,\r
- // FileAttributes.\r
- //\r
- Status = FvProtocol->ReadFile (\r
- FvProtocol,\r
- &FvFileNode->FvFileName, // NameGuid\r
- NULL, // Buffer\r
- &BufferSize,\r
- &FoundType,\r
- &FileAttributes,\r
- &AuthenticationStatus\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // The FvFile was found. Keep the boot option.\r
- //\r
- continue;\r
- }\r
- }\r
-\r
- //\r
- // Delete the boot option.\r
- //\r
- Status = EfiBootManagerDeleteLoadOptionVariable (\r
- BootOptions[Index].OptionNumber,\r
- LoadOptionTypeBoot\r
- );\r
- DEBUG_CODE_BEGIN ();\r
- CHAR16 *DevicePathString;\r
-\r
- DevicePathString = ConvertDevicePathToText (\r
- BootOptions[Index].FilePath,\r
- FALSE,\r
- FALSE\r
- );\r
- DEBUG ((\r
- EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_VERBOSE,\r
- "%a: removing stale Boot#%04x %s: %r\n",\r
- __func__,\r
- (UINT32)BootOptions[Index].OptionNumber,\r
- DevicePathString == NULL ? L"<unavailable>" : DevicePathString,\r
- Status\r
- ));\r
- if (DevicePathString != NULL) {\r
- FreePool (DevicePathString);\r
- }\r
-\r
- DEBUG_CODE_END ();\r
- }\r
-\r
- EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-ConnectRootBridge (\r
- IN EFI_HANDLE RootBridgeHandle,\r
- IN VOID *Instance,\r
- IN VOID *Context\r
- );\r
-\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-ConnectVirtioPciRng (\r
- IN EFI_HANDLE Handle,\r
- IN VOID *Instance,\r
- IN VOID *Context\r
- );\r
-\r
-//\r
-// BDS Platform Functions\r
-//\r
-\r
-/**\r
- Do the platform init, can be customized by OEM/IBV\r
-\r
- Possible things that can be done in PlatformBootManagerBeforeConsole:\r
-\r
- > Update console variable: 1. include hot-plug devices;\r
- > 2. Clear ConIn and add SOL for AMT\r
- > Register new Driver#### or Boot####\r
- > Register new Key####: e.g.: F12\r
- > Signal ReadyToLock event\r
- > Authentication action: 1. connect Auth devices;\r
- > 2. Identify auto logon user.\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBootManagerBeforeConsole (\r
- VOID\r
- )\r
-{\r
- EFI_HANDLE Handle;\r
- EFI_STATUS Status;\r
- UINT16 FrontPageTimeout;\r
-\r
- FrontPageTimeout = 0;\r
-\r
- DEBUG ((DEBUG_INFO, "PlatformBootManagerBeforeConsole\n"));\r
- InstallDevicePathCallback ();\r
-\r
- VisitAllInstancesOfProtocol (\r
- &gEfiPciRootBridgeIoProtocolGuid,\r
- ConnectRootBridge,\r
- NULL\r
- );\r
-\r
- //\r
- // Signal the ACPI platform driver that it can download QEMU ACPI tables.\r
- //\r
- EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);\r
-\r
- //\r
- // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers\r
- // the preparation of S3 system information. That logic has a hard dependency\r
- // on the presence of the FACS ACPI table. Since our ACPI tables are only\r
- // installed after PCI enumeration completes, we must not trigger the S3 save\r
- // earlier, hence we can't signal End-of-Dxe earlier.\r
- //\r
- EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
-\r
- // We need to connect all trusted consoles for TCG PP. Here we treat all\r
- // consoles in OVMF to be trusted consoles.\r
- PlatformInitializeConsole (gPlatformConsole);\r
-\r
- //\r
- // Process TPM PPI request\r
- //\r
- Tcg2PhysicalPresenceLibProcessRequest (NULL);\r
-\r
- //\r
- // Prevent further changes to LockBoxes or SMRAM.\r
- // Any TPM 2 Physical Presence Interface opcode must be handled before.\r
- //\r
- Handle = NULL;\r
- Status = gBS->InstallProtocolInterface (\r
- &Handle,\r
- &gEfiDxeSmmReadyToLockProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Dispatch deferred images after EndOfDxe event and ReadyToLock\r
- // installation.\r
- //\r
- EfiBootManagerDispatchDeferredImages ();\r
-\r
- //\r
- // GPU passthrough only allows Console enablement after ROM image load\r
- //\r
- PlatformInitializeConsole (gPlatformConsole);\r
-\r
- Status = gRT->SetVariable (\r
- EFI_TIME_OUT_VARIABLE_NAME,\r
- &gEfiGlobalVariableGuid,\r
- (EFI_VARIABLE_NON_VOLATILE |\r
- EFI_VARIABLE_BOOTSERVICE_ACCESS |\r
- EFI_VARIABLE_RUNTIME_ACCESS),\r
- sizeof FrontPageTimeout,\r
- &FrontPageTimeout\r
- );\r
- //\r
- // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL\r
- // instances on Virtio PCI RNG devices.\r
- //\r
- VisitAllInstancesOfProtocol (\r
- &gEfiPciIoProtocolGuid,\r
- ConnectVirtioPciRng,\r
- NULL\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-ConnectRootBridge (\r
- IN EFI_HANDLE RootBridgeHandle,\r
- IN VOID *Instance,\r
- IN VOID *Context\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Make the PCI bus driver connect the root bridge, non-recursively. This\r
- // will produce a number of child handles with PciIo on them.\r
- //\r
- Status = gBS->ConnectController (\r
- RootBridgeHandle, // ControllerHandle\r
- NULL, // DriverImageHandle\r
- NULL, // RemainingDevicePath -- produce all\r
- // children\r
- FALSE // Recursive\r
- );\r
- return Status;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-ConnectVirtioPciRng (\r
- IN EFI_HANDLE Handle,\r
- IN VOID *Instance,\r
- IN VOID *Context\r
- )\r
-{\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- EFI_STATUS Status;\r
- UINT16 VendorId;\r
- UINT16 DeviceId;\r
- UINT8 RevisionId;\r
- BOOLEAN Virtio10;\r
- UINT16 SubsystemId;\r
-\r
- PciIo = Instance;\r
-\r
- //\r
- // Read and check VendorId.\r
- //\r
- Status = PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint16,\r
- PCI_VENDOR_ID_OFFSET,\r
- 1,\r
- &VendorId\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- if (VendorId != VIRTIO_VENDOR_ID) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Read DeviceId and RevisionId.\r
- //\r
- Status = PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint16,\r
- PCI_DEVICE_ID_OFFSET,\r
- 1,\r
- &DeviceId\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- Status = PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- PCI_REVISION_ID_OFFSET,\r
- 1,\r
- &RevisionId\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- //\r
- // From DeviceId and RevisionId, determine whether the device is a\r
- // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can\r
- // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and\r
- // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can\r
- // only be sanity-checked, and SubsystemId will decide.\r
- //\r
- if ((DeviceId == 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE) &&\r
- (RevisionId >= 0x01))\r
- {\r
- Virtio10 = TRUE;\r
- } else if ((DeviceId >= 0x1000) && (DeviceId <= 0x103F) && (RevisionId == 0x00)) {\r
- Virtio10 = FALSE;\r
- } else {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Read and check SubsystemId as dictated by Virtio10.\r
- //\r
- Status = PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint16,\r
- PCI_SUBSYSTEM_ID_OFFSET,\r
- 1,\r
- &SubsystemId\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- if ((Virtio10 && (SubsystemId >= 0x40)) ||\r
- (!Virtio10 && (SubsystemId == VIRTIO_SUBSYSTEM_ENTROPY_SOURCE)))\r
- {\r
- Status = gBS->ConnectController (\r
- Handle, // ControllerHandle\r
- NULL, // DriverImageHandle -- connect all drivers\r
- NULL, // RemainingDevicePath -- produce all child handles\r
- FALSE // Recursive -- don't follow child handles\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-\r
-Error:\r
- DEBUG ((DEBUG_ERROR, "%a: %r\n", __func__, Status));\r
- return Status;\r
-}\r
-\r
-/**\r
- Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.\r
-\r
- @param[in] DeviceHandle Handle of the LPC Bridge device.\r
-\r
- @retval EFI_SUCCESS Console devices on the LPC bridge have been added to\r
- ConOut, ConIn, and ErrOut.\r
-\r
- @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
- from DeviceHandle.\r
-**/\r
-EFI_STATUS\r
-PrepareLpcBridgeDevicePath (\r
- IN EFI_HANDLE DeviceHandle\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
- CHAR16 *DevPathStr;\r
-\r
- DevicePath = NULL;\r
- Status = gBS->HandleProtocol (\r
- DeviceHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID *)&DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- TempDevicePath = DevicePath;\r
-\r
- //\r
- // Register Keyboard\r
- //\r
- DevicePath = AppendDevicePathNode (\r
- DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode\r
- );\r
-\r
- EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
-\r
- //\r
- // Register COM1\r
- //\r
- DevicePath = TempDevicePath;\r
- gPnp16550ComPortDeviceNode.UID = 0;\r
-\r
- DevicePath = AppendDevicePathNode (\r
- DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode\r
- );\r
- DevicePath = AppendDevicePathNode (\r
- DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode\r
- );\r
- DevicePath = AppendDevicePathNode (\r
- DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode\r
- );\r
-\r
- //\r
- // Print Device Path\r
- //\r
- DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
- if (DevPathStr != NULL) {\r
- DEBUG ((\r
- DEBUG_INFO,\r
- "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
- DEBUG_LINE_NUMBER,\r
- gPnp16550ComPortDeviceNode.UID + 1,\r
- DevPathStr\r
- ));\r
- FreePool (DevPathStr);\r
- }\r
-\r
- EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
- EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
- EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
-\r
- //\r
- // Register COM2\r
- //\r
- DevicePath = TempDevicePath;\r
- gPnp16550ComPortDeviceNode.UID = 1;\r
-\r
- DevicePath = AppendDevicePathNode (\r
- DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode\r
- );\r
- DevicePath = AppendDevicePathNode (\r
- DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode\r
- );\r
- DevicePath = AppendDevicePathNode (\r
- DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode\r
- );\r
-\r
- //\r
- // Print Device Path\r
- //\r
- DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
- if (DevPathStr != NULL) {\r
- DEBUG ((\r
- DEBUG_INFO,\r
- "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
- DEBUG_LINE_NUMBER,\r
- gPnp16550ComPortDeviceNode.UID + 1,\r
- DevPathStr\r
- ));\r
- FreePool (DevPathStr);\r
- }\r
-\r
- EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
- EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
- EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-GetGopDevicePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath\r
- )\r
-{\r
- UINTN Index;\r
- EFI_STATUS Status;\r
- EFI_HANDLE PciDeviceHandle;\r
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;\r
- UINTN GopHandleCount;\r
- EFI_HANDLE *GopHandleBuffer;\r
-\r
- if ((PciDevicePath == NULL) || (GopDevicePath == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Initialize the GopDevicePath to be PciDevicePath\r
- //\r
- *GopDevicePath = PciDevicePath;\r
- TempPciDevicePath = PciDevicePath;\r
-\r
- Status = gBS->LocateDevicePath (\r
- &gEfiDevicePathProtocolGuid,\r
- &TempPciDevicePath,\r
- &PciDeviceHandle\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Try to connect this handle, so that GOP driver could start on this\r
- // device and create child handles with GraphicsOutput Protocol installed\r
- // on them, then we get device paths of these child handles and select\r
- // them as possible console device.\r
- //\r
- gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);\r
-\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiGraphicsOutputProtocolGuid,\r
- NULL,\r
- &GopHandleCount,\r
- &GopHandleBuffer\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Add all the child handles as possible Console Device\r
- //\r
- for (Index = 0; Index < GopHandleCount; Index++) {\r
- Status = gBS->HandleProtocol (\r
- GopHandleBuffer[Index],\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID *)&TempDevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- if (CompareMem (\r
- PciDevicePath,\r
- TempDevicePath,\r
- GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH\r
- ) == 0)\r
- {\r
- //\r
- // In current implementation, we only enable one of the child handles\r
- // as console device, i.e. sotre one of the child handle's device\r
- // path to variable "ConOut"\r
- // In future, we could select all child handles to be console device\r
- //\r
-\r
- *GopDevicePath = TempDevicePath;\r
-\r
- //\r
- // Delete the PCI device's path that added by\r
- // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.\r
- //\r
- EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);\r
- EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);\r
- }\r
- }\r
-\r
- gBS->FreePool (GopHandleBuffer);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Add PCI display to ConOut.\r
-\r
- @param[in] DeviceHandle Handle of the PCI display device.\r
-\r
- @retval EFI_SUCCESS The PCI display device has been added to ConOut.\r
-\r
- @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
- from DeviceHandle.\r
-**/\r
-EFI_STATUS\r
-PreparePciDisplayDevicePath (\r
- IN EFI_HANDLE DeviceHandle\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;\r
-\r
- DevicePath = NULL;\r
- GopDevicePath = NULL;\r
- Status = gBS->HandleProtocol (\r
- DeviceHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID *)&DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- GetGopDevicePath (DevicePath, &GopDevicePath);\r
- DevicePath = GopDevicePath;\r
-\r
- EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Add PCI Serial to ConOut, ConIn, ErrOut.\r
-\r
- @param[in] DeviceHandle Handle of the PCI serial device.\r
-\r
- @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,\r
- ErrOut.\r
-\r
- @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
- from DeviceHandle.\r
-**/\r
-EFI_STATUS\r
-PreparePciSerialDevicePath (\r
- IN EFI_HANDLE DeviceHandle\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
-\r
- DevicePath = NULL;\r
- Status = gBS->HandleProtocol (\r
- DeviceHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID *)&DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- DevicePath = AppendDevicePathNode (\r
- DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode\r
- );\r
- DevicePath = AppendDevicePathNode (\r
- DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode\r
- );\r
-\r
- EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
- EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
- EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-VisitAllInstancesOfProtocol (\r
- IN EFI_GUID *Id,\r
- IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,\r
- IN VOID *Context\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN HandleCount;\r
- EFI_HANDLE *HandleBuffer;\r
- UINTN Index;\r
- VOID *Instance;\r
-\r
- //\r
- // Start to check all the PciIo to find all possible device\r
- //\r
- HandleCount = 0;\r
- HandleBuffer = NULL;\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- Id,\r
- NULL,\r
- &HandleCount,\r
- &HandleBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- for (Index = 0; Index < HandleCount; Index++) {\r
- Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- Status = (*CallBackFunction)(\r
- HandleBuffer[Index],\r
- Instance,\r
- Context\r
- );\r
- }\r
-\r
- gBS->FreePool (HandleBuffer);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-VisitingAPciInstance (\r
- IN EFI_HANDLE Handle,\r
- IN VOID *Instance,\r
- IN VOID *Context\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- PCI_TYPE00 Pci;\r
-\r
- PciIo = (EFI_PCI_IO_PROTOCOL *)Instance;\r
-\r
- //\r
- // Check for all PCI device\r
- //\r
- Status = PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint32,\r
- 0,\r
- sizeof (Pci) / sizeof (UINT32),\r
- &Pci\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN)Context)(\r
- Handle,\r
- PciIo,\r
- &Pci\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-VisitAllPciInstances (\r
- IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
- )\r
-{\r
- return VisitAllInstancesOfProtocol (\r
- &gEfiPciIoProtocolGuid,\r
- VisitingAPciInstance,\r
- (VOID *)(UINTN)CallBackFunction\r
- );\r
-}\r
-\r
-/**\r
- Do platform specific PCI Device check and add them to\r
- ConOut, ConIn, ErrOut.\r
-\r
- @param[in] Handle - Handle of PCI device instance\r
- @param[in] PciIo - PCI IO protocol instance\r
- @param[in] Pci - PCI Header register block\r
-\r
- @retval EFI_SUCCESS - PCI Device check and Console variable update\r
- successfully.\r
- @retval EFI_STATUS - PCI Device check or Console variable update fail.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-DetectAndPreparePlatformPciDevicePath (\r
- IN EFI_HANDLE Handle,\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN PCI_TYPE00 *Pci\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationEnable,\r
- EFI_PCI_DEVICE_ENABLE,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Here we decide whether it is LPC Bridge\r
- //\r
- if ((IS_PCI_LPC (Pci)) ||\r
- ((IS_PCI_ISA_PDECODE (Pci)) &&\r
- (Pci->Hdr.VendorId == 0x8086) &&\r
- (Pci->Hdr.DeviceId == 0x7000)\r
- )\r
- )\r
- {\r
- //\r
- // Add IsaKeyboard to ConIn,\r
- // add IsaSerial to ConOut, ConIn, ErrOut\r
- //\r
- DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));\r
- PrepareLpcBridgeDevicePath (Handle);\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Here we decide which Serial device to enable in PCI bus\r
- //\r
- if (IS_PCI_16550SERIAL (Pci)) {\r
- //\r
- // Add them to ConOut, ConIn, ErrOut.\r
- //\r
- DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));\r
- PreparePciSerialDevicePath (Handle);\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Here we decide which display device to enable in PCI bus\r
- //\r
- if (IS_PCI_DISPLAY (Pci)) {\r
- //\r
- // Add them to ConOut.\r
- //\r
- DEBUG ((DEBUG_INFO, "Found PCI display device\n"));\r
- PreparePciDisplayDevicePath (Handle);\r
- return EFI_SUCCESS;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Connect the predefined platform default console device.\r
-\r
- Always try to find and enable PCI display devices.\r
-\r
- @param[in] PlatformConsole Predefined platform default console device array.\r
-**/\r
-VOID\r
-PlatformInitializeConsole (\r
- IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole\r
- )\r
-{\r
- UINTN Index;\r
-\r
- //\r
- // Do platform specific PCI Device check and add them to ConOut, ConIn,\r
- // ErrOut\r
- //\r
- VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);\r
-\r
- //\r
- // Have chance to connect the platform default console,\r
- // the platform default console is the minimum device group\r
- // the platform should support\r
- //\r
- for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {\r
- //\r
- // Update the console variable with the connect type\r
- //\r
- if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r
- EfiBootManagerUpdateConsoleVariable (\r
- ConIn,\r
- PlatformConsole[Index].DevicePath,\r
- NULL\r
- );\r
- }\r
-\r
- if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
- EfiBootManagerUpdateConsoleVariable (\r
- ConOut,\r
- PlatformConsole[Index].DevicePath,\r
- NULL\r
- );\r
- }\r
-\r
- if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
- EfiBootManagerUpdateConsoleVariable (\r
- ErrOut,\r
- PlatformConsole[Index].DevicePath,\r
- NULL\r
- );\r
- }\r
- }\r
-}\r
-\r
-/**\r
- Configure PCI Interrupt Line register for applicable devices\r
- Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()\r
-\r
- @param[in] Handle - Handle of PCI device instance\r
- @param[in] PciIo - PCI IO protocol instance\r
- @param[in] PciHdr - PCI Header register block\r
-\r
- @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SetPciIntLine (\r
- IN EFI_HANDLE Handle,\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN PCI_TYPE00 *PciHdr\r
- )\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
- EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
- UINTN RootSlot;\r
- UINTN Idx;\r
- UINT8 IrqLine;\r
- EFI_STATUS Status;\r
- UINT32 RootBusNumber;\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- if (PciHdr->Device.InterruptPin != 0) {\r
- DevPathNode = DevicePathFromHandle (Handle);\r
- ASSERT (DevPathNode != NULL);\r
- DevPath = DevPathNode;\r
-\r
- RootBusNumber = 0;\r
- if ((DevicePathType (DevPathNode) == ACPI_DEVICE_PATH) &&\r
- (DevicePathSubType (DevPathNode) == ACPI_DP) &&\r
- (((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID (0x0A03)))\r
- {\r
- RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;\r
- }\r
-\r
- //\r
- // Compute index into PciHostIrqs[] table by walking\r
- // the device path and adding up all device numbers\r
- //\r
- Status = EFI_NOT_FOUND;\r
- RootSlot = 0;\r
- Idx = PciHdr->Device.InterruptPin - 1;\r
- while (!IsDevicePathEnd (DevPathNode)) {\r
- if ((DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH) &&\r
- (DevicePathSubType (DevPathNode) == HW_PCI_DP))\r
- {\r
- Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;\r
-\r
- //\r
- // Unlike SeaBIOS, which starts climbing from the leaf device\r
- // up toward the root, we traverse the device path starting at\r
- // the root moving toward the leaf node.\r
- // The slot number of the top-level parent bridge is needed for\r
- // Q35 cases with more than 24 slots on the root bus.\r
- //\r
- if (Status != EFI_SUCCESS) {\r
- Status = EFI_SUCCESS;\r
- RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;\r
- }\r
- }\r
-\r
- DevPathNode = NextDevicePathNode (DevPathNode);\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- if ((RootBusNumber == 0) && (RootSlot == 0)) {\r
- DEBUG ((\r
- DEBUG_ERROR,\r
- "%a: PCI host bridge (00:00.0) should have no interrupts!\n",\r
- __func__\r
- ));\r
- ASSERT (FALSE);\r
- }\r
-\r
- //\r
- // Final PciHostIrqs[] index calculation depends on the platform\r
- // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()\r
- //\r
- switch (mHostBridgeDevId) {\r
- case INTEL_82441_DEVICE_ID:\r
- Idx -= 1;\r
- break;\r
- case INTEL_Q35_MCH_DEVICE_ID:\r
- //\r
- // SeaBIOS contains the following comment:\r
- // "Slots 0-24 rotate slot:pin mapping similar to piix above, but\r
- // with a different starting index - see q35-acpi-dsdt.dsl.\r
- //\r
- // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"\r
- //\r
- if (RootSlot > 24) {\r
- //\r
- // in this case, subtract back out RootSlot from Idx\r
- // (SeaBIOS never adds it to begin with, but that would make our\r
- // device path traversal loop above too awkward)\r
- //\r
- Idx -= RootSlot;\r
- }\r
-\r
- break;\r
- default:\r
- ASSERT (FALSE); // should never get here\r
- }\r
-\r
- Idx %= ARRAY_SIZE (PciHostIrqs);\r
- IrqLine = PciHostIrqs[Idx];\r
-\r
- DEBUG_CODE_BEGIN ();\r
- {\r
- CHAR16 *DevPathString;\r
- STATIC CHAR16 Fallback[] = L"<failed to convert>";\r
- UINTN Segment, Bus, Device, Function;\r
-\r
- DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);\r
- if (DevPathString == NULL) {\r
- DevPathString = Fallback;\r
- }\r
-\r
- Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- DEBUG ((\r
- DEBUG_VERBOSE,\r
- "%a: [%02x:%02x.%x] %s -> 0x%02x\n",\r
- __func__,\r
- (UINT32)Bus,\r
- (UINT32)Device,\r
- (UINT32)Function,\r
- DevPathString,\r
- IrqLine\r
- ));\r
-\r
- if (DevPathString != Fallback) {\r
- FreePool (DevPathString);\r
- }\r
- }\r
- DEBUG_CODE_END ();\r
-\r
- //\r
- // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]\r
- //\r
- Status = PciIo->Pci.Write (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- PCI_INT_LINE_OFFSET,\r
- 1,\r
- &IrqLine\r
- );\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-VOID\r
-PciAcpiInitialization (\r
- )\r
-{\r
- UINTN Pmba;\r
-\r
- //\r
- // Query Host Bridge DID to determine platform type\r
- //\r
- mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);\r
- switch (mHostBridgeDevId) {\r
- case INTEL_82441_DEVICE_ID:\r
- Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);\r
- //\r
- // 00:01.0 ISA Bridge (PIIX4) LNK routing targets\r
- //\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D\r
- break;\r
- case INTEL_Q35_MCH_DEVICE_ID:\r
- Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);\r
- //\r
- // 00:1f.0 LPC Bridge (Q35) LNK routing targets\r
- //\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H\r
- break;\r
- default:\r
- DEBUG ((\r
- DEBUG_ERROR,\r
- "%a: Unknown Host Bridge Device ID: 0x%04x\n",\r
- __func__,\r
- mHostBridgeDevId\r
- ));\r
- ASSERT (FALSE);\r
- return;\r
- }\r
-\r
- //\r
- // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices\r
- //\r
- VisitAllPciInstances (SetPciIntLine);\r
-\r
- //\r
- // Set ACPI SCI_EN bit in PMCNTRL\r
- //\r
- IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-ConnectRecursivelyIfPciMassStorage (\r
- IN EFI_HANDLE Handle,\r
- IN EFI_PCI_IO_PROTOCOL *Instance,\r
- IN PCI_TYPE00 *PciHeader\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- CHAR16 *DevPathStr;\r
-\r
- //\r
- // Recognize PCI Mass Storage\r
- //\r
- if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {\r
- DevicePath = NULL;\r
- Status = gBS->HandleProtocol (\r
- Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID *)&DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Print Device Path\r
- //\r
- DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
- if (DevPathStr != NULL) {\r
- DEBUG ((\r
- DEBUG_INFO,\r
- "Found Mass Storage device: %s\n",\r
- DevPathStr\r
- ));\r
- FreePool (DevPathStr);\r
- }\r
-\r
- Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Connect with predefined platform connect sequence.\r
-\r
- The OEM/IBV can customize with their own connect sequence.\r
-**/\r
-VOID\r
-PlatformBdsConnectSequence (\r
- VOID\r
- )\r
-{\r
- UINTN Index;\r
-\r
- DEBUG ((DEBUG_INFO, "PlatformBdsConnectSequence\n"));\r
-\r
- Index = 0;\r
-\r
- //\r
- // Here we can get the customized platform connect sequence\r
- // Notes: we can connect with new variable which record the\r
- // last time boots connect device path sequence\r
- //\r
- while (gPlatformConnectSequence[Index] != NULL) {\r
- //\r
- // Build the platform boot option\r
- //\r
- EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);\r
- Index++;\r
- }\r
-\r
- EfiBootManagerConnectAll ();\r
-}\r
-\r
-/**\r
- Do the platform specific action after the console is ready\r
-\r
- Possible things that can be done in PlatformBootManagerAfterConsole:\r
-\r
- > Console post action:\r
- > Dynamically switch output mode from 100x31 to 80x25 for certain senarino\r
- > Signal console ready platform customized event\r
- > Run diagnostics like memory testing\r
- > Connect certain devices\r
- > Dispatch aditional option roms\r
- > Special boot: e.g.: USB boot, enter UI\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBootManagerAfterConsole (\r
- VOID\r
- )\r
-{\r
- EFI_BOOT_MODE BootMode;\r
-\r
- DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n"));\r
-\r
- //\r
- // Get current Boot Mode\r
- //\r
- BootMode = GetBootModeHob ();\r
- DEBUG ((DEBUG_INFO, "Boot Mode:%x\n", BootMode));\r
-\r
- //\r
- // Go the different platform policy with different boot mode\r
- // Notes: this part code can be change with the table policy\r
- //\r
- ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);\r
-\r
- //\r
- // Logo show\r
- //\r
- BootLogoEnableLogo ();\r
-\r
- //\r
- // Set PCI Interrupt Line registers and ACPI SCI_EN\r
- //\r
- PciAcpiInitialization ();\r
-\r
- //\r
- // Process QEMU's -kernel command line option\r
- //\r
- TryRunningQemuKernel ();\r
-\r
- //\r
- // Perform some platform specific connect sequence\r
- //\r
- PlatformBdsConnectSequence ();\r
-\r
- EfiBootManagerRefreshAllBootOption ();\r
-\r
- //\r
- // Register UEFI Shell (Will be removed if the Shell isn't built\r
- // which is the default)\r
- //\r
- PlatformRegisterFvBootOption (\r
- &gUefiShellFileGuid,\r
- L"EFI Internal Shell",\r
- LOAD_OPTION_ACTIVE\r
- );\r
-\r
- //\r
- // Register Grub\r
- //\r
- PlatformRegisterFvBootOption (\r
- &gGrubFileGuid,\r
- L"Grub Bootloader",\r
- LOAD_OPTION_ACTIVE\r
- );\r
-\r
- RemoveStaleFvFileOptions ();\r
-\r
- PlatformBmPrintScRegisterHandler ();\r
-}\r
-\r
-/**\r
- This notification function is invoked when an instance of the\r
- EFI_DEVICE_PATH_PROTOCOL is produced.\r
-\r
- @param Event The event that occurred\r
- @param Context For EFI compatibility. Not used.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-NotifyDevPath (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- EFI_HANDLE Handle;\r
- EFI_STATUS Status;\r
- UINTN BufferSize;\r
- EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
- ATAPI_DEVICE_PATH *Atapi;\r
-\r
- //\r
- // Examine all new handles\r
- //\r
- for ( ; ;) {\r
- //\r
- // Get the next handle\r
- //\r
- BufferSize = sizeof (Handle);\r
- Status = gBS->LocateHandle (\r
- ByRegisterNotify,\r
- NULL,\r
- mEfiDevPathNotifyReg,\r
- &BufferSize,\r
- &Handle\r
- );\r
-\r
- //\r
- // If not found, we're done\r
- //\r
- if (EFI_NOT_FOUND == Status) {\r
- break;\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- //\r
- // Get the DevicePath protocol on that handle\r
- //\r
- Status = gBS->HandleProtocol (\r
- Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **)&DevPathNode\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- while (!IsDevicePathEnd (DevPathNode)) {\r
- //\r
- // Find the handler to dump this device path node\r
- //\r
- if (\r
- (DevicePathType (DevPathNode) == MESSAGING_DEVICE_PATH) &&\r
- (DevicePathSubType (DevPathNode) == MSG_ATAPI_DP)\r
- )\r
- {\r
- Atapi = (ATAPI_DEVICE_PATH *)DevPathNode;\r
- PciOr16 (\r
- PCI_LIB_ADDRESS (\r
- 0,\r
- 1,\r
- 1,\r
- (Atapi->PrimarySecondary == 1) ? 0x42 : 0x40\r
- ),\r
- BIT15\r
- );\r
- }\r
-\r
- //\r
- // Next device path node\r
- //\r
- DevPathNode = NextDevicePathNode (DevPathNode);\r
- }\r
- }\r
-\r
- return;\r
-}\r
-\r
-VOID\r
-InstallDevicePathCallback (\r
- VOID\r
- )\r
-{\r
- DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));\r
- mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (\r
- &gEfiDevicePathProtocolGuid,\r
- TPL_CALLBACK,\r
- NotifyDevPath,\r
- NULL,\r
- &mEfiDevPathNotifyReg\r
- );\r
-}\r
-\r
-/**\r
- This function is called each second during the boot manager waits the\r
- timeout.\r
-\r
- @param TimeoutRemain The remaining timeout.\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBootManagerWaitCallback (\r
- UINT16 TimeoutRemain\r
- )\r
-{\r
- //\r
- // Since the timeout should be forced to zero we should never\r
- // Get here\r
- //\r
- ASSERT (FALSE);\r
-}\r
-\r
-/**\r
- The function is called when no boot option could be launched,\r
- including platform recovery options and options pointing to applications\r
- built into firmware volumes.\r
-\r
- If this function returns, BDS attempts to enter an infinite loop.\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBootManagerUnableToBoot (\r
- VOID\r
- )\r
-{\r
- //\r
- // If we get here something failed about the grub boot but since\r
- // We're privy to the secret we must panic and not retry or loop\r
- //\r
- ASSERT (FALSE);\r
- CpuDeadLoop ();\r
-}\r