【UEFI】PCIE学习笔记

本文是本人学习记录,不保证准确,如有错误请指出。如果侵犯请联系删除。
PCIE一共支持256条bus(8个bit),32个device(5个bit),8个function(3个bit),
假设负载全满的时候,内存分配的内存空间则是:
4K * 256 * 32 * 8 = 256 * 1024K = 256 * 1M = 256M bytes。

pcie介绍可以参考:UEFI开发历程3—PCIe总线设备的探索
《PCI Local Bus Specification 2.2.pdf》

配置空间

配置空间分三类。通用配置空间在000h-03Fh个byte大小。

一个是通用配置空间,一个是type 0配置空间,一个是type 1配置空间。我的理解是type 0 是Device,type 1是Bridge。
详情可以参考:
【精讲】PCIe基础篇——Type0 & Type1配置头及配置请求过程
PCI/PCIe那些事(3)-- Configuration Space Type 0/1
Class Code分为三个部分:ProgInterface(8-15),SubClassCode(16-23细分的类),BaseClassCode(24-31大类)对于ClassCode具体请阅读文章:PCIE的Class Code表
在这里插入图片描述
Picture 1 Device 配置空间
在这里插入图片描述
Picture 2 Bridge 配置空间
在这里插入图片描述

Picture 3 Type事务处理区分 《PCI-to-PCI Bridge Architecture.pdf》

Vendor ID

每个厂商都有一个对应的Vendor ID也是用于判断是哪个厂商生产的设备的依据
devicehunt 该网站可以查询对应的厂商ID。
在UEFI中读取配置空间的值后,进行匹配然后Show 其厂商。
Vendor ID为0xFFFF代表设备不存在,否则存在。
读取vendor id:
Width 表示要从哪个offset开始读多少个字节:
比如:读取vendorid时,从offset 0x00(Address)开始,读取16个bit。
Count 表示要读多少个32 bit的offset。比如要读0x00-0x0F,那Count 就是4(个人理解)。在这里插入图片描述
在读取设备信息之前都需要去LocateProtocolBuffer、HandleProtocol等,也就是打开Protocol。
Protocol的资料可参考:
UEFI中的Protocol浅谈
BIOS知识枝桠—— Protocol
UEFI原理与编程(八):UEFI中的Protocol基础结构及其在内核中的表示
在这里插入图片描述

在UEFI中如何获取的呢?

/*
    System inventory PCI device Id.
*/
typedef union _SYS_PCI_DEV_ID {
   UINT32                   DEV_VEN_ID;
   struct {
       // Manufacturer.
       UINT16               VendorId;
       UINT16               DeviceId;   //< Device ID.
   };
} SYS_PCI_DEV_ID;

Device ID

Device ID和Vendor ID组合可以区分是哪个厂商的哪个设备

Class Code是哪种设备的分类寄存器

Network、Storage、USB、Bridge、Serial、Display…

Revision ID是修订版本号

暂时不知道有什么用

遍历S BDF号

通过Socket Id 和Stack Id 来遍历Segment number和Bus number。每个Socket有几个Stack id 每个Stack 有8组Port: A B C D E F G H.
Bus遍历

偏移地址


///
/// Rom Base Address in Bridge, defined in PCI-to-PCI Bridge Architecture Specification,
///
#define PCI_BRIDGE_ROMBAR  0x38
#define PCI_MAX_BAR            0x0006
#define PCI_MAX_CONFIG_OFFSET  0x0100

