# PcatSingleSegmentPciCfg2Pei - PCI CFG2 PPI for Single PCI Segment

## Overview

This PEIM installs the `EFI_PEI_PCI_CFG2_PPI` on the PEI PPI database for a system
with a single PCI segment (Bus 0 only). It translates PCI CFG2 Read/Write/Modify
operations into PCI Express memory-mapped configuration space accesses (ECAM).

The module is built from `MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c`
and compiled with VS2015 DEBUG for IA32 architecture.

**GUID:** `{057A449A-1FDC-4C06-BFC9-F53F6A99BB92}` (EFI_PEI_PCI_CFG2_PPI)

## Address Range

| Section | Start | End | Size | Perms |
|---------|-------|-----|------|-------|
| HEADER  | 0xffdab714 | 0xffdab974 | 0x260 | --- |
| .text   | 0xffdab974 | 0xffdac614 | 0xca0 | rx |
| .rdata  | 0xffdac614 | 0xffdac9f4 | 0x3e0 | r  |
| .data   | 0xffdac9f4 | 0xffdaca54 | 0x60  | rw |
| .reloc  | 0xffdaca54 | 0xffdacad4 | 0x80  | r  |
| GAP     | 0xffdacad4 | 0xffdad714 | 0xc40 | rw |

**Total image size:** 0x13c0 (5056 bytes)

## Function Table

| Address | Size | Name | Description |
|---------|------|------|-------------|
| 0xffdaba34 | 0x5b | **ModuleEntryPoint** | PEIM entry; installs EFI_PEI_PCI_CFG2_PPI via PeiServices->InstallPpi |
| 0xffdaba8f | 0x52 | **PciExpressAddressToOffset** | Decodes packed PCI address (Bus:Dev:Func:Reg) into ECAM MMIO offset |
| 0xffdabae1 | 0x1b1 | **PciCfg2Read** | Read handler: 8/16/32/64-bit reads with misalignment handling |
| 0xffdabc92 | 0x1a5 | **PciCfg2Write** | Write handler: 8/16/32/64-bit writes with misalignment handling |
| 0xffdabe37 | 0x325 | **PciCfg2Modify** | Read-Modify-Write: new = (old & ~ClearBits) | SetBits |
| 0xffdab974 | 0x15 | **SetMem** | memset(buf, value, count) wrapper |
| 0xffdab994 | 0x1f | **SetMem32** | Fill buffer with 32-bit pattern (two DWORDs per iteration) |
| 0xffdab9b4 | 0x15 | **ZeroMem** | Zero buffer wrapper |
| 0xffdab9d4 | 0x3f | **CopyMem** | memcpy/memmove with overlap detection |
| 0xffdac3a8 | 0x32 | **GetPeiServicesTablePtr** | Read PEI Services Table ptr from IDT base-4 |
| 0xffdac3da | 0x23 | **ReadIdtr** | Execute SIDT instruction to read IDTR |
| 0xffdac15c | 0x31 | **GetPcdDatabasePtr** | Locate PCD database PPI via PeiServices->LocatePpi |
| 0xffdac5b5 | 0x58 | **PeiPcdLocate** | Locate PCD PPI interface |
| 0xffdac3fd | 0xc | **GetPciExpressBaseAddr** | Get PcdPciExpressBaseAddress (token=5) via PCD PPI |
| 0xffdac409 | 0x30 | **PciExpressRead8** | MMIO read 8-bit from PCIe config space |
| 0xffdac439 | 0x39 | **PciExpressWrite8** | MMIO write 8-bit to PCIe config space |
| 0xffdac472 | 0x38 | **PciExpressRead16** | MMIO read 16-bit from PCIe config space (aligned) |
| 0xffdac4aa | 0x3e | **PciExpressWrite16** | MMIO write 16-bit to PCIe config space (aligned) |
| 0xffdac4e8 | 0x33 | **PciExpressRead32** | MMIO read 32-bit from PCIe config space |
| 0xffdac51b | 0x39 | **PciExpressWrite32** | MMIO write 32-bit to PCIe config space |
| 0xffdac283 | 0x42 | **PciExpressOr8** | Atomic read-modify-write: val = (val & AndData) | OrData |
| 0xffdac2c5 | 0x52 | **PciExpressOr16** | Atomic read-modify-write 16-bit |
| 0xffdac317 | 0x42 | **PciExpressOr32** | Atomic read-modify-write 32-bit |
| 0xffdac1d5 | 0x27 | **UnalignedRead16** | Safe 16-bit read from any alignment |
| 0xffdac1fc | 0x2f | **UnalignedWrite16** | Safe 16-bit write to any alignment |
| 0xffdac22b | 0x29 | **UnalignedRead32** | Safe 32-bit read from any alignment |
| 0xffdac254 | 0x2f | **UnalignedWrite32** | Safe 32-bit write to any alignment |
| 0xffdac554 | 0x2e | **AlignedRead16** | 16-bit read with alignment check |
| 0xffdac582 | 0x33 | **AlignedWrite16** | 16-bit write with alignment check |
| 0xffdac359 | 0x4f | **GetPlatformErrorStatus** | Read CMOS register 0x4A for error status |
| 0xffdac18d | 0x2a | **ReportAssert** | Report assertion failure via PCD debug handler |
| 0xffdac1b7 | 0x1e | **ReportDebugMsg** | Report debug message via PCD debug handler |

