From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001
From: Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com>
Date: Tue, 10 Oct 2023 14:33:42 +0000
Subject: Add submodule dependency files

Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
---
 .../PcatSingleSegmentPciCfg2Pei/PciCfg2.c          | 311 +++++++++++++++++++++
 1 file changed, 311 insertions(+)
 create mode 100644 roms/edk2/MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c

(limited to 'roms/edk2/MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c')

diff --git a/roms/edk2/MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c b/roms/edk2/MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c
new file mode 100644
index 000000000..41fa92911
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c
@@ -0,0 +1,311 @@
+/** @file
+  This driver installs Single Segment Pci Configuration 2 PPI
+  to provide read, write and modify access to Pci configuration space in PEI phase.
+  To follow PI specification, these services also support access to the unaligned Pci address.
+
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Ppi/PciCfg2.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <IndustryStandard/Pci.h>
+
+/**
+   Convert EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS to PCI_LIB_ADDRESS.
+
+   @param Address   PCI address with EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS format.
+
+   @return PCI address with PCI_LIB_ADDRESS format.
+
+**/
+UINTN
+PciCfgAddressConvert (
+  EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *Address
+  )
+{
+  if (Address->ExtendedRegister == 0) {
+    return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->Register);
+  }
+
+  return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->ExtendedRegister);
+}
+
+/**
+  Reads from a given location in the PCI configuration space.
+
+  @param  PeiServices     An indirect pointer to the PEI Services Table published by the PEI Foundation.
+  @param  This            Pointer to local data for the interface.
+  @param  Width           The width of the access. Enumerated in bytes.
+                          See EFI_PEI_PCI_CFG_PPI_WIDTH above.
+  @param  Address         The physical address of the access. The format of
+                          the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.
+  @param  Buffer          A pointer to the buffer of data.
+
+  @retval EFI_SUCCESS           The function completed successfully.
+  @retval EFI_INVALID_PARAMETER The invalid access width.
+
+**/
+EFI_STATUS
+EFIAPI
+PciCfg2Read (
+  IN CONST  EFI_PEI_SERVICES          **PeiServices,
+  IN CONST  EFI_PEI_PCI_CFG2_PPI      *This,
+  IN        EFI_PEI_PCI_CFG_PPI_WIDTH Width,
+  IN        UINT64                    Address,
+  IN OUT    VOID                      *Buffer
+  )
+{
+  UINTN  PciLibAddress;
+
+  PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);
+
+  if (Width == EfiPeiPciCfgWidthUint8) {
+    *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);
+  } else if (Width == EfiPeiPciCfgWidthUint16) {
+    if ((PciLibAddress & 0x01) == 0) {
+      //
+      // Aligned Pci address access
+      //
+      WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));
+    } else {
+      //
+      // Unaligned Pci address access, break up the request into byte by byte.
+      //
+      *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);
+      *((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1);
+    }
+  } else if (Width == EfiPeiPciCfgWidthUint32) {
+    if ((PciLibAddress & 0x03) == 0) {
+      //
+      // Aligned Pci address access
+      //
+      WriteUnaligned32 (((UINT32 *) Buffer), PciRead32 (PciLibAddress));
+    } else if ((PciLibAddress & 0x01) == 0) {
+      //
+      // Unaligned Pci address access, break up the request into word by word.
+      //
+      WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));
+      WriteUnaligned16 (((UINT16 *) Buffer + 1), PciRead16 (PciLibAddress + 2));
+    } else {
+      //
+      // Unaligned Pci address access, break up the request into byte by byte.
+      //
+      *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);
+      *((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1);
+      *((UINT8 *) Buffer + 2) = PciRead8 (PciLibAddress + 2);
+      *((UINT8 *) Buffer + 3) = PciRead8 (PciLibAddress + 3);
+    }
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Write to a given location in the PCI configuration space.
+
+  @param  PeiServices     An indirect pointer to the PEI Services Table published by the PEI Foundation.
+  @param  This            Pointer to local data for the interface.
+  @param  Width           The width of the access. Enumerated in bytes.
+                          See EFI_PEI_PCI_CFG_PPI_WIDTH above.
+  @param  Address         The physical address of the access. The format of
+                          the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.
+  @param  Buffer          A pointer to the buffer of data.
+
+  @retval EFI_SUCCESS           The function completed successfully.
+  @retval EFI_INVALID_PARAMETER The invalid access width.
+
+**/
+EFI_STATUS
+EFIAPI
+PciCfg2Write (
+  IN CONST  EFI_PEI_SERVICES          **PeiServices,
+  IN CONST  EFI_PEI_PCI_CFG2_PPI      *This,
+  IN        EFI_PEI_PCI_CFG_PPI_WIDTH Width,
+  IN        UINT64                    Address,
+  IN OUT    VOID                      *Buffer
+  )
+{
+  UINTN  PciLibAddress;
+
+  PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);
+
+  if (Width == EfiPeiPciCfgWidthUint8) {
+    PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));
+  } else if (Width == EfiPeiPciCfgWidthUint16) {
+    if ((PciLibAddress & 0x01) == 0) {
+      //
+      // Aligned Pci address access
+      //
+      PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));
+    } else {
+      //
+      // Unaligned Pci address access, break up the request into byte by byte.
+      //
+      PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));
+      PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1));
+    }
+  } else if (Width == EfiPeiPciCfgWidthUint32) {
+    if ((PciLibAddress & 0x03) == 0) {
+      //
+      // Aligned Pci address access
+      //
+      PciWrite32 (PciLibAddress, ReadUnaligned32 ((UINT32 *) Buffer));
+    } else if ((PciLibAddress & 0x01) == 0) {
+      //
+      // Unaligned Pci address access, break up the request into word by word.
+      //
+      PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));
+      PciWrite16 (PciLibAddress + 2, ReadUnaligned16 ((UINT16 *) Buffer + 1));
+    } else {
+      //
+      // Unaligned Pci address access, break up the request into byte by byte.
+      //
+      PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));
+      PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1));
+      PciWrite8 (PciLibAddress + 2, *((UINT8 *) Buffer + 2));
+      PciWrite8 (PciLibAddress + 3, *((UINT8 *) Buffer + 3));
+    }
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This function performs a read-modify-write operation on the contents from a given
+  location in the PCI configuration space.
+
+  @param  PeiServices     An indirect pointer to the PEI Services Table
+                          published by the PEI Foundation.
+  @param  This            Pointer to local data for the interface.
+  @param  Width           The width of the access. Enumerated in bytes. Type
+                          EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().
+  @param  Address         The physical address of the access.
+  @param  SetBits         Points to value to bitwise-OR with the read configuration value.
+                          The size of the value is determined by Width.
+  @param  ClearBits       Points to the value to negate and bitwise-AND with the read configuration value.
+                          The size of the value is determined by Width.
+
+  @retval EFI_SUCCESS           The function completed successfully.
+  @retval EFI_INVALID_PARAMETER The invalid access width.
+
+**/
+EFI_STATUS
+EFIAPI
+PciCfg2Modify (
+  IN CONST  EFI_PEI_SERVICES          **PeiServices,
+  IN CONST  EFI_PEI_PCI_CFG2_PPI      *This,
+  IN        EFI_PEI_PCI_CFG_PPI_WIDTH Width,
+  IN        UINT64                    Address,
+  IN        VOID                      *SetBits,
+  IN        VOID                      *ClearBits
+  )
+{
+  UINTN   PciLibAddress;
+  UINT16  ClearValue16;
+  UINT16  SetValue16;
+  UINT32  ClearValue32;
+  UINT32  SetValue32;
+
+  PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);
+
+  if (Width == EfiPeiPciCfgWidthUint8) {
+    PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));
+  } else if (Width == EfiPeiPciCfgWidthUint16) {
+    if ((PciLibAddress & 0x01) == 0) {
+      //
+      // Aligned Pci address access
+      //
+      ClearValue16  = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));
+      SetValue16    = ReadUnaligned16 ((UINT16 *) SetBits);
+      PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);
+    } else {
+      //
+      // Unaligned Pci address access, break up the request into byte by byte.
+      //
+      PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));
+      PciAndThenOr8 (PciLibAddress + 1, (UINT8) (~(*((UINT8 *) ClearBits + 1))), *((UINT8 *) SetBits + 1));
+    }
+  } else if (Width == EfiPeiPciCfgWidthUint32) {
+    if ((PciLibAddress & 0x03) == 0) {
+      //
+      // Aligned Pci address access
+      //
+      ClearValue32  = (UINT32) (~ReadUnaligned32 ((UINT32 *) ClearBits));
+      SetValue32    = ReadUnaligned32 ((UINT32 *) SetBits);
+      PciAndThenOr32 (PciLibAddress, ClearValue32, SetValue32);
+    } else if ((PciLibAddress & 0x01) == 0) {
+      //
+      // Unaligned Pci address access, break up the request into word by word.
+      //
+      ClearValue16  = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));
+      SetValue16    = ReadUnaligned16 ((UINT16 *) SetBits);
+      PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);
+
+      ClearValue16  = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits + 1));
+      SetValue16    = ReadUnaligned16 ((UINT16 *) SetBits + 1);
+      PciAndThenOr16 (PciLibAddress + 2, ClearValue16, SetValue16);
+    } else {
+      //
+      // Unaligned Pci address access, break up the request into byte by byte.
+      //
+      PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));
+      PciAndThenOr8 (PciLibAddress + 1, (UINT8) (~(*((UINT8 *) ClearBits + 1))), *((UINT8 *) SetBits + 1));
+      PciAndThenOr8 (PciLibAddress + 2, (UINT8) (~(*((UINT8 *) ClearBits + 2))), *((UINT8 *) SetBits + 2));
+      PciAndThenOr8 (PciLibAddress + 3, (UINT8) (~(*((UINT8 *) ClearBits + 3))), *((UINT8 *) SetBits + 3));
+    }
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_PEI_PCI_CFG2_PPI gPciCfg2Ppi = {
+  PciCfg2Read,
+  PciCfg2Write,
+  PciCfg2Modify,
+  0
+};
+
+EFI_PEI_PPI_DESCRIPTOR gPciCfg2PpiList = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEfiPciCfg2PpiGuid,
+  &gPciCfg2Ppi
+};
+
+/**
+  Module's entry function.
+  This routine will install EFI_PEI_PCI_CFG2_PPI.
+
+  @param  FileHandle  Handle of the file being invoked.
+  @param  PeiServices Describes the list of possible PEI Services.
+
+  @return Whether success to install service.
+**/
+EFI_STATUS
+EFIAPI
+PeimInitializePciCfg (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS            Status;
+
+  (**(EFI_PEI_SERVICES **)PeiServices).PciCfg = &gPciCfg2Ppi;
+  Status = PeiServicesInstallPpi (&gPciCfg2PpiList);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
-- 
cgit