EFI_STATUS EFIAPI CpuIoServiceRead ( IN EFI_CPU_IO2_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 read 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 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; if (!UserBuffer) { return EFI_INVALID_PARAMETER; } Address = (UINTN) UserAddress; if ((Width < 0) || (Width >= EfiCpuIoWidthMaximum)) { return EFI_INVALID_PARAMETER; } Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS); if (EFI_ERROR (Status)) { return Status; } // // Do nothing for Nt32 version // return EFI_UNSUPPORTED; }
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; }
EFI_STATUS EFIAPI CpuMemoryServiceWrite ( IN EFI_CPU_IO_PROTOCOL *This, IN EFI_CPU_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN OUT VOID *Buffer ) /*++ Routine Description: Perform the Memory Access Read service for the CPU I/O Protocol Arguments: Pointer to an instance of the CPU I/O Protocol Width of the Memory Access Address of the Memory access Count of the number of accesses to perform Pointer to the buffer to read or write from memory Returns: 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 { EFI_STATUS Status; PTR In; PTR Out; if (!Buffer) { return EFI_INVALID_PARAMETER; } Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS); if (EFI_ERROR (Status)) { return Status; } In.buf = (VOID *) (UINTN) Address; Out.buf = Buffer; if (Width >= EfiCpuIoWidthUint8 && Width <= EfiCpuIoWidthUint64) { return CpuIoMemRW (Width, Count, TRUE, In, TRUE, Out); } if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) { return CpuIoMemRW (Width, Count, FALSE, In, TRUE, Out); } if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) { return CpuIoMemRW (Width, Count, TRUE, In, FALSE, Out); } return EFI_INVALID_PARAMETER; }