#define PCI_VENDOR_ID_OFFSET            0x00
#define PCI_DEVICE_ID_OFFSET            0x02
#define PCI_COMMAND_OFFSET              0x04
#define PCI_PRIMARY_STATUS_OFFSET       0x06
#define PCI_REVISION_ID_OFFSET          0x08
#define PCI_CLASSCODE_OFFSET            0x09
#define PCI_CACHELINE_SIZE_OFFSET       0x0C
#define PCI_LATENCY_TIMER_OFFSET        0x0D
#define PCI_HEADER_TYPE_OFFSET          0x0E
#define PCI_BIST_OFFSET                 0x0F
#define PCI_BASE_ADDRESSREG_OFFSET      0x10
#define PCI_CARDBUS_CIS_OFFSET          0x28
#define PCI_SVID_OFFSET                 0x2C             ///< SubSystem Vendor id
#define PCI_SUBSYSTEM_VENDOR_ID_OFFSET  0x2C
#define PCI_SID_OFFSET                  0x2E             ///< SubSystem ID
#define PCI_SUBSYSTEM_ID_OFFSET         0x2E
#define PCI_EXPANSION_ROM_BASE          0x30
#define PCI_CAPBILITY_POINTER_OFFSET    0x34
#define PCI_INT_LINE_OFFSET             0x3C             ///< Interrupt Line Register
#define PCI_INT_PIN_OFFSET              0x3D             ///< Interrupt Pin Register
#define PCI_MAXGNT_OFFSET               0x3E             ///< Max Grant Register
#define PCI_MAXLAT_OFFSET               0x3F             ///< Max Latency Register

//
// defined in PCI-to-PCI Bridge Architecture Specification
//
#define PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET      0x18
#define PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET    0x19
#define PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET  0x1a
#define PCI_BRIDGE_SECONDARY_LATENCY_TIMER_OFFSET   0x1b
#define PCI_BRIDGE_STATUS_REGISTER_OFFSET           0x1E
#define PCI_BRIDGE_CONTROL_REGISTER_OFFSET          0x3E

//Here comes some Common PCI Header Offset Definitions.
#define PCI_VID             0x0000        // Vendor ID Register
#define PCI_DID             0x0002        // Device ID Register
#define PCI_CMD             0x0004        // PCI Command Register
#define PCI_STS             0x0006        // PCI Status Register
#define PCI_RID             0x0008        // Revision ID Register
#define PCI_IFT             0x0009        // Interface Type
#define PCI_SCC             0x000A        // Sub Class Code Register
#define PCI_BCC             0x000B        // Base Class Code Register
#define PCI_CLS             0x000C        // Cache Line Size
#define PCI_PMLT            0x000D        // Primary Master Latency Timer
#define PCI_HDR             0x000E        // Header Type Register
#define PCI_BIST            0x000F        // Built in Self Test Register
#define PCI_BAR0            0x0010        // Base Address Register 0
#define PCI_BAR1            0x0014        // Base Address Register 1
#define PCI_BAR2            0x0018        // Base Address Register 2
#define PCI_PBUS            0x0018        // Primary Bus Number Register
#define PCI_SBUS            0x0019        // Secondary Bus Number Register
#define PCI_SUBUS           0x001A        // Subordinate Bus Number Register
#define PCI_SMLT            0x001B        // Secondary Master Latency Timer
#define PCI_BAR3            0x001C        // Base Address Register 3
#define PCI_IOBASE          0x001C        // I/O base Register
#define PCI_IOLIMIT         0x001D        // I/O Limit Register
#define PCI_SECSTATUS       0x001E        // Secondary Status Register
#define PCI_BAR4            0x0020        // Base Address Register 4
#define PCI_MEMBASE         0x0020        // Memory Base Register
#define PCI_MEMLIMIT        0x0022        // Memory Limit Register
#define PCI_BAR5            0x0024        // Base Address Register 5
#define PCI_PRE_MEMBASE     0x0024        // Prefetchable memory Base register
#define PCI_PRE_MEMLIMIT    0x0026        // Prefetchable memory Limit register
#define PCI_PRE_MEMBASE_U   0x0028        // Prefetchable memory base upper 32 bits
#define PCI_PRE_MEMLIMIT_U  0x002C        // Prefetchable memory limit upper 32 bits
#define PCI_SVID            0x002C        // Subsystem Vendor ID
#define PCI_SID             0x002E        // Subsystem ID
#define PCI_IOBASE_U        0x0030        // I/O base Upper Register
#define PCI_IOLIMIT_U       0x0032        // I/O Limit Upper Register
#define PCI_CAPP            0x0034        // Capabilities Pointer
#define PCI_EROM            0x0038        // Expansion ROM Base Address
#define PCI_INTLINE         0x003C        // Interrupt Line Register
#define PCI_INTPIN          0x003D        // Interrupt Pin Register
#define PCI_MAXGNT          0x003E        // Max Grant Register
#define PCI_BRIDGE_CNTL     0x003E        // Bridge Control Register
#define PCI_MAXLAT          0x003F        // Max Latency Register

