From nobody Mon Feb 9 03:13:55 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+99242+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+99242+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1674933540; cv=none; d=zohomail.com; s=zohoarc; b=R/xmN4NdSd5zzUNfgPP5yUhuAReNZzZoA4Xg6xZuNKMDwXUMdBRFvTfLCnRmkSA/WD60STHy6Fu63jtflOfjZU6xtqCw49yO2kDNPZbcPnrOmX9hqCLItA0xUvZkVO8Zq7GJYsqUlf9Lm72glNrl9D1IandxhZLdP7k8JZGlzN0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1674933540; 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=dCaBlUaPIvYVt/iYlYm6kO0LTtNRJyyczbM9bdpoSfo=; b=hHZWtd3fwAkZuXOHm4ZI9RbSbGPiZDB9VaUAyb7ox3lZyf4ZFjFXjheIj4iXP7c7d7HB/TUx1JUBwaxmi9iL1UfPr+e7/fPL56mAjUmkMggXvglLhoPdayGOleWLExFTJYDRU18v+8DvnEDALKp3ZHzoJOCslATXTfqrVDNXtCU= 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+99242+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1674933540492232.20447720533548; Sat, 28 Jan 2023 11:19:00 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id 0T9FYY1788612xMr306d12MK; Sat, 28 Jan 2023 11:19:00 -0800 X-Received: from mail-pl1-f170.google.com (mail-pl1-f170.google.com [209.85.214.170]) by mx.groups.io with SMTP id smtpd.web10.1531.1674933539439083157 for ; Sat, 28 Jan 2023 11:18:59 -0800 X-Received: by mail-pl1-f170.google.com with SMTP id z1so458905plg.6 for ; Sat, 28 Jan 2023 11:18:59 -0800 (PST) X-Gm-Message-State: iQ562q0z2vUmXJlMkmR7kqJwx1787277AA= X-Google-Smtp-Source: AK7set/ZzdfG3TUWHP0+V/VjQ4Ys4VTIuZBySPeTe+XE+bkkv7BmsytPC35cyMLNoJBQXpJLdyOmUA== X-Received: by 2002:a17:902:cec1:b0:196:3310:16cc with SMTP id d1-20020a170902cec100b00196331016ccmr14806236plg.47.1674933538595; Sat, 28 Jan 2023 11:18:58 -0800 (PST) X-Received: from kerodipc.Dlink ([49.206.11.246]) by smtp.gmail.com with ESMTPSA id n9-20020a1709026a8900b00192d9258532sm139923plk.150.2023.01.28.11.18.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 28 Jan 2023 11:18:58 -0800 (PST) From: "Sunil V L" To: devel@edk2.groups.io Cc: Ard Biesheuvel , Jiewen Yao , Jordan Justen , Gerd Hoffmann , Abner Chang Subject: [edk2-devel] [edk2-staging/RiscV64QemuVirt PATCH V7 17/20] OvmfPkg/RiscVVirt: Add PciCpuIo2Dxe module Date: Sun, 29 Jan 2023 00:48:04 +0530 Message-Id: <20230128191807.2080547-18-sunilvl@ventanamicro.com> In-Reply-To: <20230128191807.2080547-1-sunilvl@ventanamicro.com> References: <20230128191807.2080547-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=1674933540; bh=xvt1NVmv5FnPaF1ocYFHhB449tJ/p75eLIBzrKq6XhU=; h=Cc:Date:From:Reply-To:Subject:To; b=YAmM4m4oLbU2GObz/rXYPy3sn/vj0FxDdEDlNki44gC22JTKhHUEcNQEBtUbaucGjTE K3Siehhuyh9za1A848esC9kEU9iAKEhrF7sfTN4jcgTGEvcB5JgvcEsfRgICl1yOtzBIY aoPrMEJfljqnEFw6J/6WARpcUvYklJCAhAQ= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1674933541157100005 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.38.0 -=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 (#99242): https://edk2.groups.io/g/devel/message/99242 Mute This Topic: https://groups.io/mt/96593519/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-