cpuio.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 799 行 · 第 1/2 页
C
799 行
//
// If the NT32 Passthrough has forced a HostBridgeInit
//
if (gHostBridgeInit) {
if (gReadPending) {
//
// We found an access to our device
//
EFI_BREAKPOINT ();
gWinNtThunk->DeviceIoControl (
gDeviceHandle, // Handle to device
IOCTL_IO_READ, // IO Control code to use
&Address, // Address to communicate to driver
sizeof (UINT32), // Length of buffer in bytes.
&Result, // In Buffer to fill in by kernel driver.
sizeof (UINT16), // Length of buffer in bytes.
&ReturnedLength, // Bytes placed in In buffer.
NULL // NULL means wait till op. completes.
);
gReadPending = FALSE;
} else {
Result = 0xFFFF;
}
}
*Buffer.ui16 = (UINT16) Result;
break;
case EfiCpuIoWidthUint32:
//
// If the NT32 Passthrough has forced a HostBridgeInit
//
if (gHostBridgeInit) {
if (gReadPending) {
//
// We found an access to our device
//
EFI_BREAKPOINT ();
gWinNtThunk->DeviceIoControl (
gDeviceHandle, // Handle to device
IOCTL_IO_READ, // IO Control code to use
&Address, // Address to communicate to driver
sizeof (UINT32), // Length of buffer in bytes.
&Result, // In Buffer to fill in by kernel driver.
sizeof (UINT32), // Length of buffer in bytes.
&ReturnedLength, // Bytes placed in In buffer.
NULL // NULL means wait till op. completes.
);
gReadPending = FALSE;
} else {
Result = 0xFFFF;
}
}
*Buffer.ui32 = Result;
break;
default:
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
CpuIoServiceWrite (
IN EFI_CPU_IO_PROTOCOL *This,
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
/*++
Routine Description:
This is the service that implements the I/O Write
Arguments:
Pointer to an instance of the CPU I/O Protocol
Width of the Memory Access
Address of the I/O access
Count of the number of accesses to perform
Pointer to the buffer to read or write from I/O space
Returns:
Status
Status
EFI_SUCCESS - The data was read from or written to the EFI System.
EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
EFI_INVALID_PARAMETER - Buffer is NULL.
EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
EFI_UNSUPPORTED - The address range specified by Address, Width, and
Count is not valid for this EFI System.
--*/
// TODO: This - add argument and description to function comment
// TODO: UserAddress - add argument and description to function comment
// TODO: UserBuffer - add argument and description to function comment
{
UINTN Address;
EFI_STATUS Status;
UINTN InStride;
UINTN OutStride;
PTR Buffer;
LONG ReturnedLength;
UINT32 Result;
if (!UserBuffer) {
return EFI_INVALID_PARAMETER;
}
Address = (UINTN) UserAddress;
Buffer.buf = (UINT8 *) UserBuffer;
if (Width >= EfiCpuIoWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
if (EFI_ERROR (Status)) {
return Status;
}
InStride = 1 << (Width & 0x03);
OutStride = InStride;
if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
InStride = 0;
}
if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
OutStride = 0;
}
Width = Width & 0x03;
gReadPending = FALSE;
//
// NT32PASSTHRU: Thunk into our I/O routine to talk to the kernel driver IOCTL
// I/O such as write CF8->80000000, Read CFC etc...... Bit 31 = Enable PCI Config Access
// Bit 24-30 = Reserved must be zero (segment?)
// Bit 16-23 = Bus (0-255)
// Bit 11-15 = Device (0-31)
// Bit 8-10 = Function (0-7)
// Bit 2-7 = Target dword (0-63) (yields 256 bytes of access)
// Bit 0-1 = Zero's)
//
switch (Width) {
case EfiCpuIoWidthUint8:
//
// If the NT32 Passthrough has forced a HostBridgeInit and if the request is from a device
// on a given Bus/Device location. Mask off the remaining functions
//
if (gHostBridgeInit) {
if ((*(UINT32 *) Buffer.ui32 & 0xFFFFFF00) == *((UINT32 *) &gConfigData)) {
Result = *Buffer.ui8;
//
// We found an access to our device
//
EFI_BREAKPOINT ();
gWinNtThunk->DeviceIoControl (
gDeviceHandle, // Handle to device
IOCTL_IO_WRITE, // IO Control code to use
&Address, // Address to communicate to driver
sizeof (UINT32), // Length of buffer in bytes.
&Result, // In Buffer to fill in by kernel driver.
sizeof (UINT8), // Length of buffer in bytes.
&ReturnedLength, // Bytes placed in In buffer.
NULL // NULL means wait till op. completes.
);
gReadPending = TRUE;
return EFI_SUCCESS;
}
}
break;
case EfiCpuIoWidthUint16:
//
// If the NT32 Passthrough has forced a HostBridgeInit and if the request is from a device
// on a given Bus/Device location. Mask off the remaining functions
//
if (gHostBridgeInit) {
if ((*(UINT32 *) Buffer.ui32 & 0xFFFFFF00) == *((UINT32 *) &gConfigData)) {
Result = *Buffer.ui16;
//
// We found an access to our device
//
EFI_BREAKPOINT ();
gWinNtThunk->DeviceIoControl (
gDeviceHandle, // Handle to device
IOCTL_IO_WRITE, // IO Control code to use
&Address, // Address to communicate to driver
sizeof (UINT32), // Length of buffer in bytes.
&Result, // In Buffer to fill in by kernel driver.
sizeof (UINT16), // Length of buffer in bytes.
&ReturnedLength, // Bytes placed in In buffer.
NULL // NULL means wait till op. completes.
);
gReadPending = TRUE;
return EFI_SUCCESS;
}
}
break;
case EfiCpuIoWidthUint32:
//
// If the NT32 Passthrough has forced a HostBridgeInit and if the request is from a device
// on a given Bus/Device location. Mask off the remaining functions
//
if (gHostBridgeInit) {
if ((*(UINT32 *) Buffer.ui32 & 0xFFFFFF00) == *((UINT32 *) &gConfigData)) {
Result = *Buffer.ui32;
//
// We found an access to our device
//
EFI_BREAKPOINT ();
gWinNtThunk->DeviceIoControl (
gDeviceHandle, // Handle to device
IOCTL_IO_WRITE, // IO Control code to use
&Address, // Address to communicate to driver
sizeof (UINT32), // Length of buffer in bytes.
&Result, // In Buffer to fill in by kernel driver.
sizeof (UINT32), // Length of buffer in bytes.
&ReturnedLength, // Bytes placed in In buffer.
NULL // NULL means wait till op. completes.
);
gReadPending = TRUE;
return EFI_SUCCESS;
}
}
break;
default:
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
VOID
EFIAPI
CpuIoVirtualAddressChangeEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
Fixup Private data with new virtual addresses. All the member functions need
to be converted to virtual mode.
Arguments:
(Standard EFI Event - EFI_EVENT_NOTIFY)
Returns:
--*/
// TODO: Context - add argument and description to function comment
{
}
EFI_STATUS
CpuIoCheckAddressRange (
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN VOID *Buffer,
IN UINT64 Limit
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Width - TODO: add argument description
Address - TODO: add argument description
Count - TODO: add argument description
Buffer - TODO: add argument description
Limit - TODO: add argument description
Returns:
EFI_UNSUPPORTED - TODO: Add description for return value
EFI_UNSUPPORTED - TODO: Add description for return value
EFI_UNSUPPORTED - TODO: Add description for return value
EFI_SUCCESS - TODO: Add description for return value
--*/
{
UINTN AlignMask;
if (Address > Limit) {
return EFI_UNSUPPORTED;
}
//
// For FiFo type, the target address won't increase during the access, so treat count as 1
//
if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
Count = 1;
}
Width = Width & 0x03;
if (Address - 1 + (1 << Width) * Count > Limit) {
return EFI_UNSUPPORTED;
}
AlignMask = (1 << Width) - 1;
if ((UINTN) Buffer & AlignMask) {
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
CpuIoInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Initialize the state information for the CPU I/O Protocol
Arguments:
ImageHandle of the loaded driver
Pointer to the System Table
Returns:
Status
EFI_SUCCESS - Protocol successfully installed
EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
--*/
// TODO: SystemTable - add argument and description to function comment
{
EFI_STATUS Status;
UINTN NumHandles;
EFI_HANDLE *HandleBuffer;
UINTN Index;
EFI_CPU_IO_PROTOCOL *OldCpuIoProtocol;
//
// Initialize the library
//
DxeInitializeDriverLib (ImageHandle, SystemTable);
mCpuIoProtocol.Mem.Read = CpuMemoryServiceRead;
mCpuIoProtocol.Mem.Write = CpuMemoryServiceWrite;
mCpuIoProtocol.Io.Read = CpuIoServiceRead;
mCpuIoProtocol.Io.Write = CpuIoServiceWrite;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiCpuIoProtocolGuid,
NULL,
&NumHandles,
&HandleBuffer
);
if (Status == EFI_SUCCESS) {
for (Index = 0; Index < NumHandles; Index++) {
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiCpuIoProtocolGuid,
(VOID **) &OldCpuIoProtocol
);
if (Status == EFI_SUCCESS) {
gBS->ReinstallProtocolInterface (
HandleBuffer[Index],
&gEfiCpuIoProtocolGuid,
OldCpuIoProtocol,
&mCpuIoProtocol
);
}
}
}
ASSERT_EFI_ERROR (Status);
return Status;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?