@@ -244,6 +244,9 @@ def _get_ofst_cstruct(module, name, header_bytes, debug=False):
family = 'Tonga'
elif module_suffix == 'atom_gen.vega10_pptable':
family = 'Vega10'
# APU Experimantal
elif module_suffix == 'atom_gen.pptable_apu':
family = 'APU'
else:
print('ERROR: Module {} does not contain jump structures.', module)
return cs, total_len
@@ -284,6 +287,13 @@ def resolve_cstruct(name, family=family):
'VCEStateTable', 'GPIOTable'
]

# APU Experimantal
simple_tables += [
'Unknown09Table', 'Unknown0bTable', 'Unknown0dTable', 'Unknown13Table',
'Unknown2cTable', 'Unknown36Table', 'Unknown08Table', 'Unknown0aTable',
'Unknown10Table'
]

if name in simple_tables:
cs = getattr(pp_module, resolve_cstruct(name))

@@ -361,13 +371,65 @@ class FixedEntriesCountArray(ctypes.LittleEndianStructure):
cs = FixedEntriesCountArray
else:
total_len = 0
index = 0
for field in cs._fields_:
if field[1] in primitives:
total_len += struct.calcsize(field[1]._type_)
# APU Experimental, special version-less jumptable at offset @ 0x36
elif (issubclass(field[1], ctypes.Array) and
field[1]._type_ not in primitives):
entry_len = struct.unpack('B', header_bytes[:1])[0]
entry_name, entry_type = cs._fields_[-1]

class FixedEntriesArray(ctypes.LittleEndianStructure):
_pack_ = cs._pack_
_fields_ = cs._fields_[:-1] + [
(entry_name, entry_type._type_ * entry_len)]

cs = FixedEntriesArray
total_bytes = 0
for f in field[1]._type_._fields_:
fl = getattr(field[1]._type_, f[0])
total_bytes += fl.size
total_len += entry_len * total_bytes

# APU Experimental, versioned tables containing multiple sub-arrays
elif issubclass(field[1], ctypes.Structure):
for subfield in field[1]._fields_:
total_bytes = 0
if 'ucNumEntries' == subfield[0]:
entry_len = struct.unpack(
'B', header_bytes[total_len:total_len+1])[0]
total_len += 1
elif 'entries' == subfield[0]:
for f in subfield[1]._type_._fields_:
fl = getattr(subfield[1]._type_, f[0])
total_bytes += fl.size
total_len += entry_len * total_bytes

# Here we need to fix the number of entries in sub-array...
entry_name, entry_type = field[1]._fields_[-1]

class FixedEntryArray(ctypes.LittleEndianStructure):
_pack_ = field[1]._pack_
_fields_ = field[1]._fields_[:-1] + [
(entry_name, entry_type._type_ * entry_len)]

# ...as well as fix the top struct to contain correct subarrays
fixed_entry = FixedEntryArray
fix_fields = cs._fields_
fix_fields[index] = (cs._fields_[index][0], fixed_entry)

class FixedEntriesCountArray(ctypes.LittleEndianStructure):
_pack_ = cs._pack_
_fields_ = fix_fields

cs = FixedEntriesCountArray
else:
entry_len = struct.calcsize(field[1]._type_._type_)
array_size = field[1]._length_
total_len += entry_len * array_size
index += 1
if debug:
print('DEBUG: Detected C structture of', len(cs._fields_),
'elements, total size of', total_len, 'bytes')
@@ -473,6 +535,10 @@ def build_data_tree(data, raw=None, decoded=None, parent_name='/',
if name in ['a', 'b', 'c', 'm'] and ctyp_cls == ctypes.c_uint:
d_symbol = 'f'
d_value = struct.unpack(d_symbol, d_bytes)[0]
# Defined as uint in kernel, but some report these as signed?
elif name in ['VddcOffset', 'VddgfxOffset']:
d_symbol = 'h'
d_value = struct.unpack(d_symbol, d_bytes)[0]
if rawdump:
_print_raw_value(d_offset, d_symbol, d_bytes,
name, d_value)
@@ -494,7 +560,7 @@ def build_data_tree(data, raw=None, decoded=None, parent_name='/',
else:
c_struct, size = _get_ofst_cstruct(data.__module__,
name,
raw[ofst:ofst+2],
raw[ofst:],
debug)
if c_struct:
top = ofst + size
@@ -537,7 +603,11 @@ def select_pp_struct(rawbytes, rawdump=False, debug=False):
pp_header = common_hdr.from_buffer(rawbytes[:4])
pp_ver = validate_pp(pp_header, len(rawbytes), rawdump)

if pp_ver == (7, 1): # Polaris
if pp_ver == (6, 1): # APU Experimental
gpugen = 'APU'
from upp.atom_gen import pptable_apu as pp_struct
ctypes_strct = pp_struct.struct__ATOM_APU_POWERPLAYTABLE
elif pp_ver == (7, 1): # Polaris
gpugen = 'Polaris'
from upp.atom_gen import pptable_v1_0 as pp_struct
ctypes_strct = pp_struct.struct__ATOM_Tonga_POWERPLAYTABLE