Pcileech-tool/writemask.py

311 lines
8.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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