90 lines
2.7 KiB
Python
90 lines
2.7 KiB
Python
import subprocess
|
|
from enum import Enum
|
|
|
|
class ASPM(Enum):
|
|
ASPM_DISABLED = 0x40
|
|
ASPM_L0s_ONLY = 0x41
|
|
ASPM_L1_ONLY = 0x42
|
|
ASPM_L1_AND_L0s = 0x43
|
|
|
|
root_complex = "00:1c.4"
|
|
endpoint = "05:00.0"
|
|
value_to_set = ASPM.ASPM_L1_AND_L0s
|
|
|
|
def get_device_name(addr):
|
|
p = subprocess.Popen([
|
|
"lspci",
|
|
"-s",
|
|
addr,
|
|
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
return p.communicate()[0].splitlines()[0].decode()
|
|
|
|
def read_all_bytes(device):
|
|
all_bytes = bytearray()
|
|
device_name = get_device_name(device)
|
|
p = subprocess.Popen([
|
|
"lspci",
|
|
"-s",
|
|
device,
|
|
"-xxx"
|
|
], stdout= subprocess.PIPE, stderr=subprocess.PIPE)
|
|
ret = p.communicate()
|
|
ret = ret[0].decode()
|
|
for line in ret.splitlines():
|
|
if not device_name in line and ": " in line:
|
|
all_bytes.extend(bytearray.fromhex(line.split(": ")[1]))
|
|
if len(all_bytes) < 256:
|
|
print(f"Expected 256 bytes, only got {len(all_bytes)} bytes!")
|
|
print(f"Are you running this as root?")
|
|
exit()
|
|
return all_bytes
|
|
|
|
def find_byte_to_patch(bytes, pos):
|
|
print(f"{hex(pos)} points to {hex(bytes[pos])}")
|
|
pos = bytes[pos]
|
|
print(f"Value at {hex(pos)} is {hex(bytes[pos])}")
|
|
if bytes[pos] != 0x10:
|
|
print("Value is not 0x10!")
|
|
print("Reading the next byte...")
|
|
pos += 0x1
|
|
return find_byte_to_patch(bytes, pos)
|
|
else:
|
|
print(f"Found the byte at: {hex(pos)}")
|
|
print("Adding 0x10 to the register...")
|
|
pos += 0x10
|
|
print(f"Final register reads: {hex(bytes[pos])}")
|
|
return pos
|
|
|
|
def patch_byte(device, position, value):
|
|
subprocess.Popen([
|
|
"setpci",
|
|
"-s",
|
|
device,
|
|
f"{hex(position)}.B={hex(value)}"
|
|
]).communicate()
|
|
|
|
def patch_device(addr):
|
|
print(get_device_name(addr))
|
|
endpoint_bytes = read_all_bytes(addr)
|
|
byte_position_to_patch = find_byte_to_patch(endpoint_bytes, 0x34)
|
|
|
|
print(f"Byte to patch: {hex(byte_position_to_patch)}")
|
|
print(f"Byte is set to {hex(endpoint_bytes[byte_position_to_patch])}")
|
|
print(f"-> {ASPM(int(endpoint_bytes[byte_position_to_patch])).name}")
|
|
if int(endpoint_bytes[byte_position_to_patch]) != value_to_set.value:
|
|
print("Value doesn't match the one we want, setting it!")
|
|
patch_byte(addr, byte_position_to_patch, value_to_set.value)
|
|
new_bytes = read_all_bytes(addr)
|
|
print(f"Byte is set to {hex(new_bytes[byte_position_to_patch])}")
|
|
print(f"-> {ASPM(int(new_bytes[byte_position_to_patch])).name}")
|
|
else:
|
|
print("Nothing to patch!")
|
|
|
|
def main():
|
|
patch_device(root_complex)
|
|
patch_device(endpoint)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|