首页
社区
课程
招聘
查看PCI设备配置空间
发表于: 2011-10-30 21:29 6821

查看PCI设备配置空间

2011-10-30 21:29
6821
用I/O命令可以访问PCI总线设备配置空间,具体使用的端口号为CF8和CFC,所用的指令就是in和out.

编程的一些注意点:

 1.因为CF8和CFC大于FF,所以不能直接写以下指令 包括in out
   asm
    out $CF8,eax
   end;
   应该将端口号赋值dx,然后
   asm
    mov dx,$CF8
    out dx,eax
   end;

 2.调用内嵌汇编的时候有时会出现莫明奇妙的错误。有时并不是代码的问题。

 3.in out 端口需要有特权。只好写驱动程序来完成此任务。

先来理解一下PCI配置空间

 PCI配置空间是用来存放设备必要数据的地方,我的理解是系统(1个)它里面包含了总线,而总线里面包括了设备,设备又包括了功能,而每一个功能它所占的空间是256字节(0-$FF)

  那么一个系统里面又包含多少个总线啊?根据送往CF8端口的那个地址的结构来看(这个下面介绍),一个系统最多可以包括256个总线(0-$FF),一个总线又最多可以包括32个设备(0-$1F),一个设备最多可以包括8个功能(0-$7)。

  所以我们要做一个查看PCI设备配置空间工具,需要搜寻上面所有地址。
   for n1:=0 to $FF do          //系统内所有的总线
    for n2:=0 to $1F do         //总线内所有的设备
     for n3:=0 to $7 do         //设备内所有的功能
      for n4:=0 to $FF do       //功能空间内所有的字节

 理解完宏观的东西,现在理解微观的。那么我要访问一个功能上的一个字节该怎么做啊?
 用I/O命令可以办到
 
 CF8称为地址配置端口,只要往这个端口送一个32位(4字节)的数据(这个数据包含了总线,设备,功能,空间字节的信息),然后到CFC端口就可以读出我们想要的内容(32位)(4字节)。

 送往CF8的数据的结构:


 
这个DOWRD的第31位必须为1,24-30位因为保留无功能的关系为0,16-23位代表总线号(0-$FF),11-15位代表设备号(0-$1F),8-10位代表功能号(0-$7),2-7位代表要访问空间的位置(0-$3F).0-1位恒定为0.

解释一下2-7位代表要访问的空间的位置,为什么是0-$3F呢,因为0-$3F即是0-63即64个位置,因为每一个位置都会导致CFC端口返回一个4字节数据,64*4=256字节,刚好是一个功能的配置空间

举个例子说明一下:

 比如我想知道总线号为0,设备号为0,功能号为0的设备的配置空间上,256个字节当中第0-3字节的内容是什么啊?那么可以向CF8端口送入以下二进制数据:

  1 0000000 00000000 00000 000 000000 00             =   $80000000
 
 又例如我想知道总线号为0,设备号为0,功能号为0的设备的配置空间上,256个字节当中第4-7字节的内容是什么啊?那么可以向CF8端口送入以下二进制数据:

  1 0000000 00000000 00000 000 000001 00             =   $80000004

那么8-11字节呢?

  1 0000000 00000000 00000 000 000010 00             =   $80000008

 例如我想知道总线号为1,设备号为0,功能号为0的设备的配置空间上,256个字节当中第0-3字节的内容是什么啊?那么可以向CF8端口送入以下二进制数据:

  1 0000000 00000001 00000 000 000000 00             =   $80010000

 再例如我想知道总线号为1,设备号为2,功能号为3的设备的配置空间上,256个字节当中第0-3字节的内容是什么啊?那么可以向CF8端口送入以下二进制数据:

  1 0000000 00000001 00010 011 000000 00             =   $80011300

这么多例子应该很好理解.

然后读CFC端口即可获得配置空间上的数据.如果这个总线号,设备号,功能号所对应的设备不存在,那么它配置空间上的第0-1字节上数据为$FF,$FF.这样我们以对每一个功能只访问其的0-3字节的内容即可.判断存在时才继续访问4-$FF上的内容.

伪代码:

 Bus:=0;   //总线0
 Dev:=0;   //设备0
 Func:=0;  //功能0
 BytesT:=0;  //字节位置 0-3
 ToCF8:=$80000000+Bus shl 16+Dev shl 11+Func shl 8+BytesT shl 2;
 asm
  mov dx,$CF8
  mov eax,ToCF8
  out dx,eax          //将地址码送入寄存器$CF8
  mov dx,$CFC
  in eax,dx           //然后从$CFC中取出返回码
  mov Buffer,eax
 end;

其中 out dx,eax  与 in eax,dx 两个指令需要有特权才能执行.所以用了驱动

最后附上查看器源代码:

简易PCI查看.rar

(编译环境 运行文件:Delphi 6  驱动: Delphi 6+KmdKit4D)
用这个查看器查看到的数据与著名软件EVEREST查看到的基本上是相同的.

[课程]Linux pwn 探索篇!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//