telescan2rw1c-or-rw1

This commit is contained in:
3A1 2025-08-10 16:58:35 +08:00
commit 9fea2cea68
2 changed files with 381 additions and 0 deletions

71
tlscan2pcileech_rw1c.py Normal file
View File

@ -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}')

310
writemask.py Normal file
View File

@ -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")