]> xenbits.xensource.com Git - people/aperard/ovmf.git/commitdiff
ArmVirtPkg: Move PlatformBootManagerLib to OvmfPkg
authorChao Li <lichao@loongson.cn>
Fri, 2 Feb 2024 01:58:42 +0000 (09:58 +0800)
committerLiming Gao <gaoliming@byosoft.com.cn>
Tue, 6 Feb 2024 15:51:47 +0000 (23:51 +0800)
Moved the PlatformBootManagerLib to OvmfPkg and renamed to
PlatformBootManagerLibLight for easy use by other ARCH.

Build-tested only (with "ArmVirtQemu.dsc and OvmfPkgX64.dsc").

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4663

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Lazlo Ersek <lersek@redhat.com>
Signed-off-by: Chao Li <lichao@loongson.cn>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
ArmVirtPkg/ArmVirtPkg.ci.yaml
ArmVirtPkg/ArmVirtQemu.dsc
ArmVirtPkg/ArmVirtQemuKernel.dsc
ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c [deleted file]
ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.h [deleted file]
ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf [deleted file]
ArmVirtPkg/Library/PlatformBootManagerLib/QemuKernel.c [deleted file]
OvmfPkg/Library/PlatformBootManagerLibLight/PlatformBm.c [new file with mode: 0644]
OvmfPkg/Library/PlatformBootManagerLibLight/PlatformBm.h [new file with mode: 0644]
OvmfPkg/Library/PlatformBootManagerLibLight/PlatformBootManagerLib.inf [new file with mode: 0644]
OvmfPkg/Library/PlatformBootManagerLibLight/QemuKernel.c [new file with mode: 0644]

index 506b0e72f0bb2b3310cba4136eb439b8c38946c1..b186d4eb421e91a0a22efbcbe64adc1f3d5f0c3b 100644 (file)
@@ -24,7 +24,6 @@
         ],\r
         ## Both file path and directory path are accepted.\r
         "IgnoreFiles": [\r
-            "Library/PlatformBootManagerLib/PlatformBm.c"\r
         ]\r
     },\r
     ## options defined .pytool/Plugin/CompilerPlugin\r
index 147180f6453dae934fabf12552d65d13f28f1b9c..e48c75b5e99ffae5ff33ea3521f250abc2245665 100644 (file)
@@ -70,7 +70,7 @@
 \r
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf\r
   BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf\r
-  PlatformBootManagerLib|ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf\r
+  PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLibLight/PlatformBootManagerLib.inf\r
   PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf\r
   CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf\r
   FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf\r
index c22a422353d844666513f3a3fdb3577cd17c0b1c..668a65ba648f6b32eea78038eaf144a74a52ac82 100644 (file)
@@ -69,7 +69,7 @@
 \r
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf\r
   BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf\r
