deviceio.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 846 行 · 第 1/2 页

C
846
字号
                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
                                           Address,
                                           Count,
                                           Buffer
                                           );

  return Status;
}

EFI_DEVICE_PATH_PROTOCOL *
AppendPciDevicePath (
  IN     DEVICE_IO_PRIVATE_DATA    *Private,
  IN     UINT8                     Bus,
  IN     UINT8                     Device,
  IN     UINT8                     Function,
  IN     EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
  IN OUT UINT16                    *BridgePrimaryBus,
  IN OUT UINT16                    *BridgeSubordinateBus
  )
/*++

Routine Description:
  
  Append a PCI device path node to another device path.

Arguments:
  
  Private               -  A pointer to DEVICE_IO_PRIVATE_DATA instance.  
  Bus                   -  PCI bus number of the device.
  Device                -  PCI device number of the device.
  Function              -  PCI function number of the device.
  DevicePath            -  Original device path which will be appended a PCI device path node.
  BridgePrimaryBus      -  Primary bus number of the bridge.
  BridgeSubordinateBus  -  Subordinate bus number of the bridge.

Returns:
  
  Pointer to the appended PCI device path.

--*/
{
  UINT16                    ThisBus;
  UINT8                     ThisDevice;
  UINT8                     ThisFunc;
  UINT64                    Address;
  PCI_TYPE01                PciBridge;
  PCI_TYPE01                *PciPtr;
  EFI_DEVICE_PATH_PROTOCOL  *ReturnDevicePath;
  PCI_DEVICE_PATH           PciNode;

  PciPtr = &PciBridge;
  for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {
    for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {
      for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {
        Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);
        EfiZeroMem (PciPtr, sizeof (PCI_TYPE01));
        Private->DeviceIo.Pci.Read (
                                &Private->DeviceIo,
                                IO_UINT32,
                                Address,
                                1,
                                &(PciPtr->Hdr.VendorId)
                                );
        if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {
          break;
        }
        if (PciPtr->Hdr.VendorId == 0xffff) {
          continue;
        }

        Private->DeviceIo.Pci.Read (
                                &Private->DeviceIo,
                                IO_UINT32,
                                Address,
                                sizeof (PCI_TYPE01) / sizeof (UINT32),
                                PciPtr
                                );
        if (IS_PCI_BRIDGE (PciPtr)) {
          if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {

            PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
            PciNode.Header.SubType  = HW_PCI_DP;
            SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));

            PciNode.Device        = ThisDevice;
            PciNode.Function      = ThisFunc;
            ReturnDevicePath      = EfiAppendDevicePathNode (DevicePath, &PciNode.Header);

            *BridgePrimaryBus     = PciPtr->Bridge.SecondaryBus;
            *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;
            return ReturnDevicePath;
          }
        }

        if ((ThisFunc == 0) && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x0)) {
          //
          // Skip sub functions, this is not a multi function device
          //
          break;
        }
      }
    }
  }

  EfiZeroMem (&PciNode, sizeof (PciNode));
  PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
  PciNode.Header.SubType  = HW_PCI_DP;
  SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
  PciNode.Device        = Device;
  PciNode.Function      = Function;

  ReturnDevicePath      = EfiAppendDevicePathNode (DevicePath, &PciNode.Header);

  *BridgePrimaryBus     = 0xffff;
  *BridgeSubordinateBus = 0xffff;
  return ReturnDevicePath;
}

EFI_STATUS
EFIAPI
DeviceIoPciDevicePath (
  IN     EFI_DEVICE_IO_PROTOCOL        *This,
  IN     UINT64                        Address,
  IN OUT EFI_DEVICE_PATH_PROTOCOL      **PciDevicePath
  )
