/**@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; }