summaryrefslogtreecommitdiffstats
path: root/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c
diff options
context:
space:
mode:
Diffstat (limited to 'ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c')
-rw-r--r--ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c1340
1 files changed, 0 insertions, 1340 deletions
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c
deleted file mode 100644
index 8e93f3cfed..0000000000
--- a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c
+++ /dev/null
@@ -1,1340 +0,0 @@
-/** @file
- Implementation for PlatformBootManagerLib library class interfaces.
-
- Copyright (C) 2015-2016, Red Hat, Inc.
- Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
- Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <IndustryStandard/Pci22.h>
-#include <IndustryStandard/Virtio095.h>
-#include <Library/BootLogoLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/PcdLib.h>
-#include <Library/PlatformBmPrintScLib.h>
-#include <Library/QemuBootOrderLib.h>
-#include <Library/QemuFwCfgSimpleParserLib.h>
-#include <Library/TpmPlatformHierarchyLib.h>
-#include <Library/UefiBootManagerLib.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/FirmwareVolume2.h>
-#include <Protocol/GraphicsOutput.h>
-#include <Protocol/LoadedImage.h>
-#include <Protocol/PciIo.h>
-#include <Protocol/PciRootBridgeIo.h>
-#include <Protocol/VirtioDevice.h>
-#include <Guid/EventGroup.h>
-#include <Guid/GlobalVariable.h>
-#include <Guid/RootBridgesConnectedEventGroup.h>
-#include <Guid/SerialPortLibVendor.h>
-
-#include "PlatformBm.h"
-
-#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
-
-#pragma pack (1)
-typedef struct {
- VENDOR_DEVICE_PATH SerialDxe;
- UART_DEVICE_PATH Uart;
- VENDOR_DEFINED_DEVICE_PATH TermType;
- EFI_DEVICE_PATH_PROTOCOL End;
-} PLATFORM_SERIAL_CONSOLE;
-#pragma pack ()
-
-STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {
- //
- // VENDOR_DEVICE_PATH SerialDxe
- //
- {
- { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },
- EDKII_SERIAL_PORT_LIB_VENDOR_GUID
- },
-
- //
- // UART_DEVICE_PATH Uart
- //
- {
- { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) },
- 0, // Reserved
- FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
- FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits
- FixedPcdGet8 (PcdUartDefaultParity), // Parity
- FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits
- },
-
- //
- // VENDOR_DEFINED_DEVICE_PATH TermType
- //
- {
- {
- MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,
- DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)
- }
- //
- // Guid to be filled in dynamically
- //
- },
-
- //
- // EFI_DEVICE_PATH_PROTOCOL End
- //
- {
- END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
- DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
- }
-};
-
-#pragma pack (1)
-typedef struct {
- USB_CLASS_DEVICE_PATH Keyboard;
- EFI_DEVICE_PATH_PROTOCOL End;
-} PLATFORM_USB_KEYBOARD;
-#pragma pack ()
-
-STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {
- //
- // USB_CLASS_DEVICE_PATH Keyboard
- //
- {
- {
- MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,
- DP_NODE_LEN (USB_CLASS_DEVICE_PATH)
- },
- 0xFFFF, // VendorId: any
- 0xFFFF, // ProductId: any
- 3, // DeviceClass: HID
- 1, // DeviceSubClass: boot
- 1 // DeviceProtocol: keyboard
- },
-
- //
- // EFI_DEVICE_PATH_PROTOCOL End
- //
- {
- END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
- DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
- }
-};
-
-/**
- Check if the handle satisfies a particular condition.
-
- @param[in] Handle The handle to check.
- @param[in] ReportText A caller-allocated string passed in for reporting
- purposes. It must never be NULL.
-
- @retval TRUE The condition is satisfied.
- @retval FALSE Otherwise. This includes the case when the condition could not
- be fully evaluated due to an error.
-**/
-typedef
-BOOLEAN
-(EFIAPI *FILTER_FUNCTION)(
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- );
-
-/**
- Process a handle.
-
- @param[in] Handle The handle to process.
- @param[in] ReportText A caller-allocated string passed in for reporting
- purposes. It must never be NULL.
-**/
-typedef
-VOID
-(EFIAPI *CALLBACK_FUNCTION)(
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- );
-
-/**
- Locate all handles that carry the specified protocol, filter them with a
- callback function, and pass each handle that passes the filter to another
- callback.
-
- @param[in] ProtocolGuid The protocol to look for.
-
- @param[in] Filter The filter function to pass each handle to. If this
- parameter is NULL, then all handles are processed.
-
- @param[in] Process The callback function to pass each handle to that
- clears the filter.
-**/
-STATIC
-VOID
-FilterAndProcess (
- IN EFI_GUID *ProtocolGuid,
- IN FILTER_FUNCTION Filter OPTIONAL,
- IN CALLBACK_FUNCTION Process
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *Handles;
- UINTN NoHandles;
- UINTN Idx;
-
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- ProtocolGuid,
- NULL /* SearchKey */,
- &NoHandles,
- &Handles
- );
- if (EFI_ERROR (Status)) {
- //
- // This is not an error, just an informative condition.
- //
- DEBUG ((
- DEBUG_VERBOSE,
- "%a: %g: %r\n",
- __func__,
- ProtocolGuid,
- Status
- ));
- return;
- }
-
- ASSERT (NoHandles > 0);
- for (Idx = 0; Idx < NoHandles; ++Idx) {
- CHAR16 *DevicePathText;
- STATIC CHAR16 Fallback[] = L"<device path unavailable>";
-
- //
- // The ConvertDevicePathToText() function handles NULL input transparently.
- //
- DevicePathText = ConvertDevicePathToText (
- DevicePathFromHandle (Handles[Idx]),
- FALSE, // DisplayOnly
- FALSE // AllowShortcuts
- );
- if (DevicePathText == NULL) {
- DevicePathText = Fallback;
- }
-
- if ((Filter == NULL) || Filter (Handles[Idx], DevicePathText)) {
- Process (Handles[Idx], DevicePathText);
- }
-
- if (DevicePathText != Fallback) {
- FreePool (DevicePathText);
- }
- }
-
- gBS->FreePool (Handles);
-}
-
-/**
- This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
-**/
-STATIC
-BOOLEAN
-EFIAPI
-IsPciDisplay (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- )
-{
- EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- PCI_TYPE00 Pci;
-
- Status = gBS->HandleProtocol (
- Handle,
- &gEfiPciIoProtocolGuid,
- (VOID **)&PciIo
- );
- if (EFI_ERROR (Status)) {
- //
- // This is not an error worth reporting.
- //
- return FALSE;
- }
-
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint32,
- 0 /* Offset */,
- sizeof Pci / sizeof (UINT32),
- &Pci
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __func__, ReportText, Status));
- return FALSE;
- }
-
- return IS_PCI_DISPLAY (&Pci);
-}
-
-/**
- This function checks if a handle corresponds to the Virtio Device ID given
- at the VIRTIO_DEVICE_PROTOCOL level.
-**/
-STATIC
-BOOLEAN
-EFIAPI
-IsVirtio (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText,
- IN UINT16 VirtIoDeviceId
- )
-{
- EFI_STATUS Status;
- VIRTIO_DEVICE_PROTOCOL *VirtIo;
-
- Status = gBS->HandleProtocol (
- Handle,
- &gVirtioDeviceProtocolGuid,
- (VOID **)&VirtIo
- );
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
-
- return (BOOLEAN)(VirtIo->SubSystemDeviceId ==
- VirtIoDeviceId);
-}
-
-/**
- This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
- the VIRTIO_DEVICE_PROTOCOL level.
-**/
-STATIC
-BOOLEAN
-EFIAPI
-IsVirtioRng (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- )
-{
- return IsVirtio (Handle, ReportText, VIRTIO_SUBSYSTEM_ENTROPY_SOURCE);
-}
-
-/**
- This FILTER_FUNCTION checks if a handle corresponds to a Virtio serial device at
- the VIRTIO_DEVICE_PROTOCOL level.
-**/
-STATIC
-BOOLEAN
-EFIAPI
-IsVirtioSerial (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- )
-{
- return IsVirtio (Handle, ReportText, VIRTIO_SUBSYSTEM_CONSOLE);
-}
-
-/**
- This function checks if a handle corresponds to the Virtio Device ID given
- at the EFI_PCI_IO_PROTOCOL level.
-**/
-STATIC
-BOOLEAN
-EFIAPI
-IsVirtioPci (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText,
- IN UINT16 VirtIoDeviceId
- )
-{
- EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- UINT16 VendorId;
- UINT16 DeviceId;
- UINT8 RevisionId;
- BOOLEAN Virtio10;
- UINT16 SubsystemId;
-
- Status = gBS->HandleProtocol (
- Handle,
- &gEfiPciIoProtocolGuid,
- (VOID **)&PciIo
- );
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
-
- //
- // Read and check VendorId.
- //
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint16,
- PCI_VENDOR_ID_OFFSET,
- 1,
- &VendorId
- );
- if (EFI_ERROR (Status)) {
- goto PciError;
- }
-
- if (VendorId != VIRTIO_VENDOR_ID) {
- return FALSE;
- }
-
- //
- // Read DeviceId and RevisionId.
- //
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint16,
- PCI_DEVICE_ID_OFFSET,
- 1,
- &DeviceId
- );
- if (EFI_ERROR (Status)) {
- goto PciError;
- }
-
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint8,
- PCI_REVISION_ID_OFFSET,
- 1,
- &RevisionId
- );
- if (EFI_ERROR (Status)) {
- goto PciError;
- }
-
- //
- // From DeviceId and RevisionId, determine whether the device is a
- // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
- // immediately be restricted to VirtIoDeviceId, and
- // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
- // only be sanity-checked, and SubsystemId will decide.
- //
- if ((DeviceId == 0x1040 + VirtIoDeviceId) &&
- (RevisionId >= 0x01))
- {
- Virtio10 = TRUE;
- } else if ((DeviceId >= 0x1000) && (DeviceId <= 0x103F) && (RevisionId == 0x00)) {
- Virtio10 = FALSE;
- } else {
- return FALSE;
- }
-
- //
- // Read and check SubsystemId as dictated by Virtio10.
- //
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint16,
- PCI_SUBSYSTEM_ID_OFFSET,
- 1,
- &SubsystemId
- );
- if (EFI_ERROR (Status)) {
- goto PciError;
- }
-
- if (Virtio10 && (SubsystemId >= 0x40)) {
- return TRUE;
- }
-
- if (!Virtio10 && (SubsystemId == VirtIoDeviceId)) {
- return TRUE;
- }
-
- return FALSE;
-
-PciError:
- DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __func__, ReportText, Status));
- return FALSE;
-}
-
-/**
- This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at
- the EFI_PCI_IO_PROTOCOL level.
-**/
-STATIC
-BOOLEAN
-EFIAPI
-IsVirtioPciRng (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- )
-{
- return IsVirtioPci (Handle, ReportText, VIRTIO_SUBSYSTEM_ENTROPY_SOURCE);
-}
-
-/**
- This FILTER_FUNCTION checks if a handle corresponds to a Virtio serial device at
- the EFI_PCI_IO_PROTOCOL level.
-**/
-STATIC
-BOOLEAN
-EFIAPI
-IsVirtioPciSerial (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- )
-{
- return IsVirtioPci (Handle, ReportText, VIRTIO_SUBSYSTEM_CONSOLE);
-}
-
-/**
- This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
- the matching driver to produce all first-level child handles.
-**/
-STATIC
-VOID
-EFIAPI
-Connect (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- )
-{
- EFI_STATUS Status;
-
- Status = gBS->ConnectController (
- Handle, // ControllerHandle
- NULL, // DriverImageHandle
- NULL, // RemainingDevicePath -- produce all children
- FALSE // Recursive
- );
- DEBUG ((
- EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
- "%a: %s: %r\n",
- __func__,
- ReportText,
- Status
- ));
-}
-
-/**
- This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
- handle, and adds it to ConOut and ErrOut.
-**/
-STATIC
-VOID
-EFIAPI
-AddOutput (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
-
- DevicePath = DevicePathFromHandle (Handle);
- if (DevicePath == NULL) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: %s: handle %p: device path not found\n",
- __func__,
- ReportText,
- Handle
- ));
- return;
- }
-
- Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: %s: adding to ConOut: %r\n",
- __func__,
- ReportText,
- Status
- ));
- return;
- }
-
- Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: %s: adding to ErrOut: %r\n",
- __func__,
- ReportText,
- Status
- ));
- return;
- }
-
- DEBUG ((
- DEBUG_VERBOSE,
- "%a: %s: added to ConOut and ErrOut\n",
- __func__,
- ReportText
- ));
-}
-
-/**
- This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from
- the handle, appends serial, uart and terminal nodes, finally updates
- ConIn, ConOut and ErrOut.
-**/
-STATIC
-VOID
-EFIAPI
-SetupVirtioSerial (
- IN EFI_HANDLE Handle,
- IN CONST CHAR16 *ReportText
- )
-{
- STATIC CONST ACPI_HID_DEVICE_PATH SerialNode = {
- {
- ACPI_DEVICE_PATH,
- ACPI_DP,
- {
- (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)),
- (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
- },
- },
- EISA_PNP_ID (0x0501),
- 0
- };
-
- STATIC CONST UART_DEVICE_PATH UartNode = {
- {
- MESSAGING_DEVICE_PATH,
- MSG_UART_DP,
- {
- (UINT8)(sizeof (UART_DEVICE_PATH)),
- (UINT8)((sizeof (UART_DEVICE_PATH)) >> 8)
- },
- },
- 0,
- 115200,
- 8,
- 1,
- 1
- };
-
- STATIC VENDOR_DEVICE_PATH TerminalNode = {
- {
- MESSAGING_DEVICE_PATH,
- MSG_VENDOR_DP,
- {
- (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
- (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
- },
- },
- // copy from PcdTerminalTypeGuidBuffer
- };
-
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath, *OldDevicePath;
-
- DevicePath = DevicePathFromHandle (Handle);
-
- if (DevicePath == NULL) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: %s: handle %p: device path not found\n",
- __func__,
- ReportText,
- Handle
- ));
- return;
- }
-
- CopyGuid (
- &TerminalNode.Guid,
- PcdGetPtr (PcdTerminalTypeGuidBuffer)
- );
-
- DevicePath = AppendDevicePathNode (
- DevicePath,
- &SerialNode.Header
- );
-
- OldDevicePath = DevicePath;
- DevicePath = AppendDevicePathNode (
- DevicePath,
- &UartNode.Header
- );
- FreePool (OldDevicePath);
-
- OldDevicePath = DevicePath;
- DevicePath = AppendDevicePathNode (
- DevicePath,
- &TerminalNode.Header
- );
- FreePool (OldDevicePath);
-
- Status = EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: %s: adding to ConIn: %r\n",
- __func__,
- ReportText,
- Status
- ));
- return;
- }
-
- Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
-
- "%a: %s: adding to ConOut: %r\n",
- __func__,
- ReportText,
- Status
- ));
- return;
- }
-
- Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "%a: %s: adding to ErrOut: %r\n",
- __func__,
- ReportText,
- Status
- ));
- return;
- }
-
- FreePool (DevicePath);
-
- DEBUG ((
- DEBUG_VERBOSE,
- "%a: %s: added to ConIn, ConOut and ErrOut\n",
- __func__,
- ReportText
- ));
-}
-
-STATIC
-VOID
-PlatformRegisterFvBootOption (
- EFI_GUID *FileGuid,
- CHAR16 *Description,
- UINT32 Attributes
- )
-{
- EFI_STATUS Status;
- INTN OptionIndex;
- EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
- UINTN BootOptionCount;
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
-
- Status = gBS->HandleProtocol (
- gImageHandle,
- &gEfiLoadedImageProtocolGuid,
- (VOID **)&LoadedImage
- );
- ASSERT_EFI_ERROR (Status);
-
- EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
- DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
- ASSERT (DevicePath != NULL);
- DevicePath = AppendDevicePathNode (
- DevicePath,
- (EFI_DEVICE_PATH_PROTOCOL *)&FileNode
- );
- ASSERT (DevicePath != NULL);
-
- Status = EfiBootManagerInitializeLoadOption (
- &NewOption,
- LoadOptionNumberUnassigned,
- LoadOptionTypeBoot,
- Attributes,
- Description,
- DevicePath,
- NULL,
- 0
- );
- ASSERT_EFI_ERROR (Status);
- FreePool (DevicePath);
-
- BootOptions = EfiBootManagerGetLoadOptions (
- &BootOptionCount,
- LoadOptionTypeBoot
- );
-
- OptionIndex = EfiBootManagerFindLoadOption (
- &NewOption,
- BootOptions,
- BootOptionCount
- );
-
- if (OptionIndex == -1) {
- Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
- ASSERT_EFI_ERROR (Status);
- }
-
- EfiBootManagerFreeLoadOption (&NewOption);
- EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
-}
-
-/**
- Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
- whose device paths do not resolve exactly to an FvFile in the system.
-
- This removes any boot options that point to binaries built into the firmware
- and have become stale due to any of the following:
- - FvMain's base address or size changed (historical),
- - FvMain's FvNameGuid changed,
- - the FILE_GUID of the pointed-to binary changed,
- - the referenced binary is no longer built into the firmware.
-
- EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
- avoids exact duplicates.
-**/
-STATIC
-VOID
-RemoveStaleFvFileOptions (
- VOID
- )
-{
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
- UINTN BootOptionCount;
- UINTN Index;
-
- BootOptions = EfiBootManagerGetLoadOptions (
- &BootOptionCount,
- LoadOptionTypeBoot
- );
-
- for (Index = 0; Index < BootOptionCount; ++Index) {
- EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
- EFI_STATUS Status;
- EFI_HANDLE FvHandle;
-
- //
- // If the device path starts with neither MemoryMapped(...) nor Fv(...),
- // then keep the boot option.
- //
- Node1 = BootOptions[Index].FilePath;
- if (!((DevicePathType (Node1) == HARDWARE_DEVICE_PATH) &&
- (DevicePathSubType (Node1) == HW_MEMMAP_DP)) &&
- !((DevicePathType (Node1) == MEDIA_DEVICE_PATH) &&
- (DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)))
- {
- continue;
- }
-
- //
- // If the second device path node is not FvFile(...), then keep the boot
- // option.
- //
- Node2 = NextDevicePathNode (Node1);
- if ((DevicePathType (Node2) != MEDIA_DEVICE_PATH) ||
- (DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP))
- {
- continue;
- }
-
- //
- // Locate the Firmware Volume2 protocol instance that is denoted by the
- // boot option. If this lookup fails (i.e., the boot option references a
- // firmware volume that doesn't exist), then we'll proceed to delete the
- // boot option.
- //
- SearchNode = Node1;
- Status = gBS->LocateDevicePath (
- &gEfiFirmwareVolume2ProtocolGuid,
- &SearchNode,
- &FvHandle
- );
-
- if (!EFI_ERROR (Status)) {
- //
- // The firmware volume was found; now let's see if it contains the FvFile
- // identified by GUID.
- //
- EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
- UINTN BufferSize;
- EFI_FV_FILETYPE FoundType;
- EFI_FV_FILE_ATTRIBUTES FileAttributes;
- UINT32 AuthenticationStatus;
-
- Status = gBS->HandleProtocol (
- FvHandle,
- &gEfiFirmwareVolume2ProtocolGuid,
- (VOID **)&FvProtocol
- );
- ASSERT_EFI_ERROR (Status);
-
- FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
- //
- // Buffer==NULL means we request metadata only: BufferSize, FoundType,
- // FileAttributes.
- //
- Status = FvProtocol->ReadFile (
- FvProtocol,
- &FvFileNode->FvFileName, // NameGuid
- NULL, // Buffer
- &BufferSize,
- &FoundType,
- &FileAttributes,
- &AuthenticationStatus
- );
- if (!EFI_ERROR (Status)) {
- //
- // The FvFile was found. Keep the boot option.
- //
- continue;
- }
- }
-
- //
- // Delete the boot option.
- //
- Status = EfiBootManagerDeleteLoadOptionVariable (
- BootOptions[Index].OptionNumber,
- LoadOptionTypeBoot
- );
- DEBUG_CODE_BEGIN ();
- CHAR16 *DevicePathString;
-
- DevicePathString = ConvertDevicePathToText (
- BootOptions[Index].FilePath,
- FALSE,
- FALSE
- );
- DEBUG ((
- EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_VERBOSE,
- "%a: removing stale Boot#%04x %s: %r\n",
- __func__,
- (UINT32)BootOptions[Index].OptionNumber,
- DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
- Status
- ));
- if (DevicePathString != NULL) {
- FreePool (DevicePathString);
- }
-
- DEBUG_CODE_END ();
- }
-
- EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
-}
-
-STATIC
-VOID
-PlatformRegisterOptionsAndKeys (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_INPUT_KEY Enter;
- EFI_INPUT_KEY F2;
- EFI_INPUT_KEY Esc;
- EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
-
- //
- // Register ENTER as CONTINUE key
- //
- Enter.ScanCode = SCAN_NULL;
- Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
- Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Map F2 and ESC to Boot Manager Menu
- //
- F2.ScanCode = SCAN_F2;
- F2.UnicodeChar = CHAR_NULL;
- Esc.ScanCode = SCAN_ESC;
- Esc.UnicodeChar = CHAR_NULL;
- Status = EfiBootManagerGetBootManagerMenu (&BootOption);
- ASSERT_EFI_ERROR (Status);
- Status = EfiBootManagerAddKeyOptionVariable (
- NULL,
- (UINT16)BootOption.OptionNumber,
- 0,
- &F2,
- NULL
- );
- ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
- Status = EfiBootManagerAddKeyOptionVariable (
- NULL,
- (UINT16)BootOption.OptionNumber,
- 0,
- &Esc,
- NULL
- );
- ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
-}
-
-//
-// BDS Platform Functions
-//
-
-/**
- Do the platform init, can be customized by OEM/IBV
- Possible things that can be done in PlatformBootManagerBeforeConsole:
- > Update console variable: 1. include hot-plug devices;
- > 2. Clear ConIn and add SOL for AMT
- > Register new Driver#### or Boot####
- > Register new Key####: e.g.: F12
- > Signal ReadyToLock event
- > Authentication action: 1. connect Auth devices;
- > 2. Identify auto logon user.
-**/
-VOID
-EFIAPI
-PlatformBootManagerBeforeConsole (
- VOID
- )
-{
- UINT16 FrontPageTimeout;
- RETURN_STATUS PcdStatus;
- EFI_STATUS Status;
-
- //
- // Signal EndOfDxe PI Event
- //
- EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
-
- //
- // Disable the TPM 2 platform hierarchy
- //
- ConfigureTpmPlatformHierarchy ();
-
- //
- // Dispatch deferred images after EndOfDxe event.
- //
- EfiBootManagerDispatchDeferredImages ();
-
- //
- // Locate the PCI root bridges and make the PCI bus driver connect each,
- // non-recursively. This will produce a number of child handles with PciIo on
- // them.
- //
- FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);
-
- //
- // Signal the ACPI platform driver that it can download QEMU ACPI tables.
- //
- EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);
-
- //
- // Find all display class PCI devices (using the handles from the previous
- // step), and connect them non-recursively. This should produce a number of
- // child handles with GOPs on them.
- //
- FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);
-
- //
- // Now add the device path of all handles with GOP on them to ConOut and
- // ErrOut.
- //
- FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);
-
- //
- // Add the hardcoded short-form USB keyboard device path to ConIn.
- //
- EfiBootManagerUpdateConsoleVariable (
- ConIn,
- (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard,
- NULL
- );
-
- //
- // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
- //
- CopyGuid (
- &mSerialConsole.TermType.Guid,
- PcdGetPtr (PcdTerminalTypeGuidBuffer)
- );
- EfiBootManagerUpdateConsoleVariable (
- ConIn,
- (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,
- NULL
- );
- EfiBootManagerUpdateConsoleVariable (
- ConOut,
- (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,
- NULL
- );
- EfiBootManagerUpdateConsoleVariable (
- ErrOut,
- (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,
- NULL
- );
-
- //
- // Set the front page timeout from the QEMU configuration.
- //
- FrontPageTimeout = GetFrontPageTimeoutFromQemu ();
- PcdStatus = PcdSet16S (PcdPlatformBootTimeOut, FrontPageTimeout);
- ASSERT_RETURN_ERROR (PcdStatus);
- //
- // Reflect the PCD in the standard Timeout variable.
- //
- Status = gRT->SetVariable (
- EFI_TIME_OUT_VARIABLE_NAME,
- &gEfiGlobalVariableGuid,
- (EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS),
- sizeof FrontPageTimeout,
- &FrontPageTimeout
- );
- DEBUG ((
- EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
- "%a: SetVariable(%s, %u): %r\n",
- __func__,
- EFI_TIME_OUT_VARIABLE_NAME,
- FrontPageTimeout,
- Status
- ));
-
- //
- // Register platform-specific boot options and keyboard shortcuts.
- //
- PlatformRegisterOptionsAndKeys ();
-
- //
- // At this point, VIRTIO_DEVICE_PROTOCOL instances exist only for Virtio MMIO
- // transports. Install EFI_RNG_PROTOCOL instances on Virtio MMIO RNG devices.
- //
- FilterAndProcess (&gVirtioDeviceProtocolGuid, IsVirtioRng, Connect);
-
- //
- // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
- // instances on Virtio PCI RNG devices.
- //
- FilterAndProcess (&gEfiPciIoProtocolGuid, IsVirtioPciRng, Connect);
-
- //
- // Register Virtio serial devices as console.
- //
- FilterAndProcess (&gVirtioDeviceProtocolGuid, IsVirtioSerial, SetupVirtioSerial);
- FilterAndProcess (&gEfiPciIoProtocolGuid, IsVirtioPciSerial, SetupVirtioSerial);
-}
-
-/**
- Uninstall the EFI memory attribute protocol if it exists.
-**/
-STATIC
-VOID
-UninstallEfiMemoryAttributesProtocol (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE Handle;
- UINTN Size;
- VOID *MemoryAttributeProtocol;
-
- Size = sizeof (Handle);
- Status = gBS->LocateHandle (
- ByProtocol,
- &gEfiMemoryAttributeProtocolGuid,
- NULL,
- &Size,
- &Handle
- );
-
- if (EFI_ERROR (Status)) {
- ASSERT (Status == EFI_NOT_FOUND);
- return;
- }
-
- Status = gBS->HandleProtocol (
- Handle,
- &gEfiMemoryAttributeProtocolGuid,
- &MemoryAttributeProtocol
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = gBS->UninstallProtocolInterface (
- Handle,
- &gEfiMemoryAttributeProtocolGuid,
- MemoryAttributeProtocol
- );
- ASSERT_EFI_ERROR (Status);
-}
-
-/**
- Do the platform specific action after the console is ready
- Possible things that can be done in PlatformBootManagerAfterConsole:
- > Console post action:
- > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
- > Signal console ready platform customized event
- > Run diagnostics like memory testing
- > Connect certain devices
- > Dispatch additional option roms
- > Special boot: e.g.: USB boot, enter UI
-**/
-VOID
-EFIAPI
-PlatformBootManagerAfterConsole (
- VOID
- )
-{
- RETURN_STATUS Status;
- BOOLEAN Uninstall;
-
- //
- // Show the splash screen.
- //
- BootLogoEnableLogo ();
-
- //
- // Work around shim's terminally broken use of the EFI memory attributes
- // protocol, by uninstalling it if requested on the QEMU command line.
- //
- // E.g.,
- // -fw_cfg opt/org.tianocore/UninstallMemAttrProtocol,string=y
- //
- Uninstall = FixedPcdGetBool (PcdUninstallMemAttrProtocol);
- QemuFwCfgParseBool ("opt/org.tianocore/UninstallMemAttrProtocol", &Uninstall);
- DEBUG ((
- DEBUG_WARN,
- "%a: %auninstalling EFI memory protocol\n",
- __func__,
- Uninstall ? "" : "not "
- ));
- if (Uninstall) {
- UninstallEfiMemoryAttributesProtocol ();
- }
-
- //
- // Process QEMU's -kernel command line option. The kernel booted this way
- // will receive ACPI tables: in PlatformBootManagerBeforeConsole(), we
- // connected any and all PCI root bridges, and then signaled the ACPI
- // platform driver.
- //
- TryRunningQemuKernel ();
-
- //
- // Connect the purported boot devices.
- //
- Status = ConnectDevicesFromQemu ();
- if (RETURN_ERROR (Status)) {
- //
- // Connect the rest of the devices.
- //
- EfiBootManagerConnectAll ();
- }
-
- //
- // Enumerate all possible boot options, then filter and reorder them based on
- // the QEMU configuration.
- //
- EfiBootManagerRefreshAllBootOption ();
-
- //
- // Register UEFI Shell
- //
- PlatformRegisterFvBootOption (
- &gUefiShellFileGuid,
- L"EFI Internal Shell",
- LOAD_OPTION_ACTIVE
- );
-
- RemoveStaleFvFileOptions ();
- SetBootOrderFromQemu ();
-
- PlatformBmPrintScRegisterHandler ();
-}
-
-/**
- This function is called each second during the boot manager waits the
- timeout.
-
- @param TimeoutRemain The remaining timeout.
-**/
-VOID
-EFIAPI
-PlatformBootManagerWaitCallback (
- UINT16 TimeoutRemain
- )
-{
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;
- UINT16 TimeoutInitial;
-
- TimeoutInitial = PcdGet16 (PcdPlatformBootTimeOut);
-
- //
- // If PcdPlatformBootTimeOut is set to zero, then we consider
- // that no progress update should be enacted.
- //
- if (TimeoutInitial == 0) {
- return;
- }
-
- Black.Raw = 0x00000000;
- White.Raw = 0x00FFFFFF;
-
- BootLogoUpdateProgress (
- White.Pixel,
- Black.Pixel,
- L"Start boot option",
- White.Pixel,
- (TimeoutInitial - TimeoutRemain) * 100 / TimeoutInitial,
- 0
- );
-}
-
-/**
- The function is called when no boot option could be launched,
- including platform recovery options and options pointing to applications
- built into firmware volumes.
-
- If this function returns, BDS attempts to enter an infinite loop.
-**/
-VOID
-EFIAPI
-PlatformBootManagerUnableToBoot (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_INPUT_KEY Key;
- EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
- UINTN Index;
-
- //
- // BootManagerMenu doesn't contain the correct information when return status
- // is EFI_NOT_FOUND.
- //
- Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
- if (EFI_ERROR (Status)) {
- return;
- }
-
- //
- // Normally BdsDxe does not print anything to the system console, but this is
- // a last resort -- the end-user will likely not see any DEBUG messages
- // logged in this situation.
- //
- // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
- // here to see if it makes sense to request and wait for a keypress.
- //
- if (gST->ConIn != NULL) {
- AsciiPrint (
- "%a: No bootable option or device was found.\n"
- "%a: Press any key to enter the Boot Manager Menu.\n",
- gEfiCallerBaseName,
- gEfiCallerBaseName
- );
- Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
- ASSERT_EFI_ERROR (Status);
- ASSERT (Index == 0);
-
- //
- // Drain any queued keys.
- //
- while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {
- //
- // just throw away Key
- //
- }
- }
-
- for ( ; ;) {
- EfiBootManagerBoot (&BootManagerMenu);
- }
-}