Device Path

UEFI Device Path (1): 重新认识Device Path
UEFI Device Path (2): Device Path的产生

句柄和Protocol个人理解(Handle)

UEFI Driver_Writer_Guide_V1.0.1_120308.pdf

个人理解逻辑图

Handle和Protocol个人理解图
亦可参考:如何理解UEFI中handle和protocol的概念 虽然我看不太懂。Agent Handle暂时不理解用处。

ControllerHandle理解

ControllerHandle表示打开某个协议的控制器句柄,不同的协议在同一个设备上打开时,其对应的ControllerHandle是相同的。例如,对于一个PCIe设备而言,如果驱动程序同时打开了gEfiPciIoProtocolGuid和gEfiDevicePathProtocolGuid协议,则这两个协议共享同一个ControllerHandle,即该PCIe设备的句柄。

在一些情况下,系统会为一个设备创建多个实例化的句柄,每个句柄可以用来访问该设备的不同功能或特定配置。此时,每个句柄也会有自己的ControllerHandle,但它们都指向同一个设备的结构体对象。

需要注意的是,对于不同的设备,其所对应的ControllerHandle是不同的,因为每个设备都有唯一的句柄来标识。因此,在使用EFI_OPEN_PROTOCOL_INFORMATION_ENTRY数据结构来描述打开的协议句柄和协议之间的关系时,需要注意区分不同设备的情况。

控制器句柄代表存在于平台中的控制台或引导设备。如果该句柄代表物理设备,则必须支持Device Path协议。如果该句柄代表虚拟设备,则不得支持Device Path协议。此外,设备句柄必须支持一个或多个额外的I/O协议,用于抽象化访问该设备。在UEFI规范中定义了一系列I/O协议,包括:

• Console Services: These have been replaced or supplemented by HII functionality. These protocols include the Simple Input Protocol, Simple Text Output Protocol, Simple Pointer Protocol,Serial I/O Protocol and Debug Port Protocol.
• Bootable Image Services: Block I/O Protocol, Disk I/O Protocol, Simple File System Protocol and Load File Protocol.
• Network Services: Network Interface Identifier Protocol, Simple Network Protocol and PXE Base Code Protocol.
• PCI Services: PCI Root Bridge I/O Protocol and PCI I/O Protocol.
• USB Services: USB Host Controller Protocol and USB I/O Protocol.
• SCSI Services: Extended SCSI Pass Thru Protocol and SCSI I/O Protocol.
• Graphics Services: Graphics Output Protocol.

#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL   0x00000001
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL         0x00000002
#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL        0x00000004
#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER  0x00000008
#define EFI_OPEN_PROTOCOL_BY_DRIVER            0x00000010
#define EFI_OPEN_PROTOCOL_EXCLUSIVE            0x00000020

Attributes理解

这里是对UEFI规范中定义的几种协议打开方式的解释,并举例说明其使用场景:

EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:通过指定的句柄和协议GUID来打开协议,并返回指向该协议接口的指针。该方式通常用于获取设备提供的服务,并与之交互。例如,在一个PCI控制器驱动程序中,可以使用 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 方式来获取PCI总线协议的接口,以便访问设备的配置空间。

