telescan2rw1c-or-rw1
This commit is contained in:
commit
9fea2cea68
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
tlscan2pcileech_coe.py
|
||||
将 TLScan 的 .tlscan 文件转换成 PCILeech 所需的 COE 格式
|
||||
用法:
|
||||
python tlscan2pcileech_coe.py input.tlscan
|
||||
结果:
|
||||
同目录下生成 input_rw1.coe 和 input_rw1c.coe
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
# ---------- 参数 ----------
|
||||
if len(sys.argv) < 2:
|
||||
print("用法: python tlscan2pcileech_coe.py <xxx.tlscan>")
|
||||
sys.exit(1)
|
||||
|
||||
src = sys.argv[1]
|
||||
base, _ = os.path.splitext(src)
|
||||
dst_rw1 = base + "_rw1.coe"
|
||||
dst_rw1c = base + "_rw1c.coe"
|
||||
|
||||
# ---------- 读取 TLScan ----------
|
||||
try:
|
||||
bs_hex = ET.parse(src).find('.//bytes').text
|
||||
except Exception as e:
|
||||
sys.exit(f"解析 TLScan 文件失败: {e}")
|
||||
|
||||
bs_hex = ''.join(bs_hex.split())
|
||||
if len(bs_hex) != 8192: # 4096 字节 => 8192 字符
|
||||
sys.exit(f"期望 8192 个十六进制字符,实际 {len(bs_hex)}")
|
||||
|
||||
# ---------- 生成掩码 ----------
|
||||
# 4096 字节 => 1024 个 dword
|
||||
words_rw1 = [0] * 1024
|
||||
words_rw1c = [0] * 1024
|
||||
|
||||
for i in range(4096):
|
||||
val = int(bs_hex[i*2:i*2+2], 16)
|
||||
# 简易规则:0x01 视为 RW1C/RW1CS
|
||||
if val != 0x00:
|
||||
words_rw1[i//4] |= 1 << ((i % 4) * 8)
|
||||
if val == 0x01:
|
||||
words_rw1c[i//4] |= 1 << ((i % 4) * 8)
|
||||
|
||||
# ---------- 写 COE ----------
|
||||
def write_coe(path, words):
|
||||
with open(path, 'w') as f:
|
||||
f.write(f'; Converted to COE from "{src}" on {datetime.datetime.now()}\n')
|
||||
f.write('memory_initialization_radix=16;\nmemory_initialization_vector=\n')
|
||||
|
||||
for blk in range(16):
|
||||
offset = blk * 256
|
||||
f.write(f'; {offset:04x}\n')
|
||||
for line in range(16):
|
||||
idx = blk * 64 + line * 4
|
||||
line_words = [words[idx + j] for j in range(4)]
|
||||
f.write(','.join(f'{w:08x}' for w in line_words) + ',\n')
|
||||
|
||||
# 去掉最后一个逗号
|
||||
f.seek(f.tell() - 2, os.SEEK_SET) # 回退 2 字节(,\n)
|
||||
f.truncate()
|
||||
f.write('\n;\n')
|
||||
|
||||
write_coe(dst_rw1, words_rw1)
|
||||
write_coe(dst_rw1c, words_rw1c)
|
||||
|
||||
print(f'已生成:\n {dst_rw1}\n {dst_rw1c}')
|
|
@ -0,0 +1,310 @@
|
|||
import re
|
||||
|
||||
write_protected_bits_PCIE = (
|
||||
"00000f00", # 1
|
||||
"00000010", # 2
|
||||
"ff7f0f00", # 3
|
||||
"00000000", # 4
|
||||
"cb0d00c0", # 5
|
||||
"00000000", # 6
|
||||
"0000ffff", # 7
|
||||
"00000000", # 8
|
||||
"00000000", # 9
|
||||
"00000000", # 10
|
||||
"ff7f0000", # 11
|
||||
"00000000", # 12
|
||||
"bfff2000", # 13
|
||||
)
|
||||
|
||||
write_protected_bits_PM = (
|
||||
"00000000", # 1
|
||||
"00000000", # 2
|
||||
)
|
||||
|
||||
write_protected_bits_MSI = (
|
||||
"0000f104", # 1
|
||||
"03000000", # 2
|
||||
"00000000", # 3
|
||||
"00000000", # 4
|
||||
"00000000", # 5
|
||||
"00000000", # 6
|
||||
"00000000", # 7
|
||||
"ffff0000", # 8
|
||||
)
|
||||
|
||||
write_protected_bits_MSIX = (
|
||||
"000000c0", # 1
|
||||
"00000000", # 2
|
||||
"00000000", # 3
|
||||
)
|
||||
|
||||
write_protected_bits_VPD = ("00000000",)
|
||||
|
||||
write_protected_bits_VSC = (
|
||||
"000000ff", # 1
|
||||
"ffffffff", # 2
|
||||
"00000000", # 3
|
||||
)
|
||||
|
||||
write_protected_bits_PTH = ("00000000",)
|
||||
|
||||
write_protected_bits_VSEC = (
|
||||
"00000000", # 1
|
||||
"00000000", # 2
|
||||
"ffffffff", # 3
|
||||
"ffffffff", # 4
|
||||
)
|
||||
|
||||
write_protected_bits_AER = (
|
||||
"00000000", # 1
|
||||
"31f0ff07", # 2
|
||||
"31f0ff07", # 3
|
||||
"31f0ff07", # 4
|
||||
"c1f10000", # 5
|
||||
"c1f10000", # 6
|
||||
"40050000", # 7
|
||||
"00000000", # 8
|
||||
"00000000", # 9
|
||||
"00000000", # 10
|
||||
"00000000", # 11
|
||||
)
|
||||
|
||||
write_protected_bits_DSN = (
|
||||
"00000000", # 1
|
||||
"00000000", # 2
|
||||
"00000000", # 3
|
||||
)
|
||||
|
||||
write_protected_bits_LTR = (
|
||||
"00000000", # 1
|
||||
"00000000", # 2
|
||||
)
|
||||
|
||||
write_protected_bits_L1PM = (
|
||||
"00000000", # 1
|
||||
"00000000", # 2
|
||||
"3f00ffe3", # 3
|
||||
"fb000000", # 4
|
||||
)
|
||||
|
||||
write_protected_bits_PTM = (
|
||||
"00000000", # 1
|
||||
"00000000", # 2
|
||||
"00000000", # 3
|
||||
"03ff0000", # 4
|
||||
)
|
||||
|
||||
CAPABILITY_NAMES = {
|
||||
0x01: "power management",
|
||||
0x02: "AGP",
|
||||
0x03: "VPD",
|
||||
0x04: "slot identification",
|
||||
0x05: "MSI",
|
||||
0x06: "compact PCI hot swap",
|
||||
0x07: "PCI-X",
|
||||
0x08: "hyper transport",
|
||||
0x09: "vendor specific",
|
||||
0x0A: "debug port",
|
||||
0x0B: "compact PCI central resource control",
|
||||
0x0C: "PCI hot plug",
|
||||
0x0D: "PCI bridge subsystem vendor ID",
|
||||
0x0E: "AGP 8x",
|
||||
0x0F: "secure device",
|
||||
0x10: "PCI express",
|
||||
0x11: "MSI-X",
|
||||
0x12: "SATA data/index configuration",
|
||||
0x13: "advanced features",
|
||||
0x14: "enhanced allocation",
|
||||
0x15: "flattening portal bridge",
|
||||
}
|
||||
|
||||
EXTENDED_CAPABILITY_NAMES = {
|
||||
0x0001: "advanced error reporting",
|
||||
0x0002: "virtual channel",
|
||||
0x0003: "device serial number",
|
||||
0x0004: "power budgeting",
|
||||
0x0005: "root complex link declaration",
|
||||
0x0006: "root complex internal link control",
|
||||
0x0007: "root complex event collector endpoint association",
|
||||
0x0008: "multi-function virtual channel",
|
||||
0x0009: "virtual channel",
|
||||
0x000A: "root complex register block",
|
||||
0x000B: "vendor specific",
|
||||
0x000C: "configuration access correlation",
|
||||
0x000D: "access control services",
|
||||
0x000E: "alternative routing-ID interpretation",
|
||||
0x000F: "address translation services",
|
||||
0x0010: "single root IO virtualization",
|
||||
0x0011: "multi-root IO virtualization",
|
||||
0x0012: "multicast",
|
||||
0x0013: "page request interface",
|
||||
0x0014: "AMD reserved",
|
||||
0x0015: "resizable BAR",
|
||||
0x0016: "dynamic power allocation",
|
||||
0x0017: "TPH requester",
|
||||
0x0018: "latency tolerance reporting",
|
||||
0x0019: "secondary PCI express",
|
||||
0x001A: "protocol multiplexing",
|
||||
0x001B: "process address space ID",
|
||||
0x001C: "LN requester",
|
||||
0x001D: "downstream port containment",
|
||||
0x001E: "L1 PM substates",
|
||||
0x001F: "precision time measurement",
|
||||
0x0020: "M-PCIe",
|
||||
0x0021: "FRS queueing",
|
||||
0x0022: "Readyness time reporting",
|
||||
0x0023: "designated vendor specific",
|
||||
0x0024: "VF resizable BAR",
|
||||
0x0025: "data link feature",
|
||||
0x0026: "physical layer 16.0 GT/s",
|
||||
0x0027: "receiver lane margining",
|
||||
0x0028: "hierarchy ID",
|
||||
0x0029: "native PCIe enclosure management",
|
||||
0x002A: "physical layer 32.0 GT/s",
|
||||
0x002B: "alternate protocol",
|
||||
0x002C: "system firmware intermediary",
|
||||
}
|
||||
|
||||
fixed_section = [
|
||||
"00000000",
|
||||
"470500f9",
|
||||
"00000000",
|
||||
"ffff0040",
|
||||
"f0ffffff",
|
||||
"ffffffff",
|
||||
"f0ffffff",
|
||||
"ffffffff",
|
||||
"f0ffffff",
|
||||
"f0ffffff",
|
||||
"00000000",
|
||||
"00000000",
|
||||
"01f8ffff",
|
||||
"00000000",
|
||||
"00000000",
|
||||
"ff000000",
|
||||
]
|
||||
|
||||
writemask_dict = {
|
||||
"0x10": write_protected_bits_PCIE,
|
||||
"0x03": write_protected_bits_VPD,
|
||||
"0x01": write_protected_bits_PM,
|
||||
"0x05": write_protected_bits_MSI,
|
||||
"0x11": write_protected_bits_MSIX,
|
||||
"0x09": write_protected_bits_VSC,
|
||||
"0x00A": write_protected_bits_VSEC,
|
||||
"0x0001": write_protected_bits_AER,
|
||||
"0x0003": write_protected_bits_DSN,
|
||||
"0x0018": write_protected_bits_LTR,
|
||||
"0x001E": write_protected_bits_L1PM,
|
||||
"0x000B": write_protected_bits_PTM,
|
||||
"0x0017": write_protected_bits_PTH,
|
||||
}
|
||||
|
||||
|
||||
def read_cfg_space(file_path):
|
||||
# 初始化一个空字典来存储dword映射
|
||||
dword_map = {}
|
||||
# 打开指定路径的文件并读取内容
|
||||
with open(file_path, "r") as file:
|
||||
content = file.read()
|
||||
# 使用正则表达式查找所有8位的十六进制数
|
||||
dwords = re.findall(r"[0-9a-fA-F]{8}", content)
|
||||
# 遍历找到的dword并存储到字典中,最多存储1024个
|
||||
for index, dword in enumerate(dwords):
|
||||
if index < 1024:
|
||||
dword_map[index] = int(dword, 16)
|
||||
# 返回dword映射字典
|
||||
return dword_map
|
||||
|
||||
|
||||
def locate_caps(dword_map):
|
||||
# 初始化一个空字典来存储能力
|
||||
capabilities = {}
|
||||
|
||||
# 获取能力列表的起始位置
|
||||
start = dword_map[0x34 // 4] >> 24
|
||||
cap_location = start
|
||||
|
||||
# 遍历能力列表,直到cap_location为0
|
||||
while cap_location != 0:
|
||||
cap_dword = dword_map[cap_location // 4]
|
||||
cap_id = (cap_dword >> 24) & 0xFF
|
||||
next_cap = (cap_dword >> 16) & 0xFF
|
||||
|
||||
# 打印找到的能力ID和偏移量
|
||||
print(
|
||||
f"Found Cap ID: 0x{cap_id:02X}, Start offset: {hex(cap_location)}, Next cap offset: {hex(next_cap)}"
|
||||
)
|
||||
capabilities[f"0x{cap_id:02X}"] = cap_location
|
||||
cap_location = next_cap
|
||||
|
||||
# 扩展能力的起始位置
|
||||
ext_cap_location = 0x100
|
||||
while ext_cap_location != 0:
|
||||
ext_cap_dword = dword_map[ext_cap_location // 4]
|
||||
|
||||
# 将大端字节序转换为小端字节序
|
||||
ext_cap_dword_le = int.from_bytes(
|
||||
ext_cap_dword.to_bytes(4, byteorder="big"), byteorder="little"
|
||||
)
|
||||
ext_cap_id = ext_cap_dword_le & 0xFFFF
|
||||
next_ext_cap = (ext_cap_dword_le >> 20) & 0xFFF
|
||||
|
||||
# 打印找到的扩展能力ID和偏移量
|
||||
print(
|
||||
f"Found Ext Cap ID: 0x{ext_cap_id:04X}, Start offset: {hex(ext_cap_location)}, Next cap offset: {hex(next_ext_cap)}"
|
||||
)
|
||||
capabilities[f"0x{ext_cap_id:04X}"] = ext_cap_location
|
||||
ext_cap_location = next_ext_cap
|
||||
|
||||
# 返回能力字典
|
||||
return capabilities
|
||||
|
||||
|
||||
def create_wrmask(dwords):
|
||||
# 创建一个与dwords长度相同的掩码列表,初始值为"ffffffff"
|
||||
return ["ffffffff" for _ in dwords]
|
||||
|
||||
|
||||
def update_writemask(wr_mask, input, start_index):
|
||||
# 计算结束索引,确保不超过掩码列表的长度
|
||||
end_index = min(start_index + len(input), len(wr_mask))
|
||||
# 更新掩码列表中的部分值
|
||||
wr_mask[start_index:end_index] = input[: end_index - start_index]
|
||||
return wr_mask
|
||||
|
||||
|
||||
def main(file_in, file_out):
|
||||
# 读取配置空间文件并转换为字典
|
||||
cfg_space = read_cfg_space(file_in)
|
||||
# 定位能力并返回能力字典
|
||||
caps = locate_caps(cfg_space)
|
||||
|
||||
# 创建初始的写掩码
|
||||
wr_mask = create_wrmask(cfg_space)
|
||||
# 更新写掩码的固定部分
|
||||
wr_mask = update_writemask(wr_mask, fixed_section, 0)
|
||||
|
||||
# 遍历能力字典并更新写掩码
|
||||
for cap_id, cap_start in caps.items():
|
||||
if cap_id not in writemask_dict:
|
||||
print(f"Skipping cap {cap_id} as no writemask defined")
|
||||
continue
|
||||
section = writemask_dict.get(cap_id)
|
||||
cap_start_index = cap_start // 4
|
||||
wr_mask = update_writemask(wr_mask, section, cap_start_index)
|
||||
|
||||
# 写入更新后的写掩码到输出文件
|
||||
new_line_index = 0
|
||||
with open(file_out, "w") as f:
|
||||
f.write(f"; {format(new_line_index, 'X').zfill(2) + '00'}\n")
|
||||
for i in range(0, len(wr_mask), 4):
|
||||
f.write(",".join(wr_mask[i : i + 4]) + ",\n")
|
||||
if i >= 64 and (i) % 64 == 0:
|
||||
f.write("\n")
|
||||
new_line_index += 1
|
||||
f.write(f"; {format(new_line_index, 'X').zfill(2) + '00'}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main("./pcileech_cfgspace.coe", "pcileech_cfgspace_writemask.coe")
|
Loading…
Reference in New Issue