Skip to content

Commit

Permalink
Merge pull request #40 from cfwen/master
Browse files Browse the repository at this point in the history
add support for undump
  • Loading branch information
sibradzic authored Mar 23, 2024
2 parents b7859f4 + 4a2a679 commit a6a93c6
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 23 deletions.
26 changes: 21 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Alternatively, one can use this tool to get PowerPlay data by:
* Extracting PowerPlay table from Video ROM image (see extract command)
* Importing "Soft PowerPlay" table from Windows registry, directly from
offline Windows/System32/config/SYSTEM file on disk, so it would work
from Linux distro that has acces to mounted Windows partition
from Linux distro that has access to mounted Windows partition
(path to SYSTEM registry file is specified with `--from-registry` option)

This tool currently supports parsing and modifying PowerPlay tables found
Expand All @@ -39,7 +39,7 @@ PowerPlay control methods, this tool does not support them.
**WARNING**: Authors of this tool are in no way responsible for any damage
that may happen to your expansive graphics card if you choose to modify
card voltages, power limits, or any other PowerPlay parameters. Always
remember that you are doing it entierly on your own risk!
remember that you are doing it entirely on your own risk!

If you have bugs to report or features to request please create an issue on:
https://github.com/sibradzic/upp
Expand All @@ -66,8 +66,9 @@ Radeon PowerPlay table data. Currently available commands are:
* **dump** - Dumps all PowerPlay data to console
* **extract** - Extracts PowerPlay data from full VBIOS ROM image
* **inject** - Injects PowerPlay data from file into VBIOS ROM image
* **get** - Retrieves current value of one or multiple PowerPlay parametter(s)
* **get** - Retrieves current value of one or multiple PowerPlay parameter(s)
* **set** - Sets value to one or multiple PowerPlay parameters
* **undump** - Sets all PowerPlay parameters to pp file or registry
* **version** - Shows UPP version

So, an usage pattern would be like this:
Expand Down Expand Up @@ -112,11 +113,11 @@ optional `-o/--output-rom parameter`. For example:

upp -p modded.pp_table inject -i original.rom -o modded.rom

**WARNING**: Modified vROM image is probalby not going to work if flashed as is
**WARNING**: Modified vROM image is probably not going to work if flashed as is
to your card, due to ROM signature checks on recent Radeon cards. Authors of
this tool are in no way responsible for any damage that may happen to your
expansive graphics card if you choose to flash the modified video ROM, you are
doing it entierly on your own risk.
doing it entirely on your own risk.

#### Getting PowerPlay table parameter value(s):

Expand Down Expand Up @@ -146,6 +147,21 @@ parameter(s). The parameter path and value must be specified in
Note the `--write` parameter, which has to be specified to actually commit
changes to the PowerPlay table file.

#### Undumps all PowerPlay parameters:

The **undump** command sets all values from previously dumped PowerPlay table parameter(s) back to pp_table or registry. It allows you to make changes in dumped text file and write back all changes at once. Basically it's a convenient way to set multiple values. For example:

# extract pp_table from vbios
upp --pp-file=vbios.pp_table extract -r vbios.rom
# dump powerplay table to text file
upp --pp-file=vbios.pp_table dump > vbios.pp_table.dump
# make changes in vbios.pp_table.dump
# undump all changes back into pp_table
upp --pp-file=vbios.pp_table undump -d vbios.pp_table.dump -w

Note the `--write` parameter, which has to be specified to actually commit
changes to the PowerPlay table file.

#### Getting upp version

upp version
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name='upp',
version='0.1.7',
version='0.1.8',
author='Samir Ibradžić',
description='Uplift Power Play',
long_description=long_description,
Expand Down
32 changes: 16 additions & 16 deletions src/upp/decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def _write_binary_file(filename, raw_data):
f.close()
except PermissionError as e:
msg = 'ERROR: {}\n' + \
'To make PowerPlay table file writtable: sudo chmod o+w {}'
'To make PowerPlay table file writable: sudo chmod o+w {}'
print(msg.format(e, filename, filename))
print(e)

