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 + -
显示快捷键?