-  PlatformBootManagerLib|ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf\r
+  PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLibLight/PlatformBootManagerLib.inf\r
   PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf\r
   CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf\r
   FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf\r
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c
deleted file mode 100644 (file)
index 8e93f3c..0000000
+++ /dev/null
@@ -1,1340 +0,0 @@
-/** @file\r
-  Implementation for PlatformBootManagerLib library class interfaces.\r
-\r
-  Copyright (C) 2015-2016, Red Hat, Inc.\r
-  Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>\r
-  Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
-\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include <IndustryStandard/Pci22.h>\r
-#include <IndustryStandard/Virtio095.h>\r
-#include <Library/BootLogoLib.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/PlatformBmPrintScLib.h>\r
-#include <Library/QemuBootOrderLib.h>\r
-#include <Library/QemuFwCfgSimpleParserLib.h>\r
-#include <Library/TpmPlatformHierarchyLib.h>\r
-#include <Library/UefiBootManagerLib.h>\r
-#include <Protocol/DevicePath.h>\r
-#include <Protocol/FirmwareVolume2.h>\r
-#include <Protocol/GraphicsOutput.h>\r
-#include <Protocol/LoadedImage.h>\r
-#include <Protocol/PciIo.h>\r
-#include <Protocol/PciRootBridgeIo.h>\r
-#include <Protocol/VirtioDevice.h>\r
-#include <Guid/EventGroup.h>\r
-#include <Guid/GlobalVariable.h>\r
-#include <Guid/RootBridgesConnectedEventGroup.h>\r
-#include <Guid/SerialPortLibVendor.h>\r
-\r
-#include "PlatformBm.h"\r
-\r
-#define DP_NODE_LEN(Type)  { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }\r
-\r
-#pragma pack (1)\r
-typedef struct {\r
-  VENDOR_DEVICE_PATH            SerialDxe;\r
-  UART_DEVICE_PATH              Uart;\r
-  VENDOR_DEFINED_DEVICE_PATH    TermType;\r
-  EFI_DEVICE_PATH_PROTOCOL      End;\r
-} PLATFORM_SERIAL_CONSOLE;\r
-#pragma pack ()\r
-\r
-STATIC PLATFORM_SERIAL_CONSOLE  mSerialConsole = {\r
-  //\r
-  // VENDOR_DEVICE_PATH SerialDxe\r
-  //\r
-  {\r
-    { HARDWARE_DEVICE_PATH,  HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },\r
-    EDKII_SERIAL_PORT_LIB_VENDOR_GUID\r
-  },\r
-\r
-  //\r
-  // UART_DEVICE_PATH Uart\r
-  //\r
-  {\r
-    { MESSAGING_DEVICE_PATH, MSG_UART_DP,  DP_NODE_LEN (UART_DEVICE_PATH)   },\r
-    0,                                      // Reserved\r
-    FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate\r
-    FixedPcdGet8 (PcdUartDefaultDataBits),  // DataBits\r
-    FixedPcdGet8 (PcdUartDefaultParity),    // Parity\r
-    FixedPcdGet8 (PcdUartDefaultStopBits)   // StopBits\r
-  },\r
-\r
-  //\r
-  // VENDOR_DEFINED_DEVICE_PATH TermType\r
-  //\r
-  {\r
-    {\r
-      MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,\r
-      DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)\r
-    }\r
-    //\r
-    // Guid to be filled in dynamically\r
-    //\r
-  },\r
-\r
-  //\r
-  // EFI_DEVICE_PATH_PROTOCOL End\r
-  //\r
-  {\r
-    END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
-    DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
-  }\r
-};\r
-\r
-#pragma pack (1)\r
-typedef struct {\r
-  USB_CLASS_DEVICE_PATH       Keyboard;\r
-  EFI_DEVICE_PATH_PROTOCOL    End;\r
-} PLATFORM_USB_KEYBOARD;\r
-#pragma pack ()\r
-\r
-STATIC PLATFORM_USB_KEYBOARD  mUsbKeyboard = {\r
-  //\r
-  // USB_CLASS_DEVICE_PATH Keyboard\r
-  //\r
-  {\r
-    {\r
-      MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,\r
-      DP_NODE_LEN (USB_CLASS_DEVICE_PATH)\r
-    },\r
-    0xFFFF, // VendorId: any\r
-    0xFFFF, // ProductId: any\r
-    3,      // DeviceClass: HID\r
-    1,      // DeviceSubClass: boot\r
-    1       // DeviceProtocol: keyboard\r
-  },\r
-\r
-  //\r
-  // EFI_DEVICE_PATH_PROTOCOL End\r
-  //\r
-  {\r
-    END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
-    DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
-  }\r
-};\r
-\r
-/**\r
-  Check if the handle satisfies a particular condition.\r
-\r
-  @param[in] Handle      The handle to check.\r
-  @param[in] ReportText  A caller-allocated string passed in for reporting\r
-                         purposes. It must never be NULL.\r
-\r
-  @retval TRUE   The condition is satisfied.\r
-  @retval FALSE  Otherwise. This includes the case when the condition could not\r
-                 be fully evaluated due to an error.\r
-**/\r
-typedef\r
-BOOLEAN\r
-(EFIAPI *FILTER_FUNCTION)(\r
-  IN EFI_HANDLE   Handle,\r
-  IN CONST CHAR16 *ReportText\r
-  );\r
-\r
-/**\r
-  Process a handle.\r
-\r
-  @param[in] Handle      The handle to process.\r
-  @param[in] ReportText  A caller-allocated string passed in for reporting\r
-                         purposes. It must never be NULL.\r
-**/\r
-typedef\r
-VOID\r
-(EFIAPI *CALLBACK_FUNCTION)(\r
-  IN EFI_HANDLE   Handle,\r
-  IN CONST CHAR16 *ReportText\r
-  );\r
-\r
-/**\r
-  Locate all handles that carry the specified protocol, filter them with a\r
-  callback function, and pass each handle that passes the filter to another\r
-  callback.\r
-\r
-  @param[in] ProtocolGuid  The protocol to look for.\r
-\r
-  @param[in] Filter        The filter function to pass each handle to. If this\r
-                           parameter is NULL, then all handles are processed.\r
-\r
-  @param[in] Process       The callback function to pass each handle to that\r
-                           clears the filter.\r
-**/\r
-STATIC\r
-VOID\r
-FilterAndProcess (\r
-  IN EFI_GUID           *ProtocolGuid,\r
-  IN FILTER_FUNCTION    Filter         OPTIONAL,\r
-  IN CALLBACK_FUNCTION  Process\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  EFI_HANDLE  *Handles;\r
-  UINTN       NoHandles;\r
-  UINTN       Idx;\r
-\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  ProtocolGuid,\r
-                  NULL /* SearchKey */,\r
-                  &NoHandles,\r
-                  &Handles\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // This is not an error, just an informative condition.\r
-    //\r
-    DEBUG ((\r
-      DEBUG_VERBOSE,\r
-      "%a: %g: %r\n",\r
-      __func__,\r
-      ProtocolGuid,\r
-      Status\r
-      ));\r
-    return;\r
-  }\r
-\r
-  ASSERT (NoHandles > 0);\r
-  for (Idx = 0; Idx < NoHandles; ++Idx) {\r
-    CHAR16         *DevicePathText;\r
-    STATIC CHAR16  Fallback[] = L"<device path unavailable>";\r
-\r
-    //\r
-    // The ConvertDevicePathToText() function handles NULL input transparently.\r
-    //\r
-    DevicePathText = ConvertDevicePathToText (\r
-                       DevicePathFromHandle (Handles[Idx]),\r
-                       FALSE, // DisplayOnly\r
-                       FALSE  // AllowShortcuts\r
-                       );\r
-    if (DevicePathText == NULL) {\r
-      DevicePathText = Fallback;\r
-    }\r
-\r
-    if ((Filter == NULL) || Filter (Handles[Idx], DevicePathText)) {\r
-      Process (Handles[Idx], DevicePathText);\r
-    }\r
-\r
-    if (DevicePathText != Fallback) {\r
-      FreePool (DevicePathText);\r
-    }\r
-  }\r
-\r
-  gBS->FreePool (Handles);\r
-}\r
-\r
-/**\r
-  This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.\r
-**/\r
-STATIC\r
-BOOLEAN\r
-EFIAPI\r
-IsPciDisplay (\r
-  IN EFI_HANDLE    Handle,\r
-  IN CONST CHAR16  *ReportText\r
-  )\r
-{\r
-  EFI_STATUS           Status;\r
-  EFI_PCI_IO_PROTOCOL  *PciIo;\r
-  PCI_TYPE00           Pci;\r
-\r
-  Status = gBS->HandleProtocol (\r
-                  Handle,\r
-                  &gEfiPciIoProtocolGuid,\r
-                  (VOID **)&PciIo\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // This is not an error worth reporting.\r
-    //\r
-    return FALSE;\r
-  }\r
-\r
-  Status = PciIo->Pci.Read (\r
-                        PciIo,\r
-                        EfiPciIoWidthUint32,\r
-                        0 /* Offset */,\r
-                        sizeof Pci / sizeof (UINT32),\r
-                        &Pci\r
-                        );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __func__, ReportText, Status));\r
-    return FALSE;\r
-  }\r
-\r
-  return IS_PCI_DISPLAY (&Pci);\r
-}\r
-\r
-/**\r
-  This function checks if a handle corresponds to the Virtio Device ID given\r
-  at the VIRTIO_DEVICE_PROTOCOL level.\r
-**/\r
-STATIC\r
-BOOLEAN\r
-EFIAPI\r
-IsVirtio (\r
-  IN EFI_HANDLE    Handle,\r
-  IN CONST CHAR16  *ReportText,\r
-  IN UINT16        VirtIoDeviceId\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-  VIRTIO_DEVICE_PROTOCOL  *VirtIo;\r
-\r
-  Status = gBS->HandleProtocol (\r
-                  Handle,\r
-                  &gVirtioDeviceProtocolGuid,\r
-                  (VOID **)&VirtIo\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return FALSE;\r
-  }\r
-\r
-  return (BOOLEAN)(VirtIo->SubSystemDeviceId ==\r
-                   VirtIoDeviceId);\r
-}\r
-\r
-/**\r
-  This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at\r
-  the VIRTIO_DEVICE_PROTOCOL level.\r
-**/\r
-STATIC\r
-BOOLEAN\r
-EFIAPI\r
-IsVirtioRng (\r
-  IN EFI_HANDLE    Handle,\r
-  IN CONST CHAR16  *ReportText\r
-  )\r
-{\r
-  return IsVirtio (Handle, ReportText, VIRTIO_SUBSYSTEM_ENTROPY_SOURCE);\r
-}\r
-\r
-/**\r
-  This FILTER_FUNCTION checks if a handle corresponds to a Virtio serial device at\r
-  the VIRTIO_DEVICE_PROTOCOL level.\r
-**/\r
-STATIC\r
-BOOLEAN\r
-EFIAPI\r
-IsVirtioSerial (\r
-  IN EFI_HANDLE    Handle,\r
-  IN CONST CHAR16  *ReportText\r
-  )\r
-{\r
-  return IsVirtio (Handle, ReportText, VIRTIO_SUBSYSTEM_CONSOLE);\r
-}\r
-\r
-/**\r
-  This function checks if a handle corresponds to the Virtio Device ID given\r
-  at the EFI_PCI_IO_PROTOCOL level.\r
-**/\r
-STATIC\r
-BOOLEAN\r
-EFIAPI\r
-IsVirtioPci (\r
-  IN EFI_HANDLE    Handle,\r
-  IN CONST CHAR16  *ReportText,\r
-  IN UINT16        VirtIoDeviceId\r
-  )\r
-{\r
-  EFI_STATUS           Status;\r
-  EFI_PCI_IO_PROTOCOL  *PciIo;\r
-  UINT16               VendorId;\r
-  UINT16               DeviceId;\r
-  UINT8                RevisionId;\r
-  BOOLEAN              Virtio10;\r
-  UINT16               SubsystemId;\r
-\r
-  Status = gBS->HandleProtocol (\r
-                  Handle,\r
-                  &gEfiPciIoProtocolGuid,\r
-                  (VOID **)&PciIo\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return FALSE;\r
-  }\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 PciError;\r
-  }\r
-\r
-  if (VendorId != VIRTIO_VENDOR_ID) {\r
-    return FALSE;\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 PciError;\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 PciError;\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 VirtIoDeviceId, 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 + VirtIoDeviceId) &&\r
-      (RevisionId >= 0x01))\r
-  {\r
-    Virtio10 = TRUE;\r
-  } else if ((DeviceId >= 0x1000) && (DeviceId <= 0x103F) && (RevisionId == 0x00)) {\r
-    Virtio10 = FALSE;\r
-  } else {\r
-    return FALSE;\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 PciError;\r
-  }\r
-\r
-  if (Virtio10 && (SubsystemId >= 0x40)) {\r
-    return TRUE;\r
-  }\r
-\r
-  if (!Virtio10 && (SubsystemId == VirtIoDeviceId)) {\r
-    return TRUE;\r
-  }\r
-\r
-  return FALSE;\r
-\r
-PciError:\r
-  DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __func__, ReportText, Status));\r
-  return FALSE;\r
-}\r
-\r
-/**\r
-  This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at\r
-  the EFI_PCI_IO_PROTOCOL level.\r
-**/\r
-STATIC\r
-BOOLEAN\r
-EFIAPI\r
-IsVirtioPciRng (\r
-  IN EFI_HANDLE    Handle,\r
-  IN CONST CHAR16  *ReportText\r
-  )\r
-{\r
-  return IsVirtioPci (Handle, ReportText, VIRTIO_SUBSYSTEM_ENTROPY_SOURCE);\r
-}\r
-\r
-/**\r
-  This FILTER_FUNCTION checks if a handle corresponds to a Virtio serial device at\r
-  the EFI_PCI_IO_PROTOCOL level.\r
-**/\r
-STATIC\r
-BOOLEAN\r
-EFIAPI\r
-IsVirtioPciSerial (\r
-  IN EFI_HANDLE    Handle,\r
-  IN CONST CHAR16  *ReportText\r
-  )\r
-{\r
-  return IsVirtioPci (Handle, ReportText, VIRTIO_SUBSYSTEM_CONSOLE);\r
-}\r
-\r
-/**\r
-  This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking\r
-  the matching driver to produce all first-level child handles.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-Connect (\r
-  IN EFI_HANDLE    Handle,\r
-  IN CONST CHAR16  *ReportText\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-\r
-  Status = gBS->ConnectController (\r
-                  Handle, // ControllerHandle\r
-                  NULL,   // DriverImageHandle\r
-                  NULL,   // RemainingDevicePath -- produce all children\r
-                  FALSE   // Recursive\r
-                  );\r
-  DEBUG ((\r
-    EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,\r
-    "%a: %s: %r\n",\r
-    __func__,\r
-    ReportText,\r
-    Status\r
-    ));\r
-}\r
-\r
-/**\r
-  This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the\r
-  handle, and adds it to ConOut and ErrOut.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-AddOutput (\r
-  IN EFI_HANDLE    Handle,\r
-  IN CONST CHAR16  *ReportText\r
-  )\r
-{\r
-  EFI_STATUS                Status;\r
-  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
-\r
-  DevicePath = DevicePathFromHandle (Handle);\r
-  if (DevicePath == NULL) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-      "%a: %s: handle %p: device path not found\n",\r
-      __func__,\r
-      ReportText,\r
-      Handle\r
-      ));\r
-    return;\r
-  }\r
-\r
-  Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-      "%a: %s: adding to ConOut: %r\n",\r
-      __func__,\r
-      ReportText,\r
-      Status\r
-      ));\r
-    return;\r
-  }\r
-\r
-  Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-      "%a: %s: adding to ErrOut: %r\n",\r
-      __func__,\r
-      ReportText,\r
-      Status\r
-      ));\r
-    return;\r
-  }\r
-\r
-  DEBUG ((\r
-    DEBUG_VERBOSE,\r
-    "%a: %s: added to ConOut and ErrOut\n",\r
-    __func__,\r
-    ReportText\r
-    ));\r
-}\r
-\r
-/**\r
-  This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from\r
-  the handle, appends serial, uart and terminal nodes, finally updates\r
-  ConIn, ConOut and ErrOut.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-SetupVirtioSerial (\r
-  IN EFI_HANDLE    Handle,\r
-  IN CONST CHAR16  *ReportText\r
-  )\r
-{\r
-  STATIC CONST ACPI_HID_DEVICE_PATH  SerialNode = {\r
-    {\r
-      ACPI_DEVICE_PATH,\r
-      ACPI_DP,\r
-      {\r
-        (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)),\r
-        (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)\r
-      },\r
-    },\r
-    EISA_PNP_ID (0x0501),\r
-    0\r
-  };\r
-\r
-  STATIC CONST UART_DEVICE_PATH  UartNode = {\r
-    {\r
-      MESSAGING_DEVICE_PATH,\r
-      MSG_UART_DP,\r
-      {\r
-        (UINT8)(sizeof (UART_DEVICE_PATH)),\r
-        (UINT8)((sizeof (UART_DEVICE_PATH)) >> 8)\r
-      },\r
-    },\r
-    0,\r
-    115200,\r
-    8,\r
-    1,\r
-    1\r
-  };\r
-\r
-  STATIC VENDOR_DEVICE_PATH  TerminalNode = {\r
-    {\r
-      MESSAGING_DEVICE_PATH,\r
-      MSG_VENDOR_DP,\r
-      {\r
-        (UINT8)(sizeof (VENDOR_DEVICE_PATH)),\r
-        (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
-      },\r
-    },\r
-    // copy from PcdTerminalTypeGuidBuffer\r
-  };\r
-\r
-  EFI_STATUS                Status;\r
-  EFI_DEVICE_PATH_PROTOCOL  *DevicePath, *OldDevicePath;\r
-\r
-  DevicePath = DevicePathFromHandle (Handle);\r
-\r
-  if (DevicePath == NULL) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-      "%a: %s: handle %p: device path not found\n",\r
-      __func__,\r
-      ReportText,\r
-      Handle\r
-      ));\r
-    return;\r
-  }\r
-\r
-  CopyGuid (\r
-    &TerminalNode.Guid,\r
-    PcdGetPtr (PcdTerminalTypeGuidBuffer)\r
-    );\r
-\r
-  DevicePath = AppendDevicePathNode (\r
-                 DevicePath,\r
-                 &SerialNode.Header\r
-                 );\r
-\r
-  OldDevicePath = DevicePath;\r
-  DevicePath    = AppendDevicePathNode (\r
-                    DevicePath,\r
-                    &UartNode.Header\r
-                    );\r
-  FreePool (OldDevicePath);\r
-\r
-  OldDevicePath = DevicePath;\r
-  DevicePath    = AppendDevicePathNode (\r
-                    DevicePath,\r
-                    &TerminalNode.Header\r
-                    );\r
-  FreePool (OldDevicePath);\r
-\r
-  Status = EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-      "%a: %s: adding to ConIn: %r\n",\r
-      __func__,\r
-      ReportText,\r
-      Status\r
-      ));\r
-    return;\r
-  }\r
-\r
-  Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-\r
-      "%a: %s: adding to ConOut: %r\n",\r
-      __func__,\r
-      ReportText,\r
-      Status\r
-      ));\r
-    return;\r
-  }\r
-\r
-  Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-      "%a: %s: adding to ErrOut: %r\n",\r
-      __func__,\r
-      ReportText,\r
-      Status\r
-      ));\r
-    return;\r
-  }\r
-\r
-  FreePool (DevicePath);\r
-\r
-  DEBUG ((\r
-    DEBUG_VERBOSE,\r
-    "%a: %s: added to ConIn, ConOut and ErrOut\n",\r
-    __func__,\r
-    ReportText\r
-    ));\r
-}\r
-\r
-STATIC\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
-  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
-  - FvMain's base address or size changed (historical),\r
-  - FvMain'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
-STATIC\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 keep 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
-      continue;\r
-    }\r
-\r
-    //\r
-    // If the second device path node is not FvFile(...), then keep 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
-      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
-STATIC\r
-VOID\r
-PlatformRegisterOptionsAndKeys (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS                    Status;\r
-  EFI_INPUT_KEY                 Enter;\r
-  EFI_INPUT_KEY                 F2;\r
-  EFI_INPUT_KEY                 Esc;\r
-  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;\r
-\r
-  //\r
-  // Register ENTER as CONTINUE key\r
-  //\r
-  Enter.ScanCode    = SCAN_NULL;\r
-  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
-  Status            = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Map F2 and ESC to Boot Manager Menu\r
-  //\r
-  F2.ScanCode     = SCAN_F2;\r
-  F2.UnicodeChar  = CHAR_NULL;\r
-  Esc.ScanCode    = SCAN_ESC;\r
-  Esc.UnicodeChar = CHAR_NULL;\r
-  Status          = EfiBootManagerGetBootManagerMenu (&BootOption);\r
-  ASSERT_EFI_ERROR (Status);\r
-  Status = EfiBootManagerAddKeyOptionVariable (\r
-             NULL,\r
-             (UINT16)BootOption.OptionNumber,\r
-             0,\r
-             &F2,\r
-             NULL\r
-             );\r
-  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
-  Status = EfiBootManagerAddKeyOptionVariable (\r
-             NULL,\r
-             (UINT16)BootOption.OptionNumber,\r
-             0,\r
-             &Esc,\r
-             NULL\r
-             );\r
-  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
-}\r
-\r
-//\r
-// BDS Platform Functions\r
-//\r
-\r
-/**\r
-  Do the platform init, can be customized by OEM/IBV\r
-  Possible things that can be done in PlatformBootManagerBeforeConsole:\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
-  UINT16         FrontPageTimeout;\r
-  RETURN_STATUS  PcdStatus;\r
-  EFI_STATUS     Status;\r
-\r
-  //\r
-  // Signal EndOfDxe PI Event\r
-  //\r
-  EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
-\r
-  //\r
-  // Disable the TPM 2 platform hierarchy\r
-  //\r
-  ConfigureTpmPlatformHierarchy ();\r
-\r
-  //\r
-  // Dispatch deferred images after EndOfDxe event.\r
-  //\r
-  EfiBootManagerDispatchDeferredImages ();\r
-\r
-  //\r
-  // Locate the PCI root bridges and make the PCI bus driver connect each,\r
-  // non-recursively. This will produce a number of child handles with PciIo on\r
-  // them.\r
-  //\r
-  FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);\r
-\r
-  //\r
-  // Signal the ACPI platform driver that it can download QEMU ACPI tables.\r
-  //\r
-  EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);\r
-\r
-  //\r
-  // Find all display class PCI devices (using the handles from the previous\r
-  // step), and connect them non-recursively. This should produce a number of\r
-  // child handles with GOPs on them.\r
-  //\r
-  FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);\r
-\r
-  //\r
-  // Now add the device path of all handles with GOP on them to ConOut and\r
-  // ErrOut.\r
-  //\r
-  FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);\r
-\r
-  //\r
-  // Add the hardcoded short-form USB keyboard device path to ConIn.\r
-  //\r
-  EfiBootManagerUpdateConsoleVariable (\r
-    ConIn,\r
-    (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard,\r
-    NULL\r
-    );\r
-\r
-  //\r
-  // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.\r
-  //\r
-  CopyGuid (\r
-    &mSerialConsole.TermType.Guid,\r
-    PcdGetPtr (PcdTerminalTypeGuidBuffer)\r
-    );\r
-  EfiBootManagerUpdateConsoleVariable (\r
-    ConIn,\r
-    (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,\r
-    NULL\r
-    );\r
-  EfiBootManagerUpdateConsoleVariable (\r
-    ConOut,\r
-    (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,\r
-    NULL\r
-    );\r
-  EfiBootManagerUpdateConsoleVariable (\r
-    ErrOut,\r
-    (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,\r
-    NULL\r
-    );\r
-\r
-  //\r
-  // Set the front page timeout from the QEMU configuration.\r
-  //\r
-  FrontPageTimeout = GetFrontPageTimeoutFromQemu ();\r
-  PcdStatus        = PcdSet16S (PcdPlatformBootTimeOut, FrontPageTimeout);\r
-  ASSERT_RETURN_ERROR (PcdStatus);\r
-  //\r
-  // Reflect the PCD in the standard Timeout variable.\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
-  DEBUG ((\r
-    EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,\r
-    "%a: SetVariable(%s, %u): %r\n",\r
-    __func__,\r
-    EFI_TIME_OUT_VARIABLE_NAME,\r
-    FrontPageTimeout,\r
-    Status\r
-    ));\r
-\r
-  //\r
-  // Register platform-specific boot options and keyboard shortcuts.\r
-  //\r
-  PlatformRegisterOptionsAndKeys ();\r
-\r
-  //\r
-  // At this point, VIRTIO_DEVICE_PROTOCOL instances exist only for Virtio MMIO\r
-  // transports. Install EFI_RNG_PROTOCOL instances on Virtio MMIO RNG devices.\r
-  //\r
-  FilterAndProcess (&gVirtioDeviceProtocolGuid, IsVirtioRng, Connect);\r
-\r
-  //\r
-  // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL\r
-  // instances on Virtio PCI RNG devices.\r
-  //\r
-  FilterAndProcess (&gEfiPciIoProtocolGuid, IsVirtioPciRng, Connect);\r
-\r
-  //\r
-  // Register Virtio serial devices as console.\r
-  //\r
-  FilterAndProcess (&gVirtioDeviceProtocolGuid, IsVirtioSerial, SetupVirtioSerial);\r
-  FilterAndProcess (&gEfiPciIoProtocolGuid, IsVirtioPciSerial, SetupVirtioSerial);\r
-}\r
-\r
-/**\r
-  Uninstall the EFI memory attribute protocol if it exists.\r
-**/\r
-STATIC\r
-VOID\r
-UninstallEfiMemoryAttributesProtocol (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  EFI_HANDLE  Handle;\r
-  UINTN       Size;\r
-  VOID        *MemoryAttributeProtocol;\r
-\r
-  Size   = sizeof (Handle);\r
-  Status = gBS->LocateHandle (\r
-                  ByProtocol,\r
-                  &gEfiMemoryAttributeProtocolGuid,\r
-                  NULL,\r
-                  &Size,\r
-                  &Handle\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    ASSERT (Status == EFI_NOT_FOUND);\r
-    return;\r
-  }\r
-\r
-  Status = gBS->HandleProtocol (\r
-                  Handle,\r
-                  &gEfiMemoryAttributeProtocolGuid,\r
-                  &MemoryAttributeProtocol\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Status = gBS->UninstallProtocolInterface (\r
-                  Handle,\r
-                  &gEfiMemoryAttributeProtocolGuid,\r
-                  MemoryAttributeProtocol\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-}\r
-\r
-/**\r
-  Do the platform specific action after the console is ready\r
-  Possible things that can be done in PlatformBootManagerAfterConsole:\r
-  > Console post action:\r
-    > Dynamically switch output mode from 100x31 to 80x25 for certain scenario\r
-    > Signal console ready platform customized event\r
-  > Run diagnostics like memory testing\r
-  > Connect certain devices\r
-  > Dispatch additional option roms\r
-  > Special boot: e.g.: USB boot, enter UI\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBootManagerAfterConsole (\r
-  VOID\r
-  )\r
-{\r
-  RETURN_STATUS  Status;\r
-  BOOLEAN        Uninstall;\r
-\r
-  //\r
-  // Show the splash screen.\r
-  //\r
-  BootLogoEnableLogo ();\r
-\r
-  //\r
-  // Work around shim's terminally broken use of the EFI memory attributes\r
-  // protocol, by uninstalling it if requested on the QEMU command line.\r
-  //\r
-  // E.g.,\r
-  //       -fw_cfg opt/org.tianocore/UninstallMemAttrProtocol,string=y\r
-  //\r
-  Uninstall = FixedPcdGetBool (PcdUninstallMemAttrProtocol);\r
-  QemuFwCfgParseBool ("opt/org.tianocore/UninstallMemAttrProtocol", &Uninstall);\r
-  DEBUG ((\r
-    DEBUG_WARN,\r
-    "%a: %auninstalling EFI memory protocol\n",\r
-    __func__,\r
-    Uninstall ? "" : "not "\r
-    ));\r
-  if (Uninstall) {\r
-    UninstallEfiMemoryAttributesProtocol ();\r
-  }\r
-\r
-  //\r
-  // Process QEMU's -kernel command line option. The kernel booted this way\r
-  // will receive ACPI tables: in PlatformBootManagerBeforeConsole(), we\r
-  // connected any and all PCI root bridges, and then signaled the ACPI\r
-  // platform driver.\r
-  //\r
-  TryRunningQemuKernel ();\r
-\r
-  //\r
-  // Connect the purported boot devices.\r
-  //\r
-  Status = ConnectDevicesFromQemu ();\r
-  if (RETURN_ERROR (Status)) {\r
-    //\r
-    // Connect the rest of the devices.\r
-    //\r
-    EfiBootManagerConnectAll ();\r
-  }\r
-\r
-  //\r
-  // Enumerate all possible boot options, then filter and reorder them based on\r
-  // the QEMU configuration.\r
-  //\r
-  EfiBootManagerRefreshAllBootOption ();\r
-\r
-  //\r
-  // Register UEFI Shell\r
-  //\r
-  PlatformRegisterFvBootOption (\r
-    &gUefiShellFileGuid,\r
-    L"EFI Internal Shell",\r
-    LOAD_OPTION_ACTIVE\r
-    );\r
-\r
-  RemoveStaleFvFileOptions ();\r
-  SetBootOrderFromQemu ();\r
-\r
-  PlatformBmPrintScRegisterHandler ();\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
-  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION  Black;\r
-  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION  White;\r
-  UINT16                               TimeoutInitial;\r
-\r
-  TimeoutInitial = PcdGet16 (PcdPlatformBootTimeOut);\r
-\r
-  //\r
-  // If PcdPlatformBootTimeOut is set to zero, then we consider\r
-  // that no progress update should be enacted.\r
-  //\r
-  if (TimeoutInitial == 0) {\r
-    return;\r
-  }\r
-\r
-  Black.Raw = 0x00000000;\r
-  White.Raw = 0x00FFFFFF;\r
-\r
-  BootLogoUpdateProgress (\r
-    White.Pixel,\r
-    Black.Pixel,\r
-    L"Start boot option",\r
-    White.Pixel,\r
-    (TimeoutInitial - TimeoutRemain) * 100 / TimeoutInitial,\r
-    0\r
-    );\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
-  EFI_STATUS                    Status;\r
-  EFI_INPUT_KEY                 Key;\r
-  EFI_BOOT_MANAGER_LOAD_OPTION  BootManagerMenu;\r
-  UINTN                         Index;\r
-\r
-  //\r
-  // BootManagerMenu doesn't contain the correct information when return status\r
-  // is EFI_NOT_FOUND.\r
-  //\r
-  Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);\r
-  if (EFI_ERROR (Status)) {\r
-    return;\r
-  }\r
-\r
-  //\r
-  // Normally BdsDxe does not print anything to the system console, but this is\r
-  // a last resort -- the end-user will likely not see any DEBUG messages\r
-  // logged in this situation.\r
-  //\r
-  // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn\r
-  // here to see if it makes sense to request and wait for a keypress.\r
-  //\r
-  if (gST->ConIn != NULL) {\r
-    AsciiPrint (\r
-      "%a: No bootable option or device was found.\n"\r
-      "%a: Press any key to enter the Boot Manager Menu.\n",\r
-      gEfiCallerBaseName,\r
-      gEfiCallerBaseName\r
-      );\r
-    Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);\r
-    ASSERT_EFI_ERROR (Status);\r
-    ASSERT (Index == 0);\r
-\r
-    //\r
-    // Drain any queued keys.\r
-    //\r
-    while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {\r
-      //\r
-      // just throw away Key\r
-      //\r
-    }\r
-  }\r
-\r
-  for ( ; ;) {\r
-    EfiBootManagerBoot (&BootManagerMenu);\r
-  }\r
-}\r
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.h b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.h
deleted file mode 100644 (file)
index 70c52d9..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/** @file\r
-  Head file for BDS Platform specific code\r
-\r
-  Copyright (C) 2015-2016, Red Hat, Inc.\r
-  Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>\r
-\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#ifndef _PLATFORM_BM_H_\r
-#define _PLATFORM_BM_H_\r
-\r
-#include <Library/BaseLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-\r
-/**\r
-  Download the kernel, the initial ramdisk, and the kernel command line from\r
-  QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two\r
-  image files, and load and start the kernel from it.\r
-\r
-  The kernel will be instructed via its command line to load the initrd from\r
-  the same Simple FileSystem.\r
-\r
-  @retval EFI_NOT_FOUND         Kernel image was not found.\r
-  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.\r
-  @retval EFI_PROTOCOL_ERROR    Unterminated kernel command line.\r
-\r
-  @return                       Error codes from any of the underlying\r
-                                functions. On success, the function doesn't\r
-                                return.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TryRunningQemuKernel (\r
-  VOID\r
-  );\r
-\r
-#endif // _PLATFORM_BM_H_\r
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
deleted file mode 100644 (file)
index 8e7cd56..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-## @file\r
-#  Implementation for PlatformBootManagerLib library class interfaces.\r
-#\r
-#  Copyright (C) 2015-2016, Red Hat, Inc.\r
-#  Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>\r
-#  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
-#\r
-#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-#\r
-##\r
-\r
-[Defines]\r
-  INF_VERSION                    = 0x00010005\r
-  BASE_NAME                      = PlatformBootManagerLib\r
-  FILE_GUID                      = 469184E8-FADA-41E4-8823-012CA19B40D4\r
-  MODULE_TYPE                    = DXE_DRIVER\r
-  VERSION_STRING                 = 1.0\r
-  LIBRARY_CLASS                  = PlatformBootManagerLib|DXE_DRIVER\r
-\r
-#\r
-# The following information is for reference only and not required by the build tools.\r
-#\r
-#  VALID_ARCHITECTURES           = ARM AARCH64\r
-#\r
-\r
-[Sources]\r
-  PlatformBm.c\r
-  PlatformBm.h\r
-  QemuKernel.c\r
-\r
-[Packages]\r
-  MdeModulePkg/MdeModulePkg.dec\r
-  MdePkg/MdePkg.dec\r
-  OvmfPkg/OvmfPkg.dec\r
-  SecurityPkg/SecurityPkg.dec\r
-  ShellPkg/ShellPkg.dec\r
-\r
-[LibraryClasses]\r
-  BaseLib\r
-  BaseMemoryLib\r
-  BootLogoLib\r
-  DebugLib\r
-  DevicePathLib\r
-  MemoryAllocationLib\r
-  PcdLib\r
-  PlatformBmPrintScLib\r
-  QemuBootOrderLib\r
-  QemuFwCfgSimpleParserLib\r
-  QemuLoadImageLib\r
-  ReportStatusCodeLib\r
-  TpmPlatformHierarchyLib\r
-  UefiBootManagerLib\r
-  UefiBootServicesTableLib\r
-  UefiLib\r
-  UefiRuntimeServicesTableLib\r
-\r
-[FixedPcd]\r
-  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate\r
-  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits\r
-  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity\r
-  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits\r
-  gUefiOvmfPkgTokenSpaceGuid.PcdUninstallMemAttrProtocol\r
-\r
-[Pcd]\r
-  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut\r
-  gUefiOvmfPkgTokenSpaceGuid.PcdTerminalTypeGuidBuffer\r
-\r
-[Guids]\r
-  gEfiEndOfDxeEventGroupGuid\r
-  gEfiGlobalVariableGuid\r
-  gRootBridgesConnectedEventGroupGuid\r
-  gUefiShellFileGuid\r
-\r
-[Protocols]\r
-  gEfiFirmwareVolume2ProtocolGuid\r
-  gEfiGraphicsOutputProtocolGuid\r
-  gEfiMemoryAttributeProtocolGuid\r
-  gEfiPciRootBridgeIoProtocolGuid\r
-  gVirtioDeviceProtocolGuid\r
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/QemuKernel.c b/ArmVirtPkg/Library/PlatformBootManagerLib/QemuKernel.c
deleted file mode 100644 (file)
index 7dc59ae..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/** @file\r
-  Try to load an EFI-stubbed ARM Linux kernel from QEMU's fw_cfg.\r
-\r
-  This implementation differs from OvmfPkg/Library/LoadLinuxLib. An EFI\r
-  stub in the subject kernel is a hard requirement here.\r
-\r
-  Copyright (C) 2014-2016, Red Hat, Inc.\r
-\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-**/\r
-\r
-#include <Library/QemuLoadImageLib.h>\r
-#include <Library/ReportStatusCodeLib.h>\r
-\r
-#include "PlatformBm.h"\r
-\r
-//\r
-// The entry point of the feature.\r
-//\r
-\r
-/**\r
-  Download the kernel, the initial ramdisk, and the kernel command line from\r
-  QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two\r
-  image files, and load and start the kernel from it.\r
-\r
-  The kernel will be instructed via its command line to load the initrd from\r
-  the same Simple FileSystem.\r
-\r
-  @retval EFI_NOT_FOUND         Kernel image was not found.\r
-  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.\r
-  @retval EFI_PROTOCOL_ERROR    Unterminated kernel command line.\r
-\r
-  @return                       Error codes from any of the underlying\r
-                                functions. On success, the function doesn't\r
-                                return.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TryRunningQemuKernel (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  EFI_HANDLE  KernelImageHandle;\r
-\r
-  Status = QemuLoadKernelImage (&KernelImageHandle);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Signal the EFI_EVENT_GROUP_READY_TO_BOOT event.\r
-  //\r
-  EfiSignalEventReadyToBoot ();\r
-\r
-  REPORT_STATUS_CODE (\r
-    EFI_PROGRESS_CODE,\r
-    (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT)\r
-    );\r
-\r
-  //\r
-  // Start the image.\r
-  //\r
-  Status = QemuStartKernelImage (&KernelImageHandle);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-      "%a: QemuStartKernelImage(): %r\n",\r
-      __func__,\r
-      Status\r
-      ));\r
-  }\r
-\r
-  QemuUnloadKernelImage (KernelImageHandle);\r
-\r
-  return Status;\r
-}\r
diff --git a/OvmfPkg/Library/PlatformBootManagerLibLight/PlatformBm.c b/OvmfPkg/Library/PlatformBootManagerLibLight/PlatformBm.c
new file mode 100644 (file)
index 0000000..8e93f3c
--- /dev/null
@@ -0,0 +1,1340 @@
+/** @file\r
+  Implementation for PlatformBootManagerLib library class interfaces.\r
+\r
+  Copyright (C) 2015-2016, Red Hat, Inc.\r
+  Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>\r
+  Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <IndustryStandard/Pci22.h>\r
+#include <IndustryStandard/Virtio095.h>\r
+#include <Library/BootLogoLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PlatformBmPrintScLib.h>\r
+#include <Library/QemuBootOrderLib.h>\r
+#include <Library/QemuFwCfgSimpleParserLib.h>\r
+#include <Library/TpmPlatformHierarchyLib.h>\r
+#include <Library/UefiBootManagerLib.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/GraphicsOutput.h>\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
+#include <Protocol/VirtioDevice.h>\r
+#include <Guid/EventGroup.h>\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/RootBridgesConnectedEventGroup.h>\r
+#include <Guid/SerialPortLibVendor.h>\r
+\r
+#include "PlatformBm.h"\r
+\r
+#define DP_NODE_LEN(Type)  { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }\r
+\r
+#pragma pack (1)\r
+typedef struct {\r
+  VENDOR_DEVICE_PATH            SerialDxe;\r
+  UART_DEVICE_PATH              Uart;\r
+  VENDOR_DEFINED_DEVICE_PATH    TermType;\r
+  EFI_DEVICE_PATH_PROTOCOL      End;\r
+} PLATFORM_SERIAL_CONSOLE;\r
+#pragma pack ()\r
+\r
+STATIC PLATFORM_SERIAL_CONSOLE  mSerialConsole = {\r
+  //\r
+  // VENDOR_DEVICE_PATH SerialDxe\r
+  //\r
+  {\r
+    { HARDWARE_DEVICE_PATH,  HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },\r
+    EDKII_SERIAL_PORT_LIB_VENDOR_GUID\r
+  },\r
+\r
+  //\r
+  // UART_DEVICE_PATH Uart\r
+  //\r
+  {\r
+    { MESSAGING_DEVICE_PATH, MSG_UART_DP,  DP_NODE_LEN (UART_DEVICE_PATH)   },\r
+    0,                                      // Reserved\r
+    FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate\r
+    FixedPcdGet8 (PcdUartDefaultDataBits),  // DataBits\r
+    FixedPcdGet8 (PcdUartDefaultParity),    // Parity\r
+    FixedPcdGet8 (PcdUartDefaultStopBits)   // StopBits\r
+  },\r
+\r
+  //\r
+  // VENDOR_DEFINED_DEVICE_PATH TermType\r
+  //\r
+  {\r
+    {\r
+      MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,\r
+      DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)\r
+    }\r
+    //\r
+    // Guid to be filled in dynamically\r
+    //\r
+  },\r
+\r
+  //\r
+  // EFI_DEVICE_PATH_PROTOCOL End\r
+  //\r
+  {\r
+    END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+    DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
+  }\r
+};\r
+\r
+#pragma pack (1)\r
+typedef struct {\r
+  USB_CLASS_DEVICE_PATH       Keyboard;\r
+  EFI_DEVICE_PATH_PROTOCOL    End;\r
+} PLATFORM_USB_KEYBOARD;\r
+#pragma pack ()\r
+\r
+STATIC PLATFORM_USB_KEYBOARD  mUsbKeyboard = {\r
+  //\r
+  // USB_CLASS_DEVICE_PATH Keyboard\r
+  //\r
+  {\r
+    {\r
+      MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,\r
+      DP_NODE_LEN (USB_CLASS_DEVICE_PATH)\r
+    },\r
+    0xFFFF, // VendorId: any\r
+    0xFFFF, // ProductId: any\r
+    3,      // DeviceClass: HID\r
+    1,      // DeviceSubClass: boot\r
+    1       // DeviceProtocol: keyboard\r
+  },\r
+\r
+  //\r
+  // EFI_DEVICE_PATH_PROTOCOL End\r
+  //\r
+  {\r
+    END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+    DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
+  }\r
+};\r
+\r
+/**\r
+  Check if the handle satisfies a particular condition.\r
+\r
+  @param[in] Handle      The handle to check.\r
+  @param[in] ReportText  A caller-allocated string passed in for reporting\r
+                         purposes. It must never be NULL.\r
+\r
+  @retval TRUE   The condition is satisfied.\r
+  @retval FALSE  Otherwise. This includes the case when the condition could not\r
+                 be fully evaluated due to an error.\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *FILTER_FUNCTION)(\r
+  IN EFI_HANDLE   Handle,\r
+  IN CONST CHAR16 *ReportText\r
+  );\r
+\r
+/**\r
+  Process a handle.\r
+\r
+  @param[in] Handle      The handle to process.\r
+  @param[in] ReportText  A caller-allocated string passed in for reporting\r
+                         purposes. It must never be NULL.\r
+**/\r
+typedef\r
+VOID\r
+(EFIAPI *CALLBACK_FUNCTION)(\r
+  IN EFI_HANDLE   Handle,\r
+  IN CONST CHAR16 *ReportText\r
+  );\r
+\r
+/**\r
+  Locate all handles that carry the specified protocol, filter them with a\r
+  callback function, and pass each handle that passes the filter to another\r
+  callback.\r
+\r
+  @param[in] ProtocolGuid  The protocol to look for.\r
+\r
+  @param[in] Filter        The filter function to pass each handle to. If this\r
+                           parameter is NULL, then all handles are processed.\r
+\r
+  @param[in] Process       The callback function to pass each handle to that\r
+                           clears the filter.\r
+**/\r
+STATIC\r
+VOID\r
+FilterAndProcess (\r
+  IN EFI_GUID           *ProtocolGuid,\r
+  IN FILTER_FUNCTION    Filter         OPTIONAL,\r
+  IN CALLBACK_FUNCTION  Process\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_HANDLE  *Handles;\r
+  UINTN       NoHandles;\r
+  UINTN       Idx;\r
+\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  ProtocolGuid,\r
+                  NULL /* SearchKey */,\r
+                  &NoHandles,\r
+                  &Handles\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // This is not an error, just an informative condition.\r
+    //\r
+    DEBUG ((\r
+      DEBUG_VERBOSE,\r
+      "%a: %g: %r\n",\r
+      __func__,\r
+      ProtocolGuid,\r
+      Status\r
+      ));\r
+    return;\r
+  }\r
+\r
+  ASSERT (NoHandles > 0);\r
+  for (Idx = 0; Idx < NoHandles; ++Idx) {\r
+    CHAR16         *DevicePathText;\r
+    STATIC CHAR16  Fallback[] = L"<device path unavailable>";\r
+\r
+    //\r
+    // The ConvertDevicePathToText() function handles NULL input transparently.\r
+    //\r
+    DevicePathText = ConvertDevicePathToText (\r
+                       DevicePathFromHandle (Handles[Idx]),\r
+                       FALSE, // DisplayOnly\r
+                       FALSE  // AllowShortcuts\r
+                       );\r
+    if (DevicePathText == NULL) {\r
+      DevicePathText = Fallback;\r
+    }\r
+\r
+    if ((Filter == NULL) || Filter (Handles[Idx], DevicePathText)) {\r
+      Process (Handles[Idx], DevicePathText);\r
+    }\r
+\r
+    if (DevicePathText != Fallback) {\r
+      FreePool (DevicePathText);\r
+    }\r
+  }\r
+\r
+  gBS->FreePool (Handles);\r
+}\r
+\r
+/**\r
+  This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.\r
+**/\r
+STATIC\r
+BOOLEAN\r
+EFIAPI\r
+IsPciDisplay (\r
+  IN EFI_HANDLE    Handle,\r
+  IN CONST CHAR16  *ReportText\r
+  )\r
+{\r
+  EFI_STATUS           Status;\r
+  EFI_PCI_IO_PROTOCOL  *PciIo;\r
+  PCI_TYPE00           Pci;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID **)&PciIo\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // This is not an error worth reporting.\r
+    //\r
+    return FALSE;\r
+  }\r
+\r
+  Status = PciIo->Pci.Read (\r
+                        PciIo,\r
+                        EfiPciIoWidthUint32,\r
+                        0 /* Offset */,\r
+                        sizeof Pci / sizeof (UINT32),\r
+                        &Pci\r
+                        );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __func__, ReportText, Status));\r
+    return FALSE;\r
+  }\r
+\r
+  return IS_PCI_DISPLAY (&Pci);\r
+}\r
+\r
+/**\r
+  This function checks if a handle corresponds to the Virtio Device ID given\r
+  at the VIRTIO_DEVICE_PROTOCOL level.\r
+**/\r
+STATIC\r
+BOOLEAN\r
+EFIAPI\r
+IsVirtio (\r
+  IN EFI_HANDLE    Handle,\r
+  IN CONST CHAR16  *ReportText,\r
+  IN UINT16        VirtIoDeviceId\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  VIRTIO_DEVICE_PROTOCOL  *VirtIo;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gVirtioDeviceProtocolGuid,\r
+                  (VOID **)&VirtIo\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return (BOOLEAN)(VirtIo->SubSystemDeviceId ==\r
+                   VirtIoDeviceId);\r
+}\r
+\r
+/**\r
+  This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at\r
+  the VIRTIO_DEVICE_PROTOCOL level.\r
+**/\r
+STATIC\r
+BOOLEAN\r
+EFIAPI\r
+IsVirtioRng (\r
+  IN EFI_HANDLE    Handle,\r
+  IN CONST CHAR16  *ReportText\r
+  )\r
+{\r
+  return IsVirtio (Handle, ReportText, VIRTIO_SUBSYSTEM_ENTROPY_SOURCE);\r
+}\r
+\r
+/**\r
+  This FILTER_FUNCTION checks if a handle corresponds to a Virtio serial device at\r
+  the VIRTIO_DEVICE_PROTOCOL level.\r
+**/\r
+STATIC\r
+BOOLEAN\r
+EFIAPI\r
+IsVirtioSerial (\r
+  IN EFI_HANDLE    Handle,\r
+  IN CONST CHAR16  *ReportText\r
+  )\r
+{\r
+  return IsVirtio (Handle, ReportText, VIRTIO_SUBSYSTEM_CONSOLE);\r
+}\r
+\r
+/**\r
+  This function checks if a handle corresponds to the Virtio Device ID given\r
+  at the EFI_PCI_IO_PROTOCOL level.\r
+**/\r
+STATIC\r
+BOOLEAN\r
+EFIAPI\r
+IsVirtioPci (\r
+  IN EFI_HANDLE    Handle,\r
+  IN CONST CHAR16  *ReportText,\r
+  IN UINT16        VirtIoDeviceId\r
+  )\r
+{\r
+  EFI_STATUS           Status;\r
+  EFI_PCI_IO_PROTOCOL  *PciIo;\r
+  UINT16               VendorId;\r
+  UINT16               DeviceId;\r
+  UINT8                RevisionId;\r
+  BOOLEAN              Virtio10;\r
+  UINT16               SubsystemId;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID **)&PciIo\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\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 PciError;\r
+  }\r
+\r
+  if (VendorId != VIRTIO_VENDOR_ID) {\r
+    return FALSE;\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 PciError;\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 PciError;\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 VirtIoDeviceId, 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 + VirtIoDeviceId) &&\r
+      (RevisionId >= 0x01))\r
+  {\r
+    Virtio10 = TRUE;\r
+  } else if ((DeviceId >= 0x1000) && (DeviceId <= 0x103F) && (RevisionId == 0x00)) {\r
+    Virtio10 = FALSE;\r
+  } else {\r
+    return FALSE;\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 PciError;\r
+  }\r
+\r
+  if (Virtio10 && (SubsystemId >= 0x40)) {\r
+    return TRUE;\r
+  }\r
+\r
+  if (!Virtio10 && (SubsystemId == VirtIoDeviceId)) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+\r
+PciError:\r
+  DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __func__, ReportText, Status));\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  This FILTER_FUNCTION checks if a handle corresponds to a Virtio RNG device at\r
+  the EFI_PCI_IO_PROTOCOL level.\r
+**/\r
+STATIC\r
+BOOLEAN\r
+EFIAPI\r
+IsVirtioPciRng (\r
+  IN EFI_HANDLE    Handle,\r
+  IN CONST CHAR16  *ReportText\r
+  )\r
+{\r
+  return IsVirtioPci (Handle, ReportText, VIRTIO_SUBSYSTEM_ENTROPY_SOURCE);\r
+}\r
+\r
+/**\r
+  This FILTER_FUNCTION checks if a handle corresponds to a Virtio serial device at\r
+  the EFI_PCI_IO_PROTOCOL level.\r
+**/\r
+STATIC\r
+BOOLEAN\r
+EFIAPI\r
+IsVirtioPciSerial (\r
+  IN EFI_HANDLE    Handle,\r
+  IN CONST CHAR16  *ReportText\r
+  )\r
+{\r
+  return IsVirtioPci (Handle, ReportText, VIRTIO_SUBSYSTEM_CONSOLE);\r
+}\r
+\r
+/**\r
+  This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking\r
+  the matching driver to produce all first-level child handles.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+Connect (\r
+  IN EFI_HANDLE    Handle,\r
+  IN CONST CHAR16  *ReportText\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = gBS->ConnectController (\r
+                  Handle, // ControllerHandle\r
+                  NULL,   // DriverImageHandle\r
+                  NULL,   // RemainingDevicePath -- produce all children\r
+                  FALSE   // Recursive\r
+                  );\r
+  DEBUG ((\r
+    EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,\r
+    "%a: %s: %r\n",\r
+    __func__,\r
+    ReportText,\r
+    Status\r
+    ));\r
+}\r
+\r
+/**\r
+  This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the\r
+  handle, and adds it to ConOut and ErrOut.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+AddOutput (\r
+  IN EFI_HANDLE    Handle,\r
+  IN CONST CHAR16  *ReportText\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+\r
+  DevicePath = DevicePathFromHandle (Handle);\r
+  if (DevicePath == NULL) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "%a: %s: handle %p: device path not found\n",\r
+      __func__,\r
+      ReportText,\r
+      Handle\r
+      ));\r
+    return;\r
+  }\r
+\r
+  Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "%a: %s: adding to ConOut: %r\n",\r
+      __func__,\r
+      ReportText,\r
+      Status\r
+      ));\r
+    return;\r
+  }\r
+\r
+  Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "%a: %s: adding to ErrOut: %r\n",\r
+      __func__,\r
+      ReportText,\r
+      Status\r
+      ));\r
+    return;\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_VERBOSE,\r
+    "%a: %s: added to ConOut and ErrOut\n",\r
+    __func__,\r
+    ReportText\r
+    ));\r
+}\r
+\r
+/**\r
+  This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from\r
+  the handle, appends serial, uart and terminal nodes, finally updates\r
+  ConIn, ConOut and ErrOut.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+SetupVirtioSerial (\r
+  IN EFI_HANDLE    Handle,\r
+  IN CONST CHAR16  *ReportText\r
+  )\r
+{\r
+  STATIC CONST ACPI_HID_DEVICE_PATH  SerialNode = {\r
+    {\r
+      ACPI_DEVICE_PATH,\r
+      ACPI_DP,\r
+      {\r
+        (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)),\r
+        (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)\r
+      },\r
+    },\r
+    EISA_PNP_ID (0x0501),\r
+    0\r
+  };\r
+\r
+  STATIC CONST UART_DEVICE_PATH  UartNode = {\r
+    {\r
+      MESSAGING_DEVICE_PATH,\r
+      MSG_UART_DP,\r
+      {\r
+        (UINT8)(sizeof (UART_DEVICE_PATH)),\r
+        (UINT8)((sizeof (UART_DEVICE_PATH)) >> 8)\r
+      },\r
+    },\r
+    0,\r
+    115200,\r
+    8,\r
+    1,\r
+    1\r
+  };\r
+\r
+  STATIC VENDOR_DEVICE_PATH  TerminalNode = {\r
+    {\r
+      MESSAGING_DEVICE_PATH,\r
+      MSG_VENDOR_DP,\r
+      {\r
+        (UINT8)(sizeof (VENDOR_DEVICE_PATH)),\r
+        (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
+      },\r
+    },\r
+    // copy from PcdTerminalTypeGuidBuffer\r
+  };\r
+\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath, *OldDevicePath;\r
+\r
+  DevicePath = DevicePathFromHandle (Handle);\r
+\r
+  if (DevicePath == NULL) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "%a: %s: handle %p: device path not found\n",\r
+      __func__,\r
+      ReportText,\r
+      Handle\r
+      ));\r
+    return;\r
+  }\r
+\r
+  CopyGuid (\r
+    &TerminalNode.Guid,\r
+    PcdGetPtr (PcdTerminalTypeGuidBuffer)\r
+    );\r
+\r
+  DevicePath = AppendDevicePathNode (\r
+                 DevicePath,\r
+                 &SerialNode.Header\r
+                 );\r
+\r
+  OldDevicePath = DevicePath;\r
+  DevicePath    = AppendDevicePathNode (\r
+                    DevicePath,\r
+                    &UartNode.Header\r
+                    );\r
+  FreePool (OldDevicePath);\r
+\r
+  OldDevicePath = DevicePath;\r
+  DevicePath    = AppendDevicePathNode (\r
+                    DevicePath,\r
+                    &TerminalNode.Header\r
+                    );\r
+  FreePool (OldDevicePath);\r
+\r
+  Status = EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "%a: %s: adding to ConIn: %r\n",\r
+      __func__,\r
+      ReportText,\r
+      Status\r
+      ));\r
+    return;\r
+  }\r
+\r
+  Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+\r
+      "%a: %s: adding to ConOut: %r\n",\r
+      __func__,\r
+      ReportText,\r
+      Status\r
+      ));\r
+    return;\r
+  }\r
+\r
+  Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "%a: %s: adding to ErrOut: %r\n",\r
+      __func__,\r
+      ReportText,\r
+      Status\r
+      ));\r
+    return;\r
+  }\r
+\r
+  FreePool (DevicePath);\r
+\r
+  DEBUG ((\r
+    DEBUG_VERBOSE,\r
+    "%a: %s: added to ConIn, ConOut and ErrOut\n",\r
+    __func__,\r
+    ReportText\r
+    ));\r
+}\r
+\r
+STATIC\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
+  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
+  - FvMain's base address or size changed (historical),\r
+  - FvMain'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
+STATIC\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 keep 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
+      continue;\r
+    }\r
+\r
+    //\r
+    // If the second device path node is not FvFile(...), then keep 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
+      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
+STATIC\r
+VOID\r
+PlatformRegisterOptionsAndKeys (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_INPUT_KEY                 Enter;\r
+  EFI_INPUT_KEY                 F2;\r
+  EFI_INPUT_KEY                 Esc;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;\r
+\r
+  //\r
+  // Register ENTER as CONTINUE key\r
+  //\r
+  Enter.ScanCode    = SCAN_NULL;\r
+  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
+  Status            = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Map F2 and ESC to Boot Manager Menu\r
+  //\r
+  F2.ScanCode     = SCAN_F2;\r
+  F2.UnicodeChar  = CHAR_NULL;\r
+  Esc.ScanCode    = SCAN_ESC;\r
+  Esc.UnicodeChar = CHAR_NULL;\r
+  Status          = EfiBootManagerGetBootManagerMenu (&BootOption);\r
+  ASSERT_EFI_ERROR (Status);\r
+  Status = EfiBootManagerAddKeyOptionVariable (\r
+             NULL,\r
+             (UINT16)BootOption.OptionNumber,\r
+             0,\r
+             &F2,\r
+             NULL\r
+             );\r
+  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
+  Status = EfiBootManagerAddKeyOptionVariable (\r
+             NULL,\r
+             (UINT16)BootOption.OptionNumber,\r
+             0,\r
+             &Esc,\r
+             NULL\r
+             );\r
+  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
+}\r
+\r
+//\r
+// BDS Platform Functions\r
+//\r
+\r
+/**\r
+  Do the platform init, can be customized by OEM/IBV\r
+  Possible things that can be done in PlatformBootManagerBeforeConsole:\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
+  UINT16         FrontPageTimeout;\r
+  RETURN_STATUS  PcdStatus;\r
+  EFI_STATUS     Status;\r
+\r
+  //\r
+  // Signal EndOfDxe PI Event\r
+  //\r
+  EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
+\r
+  //\r
+  // Disable the TPM 2 platform hierarchy\r
+  //\r
+  ConfigureTpmPlatformHierarchy ();\r
+\r
+  //\r
+  // Dispatch deferred images after EndOfDxe event.\r
+  //\r
+  EfiBootManagerDispatchDeferredImages ();\r
+\r
+  //\r
+  // Locate the PCI root bridges and make the PCI bus driver connect each,\r
+  // non-recursively. This will produce a number of child handles with PciIo on\r
+  // them.\r
+  //\r
+  FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);\r
+\r
+  //\r
+  // Signal the ACPI platform driver that it can download QEMU ACPI tables.\r
+  //\r
+  EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);\r
+\r
+  //\r
+  // Find all display class PCI devices (using the handles from the previous\r
+  // step), and connect them non-recursively. This should produce a number of\r
+  // child handles with GOPs on them.\r
+  //\r
+  FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);\r
+\r
+  //\r
+  // Now add the device path of all handles with GOP on them to ConOut and\r
+  // ErrOut.\r
+  //\r
+  FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);\r
+\r
+  //\r
+  // Add the hardcoded short-form USB keyboard device path to ConIn.\r
+  //\r
+  EfiBootManagerUpdateConsoleVariable (\r
+    ConIn,\r
+    (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard,\r
+    NULL\r
+    );\r
+\r
+  //\r
+  // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.\r
+  //\r
+  CopyGuid (\r
+    &mSerialConsole.TermType.Guid,\r
+    PcdGetPtr (PcdTerminalTypeGuidBuffer)\r
+    );\r
+  EfiBootManagerUpdateConsoleVariable (\r
+    ConIn,\r
+    (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,\r
+    NULL\r
+    );\r
+  EfiBootManagerUpdateConsoleVariable (\r
+    ConOut,\r
+    (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,\r
+    NULL\r
+    );\r
+  EfiBootManagerUpdateConsoleVariable (\r
+    ErrOut,\r
+    (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,\r
+    NULL\r
+    );\r
+\r
+  //\r
+  // Set the front page timeout from the QEMU configuration.\r
+  //\r
+  FrontPageTimeout = GetFrontPageTimeoutFromQemu ();\r
+  PcdStatus        = PcdSet16S (PcdPlatformBootTimeOut, FrontPageTimeout);\r
+  ASSERT_RETURN_ERROR (PcdStatus);\r
+  //\r
+  // Reflect the PCD in the standard Timeout variable.\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
+  DEBUG ((\r
+    EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,\r
+    "%a: SetVariable(%s, %u): %r\n",\r
+    __func__,\r
+    EFI_TIME_OUT_VARIABLE_NAME,\r
+    FrontPageTimeout,\r
+    Status\r
+    ));\r
+\r
+  //\r
+  // Register platform-specific boot options and keyboard shortcuts.\r
+  //\r
+  PlatformRegisterOptionsAndKeys ();\r
+\r
+  //\r
+  // At this point, VIRTIO_DEVICE_PROTOCOL instances exist only for Virtio MMIO\r
+  // transports. Install EFI_RNG_PROTOCOL instances on Virtio MMIO RNG devices.\r
+  //\r
+  FilterAndProcess (&gVirtioDeviceProtocolGuid, IsVirtioRng, Connect);\r
+\r
+  //\r
+  // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL\r
+  // instances on Virtio PCI RNG devices.\r
+  //\r
+  FilterAndProcess (&gEfiPciIoProtocolGuid, IsVirtioPciRng, Connect);\r
+\r
+  //\r
+  // Register Virtio serial devices as console.\r
+  //\r
+  FilterAndProcess (&gVirtioDeviceProtocolGuid, IsVirtioSerial, SetupVirtioSerial);\r
+  FilterAndProcess (&gEfiPciIoProtocolGuid, IsVirtioPciSerial, SetupVirtioSerial);\r
+}\r
+\r
+/**\r
+  Uninstall the EFI memory attribute protocol if it exists.\r
+**/\r
+STATIC\r
+VOID\r
+UninstallEfiMemoryAttributesProtocol (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_HANDLE  Handle;\r
+  UINTN       Size;\r
+  VOID        *MemoryAttributeProtocol;\r
+\r
+  Size   = sizeof (Handle);\r
+  Status = gBS->LocateHandle (\r
+                  ByProtocol,\r
+                  &gEfiMemoryAttributeProtocolGuid,\r
+                  NULL,\r
+                  &Size,\r
+                  &Handle\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (Status == EFI_NOT_FOUND);\r
+    return;\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiMemoryAttributeProtocolGuid,\r
+                  &MemoryAttributeProtocol\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = gBS->UninstallProtocolInterface (\r
+                  Handle,\r
+                  &gEfiMemoryAttributeProtocolGuid,\r
+                  MemoryAttributeProtocol\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  Do the platform specific action after the console is ready\r
+  Possible things that can be done in PlatformBootManagerAfterConsole:\r
+  > Console post action:\r
+    > Dynamically switch output mode from 100x31 to 80x25 for certain scenario\r
+    > Signal console ready platform customized event\r
+  > Run diagnostics like memory testing\r
+  > Connect certain devices\r
+  > Dispatch additional option roms\r
+  > Special boot: e.g.: USB boot, enter UI\r
+**/\r
+VOID\r
+EFIAPI\r
+PlatformBootManagerAfterConsole (\r
+  VOID\r
+  )\r
+{\r
+  RETURN_STATUS  Status;\r
+  BOOLEAN        Uninstall;\r
+\r
+  //\r
+  // Show the splash screen.\r
+  //\r
+  BootLogoEnableLogo ();\r
+\r
+  //\r
+  // Work around shim's terminally broken use of the EFI memory attributes\r
+  // protocol, by uninstalling it if requested on the QEMU command line.\r
+  //\r
+  // E.g.,\r
+  //       -fw_cfg opt/org.tianocore/UninstallMemAttrProtocol,string=y\r
+  //\r
+  Uninstall = FixedPcdGetBool (PcdUninstallMemAttrProtocol);\r
+  QemuFwCfgParseBool ("opt/org.tianocore/UninstallMemAttrProtocol", &Uninstall);\r
+  DEBUG ((\r
+    DEBUG_WARN,\r
+    "%a: %auninstalling EFI memory protocol\n",\r
+    __func__,\r
+    Uninstall ? "" : "not "\r
+    ));\r
+  if (Uninstall) {\r
+    UninstallEfiMemoryAttributesProtocol ();\r
+  }\r
+\r
+  //\r
+  // Process QEMU's -kernel command line option. The kernel booted this way\r
+  // will receive ACPI tables: in PlatformBootManagerBeforeConsole(), we\r
+  // connected any and all PCI root bridges, and then signaled the ACPI\r
+  // platform driver.\r
+  //\r
+  TryRunningQemuKernel ();\r
+\r
+  //\r
+  // Connect the purported boot devices.\r
+  //\r
+  Status = ConnectDevicesFromQemu ();\r
+  if (RETURN_ERROR (Status)) {\r
+    //\r
+    // Connect the rest of the devices.\r
+    //\r
+    EfiBootManagerConnectAll ();\r
+  }\r
+\r
+  //\r
+  // Enumerate all possible boot options, then filter and reorder them based on\r
+  // the QEMU configuration.\r
+  //\r
+  EfiBootManagerRefreshAllBootOption ();\r
+\r
+  //\r
+  // Register UEFI Shell\r
+  //\r
+  PlatformRegisterFvBootOption (\r
+    &gUefiShellFileGuid,\r
+    L"EFI Internal Shell",\r
+    LOAD_OPTION_ACTIVE\r
+    );\r
+\r
+  RemoveStaleFvFileOptions ();\r
+  SetBootOrderFromQemu ();\r
+\r
+  PlatformBmPrintScRegisterHandler ();\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
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION  Black;\r
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION  White;\r
+  UINT16                               TimeoutInitial;\r
+\r
+  TimeoutInitial = PcdGet16 (PcdPlatformBootTimeOut);\r
+\r
+  //\r
+  // If PcdPlatformBootTimeOut is set to zero, then we consider\r
+  // that no progress update should be enacted.\r
+  //\r
+  if (TimeoutInitial == 0) {\r
+    return;\r
+  }\r
+\r
+  Black.Raw = 0x00000000;\r
+  White.Raw = 0x00FFFFFF;\r
+\r
+  BootLogoUpdateProgress (\r
+    White.Pixel,\r
+    Black.Pixel,\r
+    L"Start boot option",\r
+    White.Pixel,\r
+    (TimeoutInitial - TimeoutRemain) * 100 / TimeoutInitial,\r
+    0\r
+    );\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
+  EFI_STATUS                    Status;\r
+  EFI_INPUT_KEY                 Key;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION  BootManagerMenu;\r
+  UINTN                         Index;\r
+\r
+  //\r
+  // BootManagerMenu doesn't contain the correct information when return status\r
+  // is EFI_NOT_FOUND.\r
+  //\r
+  Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Normally BdsDxe does not print anything to the system console, but this is\r
+  // a last resort -- the end-user will likely not see any DEBUG messages\r
+  // logged in this situation.\r
+  //\r
+  // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn\r
+  // here to see if it makes sense to request and wait for a keypress.\r
+  //\r
+  if (gST->ConIn != NULL) {\r
+    AsciiPrint (\r
+      "%a: No bootable option or device was found.\n"\r
+      "%a: Press any key to enter the Boot Manager Menu.\n",\r
+      gEfiCallerBaseName,\r
+      gEfiCallerBaseName\r
+      );\r
+    Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);\r
+    ASSERT_EFI_ERROR (Status);\r
+    ASSERT (Index == 0);\r
+\r
+    //\r
+    // Drain any queued keys.\r
+    //\r
+    while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {\r
+      //\r
+      // just throw away Key\r
+      //\r
+    }\r
+  }\r
+\r
+  for ( ; ;) {\r
+    EfiBootManagerBoot (&BootManagerMenu);\r
+  }\r
+}\r
diff --git a/OvmfPkg/Library/PlatformBootManagerLibLight/PlatformBm.h b/OvmfPkg/Library/PlatformBootManagerLibLight/PlatformBm.h
new file mode 100644 (file)
index 0000000..70c52d9
--- /dev/null
@@ -0,0 +1,45 @@
+/** @file\r
+  Head file for BDS Platform specific code\r
+\r
+  Copyright (C) 2015-2016, Red Hat, Inc.\r
+  Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef _PLATFORM_BM_H_\r
+#define _PLATFORM_BM_H_\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+\r
+/**\r
+  Download the kernel, the initial ramdisk, and the kernel command line from\r
+  QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two\r
+  image files, and load and start the kernel from it.\r
+\r
+  The kernel will be instructed via its command line to load the initrd from\r
+  the same Simple FileSystem.\r
+\r
+  @retval EFI_NOT_FOUND         Kernel image was not found.\r
+  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.\r
+  @retval EFI_PROTOCOL_ERROR    Unterminated kernel command line.\r
+\r
+  @return                       Error codes from any of the underlying\r
+                                functions. On success, the function doesn't\r
+                                return.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TryRunningQemuKernel (\r
+  VOID\r
+  );\r
+\r
+#endif // _PLATFORM_BM_H_\r
diff --git a/OvmfPkg/Library/PlatformBootManagerLibLight/PlatformBootManagerLib.inf b/OvmfPkg/Library/PlatformBootManagerLibLight/PlatformBootManagerLib.inf
new file mode 100644 (file)
index 0000000..8e7cd56
--- /dev/null
@@ -0,0 +1,79 @@
+## @file\r
+#  Implementation for PlatformBootManagerLib library class interfaces.\r
+#\r
+#  Copyright (C) 2015-2016, Red Hat, Inc.\r
+#  Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>\r
+#  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
+#\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = PlatformBootManagerLib\r
+  FILE_GUID                      = 469184E8-FADA-41E4-8823-012CA19B40D4\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = PlatformBootManagerLib|DXE_DRIVER\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = ARM AARCH64\r
+#\r
+\r
+[Sources]\r
+  PlatformBm.c\r
+  PlatformBm.h\r
+  QemuKernel.c\r
+\r
+[Packages]\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  MdePkg/MdePkg.dec\r
+  OvmfPkg/OvmfPkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+  ShellPkg/ShellPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  BootLogoLib\r
+  DebugLib\r
+  DevicePathLib\r
+  MemoryAllocationLib\r
+  PcdLib\r
+  PlatformBmPrintScLib\r
+  QemuBootOrderLib\r
+  QemuFwCfgSimpleParserLib\r
+  QemuLoadImageLib\r
+  ReportStatusCodeLib\r
+  TpmPlatformHierarchyLib\r
+  UefiBootManagerLib\r
+  UefiBootServicesTableLib\r
+  UefiLib\r
+  UefiRuntimeServicesTableLib\r
+\r
+[FixedPcd]\r
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate\r
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits\r
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity\r
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdUninstallMemAttrProtocol\r
+\r
+[Pcd]\r
+  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdTerminalTypeGuidBuffer\r
+\r
+[Guids]\r
+  gEfiEndOfDxeEventGroupGuid\r
+  gEfiGlobalVariableGuid\r
+  gRootBridgesConnectedEventGroupGuid\r
+  gUefiShellFileGuid\r
+\r
+[Protocols]\r
+  gEfiFirmwareVolume2ProtocolGuid\r
+  gEfiGraphicsOutputProtocolGuid\r
+  gEfiMemoryAttributeProtocolGuid\r
+  gEfiPciRootBridgeIoProtocolGuid\r
+  gVirtioDeviceProtocolGuid\r
diff --git a/OvmfPkg/Library/PlatformBootManagerLibLight/QemuKernel.c b/OvmfPkg/Library/PlatformBootManagerLibLight/QemuKernel.c
new file mode 100644 (file)
index 0000000..7dc59ae
--- /dev/null
@@ -0,0 +1,77 @@
+/** @file\r
+  Try to load an EFI-stubbed ARM Linux kernel from QEMU's fw_cfg.\r
+\r
+  This implementation differs from OvmfPkg/Library/LoadLinuxLib. An EFI\r
+  stub in the subject kernel is a hard requirement here.\r
+\r
+  Copyright (C) 2014-2016, Red Hat, Inc.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#include <Library/QemuLoadImageLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+\r
+#include "PlatformBm.h"\r
+\r
+//\r
+// The entry point of the feature.\r
+//\r
+\r
+/**\r
+  Download the kernel, the initial ramdisk, and the kernel command line from\r
+  QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two\r
+  image files, and load and start the kernel from it.\r
+\r
+  The kernel will be instructed via its command line to load the initrd from\r
+  the same Simple FileSystem.\r
+\r
+  @retval EFI_NOT_FOUND         Kernel image was not found.\r
+  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.\r
+  @retval EFI_PROTOCOL_ERROR    Unterminated kernel command line.\r
+\r
+  @return                       Error codes from any of the underlying\r
+                                functions. On success, the function doesn't\r
+                                return.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TryRunningQemuKernel (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_HANDLE  KernelImageHandle;\r
+\r
+  Status = QemuLoadKernelImage (&KernelImageHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Signal the EFI_EVENT_GROUP_READY_TO_BOOT event.\r
+  //\r
+  EfiSignalEventReadyToBoot ();\r
+\r
+  REPORT_STATUS_CODE (\r
+    EFI_PROGRESS_CODE,\r
+    (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT)\r
+    );\r
+\r
+  //\r
+  // Start the image.\r
+  //\r
+  Status = QemuStartKernelImage (&KernelImageHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "%a: QemuStartKernelImage(): %r\n",\r
+      __func__,\r
+      Status\r
+      ));\r
+  }\r
+\r
+  QemuUnloadKernelImage (KernelImageHandle);\r
+\r
+  return Status;\r
+}\r