],\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
\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
\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
+++ /dev/null
-/** @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
+++ /dev/null
-/** @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
+++ /dev/null
-## @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
+++ /dev/null
-/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+## @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
--- /dev/null
+/** @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