6.Linux下的PCI-8.PCIEOptionRom-《计算机知识》

admin 2025-11-02 22:23:28 系统网络 来源:ZONE.CI 全球网 0 阅读模式
  • ExpansionOption ROM
    • 必读资料
    • 什么是Expansion/option rom?
    • 作用是什么?
    • 分布结构和使用
    • 怎么知道PCIE设备是否包含Expansion ROM?
    • 怎么知道Expansion ROM的空间大小
    • Expansion ROM的初始化过程
    • 在Linux读取设备的Expansion ROM方法
    • Linux代码读取过程

    ExpansionOption ROM

    必读资料

    • PCI&PCIE ExpansionOption ROM
    • PCIe Expansion Roms

    什么是Expansion/option rom?

    • Expansion rom是pci/pcie设备可选的一个外接的eprom芯片,其中用来存储相应pci设备的初始化代码或者系统启动代码(比如pxe或者pci boot)。
    • BIOS在POST(Power-on Self Test)阶段,会扫描pci设备是否有expansion_rom,有的话将其拷贝到ram中执行。
    • 在PCI规范中称为expansion rom,在BIOS术语里面称为option rom。
    • PCI Agent设备配置空间 0x30地址,4字节 为expansion rom信息

    image.png

    作用是什么?

    在《PCIE体系结构》P46中解释:

    有些PCI设备在处理器还没运行系统之前,比如在BIOS中,就需要完成基本配置,如PC的显卡,键盘,USB等。 为了实现这个”预先执行“功能,PCI设备需要提供一段ROM程序,处理器在初始化时运行这段ROM程序来初始化相关设备。 Expansion ROM 记载了ROM程序地址

    总结:系统启动前的预初始化程序,存储在PCI设备EEPROM中,系统上电时执行这部分代码来初始化基础外设

    注:Expansion ROM和BAR空间互斥使用,同一时间只能使能一个。

    分布结构和使用

    寄存器结构如上图:

    • bit[31:11]是PCIE域基地址
    • [10:1]Reserved
    • [0]使能位

    怎么知道PCIE设备是否包含Expansion ROM?

    并不是所有PCIe设备都包含Expansion ROM,所以就需要软件进行判定。《PCIe Expansion Roms》中讲了:判断长度是否为0即可。

    怎么知道Expansion ROM的空间大小

    在Expansion ROM的判定阶段,有一个过程是向Expansion ROM Base Address Register写入0xFFFF FFFF,然后读取它的值,利用这个值就可以判定出Expansion ROM的空间大小。

    假设写入0xFFFF FFFF之后,读出的值是0xFFFE_0000/0xFFFE_0001. bit[0]代表是否使能那么第17位就是非0值的最低位,那么Expansion ROM的大小就是2^17 Bytes= 128KB。PCI文档规定,ROM最大可为16MB,即bit[31:25]必须是可读/可写的。

    Expansion ROM的初始化过程

    BIOS的POST阶段,扫描并执行pci设备的expansion的过程大概分以下几步:

    • 首先判断pci设备是否实现“Expansion rom base address”寄存器,有才可以用:如何实现? 和BAR一样写入0xFFFF_FFFF到这个配置空间,然后可以读取到长度,非0代表有数据;
    • 如果有实现了expansion的基址寄存器,则配置和使能expansion rom,然后查找expansion rom是否有”AA55”的标示字符,如果有则说明设备有真实的expansion rom芯片存在
    • 如果expansion rom已经存在,则扫描是否有适合本设备和本CPU架构的image代码存在;
    • 如果有适合本环境的image代码存在,则把相应的代码拷贝到ram的合适位置,并跳入header format中指定的初始化入口执行;
    • 最后关闭expansion rom的使能。

    在Linux读取设备的Expansion ROM方法

    1. echo 1 > /sys/bus/pci/devices/0000:01:00.0/enable # 需要是能command的memory位才能读写。
    2. echo 1 > /sys/bus/pci/devices/0000:01:00.0/rom
    3. cat /sys/bus/pci/devices/0000:01:00.0/rom > /tmp/image.rom
    4. echo 0 > /sys/bus/pci/devices/0000:01:00.0/rom
    5. echo 0 > /sys/bus/pci/devices/0000:01:00.0/enable

    Expansion rom解析工具: https://github.com/awilliam/rom-parser

    Linux代码读取过程

    这部分推荐参考sysfs中读取optionRom代码,没必要自己写。参考:driver/pci/pci-sysfs.c即可

    1. // 1.使能 《PCIE体系结构》P48:command寄存器只有在使能IO/MEMORY后才能访问BAR和Expansion ROM空间pci_enable_device
    2. // 2.获取资源空间,因为这里地址是PCI域地址,所以不能直接读取配置空间
    3. // 《PCIE体系结构》P48:不能使用读取配置空间操作来访问这块地址,必须用
    4. // pci_dev->resource[6].start或者pci_resource_start 系列函数
    5. // struct pci_dev中:
    6. // struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
    7. // 由宏可知 0-5是bar空间,6是Expansion rom空间
    8. for(loop=0;loop<DEVICE_COUNT_RESOURCE; ++loop){
    9. printk("resource: start:%#llx,end:%#llx,name:%s,flags:%#lx,desc:%#lx\n",
    10. r->start,r->end,r->name,r->flags,r->desc);
    11. r++;
    12. }
    13. // 判断Expansion rom是否存在?如果存在,读取
    14. struct pci_bus *bus;
    15. struct pci_ops *ops;
    16. bus = pci_dev->bus;
    17. ops = bus->ops;
    18. printk("check Expansion ROM"); // devfn need to be ensuere
    19. ops->write(bus,0,0x30,4,0xffffffff);
    20. ops->read(bus,0,0x30,4,&tmp_val);
    21. printk("Expansion ROM len is %#x\n",tmp_val); // 可以读出长度
    22. ops->write(bus,0,0x30,4,0x00000000); // 用完之后记得释放
    01-shell脚本介绍-《shell脚本》 系统网络

    01-shell脚本介绍-《shell脚本》

    一、shell脚本是什么二、为什么要学shell,而不是其他计算机语言三、学习这门课程的优势四、学了能干什么五、学习什么内容六、学习的技巧七、成长路径八、学习环
    评论:0   参与:  17