我正在尝试将PCI配置空间数据加载到python中进行评估,但是遇到了使用c_unit32 for BAR0的问题。我设法简化了问题/脚本,以显示c_uint16的行为符合我的预期,但c_uint32失败了。 Bar0必须是c_unit32,就像在实际脚本中一样,Bar0被解码为一个单独的结构,它使用位0-13表示各种字段,然后位14:31表示较低的BAR。
在脚本中,数据从/ sys / pci / bus / devices / x / config加载,因此返回为一个十六进制字符串,这在示例中通过加载较小的字符串来模拟,仅代表少数几个字符串的字段
输入字符串:“86802010f6710000”
VendorID:0x8086
DeviceID:0x1020
Bar0:0x71f60000
输入字符串:“86802010f6710000”
VendorID:0x8086
DeviceID:0x1020
Bar0:0x71f6
正确交换VendorID和DeviceID字段。我假设“0000”正在进行字节交换并被置于f671的前面,然后f671被字节交换为71f6。然后消除前导00,创建“0x71f6”。如果我使用“f6710100”变为0x171f6,则确认。
代码:
from ctypes import *
class PCICfg(Structure):
_pack_ = 1
_fields_ = [
("VendorID", c_uint16),
("DeviceID", c_uint16),
("Bar0", c_uint32),
]
class PCIUnion(Union):
_pack_ = 1
_fields_ = [
("ConfigSpace", PCICfg),
("Bytes", c_ubyte * sizeof(PCICfg))
]
def from_str(self, input):
print("Input String: ", input)
hex_data = bytearray.fromhex(input)
for x in range(0, len(hex_data)):
self.Bytes[x] = hex_data[x]
if __name__ == '__main__':
cfg = PCIUnion()
cfg.from_str("86802010f6710100")
print("VID: %s" % hex(cfg.ConfigSpace.VendorID))
print("DID: %s" % hex(cfg.ConfigSpace.DeviceID))
print("BA0: %s" % hex(cfg.ConfigSpace.Bar0))
答案 0 :(得分:2)
您所看到的是输入的正确的小端32位结果,但如果您的输入实际上是小端16位字的十六进制表示,那么就这样对待:
from ctypes import *
from binascii import unhexlify
class PCICfg(Structure):
_pack_ = 1
_fields_ = [("VendorID", c_uint16),
("DeviceID", c_uint16),
("Bar0Hi", c_uint16),
("Bar0Lo", c_uint16)]
class PCIUnion(Union):
_pack_ = 1
_fields_ = [("ConfigSpace", PCICfg),
("Bytes", c_ubyte * sizeof(PCICfg))]
def from_str(self, inp):
print("Input String: ", inp)
self.Bytes[:] = unhexlify(inp)
if __name__ == '__main__':
cfg = PCIUnion()
cfg.from_str("86802010f6710100")
print("VID: {:#04x}".format(cfg.ConfigSpace.VendorID))
print("DID: {:#04x}".format(cfg.ConfigSpace.DeviceID))
print("BA0: {:#04x}{:04x}".format(cfg.ConfigSpace.Bar0Hi,cfg.ConfigSpace.Bar0Lo))
Input String: 86802010f6710100 VID: 0x8086 DID: 0x1020 BA0: 0x71f60001