## Data Structures (.data section @ 0xffdac9f4, size 0x60)

```
0xffdac9f4:  mPcdDatabaseGuid        - 16 bytes - GUID for PCD database PPI
0xffdaca04:  mPcatSingleSegmentPciCfg2PpiGuid - 16 bytes - {057A449A-1FDC-4C06-BFC9-F53F6A99BB92}
0xffdaca14:  Reserved                 - 16 bytes - (unused GUID slot)
0xffdaca24:  mPrivateData             - 16 bytes - EFI_PEI_PCI_CFG2_PPI function table:
              [0] PciCfg2Read    (0xffdabae1)
              [1] PciCfg2Write   (0xffdabc92)
              [2] PciCfg2Modify  (0xffdabe37)
              [3] Reserved       (0)
0xffdaca34:  mPpiDescriptor           - 16 bytes - EFI_PEI_PPI_DESCRIPTOR:
              Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
              Guid  = &mPcatSingleSegmentPciCfg2PpiGuid  (0xffdaca04)
              Ppi   = &mPrivateData                       (0xffdaca24)
0xffdaca44:  Padding                  - 16 bytes - zero-filled
```

## Architecture

### PCI Express MMIO Access

This module uses the PCI Express Enhanced Configuration Access Mechanism (ECAM),
which maps PCI configuration space to a memory-mapped region. The base address
is retrieved from the PCD database as `PcdPciExpressBaseAddress` (token value 5).

### Address Encoding

The EFI_PEI_PCI_CFG2_PPI packs the PCI address into a UINT64 in this format:

| Byte | Field | Bits | Description |
|------|-------|------|-------------|
| 0 | Register | 7:0 | Configuration register offset (0-255) |
| 1 | Function | 2:0 | PCI function number (0-7) |
| 2 | Device | 4:0 | PCI device number (0-31) |
| 3 | Bus | 7:0 | PCI bus number (0-255) |
| 4-7 | ExtendedRegister | 31:0 | Extended register offset for ECAM (>255) |

The ECAM MMIO offset is computed as:
```
Offset = (Bus << 20) | (Device << 15) | (Function << 12) | Register
```

If ExtendedRegister is non-zero, it replaces Register (enabling access to
extended PCIe config space at offsets 256-4095).

### Misaligned Access Handling

All three PPI callbacks (Read/Write/Modify) handle misaligned offsets by
breaking operations into smaller aligned sub-accesses:

- **Offset & 1 (byte-misaligned):** Decompose into individual byte operations
- **Offset & 3 but not & 1 (halfword-misaligned):** Decompose into 16-bit operations
- **Offset & 3 == 0 (word-aligned):** Full 32-bit or 64-bit operations

## Dependencies

### PPIs Installed
- **EFI_PEI_PCI_CFG2_PPI** `{057A449A-1FDC-4C06-BFC9-F53F6A99BB92}`

### PPIs Used
- **PCD Database PPI** `{36232936-0E76-31C8-A13A-3AF2FC1C3932}` - for PCD access

### Libraries Used
| Library | Source | Purpose |
|---------|--------|---------|
| BasePciExpressLib | MdePkg | PCI Express MMIO 8/16/32 read/write |
| BaseLib | MdePkg | memset, memcpy, unaligned access |
| BaseIoLibIntrinsic | MdePkg | IO port (CMOS) access |
| PeiServicesTablePointerLibIdt | MdePkg | Get PEI Services Table via IDTR |
| DxePcdLib / PeiPcdLib | MdePkg | PCD database access |
| DxeServicesTableLib | MdePkg | DXE Services Table (stub) |
| DxeMmPciBaseLib | CpRcPkg | PCIe segment bus table |
| UefiLib | MdePkg | UEFI library helpers |

### Build Information
- **Toolchain:** VS2015 DEBUG IA32
- **Source path:** `MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c`
- **PDB file:** `PcatSingleSegmentPciCfg2Pei.pdb`
- **Build path:** `e:\hs\Build\HR6N0XMLK\DEBUG_VS2015\X64\AmiModulePkg\OemActivation\OA3\OA3\DEBUG\AutoGen.c`
- **Platform:** HR6N0XMLK (Intel Grantley-EP platform)

## Source Files

| File | Description |
|------|-------------|
| `PcatSingleSegmentPciCfg2Pei.c` | Full decompilation in clean C |
| `PcatSingleSegmentPciCfg2Pei.h` | Complete function prototypes and type definitions |