| /*++ | |
| Copyright (c) 2006, Intel Corporation | |
| All rights reserved. This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| 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 <CpuDriver.h> | |
| #define IA32_MAX_IO_ADDRESS 0xFFFF | |
| #define IA32_MAX_MEM_ADDRESS 0xFFFFFFFF | |
| EFI_CPU_IO_PROTOCOL mCpuIoProtocol; | |
| 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_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; | |
| if (!Buffer) { | |
| 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_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; | |
| if (!Buffer) { | |
| 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_SUCCESS; | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| CpuIoServiceRead ( | |
| 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 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 >= 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_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; | |
| if (!UserBuffer) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| Address = (UINTN) UserAddress; | |
| if (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_SUCCESS; | |
| } | |
| 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; | |
| } | |