/*++

Routine Description:
  
  Provides an EFI Device Path for a PCI device with the given PCI configuration space address.

Arguments:
  
  This           -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.  
  Address        -  The PCI configuration space address of the device whose Device Path
                    is going to be returned.           
  PciDevicePath  -  A pointer to the pointer for the EFI Device Path for PciAddress.
                    Memory for the Device Path is allocated from the pool.

Returns:
  
  EFI_SUCCESS           -  The PciDevicePath returns a pointer to a valid EFI Device Path.
  EFI_UNSUPPORTED       -  The PciAddress does not map to a valid EFI Device Path. 
  EFI_OUT_OF_RESOURCES  -  The request could not be completed due to a lack of resources.

--*/
{
  DEVICE_IO_PRIVATE_DATA  *Private;
  UINT16                  PrimaryBus;
  UINT16                  SubordinateBus;
  UINT8                   Bus;
  UINT8                   Device;
  UINT8                   Func;

  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

  Bus     = (UINT8) (((UINT32) Address >> 24) & 0xff);
  Device  = (UINT8) (((UINT32) Address >> 16) & 0xff);
  Func    = (UINT8) (((UINT32) Address >> 8) & 0xff);

  if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {
    return EFI_UNSUPPORTED;
  }

  *PciDevicePath  = Private->DevicePath;
  PrimaryBus      = Private->PrimaryBus;
  SubordinateBus  = Private->SubordinateBus;
  do {
    *PciDevicePath = AppendPciDevicePath (
                       Private,
                       Bus,
                       Device,
                       Func,
                       *PciDevicePath,
                       &PrimaryBus,
                       &SubordinateBus
                       );
    if (*PciDevicePath == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
  } while (PrimaryBus != 0xffff);

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
DeviceIoMap (
  IN     EFI_DEVICE_IO_PROTOCOL   *This,
  IN     EFI_IO_OPERATION_TYPE    Operation,
  IN     EFI_PHYSICAL_ADDRESS     *HostAddress,
  IN OUT UINTN                    *NumberOfBytes,
  OUT    EFI_PHYSICAL_ADDRESS     *DeviceAddress,
  OUT    VOID                     **Mapping
  )
/*++

Routine Description:
  
  Provides the device-specific addresses needed to access system memory.

Arguments:
  
  This           -  A pointer to the EFI_DEVICE_IO_INTERFACE instance. 
  Operation      -  Indicates if the bus master is going to read or write to system memory.  
  HostAddress    -  The system memory address to map to the device.
  NumberOfBytes  -  On input the number of bytes to map. On output the number of bytes
                    that were mapped.
  DeviceAddress  -  The resulting map address for the bus master device to use to access the
                    hosts HostAddress.
  Mapping        -  A resulting value to pass to Unmap().

Returns:
  
  EFI_SUCCESS            -  The range was mapped for the returned NumberOfBytes. 
  EFI_INVALID_PARAMETER  -  The Operation or HostAddress is undefined. 
  EFI_UNSUPPORTED        -  The HostAddress cannot be mapped as a common buffer.
  EFI_DEVICE_ERROR       -  The system hardware could not map the requested address. 
  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of resources.

--*/
{
  EFI_STATUS              Status;
  DEVICE_IO_PRIVATE_DATA  *Private;

  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

  if (Operation < 0 || Operation > EfiBusMasterCommonBuffer) {
    return EFI_INVALID_PARAMETER;
  }

  if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {
    return EFI_UNSUPPORTED;
  }

  Status = Private->PciRootBridgeIo->Map (
                                       Private->PciRootBridgeIo,
                                       (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
                                       (VOID *) (UINTN) (*HostAddress),
                                       NumberOfBytes,
                                       DeviceAddress,
                                       Mapping
                                       );

  return Status;
}

EFI_STATUS
EFIAPI
DeviceIoUnmap (
  IN EFI_DEVICE_IO_PROTOCOL   *This,
  IN VOID                     *Mapping
  )
/*++

Routine Description:
  
  Completes the Map() operation and releases any corresponding resources.

Arguments:
  
  This     -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
  Mapping  -  The mapping value returned from Map().

Returns:
  
  EFI_SUCCESS       -  The range was unmapped.
  EFI_DEVICE_ERROR  -  The data was not committed to the target system memory.

--*/
{
  EFI_STATUS              Status;
  DEVICE_IO_PRIVATE_DATA  *Private;

  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

  Status = Private->PciRootBridgeIo->Unmap (
                                       Private->PciRootBridgeIo,
                                       Mapping
                                       );

  return Status;
}

EFI_STATUS
EFIAPI
DeviceIoAllocateBuffer (
  IN     EFI_DEVICE_IO_PROTOCOL    *This,
  IN     EFI_ALLOCATE_TYPE         Type,
  IN     EFI_MEMORY_TYPE           MemoryType,
  IN     UINTN                     Pages,
  IN OUT EFI_PHYSICAL_ADDRESS      *PhysicalAddress
  )
/*++

Routine Description:
  
  Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.

Arguments:
  
  This             -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
  Type             -  The type allocation to perform.
  MemoryType       -  The type of memory to allocate, EfiBootServicesData or
                      EfiRuntimeServicesData.
  Pages            -  The number of pages to allocate.
  PhysicalAddress  -  A pointer to store the base address of the allocated range.

Returns:
  
  EFI_SUCCESS            -  The requested memory pages were allocated.
  EFI_OUT_OF_RESOURCES   -  The memory pages could not be allocated.
  EFI_INVALID_PARAMETER  -  The requested memory type is invalid.
  EFI_UNSUPPORTED        -  The requested PhysicalAddress is not supported on
                            this platform.

--*/
{
  EFI_STATUS            Status;
  EFI_PHYSICAL_ADDRESS  HostAddress;

  HostAddress = *PhysicalAddress;

  if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
    return EFI_INVALID_PARAMETER;
  }

  if ((Type >= MaxAllocateType) || (Type < AllocateAnyPages)) {
    return EFI_INVALID_PARAMETER;
  }

  if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {
    return EFI_UNSUPPORTED;
  }

  if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {
    Type        = AllocateMaxAddress;
    HostAddress = MAX_COMMON_BUFFER;
  }

  Status = gBS->AllocatePages (
                  Type,
                  MemoryType,
                  Pages,
                  &HostAddress
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }


  *PhysicalAddress = HostAddress;

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
DeviceIoFlush (
  IN EFI_DEVICE_IO_PROTOCOL  *This
  )
/*++

Routine Description:
  
  Flushes any posted write data to the device.

Arguments:
  
  This  -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.

Returns:
  
  EFI_SUCCESS       -  The buffers were flushed.
  EFI_DEVICE_ERROR  -  The buffers were not flushed due to a hardware error.

--*/
{
  EFI_STATUS              Status;
  DEVICE_IO_PRIVATE_DATA  *Private;

  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

  Status  = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);

  return Status;
}

EFI_STATUS
EFIAPI
DeviceIoFreeBuffer (
  IN EFI_DEVICE_IO_PROTOCOL   *This,
  IN UINTN                    Pages,
  IN EFI_PHYSICAL_ADDRESS     HostAddress
  )
/*++

Routine Description:
  
  Frees pages that were allocated with AllocateBuffer().

Arguments:
  
  This         -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
  Pages        -  The number of pages to free.
  HostAddress  -  The base address of the range to free.

Returns:
  
  EFI_SUCCESS            -  The requested memory pages were freed.
  EFI_NOT_FOUND          -  The requested memory pages were not allocated with
                            AllocateBuffer().               
  EFI_INVALID_PARAMETER  -  HostAddress is not page aligned or Pages is invalid.

--*/
{
  if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {
    return EFI_INVALID_PARAMETER;
  }

  return gBS->FreePages (HostAddress, Pages);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?