#!/usr/bin/env python3 """Parse an amdgpu `*_dmcub.bin` container: common ucode header, the DMCUB extension fields, and the trailing `dmub_fw_meta_info` block. Field names follow the kernel's `struct dmcub_firmware_header_v1_0` (drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h) and `struct dmub_fw_meta_info` (drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h). Usage: dmcub_parse.py fw/*.bin """ import struct import sys import hashlib import zlib META_MAGIC = 0x444D5542 # 'DMUB' META_OFFSET_FROM_END = 0x24 # DMUB_FW_META_OFFSET def parse_container(blob): o = {} (o['size_bytes'], o['header_size_bytes'], o['hdr_ver_major'], o['hdr_ver_minor'], o['ip_ver_major'], o['ip_ver_minor'], o['ucode_version'], o['ucode_size_bytes'], o['ucode_array_offset_bytes'], o['crc32']) = struct.unpack_from('= 0x28: o['inst_const_bytes'], o['bss_data_bytes'] = struct.unpack_from('> 24) & 0xff, (v >> 16) & 0xff, v & 0xffff) for path in sys.argv[1:]: blob = open(path, 'rb').read() h = parse_container(blob) print('=' * 78) print(path) print(' file size %d (0x%x)' % (len(blob), len(blob))) print(' sha256 %s' % hashlib.sha256(blob).hexdigest()) print(' size_bytes 0x%08x %s' % (h['size_bytes'], 'OK' if h['size_bytes'] == len(blob) else 'MISMATCH')) print(' header_size_bytes 0x%x' % h['header_size_bytes']) print(' header version %d.%d' % (h['hdr_ver_major'], h['hdr_ver_minor'])) print(' ip version %d.%d' % (h['ip_ver_major'], h['ip_ver_minor'])) print(' ucode_version 0x%08x' % h['ucode_version']) print(' ucode_size_bytes 0x%x' % h['ucode_size_bytes']) print(' ucode_array_offset 0x%x' % h['ucode_array_offset_bytes']) payload = blob[h['ucode_array_offset_bytes']: h['ucode_array_offset_bytes'] + h['ucode_size_bytes']] calc = zlib.crc32(payload) & 0xffffffff print(' crc32 (header) 0x%08x crc32(payload)=0x%08x %s' % (h['crc32'], calc, 'MATCH' if calc == h['crc32'] else 'no-match')) if 'inst_const_bytes' in h: print(' inst_const_bytes 0x%x' % h['inst_const_bytes']) print(' bss_data_bytes 0x%x' % h['bss_data_bytes']) print(' payload span 0x%x..0x%x trailing bytes: %d' % ( h['ucode_array_offset_bytes'], h['ucode_array_offset_bytes'] + h['ucode_size_bytes'], len(blob) - h['ucode_array_offset_bytes'] - h['ucode_size_bytes'])) for how, off in find_meta(blob, h): m = parse_meta(blob, off) print(' -- dmub_fw_meta_info @ 0x%x (%s)' % (off, how)) print(' fw_version 0x%08x (%s)' % (m['fw_version'], ver(m['fw_version']))) print(' fw_region_size 0x%x' % m['fw_region_size']) print(' trace_buffer_size 0x%x' % m['trace_buffer_size']) print(' dal_fw %d' % m['dal_fw']) print(' shared_state_size 0x%x features=0x%x' % (m['shared_state_size'], m['shared_state_features'])) print(' feature_bits 0x%08x' % m['feature_bits'])