/**@file
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
Module Name:
CpuIo.c
Abstract:
This is the code that publishes the CPU I/O Protocol.
The intent herein is to have a single I/O service that can load
as early as possible, extend into runtime, and be layered upon by
the implementations of architectural protocols and the PCI Root
Bridge I/O Protocol.
**/
#include
#define IA32_MAX_IO_ADDRESS 0xFFFF
#define IA32_MAX_MEM_ADDRESS 0xFFFFFFFF
EFI_STATUS
CpuIoCheckAddressRange (
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN VOID *Buffer,
IN UINT64 Limit
);
EFI_STATUS
EFIAPI
CpuMemoryServiceRead (
IN EFI_CPU_IO2_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;
if (!Buffer) {
return EFI_INVALID_PARAMETER;
}
if ((Width < 0) || (Width >= EfiCpuIoWidthMaximum)) {
return EFI_INVALID_PARAMETER;
}
Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Do nothing for Nt32 version
//
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
CpuMemoryServiceWrite (
IN EFI_CPU_IO2_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;
if (!Buffer) {
return EFI_INVALID_PARAMETER;
}
if ((Width < 0) || (Width >= EfiCpuIoWidthMaximum)) {
return EFI_INVALID_PARAMETER;
}
Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Do nothing for Nt32 version
//
return EFI_UNSUPPORTED;
}
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_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 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;
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
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 = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
if (Address - 1 + ((UINTN)1 << Width) * Count > Limit) {
return EFI_UNSUPPORTED;
}
AlignMask = ((UINTN)1 << Width) - 1;
if ((UINTN) Buffer & AlignMask) {
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}