VC 获得系统的 MCFG Table

之前介绍过我们可以从内存来进行 PCI 配置空间的访问,前提是需要找到 PCI Base Address。在现在的系统中,这个地址是放在 ACPI MCFG Table 中来通知系统的。例如,下面就是我电脑上的 Base Address。

RW Everything 读取 MCFG Table

为了完成这个目标,分作两步,第一步是取得 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;
}

运行结果:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注