4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Produces the SMM CPU I/O Protocol.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCopyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncThis program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncare licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncwhich accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynchttp://opensource.org/licenses/bsd-license.php
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "CpuIo2Smm.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Handle for the SMM CPU I/O Protocol
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_HANDLE mHandle = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// SMM CPU I/O Protocol instance
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_SMM_CPU_IO2_PROTOCOL mSmmCpuIo2 = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CpuMemoryServiceRead,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CpuMemoryServiceWrite
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CpuIoServiceRead,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CpuIoServiceWrite
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Lookup table for increment values based on transfer widths
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT8 mStride[] = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 1, // SMM_IO_UINT8
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 2, // SMM_IO_UINT16
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 4, // SMM_IO_UINT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 8 // SMM_IO_UINT64
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check parameters to a SMM CPU I/O Protocol service request.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Width Signifies the width of the I/O operations.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Address The base address of the I/O operations. The caller is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync responsible for aligning the Address if required.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Count The number of I/O operations to perform.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Buffer For read operations, the destination buffer to store
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the results. For write operations, the source buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync from which to write data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The data was read from or written to the device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_UNSUPPORTED The Address is not valid for this system.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCpuIoCheckParameter (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN MmioOperation,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SMM_IO_WIDTH Width,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT64 Address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Count,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT64 MaxCount;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT64 Limit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check to see if Buffer is NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Buffer == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check to see if Width is in the valid range
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Width < 0 || Width > SMM_IO_UINT64) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check to see if Width is in the valid range for I/O Port operations
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!MmioOperation && (Width == SMM_IO_UINT64)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check to see if any address associated with this transfer exceeds the maximum
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // allowed address. The maximum address implied by the parameters passed in is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Address + Size * Count. If the following condition is met, then the transfer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is not supported.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // can also be the maximum integer value supported by the CPU, this range
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // check must be adjusted to avoid all overflow conditions.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The following form of the range check is equivalent but assumes that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Count == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Address > Limit) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MaxCount = RShiftU64 (Limit, Width);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (MaxCount < (Count - 1)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check to see if Address is aligned
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Address & (UINT64)(mStride[Width] - 1)) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reads memory-mapped registers.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The I/O operations are carried out exactly as requested. The caller is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync responsible for any alignment and I/O width issues that the bus, device,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync platform, or type of I/O might require.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Width Signifies the width of the I/O operations.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Address The base address of the I/O operations. The caller is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync responsible for aligning the Address if required.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Count The number of I/O operations to perform.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] Buffer For read operations, the destination buffer to store
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the results. For write operations, the source buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync from which to write data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The data was read from or written to the device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_UNSUPPORTED The Address is not valid for this system.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lack of resources
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCpuMemoryServiceRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SMM_IO_WIDTH Width,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT64 Address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Count,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT VOID *Buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Stride;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Uint8Buffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Select loop based on the width of the transfer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Stride = mStride[Width];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Width == SMM_IO_UINT8) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Uint8Buffer = MmioRead8 ((UINTN)Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Width == SMM_IO_UINT16) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Width == SMM_IO_UINT32) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Width == SMM_IO_UINT64) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Writes memory-mapped registers.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The I/O operations are carried out exactly as requested. The caller is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync responsible for any alignment and I/O width issues that the bus, device,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync platform, or type of I/O might require.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Width Signifies the width of the I/O operations.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Address The base address of the I/O operations. The caller is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync responsible for aligning the Address if required.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Count The number of I/O operations to perform.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Buffer For read operations, the destination buffer to store
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the results. For write operations, the source buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync from which to write data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The data was read from or written to the device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_UNSUPPORTED The Address is not valid for this system.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lack of resources
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCpuMemoryServiceWrite (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SMM_IO_WIDTH Width,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT64 Address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Count,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Stride;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Uint8Buffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Select loop based on the width of the transfer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Stride = mStride[Width];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Width == SMM_IO_UINT8) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MmioWrite8 ((UINTN)Address, *Uint8Buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Width == SMM_IO_UINT16) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Width == SMM_IO_UINT32) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Width == SMM_IO_UINT64) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reads I/O registers.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The I/O operations are carried out exactly as requested. The caller is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync responsible for any alignment and I/O width issues that the bus, device,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync platform, or type of I/O might require.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Width Signifies the width of the I/O operations.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Address The base address of the I/O operations. The caller is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync responsible for aligning the Address if required.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Count The number of I/O operations to perform.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] Buffer For read operations, the destination buffer to store
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the results. For write operations, the source buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync from which to write data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The data was read from or written to the device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_UNSUPPORTED The Address is not valid for this system.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lack of resources
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCpuIoServiceRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SMM_IO_WIDTH Width,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT64 Address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Count,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT VOID *Buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Stride;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Uint8Buffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Select loop based on the width of the transfer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Stride = mStride[Width];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Width == SMM_IO_UINT8) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Uint8Buffer = IoRead8 ((UINTN)Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Width == SMM_IO_UINT16) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Width == SMM_IO_UINT32) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Write I/O registers.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The I/O operations are carried out exactly as requested. The caller is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync responsible for any alignment and I/O width issues that the bus, device,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync platform, or type of I/O might require.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Width Signifies the width of the I/O operations.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Address The base address of the I/O operations. The caller is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync responsible for aligning the Address if required.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Count The number of I/O operations to perform.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Buffer For read operations, the destination buffer to store
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the results. For write operations, the source buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync from which to write data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The data was read from or written to the device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_UNSUPPORTED The Address is not valid for this system.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lack of resources
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCpuIoServiceWrite (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SMM_IO_WIDTH Width,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT64 Address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Count,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Stride;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Uint8Buffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure the parameters are valid
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Select loop based on the width of the transfer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Stride = mStride[Width];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Width == SMM_IO_UINT8) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IoWrite8 ((UINTN)Address, *Uint8Buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Width == SMM_IO_UINT16) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Width == SMM_IO_UINT32) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The module Entry Point SmmCpuIoProtocol driver
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] ImageHandle The firmware allocated handle for the EFI image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] SystemTable A pointer to the EFI System Table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The entry point is executed successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Other Some error occurs when executing this entry point.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSmmCpuIo2Initialize (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_HANDLE ImageHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SYSTEM_TABLE *SystemTable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Copy the SMM CPU I/O Protocol instance into the System Management System Table
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&gSmst->SmmIo, &mSmmCpuIo2, sizeof (mSmmCpuIo2));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Install the SMM CPU I/O Protocol into the SMM protocol database
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gSmst->SmmInstallProtocolInterface (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &mHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiSmmCpuIo2ProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_NATIVE_INTERFACE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &mSmmCpuIo2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT_EFI_ERROR (Status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}