From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ard Biesheuvel Subject: [PATCH v3 18/27] Ovmf/Xen: add separate driver for Xen PCI device Date: Tue, 3 Feb 2015 19:20:03 +0000 Message-ID: <1422991212-9257-19-git-send-email-ard.biesheuvel__6406.49609636075$1422991375$gmane$org@linaro.org> References: <1422991212-9257-1-git-send-email-ard.biesheuvel@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1422991212-9257-1-git-send-email-ard.biesheuvel@linaro.org> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: edk2-devel@lists.sourceforge.net, lersek@redhat.com, olivier.martin@arm.com, roy.franz@linaro.org, leif.lindholm@linaro.org, stefano.stabellini@eu.citrix.com, ian.campbell@citrix.com, anthony.perard@citrix.com, christoffer.dall@linaro.org, xen-devel@lists.xen.org, ilias.biris@linaro.org, julien.grall@linaro.org Cc: Ard Biesheuvel List-Id: xen-devel@lists.xenproject.org Prepare for making XenBusDxe suitable for use with non-PCI devices (such as the DT node exposed by Xen on ARM) by introducing a separate DXE driver that binds to the Xen virtual PCI device and exposes the abstract XENIO_PROTOCOL for XenBusDxe to bind against. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel --- OvmfPkg/XenIoPciDxe/XenIoPciDxe.c | 367 ++++++++++++++++++++++++++++++++++++ OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf | 45 +++++ 2 files changed, 412 insertions(+) create mode 100644 OvmfPkg/XenIoPciDxe/XenIoPciDxe.c create mode 100644 OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf diff --git a/OvmfPkg/XenIoPciDxe/XenIoPciDxe.c b/OvmfPkg/XenIoPciDxe/XenIoPciDxe.c new file mode 100644 index 000000000000..c205cf74db34 --- /dev/null +++ b/OvmfPkg/XenIoPciDxe/XenIoPciDxe.c @@ -0,0 +1,367 @@ +/** @file + + Driver for the virtual Xen PCI device + + Copyright (C) 2012, Red Hat, Inc. + Copyright (c) 2012, Intel Corporation. All rights reserved.
+ Copyright (C) 2013, ARM Ltd. + Copyright (C) 2015, Linaro Ltd. + + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define PCI_VENDOR_ID_XEN 0x5853 +#define PCI_DEVICE_ID_XEN_PLATFORM 0x0001 + +/** + + Device probe function for this driver. + + The DXE core calls this function for any given device in order to see if the + driver can drive the device. + + @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object + incorporating this driver (independently of + any device). + + @param[in] DeviceHandle The device to probe. + + @param[in] RemainingDevicePath Relevant only for bus drivers, ignored. + + + @retval EFI_SUCCESS The driver supports the device being probed. + + @retval EFI_UNSUPPORTED The driver does not support the device being probed. + + @return Error codes from the OpenProtocol() boot service or + the PciIo protocol. + +**/ +STATIC +EFI_STATUS +EFIAPI +XenIoPciDeviceBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + // + // Attempt to open the device with the PciIo set of interfaces. On success, + // the protocol is "instantiated" for the PCI device. Covers duplicate open + // attempts (EFI_ALREADY_STARTED). + // + Status = gBS->OpenProtocol ( + DeviceHandle, // candidate device + &gEfiPciIoProtocolGuid, // for generic PCI access + (VOID **)&PciIo, // handle to instantiate + This->DriverBindingHandle, // requestor driver identity + DeviceHandle, // ControllerHandle, according to + // the UEFI Driver Model + EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to + // the device; to be released + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Read entire PCI configuration header for more extensive check ahead. + // + Status = PciIo->Pci.Read ( + PciIo, // (protocol, device) + // handle + EfiPciIoWidthUint32, // access width & copy + // mode + 0, // Offset + sizeof Pci / sizeof (UINT32), // Count + &Pci // target buffer + ); + + if (Status == EFI_SUCCESS) { + if ((Pci.Hdr.VendorId == PCI_VENDOR_ID_XEN) && + (Pci.Hdr.DeviceId == PCI_DEVICE_ID_XEN_PLATFORM)) { + Status = EFI_SUCCESS; + } else { + Status = EFI_UNSUPPORTED; + } + } + + // + // We needed PCI IO access only transitorily, to see whether we support the + // device or not. + // + gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, DeviceHandle); + + return Status; +} + +/** + + After we've pronounced support for a specific device in + DriverBindingSupported(), we start managing said device (passed in by the + Driver Exeuction Environment) with the following service. + + See DriverBindingSupported() for specification references. + + @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object + incorporating this driver (independently of + any device). + + @param[in] DeviceHandle The supported device to drive. + + @param[in] RemainingDevicePath Relevant only for bus drivers, ignored. + + + @retval EFI_SUCCESS The device was started. + + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + + @return Error codes from the OpenProtocol() boot + service, the PciIo protocol or the + InstallProtocolInterface() boot service. + +**/ +STATIC +EFI_STATUS +EFIAPI +XenIoPciDeviceBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + XENIO_PROTOCOL *XenIo; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc; + + XenIo = (XENIO_PROTOCOL *) AllocateZeroPool (sizeof *XenIo); + if (XenIo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + (VOID **)&PciIo, This->DriverBindingHandle, + DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); + if (EFI_ERROR (Status)) { + goto FreeXenIo; + } + + // + // The BAR1 of this PCI device is used for shared memory and is supposed to + // look like MMIO. The address space of the BAR1 will be used to map the + // Grant Table. + // + Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX1, NULL, (VOID**) &BarDesc); + ASSERT_EFI_ERROR (Status); + ASSERT (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM); + + /* Get a Memory address for mapping the Grant Table. */ + DEBUG ((EFI_D_INFO, "XenIoPci: BAR at %LX\n", BarDesc->AddrRangeMin)); + XenIo->GrantTableAddress = BarDesc->AddrRangeMin; + FreePool (BarDesc); + + Status = gBS->InstallProtocolInterface (&DeviceHandle, + &gXenIoProtocolGuid, EFI_NATIVE_INTERFACE, XenIo); + + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, DeviceHandle); + +FreeXenIo: + FreePool (XenIo); + + return Status; +} + +/** + + Stop driving the XenIo PCI device + + @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object + incorporating this driver (independently of any + device). + + @param[in] DeviceHandle Stop driving this device. + + @param[in] NumberOfChildren Since this function belongs to a device driver + only (as opposed to a bus driver), the caller + environment sets NumberOfChildren to zero, and + we ignore it. + + @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren). + + @retval EFI_SUCCESS Driver instance has been stopped and the PCI + configuration attributes have been restored. + + @return Error codes from the OpenProtocol() or + CloseProtocol(), UninstallProtocolInterface() + boot services. + +**/ +STATIC +EFI_STATUS +EFIAPI +XenIoPciDeviceBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + XENIO_PROTOCOL *XenIo; + + Status = gBS->OpenProtocol ( + DeviceHandle, // candidate device + &gXenIoProtocolGuid, // retrieve the XenIo iface + (VOID **)&XenIo, // target pointer + This->DriverBindingHandle, // requestor driver identity + DeviceHandle, // requesting lookup for dev. + EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Handle Stop() requests for in-use driver instances gracefully. + // + Status = gBS->UninstallProtocolInterface (DeviceHandle, + &gXenIoProtocolGuid, XenIo); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, DeviceHandle); + + FreePool (XenIo); + + return Status; +} + + +// +// The static object that groups the Supported() (ie. probe), Start() and +// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata +// C, 10.1 EFI Driver Binding Protocol. +// +STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = { + &XenIoPciDeviceBindingSupported, + &XenIoPciDeviceBindingStart, + &XenIoPciDeviceBindingStop, + 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers + NULL, // ImageHandle, to be overwritten by + // EfiLibInstallDriverBindingComponentName2() in XenIoPciDeviceEntryPoint() + NULL // DriverBindingHandle, ditto +}; + + +// +// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and +// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name +// in English, for display on standard console devices. This is recommended for +// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's +// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names. +// +STATIC +EFI_UNICODE_STRING_TABLE mDriverNameTable[] = { + { "eng;en", L"XenIo PCI Driver" }, + { NULL, NULL } +}; + +STATIC +EFI_COMPONENT_NAME_PROTOCOL gComponentName; + +EFI_STATUS +EFIAPI +XenIoPciGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mDriverNameTable, + DriverName, + (BOOLEAN)(This == &gComponentName) // Iso639Language + ); +} + +EFI_STATUS +EFIAPI +XenIoPciGetDeviceName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN EFI_HANDLE ChildHandle, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} + +STATIC +EFI_COMPONENT_NAME_PROTOCOL gComponentName = { + &XenIoPciGetDriverName, + &XenIoPciGetDeviceName, + "eng" // SupportedLanguages, ISO 639-2 language codes +}; + +STATIC +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &XenIoPciGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &XenIoPciGetDeviceName, + "en" // SupportedLanguages, RFC 4646 language codes +}; + + +// +// Entry point of this driver. +// +EFI_STATUS +EFIAPI +XenIoPciDeviceEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gDriverBinding, + ImageHandle, + &gComponentName, + &gComponentName2 + ); +} diff --git a/OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf b/OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf new file mode 100644 index 000000000000..b32075a38163 --- /dev/null +++ b/OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf @@ -0,0 +1,45 @@ +## @file +# Driver for the virtual Xen PCI device +# +# Copyright (C) 2015, Linaro Ltd. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = XenIoPciDxe + FILE_GUID = cf569f50-de44-4f54-b4d7-f4ae25cda599 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = XenIoPciDeviceEntryPoint + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[Sources] + XenIoPciDxe.c + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiLib + DebugLib + +[Protocols] + gEfiDriverBindingProtocolGuid + gEfiPciIoProtocolGuid + gEfiComponentName2ProtocolGuid + gEfiComponentNameProtocolGuid + gXenIoProtocolGuid -- 1.8.3.2