From nobody Sun Feb 8 22:34:56 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+99997+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+99997+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1676032292; cv=none; d=zohomail.com; s=zohoarc; b=m2FdN/ZyysuzCrE4VWMUfJ1xUsWTqtKvUwc+8g7IDJGYVxKCAfxrME+vjC4MCLK5TxTOuDC11bYFXGQ7/nDSk9Z3wu+8hr5UOooGgZB3BlhbRkZ6qMPIqPna+qnoLb6NFllKc6cXj7QHKHHcUHy5rFD3hW9BFEweEmHq3e7asZs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1676032292; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=tcu8WLtLZs6sZcfwhbx7kPDVcbYi6NMmBLoxHqbGqHk=; b=RaqoOaRc3cEcKkigETctIFvmdOaSONd2/O5p83n0BFcbPQlpWMzccugAfSewdbPDMW6IO8t67EWqQa3IHmNF/HLKUSv+GQiwub4GSUjLwy99fB3Oh/gdeQ8F44Mfvc+JaQ+mUgm8cAfmL1U4Rqx+LcTXf98/3UIH/znIpo43fKY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+99997+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1676032292625651.6840743048027; Fri, 10 Feb 2023 04:31:32 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id 7OhpYY1788612xXvluYFZxun; Fri, 10 Feb 2023 04:31:32 -0800 X-Received: from mail-pj1-f51.google.com (mail-pj1-f51.google.com [209.85.216.51]) by mx.groups.io with SMTP id smtpd.web11.13161.1676032291270296880 for ; Fri, 10 Feb 2023 04:31:31 -0800 X-Received: by mail-pj1-f51.google.com with SMTP id e10-20020a17090a630a00b0022bedd66e6dso9644166pjj.1 for ; Fri, 10 Feb 2023 04:31:31 -0800 (PST) X-Gm-Message-State: qUYzglIkgc8pQ0oPtbK1fTgPx1787277AA= X-Google-Smtp-Source: AK7set+rSU9n51KaLLQ2SrZAlm8lP4dhdx2mQo3tpX9dM1gZV2atTQDj4aVpLkhUul6W7eYBR580tA== X-Received: by 2002:a17:902:ea0e:b0:199:4362:93df with SMTP id s14-20020a170902ea0e00b00199436293dfmr12411122plg.12.1676032290483; Fri, 10 Feb 2023 04:31:30 -0800 (PST) X-Received: from localhost.localdomain ([49.206.14.226]) by smtp.gmail.com with ESMTPSA id b17-20020a170902ed1100b0019a73faf773sm1172961pld.71.2023.02.10.04.31.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Feb 2023 04:31:30 -0800 (PST) From: "Sunil V L" To: devel@edk2.groups.io Cc: Ard Biesheuvel , Jiewen Yao , Jordan Justen , Gerd Hoffmann , Abner Chang , Andrei Warkentin Subject: [edk2-devel] [edk2-staging/RiscV64QemuVirt PATCH V8 16/19] OvmfPkg/RiscVVirt: Add PciCpuIo2Dxe module Date: Fri, 10 Feb 2023 18:00:38 +0530 Message-Id: <20230210123041.1489506-17-sunilvl@ventanamicro.com> In-Reply-To: <20230210123041.1489506-1-sunilvl@ventanamicro.com> References: <20230210123041.1489506-1-sunilvl@ventanamicro.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sunilvl@ventanamicro.com Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1676032292; bh=cVl+qG99nVwjJ9WNuibkVgqWgFI113jV0M1NAxyIhMI=; h=Cc:Date:From:Reply-To:Subject:To; b=PwF9V2gz8mbI6LWcU8X4MyjUE5FvRE2Hqx07OK7FmizzYG2DzjZOAtZ0DK5Hp7rG8rU 6tY3eXni0gKLQGVSJ8pV7y2lIxv92NI3k3S7U1BVWWCBaSiJqZPLGjpprePYVr1yntO4i JKGYRttiqjIKMzHxHzxVS1f6DNUsLPM2ot4= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1676032293193100002 Content-Type: text/plain; charset="utf-8" Add PciCpuIo2Dxe driver to implement EFI_CPU_IO2_PROTOCOL to add the translation for IO access. This is copied from ArmPciCpuIo2Dxe driver. Cc: Ard Biesheuvel Cc: Jiewen Yao Cc: Jordan Justen Cc: Gerd Hoffmann Signed-off-by: Sunil V L Acked-by: Abner Chang Reviewed-by: Andrei Warkentin --- OvmfPkg/RiscVVirt/PciCpuIo2Dxe/PciCpuIo2Dxe.inf | 48 ++ OvmfPkg/RiscVVirt/PciCpuIo2Dxe/PciCpuIo2Dxe.c | 557 ++++++++++++++++++++ 2 files changed, 605 insertions(+) diff --git a/OvmfPkg/RiscVVirt/PciCpuIo2Dxe/PciCpuIo2Dxe.inf b/OvmfPkg/Risc= VVirt/PciCpuIo2Dxe/PciCpuIo2Dxe.inf new file mode 100644 index 000000000000..4f78cfa4067b --- /dev/null +++ b/OvmfPkg/RiscVVirt/PciCpuIo2Dxe/PciCpuIo2Dxe.inf @@ -0,0 +1,48 @@ +## @file +# Produces the CPU I/O 2 Protocol by using the services of the I/O Librar= y. +# +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2016, Linaro Ltd. All rights reserved.
+# Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x0001001B + BASE_NAME =3D PciCpuIo2Dxe + FILE_GUID =3D 9BD3C765-2579-4CF0-9349-D77205565030 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D PciCpuIo2Initialize + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D RISCV64 +# + +[Sources] + PciCpuIo2Dxe.c + +[Packages] + OvmfPkg/OvmfPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + BaseLib + DebugLib + IoLib + PcdLib + UefiBootServicesTableLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation + +[Protocols] + gEfiCpuIo2ProtocolGuid ## PRODUCES + +[Depex] + TRUE diff --git a/OvmfPkg/RiscVVirt/PciCpuIo2Dxe/PciCpuIo2Dxe.c b/OvmfPkg/RiscVV= irt/PciCpuIo2Dxe/PciCpuIo2Dxe.c new file mode 100644 index 000000000000..f3bf07e63141 --- /dev/null +++ b/OvmfPkg/RiscVVirt/PciCpuIo2Dxe/PciCpuIo2Dxe.c @@ -0,0 +1,557 @@ +/** @file + Produces the CPU I/O 2 Protocol. + +Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
+Copyright (c) 2016, Linaro Ltd. All rights reserved.
+Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include +#include +#include + +#define MAX_IO_PORT_ADDRESS 0xFFFF + +// +// Handle for the CPU I/O 2 Protocol +// +STATIC EFI_HANDLE mHandle =3D NULL; + +// +// Lookup table for increment values based on transfer widths +// +STATIC CONST UINT8 mInStride[] =3D { + 1, // EfiCpuIoWidthUint8 + 2, // EfiCpuIoWidthUint16 + 4, // EfiCpuIoWidthUint32 + 8, // EfiCpuIoWidthUint64 + 0, // EfiCpuIoWidthFifoUint8 + 0, // EfiCpuIoWidthFifoUint16 + 0, // EfiCpuIoWidthFifoUint32 + 0, // EfiCpuIoWidthFifoUint64 + 1, // EfiCpuIoWidthFillUint8 + 2, // EfiCpuIoWidthFillUint16 + 4, // EfiCpuIoWidthFillUint32 + 8 // EfiCpuIoWidthFillUint64 +}; + +// +// Lookup table for increment values based on transfer widths +// +STATIC CONST UINT8 mOutStride[] =3D { + 1, // EfiCpuIoWidthUint8 + 2, // EfiCpuIoWidthUint16 + 4, // EfiCpuIoWidthUint32 + 8, // EfiCpuIoWidthUint64 + 1, // EfiCpuIoWidthFifoUint8 + 2, // EfiCpuIoWidthFifoUint16 + 4, // EfiCpuIoWidthFifoUint32 + 8, // EfiCpuIoWidthFifoUint64 + 0, // EfiCpuIoWidthFillUint8 + 0, // EfiCpuIoWidthFillUint16 + 0, // EfiCpuIoWidthFillUint32 + 0 // EfiCpuIoWidthFillUint64 +}; + +/** + Check parameters to a CPU I/O 2 Protocol service request. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port= operation. + @param[in] Width Signifies the width of the I/O or Memory opera= tion. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The n= umber of + bytes moved is Width size * Count, starting at= Address. + @param[in] Buffer For read operations, the destination buffer to= store the results. + For write operations, the source buffer from w= hich to write data. + + @retval EFI_SUCCESS The parameters for this request pass the = checks. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +STATIC +EFI_STATUS +CpuIoCheckParameter ( + IN BOOLEAN MmioOperation, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT64 MaxCount; + UINT64 Limit; + + // + // Check to see if Buffer is NULL + // + if (Buffer =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if Width is in the valid range + // + if ((UINT32)Width >=3D EfiCpuIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + // + // For FIFO type, the target address won't increase during the access, + // so treat Count as 1 + // + if ((Width >=3D EfiCpuIoWidthFifoUint8) && (Width <=3D EfiCpuIoWidthFifo= Uint64)) { + Count =3D 1; + } + + // + // Check to see if Width is in the valid range for I/O Port operations + // + Width =3D (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03); + if (!MmioOperation && (Width =3D=3D EfiCpuIoWidthUint64)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if Address is aligned + // + if ((Address & (UINT64)(mInStride[Width] - 1)) !=3D 0) { + return EFI_UNSUPPORTED; + } + + // + // Check to see if any address associated with this transfer exceeds the= maximum + // allowed address. The maximum address implied by the parameters passe= d in is + // Address + Size * Count. If the following condition is met, then the = transfer + // is not supported. + // + // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_POR= T_ADDRESS) + 1 + // + // Since MAX_ADDRESS can be the maximum integer value supported by the C= PU and Count + // can also be the maximum integer value supported by the CPU, this range + // check must be adjusted to avoid all overflow conditions. + // + // The following form of the range check is equivalent but assumes that + // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1). + // + Limit =3D (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS); + if (Count =3D=3D 0) { + if (Address > Limit) { + return EFI_UNSUPPORTED; + } + } else { + MaxCount =3D RShiftU64 (Limit, Width); + if (MaxCount < (Count - 1)) { + return EFI_UNSUPPORTED; + } + + if (Address > LShiftU64 (MaxCount - Count + 1, Width)) { + return EFI_UNSUPPORTED; + } + } + + // + // Check to see if Buffer is aligned + // + if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != =3D 0) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Reads memory-mapped registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number= of + bytes moved is Width size * Count, starting at Addr= ess. + @param[out] Buffer For read operations, the destination buffer to stor= e the results. + For write operations, the source buffer from which = to write data. + + @retval EFI_SUCCESS The data was read from or written to the = PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +STATIC +EFI_STATUS +EFIAPI +CpuMemoryServiceRead ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + Status =3D CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select loop based on the width of the transfer + // + InStride =3D mInStride[Width]; + OutStride =3D mOutStride[Width]; + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03); + for (Uint8Buffer =3D Buffer; Count > 0; Address +=3D InStride, Uint8Buff= er +=3D OutStride, Count--) { + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) { + *Uint8Buffer =3D MmioRead8 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) { + *((UINT16 *)Uint8Buffer) =3D MmioRead16 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) { + *((UINT32 *)Uint8Buffer) =3D MmioRead32 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint64) { + *((UINT64 *)Uint8Buffer) =3D MmioRead64 ((UINTN)Address); + } + } + + return EFI_SUCCESS; +} + +/** + Writes memory-mapped registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number= of + bytes moved is Width size * Count, starting at Addr= ess. + @param[in] Buffer For read operations, the destination buffer to stor= e the results. + For write operations, the source buffer from which = to write data. + + @retval EFI_SUCCESS The data was read from or written to the = PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +STATIC +EFI_STATUS +EFIAPI +CpuMemoryServiceWrite ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + Status =3D CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select loop based on the width of the transfer + // + InStride =3D mInStride[Width]; + OutStride =3D mOutStride[Width]; + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03); + for (Uint8Buffer =3D Buffer; Count > 0; Address +=3D InStride, Uint8Buff= er +=3D OutStride, Count--) { + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) { + MmioWrite8 ((UINTN)Address, *Uint8Buffer); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) { + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) { + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint64) { + MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); + } + } + + return EFI_SUCCESS; +} + +/** + Reads I/O registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number= of + bytes moved is Width size * Count, starting at Addr= ess. + @param[out] Buffer For read operations, the destination buffer to stor= e the results. + For write operations, the source buffer from which = to write data. + + @retval EFI_SUCCESS The data was read from or written to the = PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +STATIC +EFI_STATUS +EFIAPI +CpuIoServiceRead ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + Status =3D CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + Address +=3D PcdGet64 (PcdPciIoTranslation); + + // + // Select loop based on the width of the transfer + // + InStride =3D mInStride[Width]; + OutStride =3D mOutStride[Width]; + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03); + + for (Uint8Buffer =3D Buffer; Count > 0; Address +=3D InStride, Uint8Buff= er +=3D OutStride, Count--) { + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) { + *Uint8Buffer =3D MmioRead8 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) { + *((UINT16 *)Uint8Buffer) =3D MmioRead16 ((UINTN)Address); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) { + *((UINT32 *)Uint8Buffer) =3D MmioRead32 ((UINTN)Address); + } + } + + return EFI_SUCCESS; +} + +/** + Write I/O registers. + + The I/O operations are carried out exactly as requested. The caller is r= esponsible + for satisfying any alignment and I/O width restrictions that a PI System= on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, = will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read= or + write operation is performed Count times from the first element of Buffe= r. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number= of + bytes moved is Width size * Count, starting at Addr= ess. + @param[in] Buffer For read operations, the destination buffer to stor= e the results. + For write operations, the source buffer from which = to write data. + + @retval EFI_SUCCESS The data was read from or written to the = PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given W= idth. + @retval EFI_UNSUPPORTED The address range specified by Address, W= idth, + and Count is not valid for this PI system. + +**/ +STATIC +EFI_STATUS +EFIAPI +CpuIoServiceWrite ( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 InStride; + UINT8 OutStride; + EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; + UINT8 *Uint8Buffer; + + // + // Make sure the parameters are valid + // + Status =3D CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + Address +=3D PcdGet64 (PcdPciIoTranslation); + + // + // Select loop based on the width of the transfer + // + InStride =3D mInStride[Width]; + OutStride =3D mOutStride[Width]; + OperationWidth =3D (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03); + + for (Uint8Buffer =3D (UINT8 *)Buffer; Count > 0; Address +=3D InStride, = Uint8Buffer +=3D OutStride, Count--) { + if (OperationWidth =3D=3D EfiCpuIoWidthUint8) { + MmioWrite8 ((UINTN)Address, *Uint8Buffer); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint16) { + MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); + } else if (OperationWidth =3D=3D EfiCpuIoWidthUint32) { + MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); + } + } + + return EFI_SUCCESS; +} + +// +// CPU I/O 2 Protocol instance +// +STATIC EFI_CPU_IO2_PROTOCOL mCpuIo2 =3D { + { + CpuMemoryServiceRead, + CpuMemoryServiceWrite + }, + { + CpuIoServiceRead, + CpuIoServiceWrite + } +}; + +/** + The user Entry Point for module CpuIo2Dxe. The user code starts with thi= s function. + + @param[in] ImageHandle The firmware allocated handle for the EFI imag= e. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry po= int. + +**/ +EFI_STATUS +EFIAPI +PciCpuIo2Initialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid); + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEfiCpuIo2ProtocolGuid, + &mCpuIo2, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} --=20 2.34.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#99997): https://edk2.groups.io/g/devel/message/99997 Mute This Topic: https://groups.io/mt/96874999/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-