EFI_OPEN_PROTOCOL_GET_PROTOCOL:从指定句柄上获取指定协议的接口指针。该方式通常也用于获取设备提供的服务,与 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 类似。例如,在一个USB驱动程序中,可以使用 EFI_OPEN_PROTOCOL_GET_PROTOCOL 方式来获取USB I/O协议的接口,以便进行USB数据传输操作。

EFI_OPEN_PROTOCOL_TEST_PROTOCOL:测试指定句柄是否支持指定协议,并返回测试结果。如果指定句柄支持指定协议,则函数返回EFI_SUCCESS;否则函数返回EFI_UNSUPPORTED。该方式通常用于测试一个设备是否支持需要的协议。例如,在一个文件系统驱动程序中,可以使用 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 方式来测试指定句柄是否支持文件系统协议,以便判断设备是否可以挂载为文件系统。

EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:获取指定设备的子控制器所暴露出的协议接口。该方式通常用于枚举设备或处理设备的子组件。例如,在一个PCI总线驱动程序中,可以使用 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 方式来获取PCI设备的控制器接口,以便管理PCI设备及其资源。

EFI_OPEN_PROTOCOL_BY_DRIVER:将指定协议安装到指定句柄上,并返回指向该协议接口的指针。该方式通常用于将驱动程序所提供的服务安装到设备句柄上,以便其它应用程序或驱动程序可以使用该服务。例如,在一个网络驱动程序中,可以使用 EFI_OPEN_PROTOCOL_BY_DRIVER 方式将TCP/IP协议栈协议安装到网络设备句柄上,以便其它应用程序或驱动程序可以使用网络服务。

EFI_OPEN_PROTOCOL_EXCLUSIVE:以独占的方式打开指定句柄上的指定协议。如果其它驱动程序或应用程序已经打开了该协议,那么该函数将返回错误码EFI_ACCESS_DENIED。该方式通常用于需要独占设备的操作。例如,在一个硬盘设备驱动程序中,可以使用 EFI_OPEN_PROTOCOL_EXCLUSIVE 方式打开硬盘控制器协议,以便进行独占式的读写操作。

  • 29
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
UEFI Shell是一种全新的操作系统环境,在现代计算机上广泛使用。相较于BIOS,UEFI Shell在启动时间和性能方面都有着很大的优势。UEFI Shell有其独特的运行环境,为用户提供了一种类似于操作系统的命令行界面来控制计算机的硬件和软件。 UEFI Shell可以很好的应用于系统调试和维护工作。因为UEFI Shell能够与UEFI BIOS直接进行交互,可以读取和修改UEFI BIOS中的各种变量。这些变量包括了计算机的系统时间、启动磁盘分区信息、设备启用状态等等。所以,当系统出现问题时,可以通过UEFI Shell来获取更多的系统信息、检测硬件故障以及查找系统错误等。 同时,UEFI Shell也支持各种文件系统格式。这使得我们可以在UEFI Shell中查看和管理硬盘分区,从而进行数据备份与还原、系统安装和修复等操作。此外,UEFI Shell还支持各种基本的命令,如文件与目录操作、网络连接管理、进程控制等。这让我们可以在更高效的状态下调试和管理系统。 对于初学者来说,UEFI Shell学习并不是一件容易的事情。因为UEFI Shell的命令和语法都有一定的学习曲线,需要一定的时间和经验去掌握。但是,如果您熟练掌握了UEFI Shell的使用,不仅可以解决常见的操作问题,还可以探究计算机系统的底层运作机理。这对于系统工程师来说尤为重要。 总之,UEFI Shell作为一种新兴的操作系统环境,拥有着广泛的应用场景和巨大的优势,不管是对于初学者还是经验丰富的系统工程师来说,掌握UEFI Shell的各种技术是一个不可或缺的技能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值