123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- /*++ @file
- 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.
- Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
- Portions copyright (c) 2011, Apple Inc. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <PiDxe.h>
- #include <Protocol/Cpu.h>
- #include <Protocol/CpuIo2.h>
- #include <Library/BaseLib.h>
- #include <Library/DebugLib.h>
- #include <Library/HiiLib.h>
- #include <Library/UefiLib.h>
- #include <Library/UefiDriverEntryPoint.h>
- #include <Library/BaseMemoryLib.h>
- #include <Library/MemoryAllocationLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <CpuDriver.h>
- #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.
- **/
- {
- 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_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.
- **/
- {
- 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_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.
- **/
- {
- 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_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.
- **/
- {
- 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;
- }
- /*++
- Routine 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
- **/
- EFI_STATUS
- CpuIoCheckAddressRange (
- IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN VOID *Buffer,
- IN UINT64 Limit
- )
- {
- 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 + LShiftU64 (Count, Width)) > Limit) {
- return EFI_UNSUPPORTED;
- }
- AlignMask = (1 << Width) - 1;
- if ((UINTN)Buffer & AlignMask) {
- return EFI_UNSUPPORTED;
- }
- return EFI_SUCCESS;
- }
|