天天看點

ACPI.sys,從Windows到Bios的橋梁(1.5):PCIe device 配置空間

    在繼續<ACPI.sys,從Windows到Bios的橋梁>系列之前,先暫停補充一下PCIe device MMIO相關的知識。PCIe MMIO比較複雜,推薦以這兩篇文章入門: 

<​​System Address Map Initialization in x86/x64 Architecture Part 1: PCI-Based Systems​​​> &<​​System Address Map Initialization in x86/x64 Architecture Part 2: PCI Express-Based Systems​​>。本文基于這兩篇文章,總結如何在Intel平台上讀取PCIe device配置空間。

0.收集主機闆資訊:

不同平台,PCH上提供相同功能的PCIe device的Bus/Device/Function/Register Number可能會發生變化,為了趕上這種變化,需要先确定CPU和平台型号,如我的筆記本是WhiskyLake平台(見笑了):

ACPI.sys,從Windows到Bios的橋梁(1.5):PCIe device 配置空間

确定型号後,根據PCH EDS spec得到 Bus/Device/Function/Register Number(當然完全可以用RW放飛自我,不過PCH上有部分PCIe裝置對RW等工具不可見)。

1.擷取PCIEX_BASE_ADDRESS

根據CPU EDS Vol2,PCIEX_BASE_ADDRESS的值通過下列方式獲得:

ACPI.sys,從Windows到Bios的橋梁(1.5):PCIe device 配置空間
ACPI.sys,從Windows到Bios的橋梁(1.5):PCIe device 配置空間

Bus:0 Device:0 Function:0 Register:0x60 bit[28:36]存放PCIEXBAR的位址,當然,這個可以用RW擷取。如下圖,對于WHL平台,PCIEXBAR位址為E0000000:

ACPI.sys,從Windows到Bios的橋梁(1.5):PCIe device 配置空間

2.通路PCIe裝置配置空間: 

#define SB_PCIE_CFG_ADDRESS(bus, dev, func, reg) \

            ((UINTN)(PCIEX_BASE_ADDRESS + ((UINT8)(bus) << 20) + \

            ((UINT8)(dev) << 15) + ((UINT8)(func) << 12) + (reg)))

 

#define PCIEX_BASE_ADDRESS  0xe0000000      

根據這個宏定義可以通路多數PCIe裝置(除了P2SB/PMC controller這種隐藏裝置)的配置空間,比如VGA Controller:B:0 D:2 F:0,經過計算其配置空間起始位址:E0010000,對比從RW PCIe device獲得的配置空間,兩者内容相同:

ACPI.sys,從Windows到Bios的橋梁(1.5):PCIe device 配置空間

3.獲得PCIe BAR1\BAR2...:

PCIe超過256B以外的配置空間以Mem方式通路,該配置空間起始位址存放于BAR1\BAR2,其Register offset分别為0x10\0x14,我們看下XHCI 配置空間為E00A0000/XHCI Bar Address為0x6001100000:

#define PCI_BUS_NUMBER_PCH_XHCI             0
#define PCI_DEVICE_NUMBER_PCH_XHCI          20
#define PCI_FUNCTION_NUMBER_PCH_XHCI        0
    
    XhciPciMmBase   = MmPciBase (
                      DEFAULT_PCI_BUS_NUMBER_PCH,
                      PCI_DEVICE_NUMBER_PCH_XHCI,
                      PCI_FUNCTION_NUMBER_PCH_XHCI
                      );
//獲得XHci BAR Address
    UsbBase = MmioRead32 (XhciPciMmBase + PCI_BASE_ADDRESSREG_OFFSET + 4);
                UsbBase = (UsbBase << 32);
                UsbBase |= MmioRead32 (XhciPciMmBase + PCI_BASE_ADDRESSREG_OFFSET);
                UsbBase &= 0xFFFFFFFFFFFF0000;      
ACPI.sys,從Windows到Bios的橋梁(1.5):PCIe device 配置空間

 從RW Memory獲得的XHCI Bar Address各Offset的具體内容需要與PCH EDS對比,當然這不是本文内容,不再讨論。

ACPI.sys,從Windows到Bios的橋梁(1.5):PCIe device 配置空間

 參考: