mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-11-04 05:38:26 +00:00 
			
		
		
		
	Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Ruiyu Ni <ruiyu.ni@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Dandan Bi <dandan.bi@intel.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
		
			
				
	
	
		
			280 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			280 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
  Copyright (C) 2016, Linaro Ltd. All rights reserved.<BR>
 | 
						|
 | 
						|
  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 "NonDiscoverablePciDeviceIo.h"
 | 
						|
 | 
						|
#include <Protocol/DriverBinding.h>
 | 
						|
 | 
						|
EFI_CPU_ARCH_PROTOCOL      *mCpu;
 | 
						|
 | 
						|
//
 | 
						|
// We only support the following device types
 | 
						|
//
 | 
						|
STATIC
 | 
						|
CONST EFI_GUID * CONST
 | 
						|
SupportedNonDiscoverableDevices[] = {
 | 
						|
  &gEdkiiNonDiscoverableAhciDeviceGuid,
 | 
						|
  &gEdkiiNonDiscoverableEhciDeviceGuid,
 | 
						|
  &gEdkiiNonDiscoverableNvmeDeviceGuid,
 | 
						|
  &gEdkiiNonDiscoverableOhciDeviceGuid,
 | 
						|
  &gEdkiiNonDiscoverableSdhciDeviceGuid,
 | 
						|
  &gEdkiiNonDiscoverableUfsDeviceGuid,
 | 
						|
  &gEdkiiNonDiscoverableUhciDeviceGuid,
 | 
						|
  &gEdkiiNonDiscoverableXhciDeviceGuid,
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Probe, start and stop functions of this driver, called by the DXE core for
 | 
						|
// specific devices.
 | 
						|
//
 | 
						|
// The following specifications document these interfaces:
 | 
						|
// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
 | 
						|
// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
 | 
						|
//
 | 
						|
// The implementation follows:
 | 
						|
// - Driver Writer's Guide for UEFI 2.3.1 v1.01
 | 
						|
//   - 5.1.3.4 OpenProtocol() and CloseProtocol()
 | 
						|
// - UEFI Spec 2.3.1 + Errata C
 | 
						|
//   -  6.3 Protocol Handler Services
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Supported function of Driver Binding protocol for this driver.
 | 
						|
  Test to see if this driver supports ControllerHandle.
 | 
						|
 | 
						|
  @param This                   Protocol instance pointer.
 | 
						|
  @param DeviceHandle           Handle of device to test.
 | 
						|
  @param RemainingDevicePath    A pointer to the device path.
 | 
						|
                                it should be ignored by device driver.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           This driver supports this device.
 | 
						|
  @retval other                 This driver does not support this device.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
NonDiscoverablePciDeviceSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL *This,
 | 
						|
  IN EFI_HANDLE                  DeviceHandle,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  NON_DISCOVERABLE_DEVICE             *Device;
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
 | 
						|
  INTN                                Idx;
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (DeviceHandle,
 | 
						|
                  &gEdkiiNonDiscoverableDeviceProtocolGuid, (VOID **)&Device,
 | 
						|
                  This->DriverBindingHandle, DeviceHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EFI_UNSUPPORTED;
 | 
						|
  for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) {
 | 
						|
    if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) {
 | 
						|
      Status = EFI_SUCCESS;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto CloseProtocol;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // We only support MMIO devices, so iterate over the resources to ensure
 | 
						|
  // that they only describe things that we can handle
 | 
						|
  //
 | 
						|
  for (Desc = Device->Resources; Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
 | 
						|
       Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
 | 
						|
    if (Desc->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR ||
 | 
						|
        Desc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
 | 
						|
      Status = EFI_UNSUPPORTED;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
CloseProtocol:
 | 
						|
  gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
 | 
						|
         This->DriverBindingHandle, DeviceHandle);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This routine is called right after the .Supported() called and
 | 
						|
  Start this driver on ControllerHandle.
 | 
						|
 | 
						|
  @param This                   Protocol instance pointer.
 | 
						|
  @param DeviceHandle           Handle of device to bind driver to.
 | 
						|
  @param RemainingDevicePath    A pointer to the device path.
 | 
						|
                                it should be ignored by device driver.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           This driver is added to this device.
 | 
						|
  @retval other                 Some error occurs when binding this driver to this device.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
NonDiscoverablePciDeviceStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL *This,
 | 
						|
  IN EFI_HANDLE                  DeviceHandle,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  NON_DISCOVERABLE_PCI_DEVICE   *Dev;
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
 | 
						|
  Dev = AllocateZeroPool (sizeof *Dev);
 | 
						|
  if (Dev == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (DeviceHandle,
 | 
						|
                  &gEdkiiNonDiscoverableDeviceProtocolGuid,
 | 
						|
                  (VOID **)&Dev->Device, This->DriverBindingHandle,
 | 
						|
                  DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto FreeDev;
 | 
						|
  }
 | 
						|
 | 
						|
  InitializePciIoProtocol (Dev);
 | 
						|
 | 
						|
  //
 | 
						|
  // Setup complete, attempt to export the driver instance's
 | 
						|
  // EFI_PCI_IO_PROTOCOL interface.
 | 
						|
  //
 | 
						|
  Dev->Signature = NON_DISCOVERABLE_PCI_DEVICE_SIG;
 | 
						|
  Status = gBS->InstallProtocolInterface (&DeviceHandle, &gEfiPciIoProtocolGuid,
 | 
						|
                  EFI_NATIVE_INTERFACE, &Dev->PciIo);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto CloseProtocol;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
CloseProtocol:
 | 
						|
  gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
 | 
						|
         This->DriverBindingHandle, DeviceHandle);
 | 
						|
 | 
						|
FreeDev:
 | 
						|
  FreePool (Dev);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Stop this driver on ControllerHandle.
 | 
						|
 | 
						|
  @param This               Protocol instance pointer.
 | 
						|
  @param DeviceHandle       Handle of device to stop driver on.
 | 
						|
  @param NumberOfChildren   Not used.
 | 
						|
  @param ChildHandleBuffer  Not used.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   This driver is removed from this device.
 | 
						|
  @retval other         Some error occurs when removing this driver from this device.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
NonDiscoverablePciDeviceStop (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL *This,
 | 
						|
  IN EFI_HANDLE                  DeviceHandle,
 | 
						|
  IN UINTN                       NumberOfChildren,
 | 
						|
  IN EFI_HANDLE                  *ChildHandleBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  EFI_PCI_IO_PROTOCOL             *PciIo;
 | 
						|
  NON_DISCOVERABLE_PCI_DEVICE     *Dev;
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (PciIo);
 | 
						|
 | 
						|
  //
 | 
						|
  // Handle Stop() requests for in-use driver instances gracefully.
 | 
						|
  //
 | 
						|
  Status = gBS->UninstallProtocolInterface (DeviceHandle,
 | 
						|
                  &gEfiPciIoProtocolGuid, &Dev->PciIo);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
 | 
						|
         This->DriverBindingHandle, DeviceHandle);
 | 
						|
 | 
						|
  FreePool (Dev);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//
 | 
						|
// 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 = {
 | 
						|
  &NonDiscoverablePciDeviceSupported,
 | 
						|
  &NonDiscoverablePciDeviceStart,
 | 
						|
  &NonDiscoverablePciDeviceStop,
 | 
						|
  0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Entry point of this driver.
 | 
						|
 | 
						|
  @param  ImageHandle     Image handle this driver.
 | 
						|
  @param  SystemTable     Pointer to the System Table.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS     The entry point is executed successfully.
 | 
						|
  @retval other           Some error occurred when executing this entry point.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
NonDiscoverablePciDeviceDxeEntryPoint (
 | 
						|
  IN EFI_HANDLE       ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS      Status;
 | 
						|
 | 
						|
  Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
 | 
						|
  ASSERT_EFI_ERROR(Status);
 | 
						|
 | 
						|
  return EfiLibInstallDriverBindingComponentName2 (
 | 
						|
           ImageHandle,
 | 
						|
           SystemTable,
 | 
						|
           &gDriverBinding,
 | 
						|
           ImageHandle,
 | 
						|
           &gComponentName,
 | 
						|
           &gComponentName2
 | 
						|
           );
 | 
						|
}
 |