为了工作,我正在学习更多有关计算机体系结构的知识,并且刚刚学完 ACPI。通过与其他一些工程师的交谈,我对 NVMe 之类的东西的理解是,OEM 将拥有 UEFI NVMe 驱动程序,但操作系统的驱动程序将在启动后接管该功能。
在引导过程中,Linux 利用 UEFI 的驱动程序,然后一旦加载了自己的驱动程序,就会与之交换。
我的问题是源代码是什么样的?例如,我正在看NVMe源代码。
我假设固件必须暴露一些基于标准的接口,Linux 驱动程序必须调用这些接口? (ACPI?)
答案1
当今世界,外部设备通常是 PCIe。每个 PCIe 设备都有自己的 PCIe 配置空间,对于非桥接设备,该空间的标头如下所示:
BIOS(或 UEFI)的主要任务之一是询问每个 PCIe 设备Base Address Registers
(=BAR)需要多少内存,在 CPU 内存中的某个位置保留该区域,并写回这些区域的起始地址。
当操作系统启动时,它会检查每个设备的 PCIe 配置空间中的Vendor ID
值Device ID
,并根据该信息设置适当的驱动程序。驱动程序从 BIOS (UEFI) 写入的 BAR 寄存器中读取值,并使用该内存(或 io)。
因此,如您所见,主要信息写入设备本身,无需在设备驱动程序中询问任何 UEFI 服务。
至于 Linux API,有几个函数可以与这些 BAR 一起使用,例如您可能想查看:
unsigned long pci_resource_start(struct pci_dev *dev, int bar);
unsigned long pci_resource_end(struct pci_dev *dev, int bar);
unsigned long pci_resource_flags(struct pci_dev *dev, int bar);
或者
int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
如需更完整的文档,请参阅Linux Device Drivers
书籍:
https://www.xml.com/ldd/chapter/book/ch15.html
或者 PCI 上的内核文档:
https://www.kernel.org/doc/html/latest/driver-api/pci/pci.html#c.pci_request_region