Expand All @@ -78,11 +78,11 @@ def _checksum(rom_bytes):

def _rom_info(vrom_file):
"""
Displays the VROM image info and returns PowrPlay table offest and size
Displays the VROM image info and returns PowerPlay table offset and size
Returns:
pp_offset, pp_lenght (touple): pp_offset (int): pp table offset in vROM
pp_lenght (int): pp table lenght
pp_offset, pp_length (tuple): pp_offset (int): pp table offset in vROM
pp_length (int): pp table length
"""

Expand Down Expand Up @@ -192,7 +192,7 @@ def inject_pp_table(input_rom, output_rom, pp_bin_file):
return None
pp_bytes = _read_binary_file(pp_bin_file)
if len(pp_bytes) != pp_tbl_len:
msg = 'ERROR: The lenght of {} PowerPlay table must match the ' + \
msg = 'ERROR: The length of {} PowerPlay table must match the ' + \
'length of PowerPlay table in {} vROM image ({} bytes)'
print(msg.format(pp_bin_file, input_rom, pp_tbl_len))
return None
Expand All @@ -217,7 +217,7 @@ def validate_pp(header, length, rawdump):
pp_len = header.usStructureSize

if pp_len != length:
msg = 'ERROR: Header length ({}) diffes from file length ({}). ' + \
msg = 'ERROR: Header length ({}) differs from file length ({}). ' + \
'Is this a valid PowerPlay table?'
print(msg.format(pp_len, length))
return None
Expand Down Expand Up @@ -291,11 +291,11 @@ def _get_ofst_cstruct(module, name, header_bytes, debug=False):
name (string): Name of the child table used for data structure resolution
header_bytes (bytearray): A 2-byte array where 1st byte contains the nested
table revision id and 2nd byte number of entries
debug (bool): Debbuging output enabled
debug (bool): Debugging output enabled
Returns:
cs, total_len (touple): cs (class): resolved C structure
lotal_len (int): structure's data length in bytes
cs, total_len (tuple): cs (class): resolved C structure
total_len (int): structure's data length in bytes
"""

Expand Down Expand Up @@ -418,7 +418,7 @@ class FixedEntriesTypeArray(ctypes.LittleEndianStructure):
entry_len = cs_entries.size
total_len = cs_entries.offset + cs_entries.size * entry_count

# Vega10 and older C strutures all have number of entries set to 1, we
# Vega10 and older C structures all have number of entries set to 1, we
# override it with real value that we get from an actual pp_table data
entry_name, entry_type = cs._fields_[-1]

Expand Down Expand Up @@ -454,21 +454,21 @@ def build_data_tree(data, raw=None, decoded=None, parent_name='/',
Parameters:
data (ctypes instance): Contains binary data that can be referenced by C
veriable names that has been decoded using ctypes
variable names that has been decoded using ctypes
from_buffer() call
raw (bytearray): Raw PowerPlay data buffer in bytearray format
decoded (OrderedDictdict): A special tree-like structure of nested ordered
dictionaries that describes binary data
structures containing PowerPlay parameteres,
structures containing PowerPlay parameters,
used as parameter due to recursive nature of
this function
parent_name (string): Reference to a parent of data-structure currently
being processed, used for recursion
meta (dict): Containing 'size' and 'offset' keys, used for calculating
offsets & sizes for PowerPlay sub-structure tables
rawdump (bool): Shows PowerPlay data in a table format showing offsets
and hex values on a console instead of returing data dict
debug (bool): Debbuging output enabled
and hex values on a console instead of returning data dict
debug (bool): Debugging output enabled
Returns:
decoded (dict): A resulting PowerPlay data-structure in a dictionary form
Expand Down Expand Up @@ -536,7 +536,7 @@ def build_data_tree(data, raw=None, decoded=None, parent_name='/',
else:
d_offset = meta['ofs'] + d_meta.offset

# Base types parsed as is, excetption are floats & offseted tables
# Base types parsed as is, exception are floats & offset tables
if ctyp_cls in primitives:
d_symbol = ctyp_cls._type_
d_size = d_meta.size
Expand Down Expand Up @@ -585,7 +585,7 @@ def build_data_tree(data, raw=None, decoded=None, parent_name='/',
# Other types are recursed back into this very same function
else:
if debug:
msg = 'DEBUG: Recursive dive from {} stuct into "{}"'
msg = 'DEBUG: Recursive dive from {} struct into "{}"'
print(msg.format(parent_name, name))
r_meta = {'ofs': d_offset, 'size': d_size}
decoded[name] = odict()
Expand Down
53 changes: 52 additions & 1 deletion src/upp/upp.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,35 @@ def _write_pp_to_reg_file(filename, data, debug=False):
print('Can not write to {}'.format(filename))
return 0

def _load_variable_set(dump_filename):
variable_set = []
with open(dump_filename, 'r') as file:
keys = []
indent = 0
prev_indent = 0
lines = file.readlines()
for line in lines:
prev_indent = indent
indent = (len(line) - len(line.lstrip()))//2
if line.strip() == '':
continue
if indent == 0:
keys.clear()
elif indent <= prev_indent:
keys = keys[0:indent]

key, value = line.split(':')
key = key.strip()
value = value.strip()
if key.find('Unused') == 0 or value.find('UNUSED') == 0:
continue
if len(keys) > 0 and key.find(keys[-1]) == 0:
key = key.split(' ')[1]
keys.append(key)
if value != '':
variable_set.append('{}={}'.format('/'.join(keys), value))
return variable_set


@click.group(context_settings=CONTEXT_SETTINGS)
@click.option('-p', '--pp-file', help='Input/output PP table binary file.',
Expand Down Expand Up @@ -208,6 +237,27 @@ def dump(ctx, raw):
decode.dump_pp_table(pp_file, rawdump=raw, debug=debug)
return 0

@click.command(short_help='Undumps all PowerPlay parameters to pp file or registry.')
@click.option('-d', '--dump-filename', help='File path of dumped powerplay parameters.')
@click.option('-t', '--to-registry', metavar='<filename>',
help='Output to Windows registry .reg file.')
@click.option('-w', '--write', is_flag=True,
help='Write changes to PP binary.', default=False)
@click.pass_context
def undump(ctx, dump_filename, to_registry, write):
"""Undumps all PowerPlay data to pp file or registry
Serializes previously dumped PowerPlay text to pp file or registry.
For example:
\b
upp --pp-file=radeon.pp_table undump -d pp.dump --write
"""
variable_set = _load_variable_set(dump_filename)
ctx.invoke(set, variable_path_set=variable_set, to_registry=to_registry, write=write)
return 0


@click.command(short_help='Extract PowerPlay table from Video BIOS ROM image.')
@click.option('-r', '--video-rom', required=True, metavar='<filename>',
Expand Down Expand Up @@ -364,7 +414,7 @@ def set(ctx, variable_path_set, to_registry, write):
decode.set_value(pp_file, pp_bytes, set_list[:-1], set_list[-1],
data_dict=data, write=False, debug=debug)
if write:
print("Commiting changes to '{}'.".format(pp_file))
print("Committing changes to '{}'.".format(pp_file))
decode._write_binary_file(pp_file, pp_bytes)
else:
print("WARNING: Nothing was written to '{}'.".format(pp_file),
Expand All @@ -378,6 +428,7 @@ def set(ctx, variable_path_set, to_registry, write):
cli.add_command(extract)
cli.add_command(inject)
cli.add_command(dump)
cli.add_command(undump)
cli.add_command(get)
cli.add_command(set)
cli.add_command(version)
Expand Down

0 comments on commit a6a93c6

Please sign in to comment.