之前介绍过我们可以从内存来进行 PCI 配置空间的访问,前提是需要找到 PCI Base Address。在现在的系统中,这个地址是放在 ACPI MCFG Table 中来通知系统的。例如,下面就是我电脑上的 Base Address。
为了完成这个目标,分作两步,第一步是取得 MCFG Table,通过 GetSystemFirmwareTable() 函数来完成;第二步,根据 MCFG Structure Definitions 来解析 MCFG Table,即可获得我们需要的值。最终代码如下:
// GetMCFGTable.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <sysinfoapi.h>
//
// Common ACPI description table header. This structure prefaces most ACPI tables.
//
#pragma pack(1)
typedef struct {
UINT32 Signature;
UINT32 Length;
UINT8 Revision;
UINT8 Checksum;
UINT8 OemId[6];
UINT64 OemTableId;
UINT32 OemRevision;
UINT32 CreatorId;
UINT32 CreatorRevision;
} EFI_ACPI_DESCRIPTION_HEADER;
//
// MCFG Structure Definitions
//
//
// Memory Mapped Enhanced Configuration Base Address Allocation
// Structure Definition
//
typedef struct {
UINT64 BaseAddress;
UINT16 PciSegmentGroupNumber;
UINT8 StartBusNumber;
UINT8 EndBusNumber;
UINT32 Reserved;
} EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_BASE_ADDRESS_STRUCTURE;
///
/// MCFG Table header definition. The rest of the table
/// must be defined in a platform specific manner.
///
typedef struct {
EFI_ACPI_DESCRIPTION_HEADER Header;
UINT64 Reserved;
} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER;
typedef struct {
EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER Header;
EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_BASE_ADDRESS_STRUCTURE Segment;
} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE;
#pragma pack()
EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE MCFG;
int main()
{
DWORD MCFGDataSize;
MCFGDataSize=GetSystemFirmwareTable(
'ACPI',
*(DWORD *)"MCFG",
&MCFG,
sizeof(EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE));
printf("MCFG Table size = %d bytes\n", MCFGDataSize);
printf("BaseAddress = 0x%X \n", MCFG.Segment.BaseAddress);
getchar();
return 0;
}
运行结果: