手记

wdmWin10下读取PCI配置空间


WDM下HalGetBusData不能用了。加上感觉pnp方式太麻烦。

自己修改了驱动开发技术详解上的代码直接在驱动下获取信息

#include "Driver.h"

NTSTATUS DriverEntry(

    IN PDRIVER_OBJECT pDriverObject,

    IN PUNICODE_STRING pRegistryPath)

{

    NTSTATUS status;

    //判断CPU类型

    CPUType();

    //枚举

    EnumeratePCI();

    KdPrint(("Enter DriverEntry\n"));

    //DbgBreakPoint();

    //设置卸载函数

    pDriverObject->DriverUnload =DDKUnload;

    //设置派遣函数

    pDriverObject->MajorFunction[IRP_MJ_CREATE] = DDKDispatchRoutin;

    pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DDKDispatchRoutin;

    pDriverObject->MajorFunction[IRP_MJ_WRITE] = DDKDispatchRoutin;

    pDriverObject->MajorFunction[IRP_MJ_READ] = DDKDispatchRoutin;

    pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = DDKDispatchRoutin;

    pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DDKDispatchRoutin;

    pDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = DDKDispatchRoutin;

    pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = DDKDispatchRoutin;

    pDriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DDKDispatchRoutin;

    //创建驱动设备对象

    status = CreateDevice(pDriverObject);

    KdPrint(("Leave DriverEntry\n"));

    return status;

}

NTSTATUS CreateDevice(

    IN PDRIVER_OBJECT   pDriverObject)

{

    NTSTATUS status;

    PDEVICE_OBJECT pDevObj;

    PDEVICE_EXTENSION pDevExt;

    //创建设备名称

    UNICODE_STRING devName;

    RtlInitUnicodeString(&devName, L"\\Device\\MyDDKDevice");

    //创建设备

    status = IoCreateDevice(pDriverObject,

        sizeof(DEVICE_EXTENSION),

        &devName,

        FILE_DEVICE_UNKNOWN,

        0, TRUE,

        &pDevObj);

    if (!NT_SUCCESS(status))

        return status;

    pDevObj->Flags |= DO_BUFFERED_IO;

    pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

    pDevExt->pDevice = pDevObj;

    pDevExt->ustrDeviceName = devName;

    //创建符号链接

    UNICODE_STRING symLinkName;

    RtlInitUnicodeString(&symLinkName, L"\\??\\TESTDDK");

    pDevExt->ustrSymLinkName = symLinkName;

    status = IoCreateSymbolicLink(&symLinkName, &devName);

    if (!NT_SUCCESS(status))

    {

        IoDeleteDevice(pDevObj);

        return status;

    }

    return STATUS_SUCCESS;

}

#pragma PAGEDCODE

VOID DDKUnload(IN PDRIVER_OBJECT pDriverObject)

{

    PDEVICE_OBJECT  pNextObj;

    KdPrint(("Enter DriverUnload\n"));

    pNextObj = pDriverObject->DeviceObject;

    while (pNextObj != NULL)

    {

        PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)

            pNextObj->DeviceExtension;

        //删除符号链接

        UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;

        IoDeleteSymbolicLink(&pLinkName);

        pNextObj = pNextObj->NextDevice;

        IoDeleteDevice(pDevExt->pDevice);

    }

}

#pragma PAGEDCODE

NTSTATUS DDKDispatchRoutin(IN PDEVICE_OBJECT pDevObj,

    IN PIRP pIrp)

{

    KdPrint(("Enter HelloDDKDispatchRoutin\n"));

    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);

    //建立一个字符串数组与IRP类型对应起来

    static char* irpname[] =

    {

        "IRP_MJ_CREATE",

        "IRP_MJ_CREATE_NAMED_PIPE",

        "IRP_MJ_CLOSE",

        "IRP_MJ_READ",

        "IRP_MJ_WRITE",

        "IRP_MJ_QUERY_INFORMATION",

        "IRP_MJ_SET_INFORMATION",

        "IRP_MJ_QUERY_EA",

        "IRP_MJ_SET_EA",

        "IRP_MJ_FLUSH_BUFFERS",

        "IRP_MJ_QUERY_VOLUME_INFORMATION",

        "IRP_MJ_SET_VOLUME_INFORMATION",

        "IRP_MJ_DIRECTORY_CONTROL",

        "IRP_MJ_FILE_SYSTEM_CONTROL",

        "IRP_MJ_DEVICE_CONTROL",

        "IRP_MJ_INTERNAL_DEVICE_CONTROL",

        "IRP_MJ_SHUTDOWN",

        "IRP_MJ_LOCK_CONTROL",

        "IRP_MJ_CLEANUP",

        "IRP_MJ_CREATE_MAILSLOT",

        "IRP_MJ_QUERY_SECURITY",

        "IRP_MJ_SET_SECURITY",

        "IRP_MJ_POWER",

        "IRP_MJ_SYSTEM_CONTROL",

        "IRP_MJ_DEVICE_CHANGE",

        "IRP_MJ_QUERY_QUOTA",

        "IRP_MJ_SET_QUOTA",

        "IRP_MJ_PNP",

    };

    UCHAR type = stack->MajorFunction;

    if (type >= arraysize(irpname))

        KdPrint((" - Unknown IRP, major type %X\n", type));

    else

        KdPrint(("\t%s\n", irpname[type]));

    //对一般IRP的简单操作,后面会介绍对IRP更复杂的操作

    NTSTATUS status = STATUS_SUCCESS;

    // 完成IRP

    pIrp->IoStatus.Status = status;

    pIrp->IoStatus.Information = 0; // bytes xfered

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    KdPrint(("Leave DDKDispatchRoutin\n"));

    return status;

}

stRet CPUType()

{

    stRet st_Ret = {FALSE,FALSE}; 

    ULONG CPUInfo[4] = { -1 };

    CHAR cpu_string[48];

    __cpuid(CPUInfo, 0);

    INT num_ids = CPUInfo[0];

    //GenuineIntel是Intel的CPU 

    //0x47, 0x65, 0x6E, 0x75,   0x69, 0x6E, 0x65, 0x49,   0x6E, 0x74, 0x65, 0x6C,   0x00, 0x00, 0x00, 0x00 GenuineIntel

    if ((CPUInfo[1] == 0x756e6547) && (CPUInfo[2] == 0x6c65746e) && (CPUInfo[3] == 0x49656e69))

    {

        st_Ret.bIntelCPU=TRUE;

        KdPrint(("GenuineIntel\n"));

    }

    //AuthenticAMD 是AMD的CPU

    //0x41, 0x75, 0x74, 0x68,   0x65, 0x6E, 0x74, 0x69,   0x63, 0x41, 0x4D, 0x44,   0x00, 0x00, 0x00, 0x00  AuthenticAMD

    if ((CPUInfo[1] == 0x68747541) && (CPUInfo[2] == 0x444d4163) && (CPUInfo[3] == 0x69746e65))

    {

        st_Ret.bIntelCPU = TRUE;

        KdPrint(("AuthenticAMD\n"));

    }

    INT cpu_info[4] = { -1 };

    __cpuid(cpu_info, 0);

    // Interpret CPU feature information.

    if (num_ids > 0) {

        int cpu_info7[4] = { 0 };

        __cpuid(cpu_info, 1);

        if (num_ids >= 7) {

            __cpuid(cpu_info7, 7);

        }

        signature_ = cpu_info[0];

        stepping_ = cpu_info[0] & 0xf;

        model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0);

        family_ = (cpu_info[0] >> 8) & 0xf;

        type_ = (cpu_info[0] >> 12) & 0x3;

        ext_model_ = (cpu_info[0] >> 16) & 0xf;

        ext_family_ = (cpu_info[0] >> 20) & 0xff;

        has_mmx_ = (cpu_info[3] & 0x00800000) != 0;

        has_sse_ = (cpu_info[3] & 0x02000000) != 0;

        has_sse2_ = (cpu_info[3] & 0x04000000) != 0;

        has_sse3_ = (cpu_info[2] & 0x00000001) != 0;

        has_ssse3_ = (cpu_info[2] & 0x00000200) != 0;

        has_sse41_ = (cpu_info[2] & 0x00080000) != 0;

        has_sse42_ = (cpu_info[2] & 0x00100000) != 0;

        has_aesni_ = (cpu_info[2] & 0x02000000) != 0;

        has_avx2_ = has_avx_ && (cpu_info7[1] & 0x00000020) != 0;

    }

    // Get the brand string of the cpu.

    __cpuid(cpu_info, 0x80000000);

    const int parameter_end = 0x80000004;

    int max_parameter = cpu_info[0];

    //CHAR temp[40] = { -1 };

    if (cpu_info[0] >= parameter_end) {

        PCHAR cpu_string_ptr = cpu_string;

        for (int parameter = 0x80000002; parameter <= parameter_end &&

            cpu_string_ptr < &cpu_string[lstrlen(cpu_string)]; parameter++) {

            __cpuid(cpu_info, parameter);

            lstrcpy(cpu_string_ptr, cpu_info, lstrlen(cpu_info));

            cpu_string_ptr += lstrlen(cpu_info);

        }

        //lstrcpy(g_cpu_string, cpu_string_ptr-34, 32);

        KdPrint(("cpu_string:%s cpu_string:%x\n", cpu_string, cpu_string));

        //DbgBreakPoint(); 

    }

    const int parameter_containing_non_stop_time_stamp_counter = 0x80000007;

    if (max_parameter >= parameter_containing_non_stop_time_stamp_counter) {

        __cpuid(cpu_info, parameter_containing_non_stop_time_stamp_counter);

        has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0;

    } 

    return st_Ret;

}

//  字符串长度

DWORD lstrlen(PCHAR pSrc)

{

    DWORD   dwRet = 0;

    while (*pSrc != 0)

    {

        dwRet++;

        pSrc++;

    }

    return dwRet;

}

//  字符拷贝

VOID lstrcpy(PCHAR pDst, PCHAR pSrc, DWORD len)

{

    //while (1)

    //{

    //  //  复制字符,直到零结尾

    //  *pDst = *pSrc;

    //  if (*pSrc == 0)

    //      break;

    //  //  下一个字符

    //  pSrc++;

    //  pDst++;

    //}

    for (DWORD i = 0; i < len; i++) {

            //  复制字符 

            *pDst = *pSrc;

            if (*pSrc == 0)

                break;

            //  下一个字符

            pSrc++;

            pDst++;

    }

}

//VOID EnumeratePCI()

//{

//  ULONG bus;

//  ULONG dev;

//  ULONG func;

//

//  PCI_COMMON_CONFIG PciConfig;

//  PCI_SLOT_NUMBER SlotNumber;

//

//  KdPrint(("Bus\tDevice\tFunc\tVendor\tDevice\tBaseCls\tSubCls\tIRQ\tPIN\n"));

//

//  for (bus = 0; bus <= PDI_BUS_MAX; ++bus)

//  {

//      for (dev = 0; dev <= PDI_DEVICE_MAX; ++dev)

//      {

//          for (func = 0; func <= PDI_FUNCTION_MAX; ++func)

//          {

//              SlotNumber.u.AsULONG = 0;

//              SlotNumber.u.bits.DeviceNumber = dev;

//              SlotNumber.u.bits.FunctionNumber = func;

//

//              RtlZeroMemory(&PciConfig,

//                  sizeof(PCI_COMMON_CONFIG));

//              ULONG Size = HalGetBusData(PCIConfiguration,

//                  bus,

//                  SlotNumber.u.AsULONG,

//                  &PciConfig,

//                  PCI_COMMON_HDR_LENGTH);

//              if (Size == PCI_COMMON_HDR_LENGTH)

//              {

//                  KdPrint(("%02X\t%02X\t%x\t%x\t%x\t%02X\t%02X\t%d\t%d\n",

//                      bus,

//                      dev,

//                      func,

//                      PciConfig.VendorID,

//                      PciConfig.DeviceID,

//                      PciConfig.BaseClass,

//                      PciConfig.SubClass,

//                      PciConfig.u.type0.InterruptLine,

//                      PciConfig.u.type0.InterruptPin));

//              }

//

//          }

//      }

//  }

//

//}

void Out_32(USHORT port, ULONG value)

    UCHAR method = 4; 

    //KdPrint(("port:%x\n", port));

    //KdPrint(("method:%x\n", method));

    //KdPrint(("value:%x\n", value));

    if (method == 1)//8位操作

    {

        WRITE_PORT_UCHAR((PUCHAR)port, (UCHAR)value);

    }

    else if (method == 2)//16位操作

    {

        WRITE_PORT_USHORT((PUSHORT)port, (USHORT)value);

    }

    else if (method == 4)//32位操作

    {

        WRITE_PORT_ULONG((PULONG)port, (ULONG)value);

    }

}

DWORD In_32(USHORT port)

    UCHAR method = 4;

    //KdPrint(("port:%x\n", port));

    //KdPrint(("method:%x\n", method));

    if (method == 1)//8位操作

    {

        return READ_PORT_UCHAR((PUCHAR)port);

    }

    else if (method == 2)//16位操作

    {

        return READ_PORT_USHORT((PUSHORT)port);

    }

    else if (method == 4)//32位操作

    {

        return  READ_PORT_ULONG((PULONG)port);

    } 

    return 0;

}

void DisplayPCIConfiguation(int bus, int dev, int func)

{

    DWORD   dwAddr;

    DWORD   dwData;

    MYPCI_COMMON_CONFIG pci_config;

    MYPCI_SLOT_NUMBER SlotNumber;

    SlotNumber.u.AsULONG = 0;

    SlotNumber.u.bits.DeviceNumber = dev;

    SlotNumber.u.bits.FunctionNumber = func;

    dwAddr = 0x80000000 | (bus << 16) | (SlotNumber.u.AsULONG << 8);

    /* 256字节的PCI配置空间 */

    for (int i = 0; i < 0x100; i += 4)

    {

        /* Read */

        Out_32(PCI_CONFIG_ADDRESS, dwAddr | i);

        dwData = In_32(PCI_CONFIG_DATA);

        memcpy(((PUCHAR)&pci_config) + i, &dwData, 4);

    }

//bus:2 dev : 1 func : 0

//  VendorID : 15ad

//  DeviceID : 1977

//  Command : 6

//  Status : 10

//  RevisionID : 9

//  ProgIf : 0

//  SubClass : 3

//  BaseClass : 4

//  CacheLineSize : 40

//  LatencyTimer : 0

//  HeaderType : 0

//  BIST : 0

//  BaseAddresses[0] : 0XFC000004

//  BaseAddresses[1] : 0X00000000

//  BaseAddresses[2] : 0X00000000

//  BaseAddresses[3] : 0X00000000

//  BaseAddresses[4] : 0X00000000

//  BaseAddresses[5] : 0X00000000

//  InterruptLine : 19

//  InterruptPin : 1

    KdPrint(("bus:%d\tdev:%d\tfunc:%d\n", bus, dev, func));

    KdPrint(("VendorID:%x\n", pci_config.VendorID));

    KdPrint(("DeviceID:%x\n", pci_config.DeviceID));

    KdPrint(("Command:%x\n", pci_config.Command));

    KdPrint(("Status:%x\n", pci_config.Status));

    KdPrint(("RevisionID:%x\n", pci_config.RevisionID));

    KdPrint(("ProgIf:%x\n", pci_config.ProgIf));

    KdPrint(("SubClass:%x\n", pci_config.SubClass));

    KdPrint(("BaseClass:%x\n", pci_config.BaseClass));

    KdPrint(("CacheLineSize:%x\n", pci_config.CacheLineSize));

    KdPrint(("LatencyTimer:%x\n", pci_config.LatencyTimer));

    KdPrint(("HeaderType:%x\n", pci_config.HeaderType));

    KdPrint(("BIST:%x\n", pci_config.BIST));

    for (int i = 0; i < 6; i++)

    {

        KdPrint(("BaseAddresses[%d]:0X%08X\n", i, pci_config.u.type0.BaseAddresses[i]));

    }

    KdPrint(("InterruptLine:%d\n", pci_config.u.type0.InterruptLine));

    KdPrint(("InterruptPin:%d\n", pci_config.u.type0.InterruptPin));

}

VOID EnumeratePCI() {

    DisplayPCIConfiguation( 2, 1, 0);

}

Driver.h

#include <ntifs.h>

#include <NTDDK.h>

#include <string.h>

#include <ntstrsafe.h>

#define PAGEDCODE code_seg("PAGE")

#define LOCKEDCODE code_seg()

#define INITCODE code_seg("INIT")

#define PDI_BUS_MAX     0xFF

#define PDI_DEVICE_MAX     0x1F

#define PDI_FUNCTION_MAX     0x7 

#define PAGEDDATA data_seg("PAGE")

#define LOCKEDDATA data_seg()

#define INITDATA data_seg("INIT")

#define arraysize(p) (sizeof(p)/sizeof((p)[0]))

typedef struct _DEVICE_EXTENSION {

    PDEVICE_OBJECT pDevice;

    UNICODE_STRING ustrDeviceName;  //设备名称

    UNICODE_STRING ustrSymLinkName; //符号链接名

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

typedef struct MyStruct

{

    //Intel

    BOOLEAN bIntelCPU;

    //AMD

    BOOLEAN bAMDCPU;

}stRet;

INT signature_;  // raw form of type, family, model, and stepping

INT type_;  // process type

INT family_;  // family of the processor

INT model_;  // model of processor

INT stepping_;  // processor revision number

INT ext_model_;

INT ext_family_;

BOOLEAN has_mmx_;

BOOLEAN has_sse_;

BOOLEAN has_sse2_;

BOOLEAN has_sse3_;

BOOLEAN has_ssse3_;

BOOLEAN has_sse41_;

BOOLEAN has_sse42_;

BOOLEAN has_avx_;

BOOLEAN has_avx2_;

BOOLEAN has_aesni_;

BOOLEAN has_non_stop_time_stamp_counter_;

ULONG CPUInfo[4] = { -1 };

// 函数声明

stRet CPUType();

NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject);

VOID DDKUnload(IN PDRIVER_OBJECT pDriverObject);

NTSTATUS DDKDispatchRoutin(IN PDEVICE_OBJECT pDevObj,

    IN PIRP pIrp);

//  字符串长度

DWORD lstrlen(PCHAR pSrc);

//  字符拷贝

VOID lstrcpy(PCHAR pDst, PCHAR pSrc, DWORD len);

//////////////////////////////////////////////////////////////

/* PCI配置空间寄存器 */

#define PCI_CONFIG_ADDRESS      0xCF8

#define PCI_CONFIG_DATA         0xCFC

#define PCI_TYPE0_ADDRESSES             6

#define PCI_TYPE1_ADDRESSES             2

#define PCI_TYPE2_ADDRESSES             5

typedef struct _MYPCI_COMMON_CONFIG {

    USHORT  VendorID;                   // (ro)

    USHORT  DeviceID;                   // (ro)

    USHORT  Command;                    // Device control

    USHORT  Status;

    UCHAR   RevisionID;                 // (ro)

    UCHAR   ProgIf;                     // (ro)

    UCHAR   SubClass;                   // (ro)

    UCHAR   BaseClass;                  // (ro)

    UCHAR   CacheLineSize;              // (ro+)

    UCHAR   LatencyTimer;               // (ro+)

    UCHAR   HeaderType;                 // (ro)

    UCHAR   BIST;                       // Built in self test

    union {

        struct _MYPCI_HEADER_TYPE_0 {

            ULONG   BaseAddresses[PCI_TYPE0_ADDRESSES];

            ULONG   CIS;

            USHORT  SubVendorID;

            USHORT  SubSystemID;

            ULONG   ROMBaseAddress;

            UCHAR   CapabilitiesPtr;

            UCHAR   Reserved1[3];

            ULONG   Reserved2;

            UCHAR   InterruptLine;      //

            UCHAR   InterruptPin;       // (ro)

            UCHAR   MinimumGrant;       // (ro)

            UCHAR   MaximumLatency;     // (ro)

        } type0;

        // end_wdm end_ntminiport end_ntndis

        //

        // PCI to PCI Bridge

        //

        struct _MYPCI_HEADER_TYPE_1 {

            ULONG   BaseAddresses[PCI_TYPE1_ADDRESSES];

            UCHAR   PrimaryBus;

            UCHAR   SecondaryBus;

            UCHAR   SubordinateBus;

            UCHAR   SecondaryLatency;

            UCHAR   IOBase;

            UCHAR   IOLimit;

            USHORT  SecondaryStatus;

            USHORT  MemoryBase;

            USHORT  MemoryLimit;

            USHORT  PrefetchBase;

            USHORT  PrefetchLimit;

            ULONG   PrefetchBaseUpper32;

            ULONG   PrefetchLimitUpper32;

            USHORT  IOBaseUpper16;

            USHORT  IOLimitUpper16;

            UCHAR   CapabilitiesPtr;

            UCHAR   Reserved1[3];

            ULONG   ROMBaseAddress;

            UCHAR   InterruptLine;

            UCHAR   InterruptPin;

            USHORT  BridgeControl;

        } type1;

        //

        // PCI to CARDBUS Bridge

        //

        struct _MYPCI_HEADER_TYPE_2 {

            ULONG   SocketRegistersBaseAddress;

            UCHAR   CapabilitiesPtr;

            UCHAR   Reserved;

            USHORT  SecondaryStatus;

            UCHAR   PrimaryBus;

            UCHAR   SecondaryBus;

            UCHAR   SubordinateBus;

            UCHAR   SecondaryLatency;

            struct {

                ULONG   Base;

                ULONG   Limit;

            }       Range[PCI_TYPE2_ADDRESSES - 1];

            UCHAR   InterruptLine;

            UCHAR   InterruptPin;

            USHORT  BridgeControl;

        } type2;

        // begin_wdm begin_ntminiport begin_ntndis

    } u;

    UCHAR   DeviceSpecific[192];

} MYPCI_COMMON_CONFIG, *MYPPCI_COMMON_CONFIG;

typedef struct _MYPCI_SLOT_NUMBER {

    union {

        struct {

            ULONG   FunctionNumber : 3;

            ULONG   DeviceNumber : 5;

            ULONG   Reserved : 24;

        } bits;

        ULONG   AsULONG;

    } u;

} MYPCI_SLOT_NUMBER, *MYPPCI_SLOT_NUMBER;

VOID EnumeratePCI();

对比书中的源码:

wdmWin10下读取PCI配置空间

©著作权归作者所有:来自51CTO博客作者土匪猿的原创作品,如需转载,请注明出处,否则将追究法律责任


0人推荐
随时随地看视频
慕课网APP