文章目录
概要
本文将介绍VPD信息,以及UEFI中的读取方式。
提示:Vital Product Data (VPD) is the information that uniquely defines items such as the hardware, software, and microcode elements of a system. The VPD provides the system with information on various FRUs (Field Replaceable Unit) including Part Number, Serial Number, and other detailed information. VPD also provides a mechanism for storing information such as performance and failure data on the device being monitored. The objective, from a system point of view, is to collect this information by reading it from the hardware, software, and microcode components. Support of VPD within add-in cards is optional depending on the manufacturer. Though support of VPD is optional, add-in card manufacturers are encouraged to provide VPD due to its inherent benefits for the add-in card, system manufacturers, and for Plug and Play.
Spec:
《NCB-PCI_Express_Base_6.0.pdf》。
怎么读取PCIe设备的VPD信息?
数据结构定义介绍
都在spec里面。
VPD的主要格式(Ascii码值):
关键字+长度+数据。关键字是2Byte,比如“PN”,0B是’P’,1B是’N’,2B是Length,随后就是数据块了(Byte 3 到 N + 2)。那么“EC”亦是如此:N + 3 B就是 ‘E’…。
感觉上图是不是少了Byte 2 ?
完整举例:
Offset | Item Value |
---|---|
0 | Large Resource Type ID String Tag (02h) 82h “Product Name” |
1 | Length 0021h |
3 | Data “ABCD Super-Fast Widget Controller” |
36 | Large Resource Type VPD-R Tag (10h) 90h |
37 | Length 0059h |
39 | VPD Keyword “PN” |
41 | Length 08h |
42 | Data “6181682A” |
50 | VPD Keyword “EC” |
52 | Length 0Ah |
53 | Data “4950262536” |
63 | VPD Keyword “SN” |
65 | Length 08h |
66 | Data “00000194” |
74 | VPD Keyword “MN” |
76 | Length 04h |
77 | Data “1037” |
81 | VPD Keyword “RV” |
83 | Length 2Ch |
84 | Data Checksum |
85 | Data Reserved (00h) |
128 | Large Resource Type VPD-W Tag (11h) 91h |
129 | Length 007Ch |
131 | VPD Keyword “V1” |
133 | Length 05h |
134 | Data “65A01” |
139 | VPD Keyword “Y1” |
141 | Length 0Dh |
142 | Data “Error Code 26” |
155 | VPD Keyword “RW” |
157 | Length 61h |
158 | Data Reserved (00h) |
255 | Small Resource Type End Tag (0Fh) 78h |
Vital Product Data Capability (VPD Capability)
如何获取VPD Address Register?
VPD Capability ID 是固定的值:0x03
EDK 2中定义如下:
//
// PCI Capability List IDs and records
//
#define EFI_PCI_CAPABILITY_ID_PMI 0x01
#define EFI_PCI_CAPABILITY_ID_AGP 0x02
**#define EFI_PCI_CAPABILITY_ID_VPD 0x03**
#define EFI_PCI_CAPABILITY_ID_SLOTID 0x04
#define EFI_PCI_CAPABILITY_ID_MSI 0x05
#define EFI_PCI_CAPABILITY_ID_HOTPLUG 0x06
#define EFI_PCI_CAPABILITY_ID_PCIX 0x07
我们现在知道了它在0x03处,但是在哪里的0x03呢?
因此需要继续探索。
没错的就是在PCI配置空间中的Capability Pointer(0x34)。
配置空间详见:【UEFI】PCIE学习笔记
UINT8 CapIdPtr;。
因此我们需要读取Capability Pointer == CapIdPtr 首地址,然后依次 CapIdPtr + 1 延申读取,直到CapId == 0x03。
EDK2 中有很多例子可以找到类似的读取CapId的实例,如下,将PCI_CAPABILITY_ID_DEBUG_PORT 替换成 EFI_PCI_CAPABILITY_ID_VPD即可,当然最好要判断一下这个设备有没有VPD。
如:
//
// Get Pointer To Capability List
//
CapabilityPtr = PciRead8 (PCI_CAPBILITY_POINTER_OFFSET);
//
// Find Capability ID 0xA, Which Is For Debug Port
//
while (CapabilityPtr != 0) {
CapabilityId = PciRead8 (CapabilityPtr);
if (CapabilityId == PCI_CAPABILITY_ID_DEBUG_PORT) {
break;
}
CapabilityPtr = PciRead8 (CapabilityPtr + 1);
}
//
// No Debug Port Capability Found
//
if (CapabilityPtr == 0) {
return RETURN_UNSUPPORTED;
}
获取到CapIdPtr后如何操作?
根据Spec
;Pci.read();两个函数。
由 Vital Product Data Capability (VPD Capability)下的图可知
VPD Address Register 在offset 0x02处,占两个字节。
VPD Data Register 在offset 0x04处,占四个字节。
再参考博客:怎么读取PCIe设备的VPD信息?
首次写操作:
UINT16 Value = 0;
UINT8 DataValue = 0;
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, CapIdPtr + 0x02, 1, &Value);//这里 + 0x02,写两个字节(DWORD),然后低 2 bit 需要为0。因此 0000,1000...就是文献中说的在写下一个地址时要加4。
//写完后,再读取一遍看看F bit的值是否为1.
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, CapIdPtr + 0x02, 1, &Value);
//然后就是读取 0x04位置的Data Address 中的内容。
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, CapIdPtr + 0x4, 1, &DataValue + );
//第一次读取数据成功,接下来就是下一个了,也就是 Value + 4;依次类推....
读取完毕后,即可根据Format 来收集 PN/SN等内容了。
技术名词解释
例如:
- Part Number :PN
- Engineering Change :EC
- Serial Number :SN
- Manufacture ID :MN
- …
- see spec part:Read-Only Fields
技术细节
提示:UEFI,PCIE,Address,Capability Pointer...
小结
提示:一串数据集,存储着该PCIE设备的基本信息,如PN,SN,EC,RV等等,一次读取出来,然后根据格式分析出来即可