mirror of https://github.com/thesofproject/sof.git
971 lines
37 KiB
Python
971 lines
37 KiB
Python
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
#
|
|
# Copyright (c) 2019, Intel Corporation. All rights reserved.
|
|
#
|
|
# Author: Marcin Maka <marcin.maka@linux.intel.com>
|
|
|
|
""" Parses manifests included in sof binary and prints extracted metadata
|
|
in readable form.
|
|
"""
|
|
|
|
# pylint: disable=too-few-public-methods
|
|
# pylint: disable=too-many-arguments
|
|
# pylint: disable=too-many-instance-attributes
|
|
|
|
import sys
|
|
import argparse
|
|
import struct
|
|
|
|
# Public keys signatures recognized by parse_css_manifest()
|
|
# - add a new one as array of bytes and append entry to KNOWN_KEYS below.
|
|
|
|
APL_INTEL_PROD_KEY = bytes([0x1f, 0xf4, 0x58, 0x74, 0x64, 0xd4, 0xae, 0x90,
|
|
0x03, 0xb6, 0x71, 0x0d, 0xb5, 0xaf, 0x6d, 0xd6,
|
|
0x96, 0xce, 0x28, 0x95, 0xd1, 0x5b, 0x40, 0x59,
|
|
0xcd, 0xdf, 0x0c, 0x55, 0xd2, 0xc1, 0xbd, 0x58,
|
|
0xc3, 0x0d, 0x83, 0xe2, 0xac, 0xfa, 0xe0, 0xcc,
|
|
0x54, 0xf6, 0x5f, 0x72, 0xc2, 0x11, 0x05, 0x93,
|
|
0x1d, 0xb7, 0xe4, 0x4f, 0xa4, 0x95, 0xf5, 0x84,
|
|
0x77, 0x07, 0x24, 0x6e, 0x72, 0xce, 0x57, 0x41,
|
|
0xf2, 0x0b, 0x49, 0x49, 0x0c, 0xe2, 0x76, 0xf8,
|
|
0x19, 0xc7, 0x9f, 0xe1, 0xca, 0x77, 0x20, 0x1b,
|
|
0x5d, 0x1d, 0xed, 0xee, 0x5c, 0x54, 0x1d, 0xf6,
|
|
0x76, 0x14, 0xce, 0x6a, 0x24, 0x80, 0xc9, 0xce,
|
|
0x2e, 0x92, 0xe9, 0x35, 0xc7, 0x1a, 0xe9, 0x97,
|
|
0x7f, 0x25, 0x2b, 0xa8, 0xf3, 0xc1, 0x4d, 0x6b,
|
|
0xae, 0xd9, 0xcd, 0x0c, 0xbb, 0x08, 0x6d, 0x2b,
|
|
0x01, 0x44, 0xe2, 0xb9, 0x44, 0x4e, 0x4d, 0x5c,
|
|
0xdf, 0x8a, 0x89, 0xa5, 0x3c, 0x27, 0xa0, 0x54,
|
|
0xde, 0xc5, 0x5b, 0xde, 0x58, 0x10, 0x8c, 0xaa,
|
|
0xc4, 0x37, 0x5b, 0x73, 0x58, 0xfb, 0xe3, 0xcf,
|
|
0x57, 0xf5, 0x65, 0xd3, 0x19, 0x06, 0xed, 0x36,
|
|
0x47, 0xb0, 0x91, 0x67, 0xec, 0xc1, 0xe1, 0x7b,
|
|
0x4f, 0x85, 0x66, 0x61, 0x31, 0x99, 0xfc, 0x98,
|
|
0x7a, 0x56, 0x70, 0x95, 0x85, 0x52, 0xa0, 0x30,
|
|
0x37, 0x92, 0x11, 0x9e, 0x7f, 0x33, 0x44, 0xd3,
|
|
0x81, 0xfd, 0x14, 0x74, 0x51, 0x1c, 0x01, 0x14,
|
|
0xc8, 0x4b, 0xf6, 0xd6, 0xeb, 0x67, 0xef, 0xfc,
|
|
0x0a, 0x5f, 0xcc, 0x31, 0x73, 0xf8, 0xa9, 0xe3,
|
|
0xcb, 0xb4, 0x8b, 0x91, 0xa1, 0xf0, 0xb9, 0x6e,
|
|
0x1f, 0xea, 0xd3, 0xa3, 0xe4, 0x0f, 0x96, 0x74,
|
|
0x3c, 0x17, 0x5b, 0x68, 0x7c, 0x87, 0xfc, 0x90,
|
|
0x10, 0x89, 0x23, 0xca, 0x5d, 0x17, 0x5b, 0xc1,
|
|
0xb5, 0xc2, 0x49, 0x4e, 0x2a, 0x5f, 0x47, 0xc2])
|
|
|
|
CNL_INTEL_PROD_KEY = bytes([0x41, 0xa0, 0x3e, 0x14, 0x1e, 0x7e, 0x29, 0x72,
|
|
0x89, 0x97, 0xc2, 0xa7, 0x7d, 0xbc, 0x1d, 0x25,
|
|
0xf4, 0x9a, 0xa8, 0xb7, 0x89, 0x10, 0x73, 0x31,
|
|
0x58, 0xbd, 0x46, 0x55, 0x78, 0xcf, 0xd9, 0xe1,
|
|
0x7d, 0xfa, 0x24, 0x23, 0xfa, 0x5c, 0x7c, 0xc9,
|
|
0x3d, 0xc8, 0xb5, 0x74, 0x87, 0xa, 0x8c, 0xe7,
|
|
0x33, 0xc2, 0x71, 0x26, 0xb1, 0x4d, 0x32, 0x45,
|
|
0x23, 0x17, 0xcb, 0xa6, 0xa2, 0xd0, 0xcc, 0x9e,
|
|
0x2b, 0xa6, 0x9, 0x42, 0x52, 0xf1, 0xe6, 0xbd,
|
|
0x73, 0x92, 0x2a, 0xfb, 0x7f, 0xc4, 0x8d, 0x5,
|
|
0xec, 0x69, 0x7f, 0xd4, 0xa2, 0x6c, 0x46, 0xd4,
|
|
0x5d, 0x92, 0x1d, 0x17, 0x75, 0x39, 0x16, 0x4c,
|
|
0x61, 0xa8, 0xda, 0x93, 0xd6, 0x26, 0x23, 0xa,
|
|
0xc8, 0x2d, 0xcc, 0x81, 0xf4, 0xcc, 0x85, 0x42,
|
|
0xaa, 0xa3, 0x15, 0x8, 0x62, 0x8f, 0x72, 0x9b,
|
|
0x5f, 0x90, 0x2f, 0xd5, 0x94, 0xdc, 0xad, 0xf,
|
|
0xa9, 0x8, 0x8c, 0x2e, 0x20, 0xf4, 0xdf, 0x12,
|
|
0xf, 0xe2, 0x1e, 0xeb, 0xfb, 0xf7, 0xe9, 0x22,
|
|
0xef, 0xa7, 0x12, 0x3d, 0x43, 0x3b, 0x62, 0x8e,
|
|
0x2e, 0xeb, 0x78, 0x8, 0x6e, 0xd0, 0xb0, 0xea,
|
|
0x37, 0x43, 0x16, 0xd8, 0x11, 0x5a, 0xb5, 0x5,
|
|
0x60, 0xf2, 0x91, 0xa7, 0xaa, 0x7d, 0x7, 0x17,
|
|
0xb7, 0x5b, 0xec, 0x45, 0xf4, 0x4a, 0xaf, 0x5c,
|
|
0xa3, 0x30, 0x62, 0x8e, 0x4d, 0x63, 0x2, 0x2,
|
|
0xed, 0x4b, 0x1f, 0x1b, 0x9a, 0x2, 0x29, 0x9,
|
|
0xc1, 0x7a, 0xc5, 0xeb, 0xc7, 0xdb, 0xa1, 0x6f,
|
|
0x61, 0x31, 0xfa, 0x7b, 0x3b, 0xe0, 0x6a, 0x1c,
|
|
0xee, 0x55, 0xed, 0xf0, 0xf9, 0x7a, 0xaf, 0xaa,
|
|
0xc7, 0x76, 0xf5, 0xfb, 0x6a, 0xbc, 0x65, 0xde,
|
|
0x42, 0x3e, 0x1c, 0xdf, 0xcc, 0x69, 0x75, 0x1,
|
|
0x38, 0x8, 0x66, 0x20, 0xea, 0x6, 0x91, 0xb8,
|
|
0xcd, 0x1d, 0xfa, 0xfd, 0xe8, 0xa0, 0xba, 0x91])
|
|
|
|
ICL_INTEL_PROD_KEY = bytes([0x63, 0xdf, 0x54, 0xe3, 0xc1, 0xe5, 0xd9, 0xd2,
|
|
0xb8, 0xb5, 0x13, 0xb3, 0xec, 0xc2, 0x64, 0xb5,
|
|
0x16, 0xb4, 0xfc, 0x56, 0x92, 0x67, 0x17, 0xc7,
|
|
0x91, 0x7b, 0x3d, 0xb0, 0x22, 0xbf, 0x7f, 0x92,
|
|
0x39, 0x35, 0xcc, 0x64, 0x1c, 0xad, 0x8, 0x75,
|
|
0xe7, 0x67, 0xb, 0x8, 0xf8, 0x57, 0xdb, 0x9c,
|
|
0xde, 0xab, 0xe, 0xbd, 0x27, 0x5f, 0x5, 0x51,
|
|
0xcf, 0x6e, 0x3e, 0xc9, 0xdd, 0xe6, 0x51, 0x14,
|
|
0x57, 0xe1, 0x8a, 0x23, 0xae, 0x7a, 0xa5, 0x5f,
|
|
0xdc, 0x16, 0x13, 0x1b, 0x28, 0x3b, 0xab, 0xf1,
|
|
0xc3, 0xb5, 0x73, 0xc0, 0x72, 0xd8, 0x86, 0x7a,
|
|
0x76, 0x3a, 0x2, 0xbe, 0x2f, 0x3e, 0xfe, 0x93,
|
|
0x83, 0xa1, 0xd, 0xa0, 0xfc, 0x26, 0x7f, 0x6b,
|
|
0x2e, 0x5a, 0xfd, 0xac, 0x6b, 0x53, 0xd3, 0xb8,
|
|
0xff, 0x5e, 0xc7, 0x5, 0x25, 0xff, 0xe7, 0x78,
|
|
0x9c, 0x45, 0xe4, 0x17, 0xbd, 0xf4, 0x52, 0x4e,
|
|
0x3c, 0xa2, 0xa, 0x4d, 0x54, 0xb5, 0x40, 0x30,
|
|
0xb3, 0x48, 0xba, 0x6c, 0xfa, 0x63, 0xc0, 0x65,
|
|
0x2e, 0xde, 0x9, 0x2e, 0xa1, 0x95, 0x85, 0xc0,
|
|
0x78, 0xd9, 0x98, 0x64, 0x3c, 0x29, 0x2e, 0x48,
|
|
0x66, 0x1e, 0xaf, 0x1d, 0xa0, 0x7c, 0x15, 0x3,
|
|
0x7f, 0x9e, 0x5f, 0x38, 0xf5, 0xc1, 0xe1, 0xe9,
|
|
0xbe, 0x77, 0xa2, 0x9c, 0x83, 0xf2, 0x25, 0x54,
|
|
0x22, 0xfe, 0x29, 0x66, 0x5, 0xc2, 0xc9, 0x6b,
|
|
0x8b, 0xa6, 0xa3, 0xf9, 0xb1, 0x6b, 0xaf, 0xe7,
|
|
0x14, 0x77, 0xff, 0x17, 0xc9, 0x7c, 0x7c, 0x4e,
|
|
0x83, 0x28, 0x2a, 0xe5, 0xc3, 0xcc, 0x6e, 0x25,
|
|
0xa, 0x62, 0xbb, 0x97, 0x44, 0x86, 0x7c, 0xa2,
|
|
0xd4, 0xf1, 0xd4, 0xf8, 0x8, 0x17, 0xf4, 0x6c,
|
|
0xcc, 0x95, 0x99, 0xd4, 0x86, 0x37, 0x4, 0x9f,
|
|
0x5, 0x76, 0x1b, 0x44, 0x55, 0x75, 0xd9, 0x32,
|
|
0x35, 0xf1, 0xec, 0x4d, 0x93, 0x73, 0xe6, 0xc4])
|
|
|
|
COMMUNITY_KEY = bytes([0x85, 0x00, 0xe1, 0x68, 0xaa, 0xeb, 0xd2, 0x07,
|
|
0x1b, 0x7c, 0x5e, 0xed, 0xd6, 0xe7, 0xe5, 0xf9,
|
|
0xc1, 0x0e, 0x47, 0xd4, 0x4c, 0xab, 0x8c, 0xf0,
|
|
0xe8, 0xee, 0x8b, 0x40, 0x36, 0x35, 0x58, 0x8f,
|
|
0xf4, 0x6f, 0xfc, 0xfd, 0x0f, 0xdd, 0x55, 0x8b,
|
|
0x45, 0x8c, 0xf0, 0x47, 0xdc, 0xb4, 0xac, 0x21,
|
|
0x3b, 0x4b, 0x20, 0xe6, 0x81, 0xb3, 0xcc, 0x90,
|
|
0xd4, 0x5e, 0xf1, 0xa4, 0x9b, 0x68, 0x52, 0xc8,
|
|
0xf1, 0x2d, 0xf9, 0xc4, 0x77, 0xc6, 0x4d, 0xa9,
|
|
0x90, 0xc7, 0x10, 0xfd, 0x43, 0xc8, 0x4b, 0x6b,
|
|
0x23, 0x5e, 0x92, 0xf5, 0x8f, 0xac, 0xd5, 0x7d,
|
|
0x60, 0x27, 0x36, 0x7c, 0x21, 0x4e, 0x21, 0x99,
|
|
0xde, 0xcb, 0xc0, 0x45, 0xf3, 0x04, 0x22, 0xb8,
|
|
0x7d, 0x16, 0x68, 0x40, 0xf9, 0x5c, 0xf0, 0xb9,
|
|
0x7e, 0x8c, 0x05, 0xb6, 0xfc, 0x28, 0xbb, 0x3d,
|
|
0xd8, 0xff, 0xb6, 0xa4, 0xd4, 0x54, 0x27, 0x3b,
|
|
0x1a, 0x42, 0x4e, 0xf5, 0xa6, 0xa8, 0x5e, 0x44,
|
|
0xe2, 0x9e, 0xed, 0x68, 0x6a, 0x27, 0x60, 0x13,
|
|
0x8d, 0x2f, 0x27, 0x70, 0xcd, 0x57, 0xc9, 0x18,
|
|
0xa3, 0xb0, 0x30, 0xa1, 0xf4, 0xe6, 0x32, 0x12,
|
|
0x89, 0x2a, 0xaf, 0x40, 0xa5, 0xfd, 0x52, 0xf1,
|
|
0xaa, 0x8a, 0xa4, 0xef, 0x20, 0x3d, 0x10, 0xa3,
|
|
0x70, 0xf2, 0x39, 0xc5, 0x05, 0x99, 0x22, 0x10,
|
|
0x81, 0x83, 0x6e, 0x45, 0xa4, 0xf3, 0x5a, 0x9d,
|
|
0x6a, 0xb8, 0x88, 0xfe, 0x69, 0x40, 0xd1, 0xb1,
|
|
0xcb, 0x2a, 0xdb, 0x28, 0x05, 0xde, 0x54, 0xbf,
|
|
0x3d, 0x86, 0x5f, 0x39, 0x8b, 0xc1, 0xf4, 0xaf,
|
|
0x00, 0x61, 0x86, 0x01, 0xfa, 0x22, 0xac, 0xf6,
|
|
0x2c, 0xa4, 0x17, 0x6a, 0xa7, 0xd8, 0x0a, 0x8c,
|
|
0x9f, 0xbf, 0x1f, 0x62, 0xb2, 0x2e, 0x68, 0x52,
|
|
0x3f, 0x82, 0x8f, 0xe5, 0x28, 0x4d, 0xdb, 0xb5,
|
|
0x5a, 0x96, 0x28, 0x27, 0x19, 0xaf, 0x43, 0xb9])
|
|
|
|
KNOWN_KEYS = {APL_INTEL_PROD_KEY : 'APL Intel prod key',
|
|
CNL_INTEL_PROD_KEY : 'CNL Intel prod key',
|
|
ICL_INTEL_PROD_KEY : 'ICL Intel prod key',
|
|
COMMUNITY_KEY : 'Community key'}
|
|
|
|
def parse_params():
|
|
""" Parses parameters
|
|
"""
|
|
parser = argparse.ArgumentParser(description='SOF Binary Info Utility')
|
|
parser.add_argument('-v', '--verbose', help='increase output verbosity',
|
|
action='store_true')
|
|
parser.add_argument('--headers', help='display headers only',
|
|
action='store_true')
|
|
parser.add_argument('--full_bytes', help='display full byte arrays',
|
|
action='store_true')
|
|
parser.add_argument('--no_colors', help='disable colors in output',
|
|
action='store_true')
|
|
parser.add_argument('sof_ri_path', help='path to fw binary file to parse')
|
|
parsed_args = parser.parse_args()
|
|
|
|
return parsed_args
|
|
|
|
# Helper Functions
|
|
|
|
def change_color(color):
|
|
""" Prints escape code to change text color
|
|
"""
|
|
color_code = {'red':91, 'green':92, 'yellow':93, 'blue':94,
|
|
'magenta':95, 'cyan':96, 'white':98, 'none':0}
|
|
return '\033[{}m'.format(color_code[color])
|
|
|
|
def uint_to_string(uint, both=False):
|
|
""" Prints uint in readable form
|
|
"""
|
|
if both:
|
|
return hex(uint) + ' (' + repr(uint) + ')'
|
|
return hex(uint)
|
|
|
|
def date_to_string(date):
|
|
""" Prints BCD date in readable form
|
|
"""
|
|
return date[2:6]+'/'+date[6:8]+'/'+date[8:10]
|
|
|
|
def chararr_to_string(chararr, max_len):
|
|
""" Prints array of characters (null terminated or till max_len)
|
|
in readable form
|
|
"""
|
|
out = ''
|
|
for i in range(0, max_len):
|
|
if chararr[i] == 0:
|
|
return out
|
|
out += '{:c}'.format(chararr[i])
|
|
return out
|
|
|
|
def mod_type_to_string(mod_type):
|
|
""" Prints module type in readable form
|
|
"""
|
|
out = '('
|
|
# type
|
|
if (mod_type & 0xf) == 0:
|
|
out += ' builtin'
|
|
elif (mod_type & 0xf) == 1:
|
|
out += ' loadable'
|
|
# Module that may be instantiated by fw on startup
|
|
if ((mod_type >> 4) & 0x1) == 1:
|
|
out += ' auto_start'
|
|
# Module designed to run with low latency scheduler
|
|
if ((mod_type >> 5) & 0x1) == 1:
|
|
out += ' LL'
|
|
# Module designed to run with edf scheduler
|
|
if ((mod_type >> 6) & 0x1) == 1:
|
|
out += ' DP'
|
|
out += ' )'
|
|
return out
|
|
|
|
def seg_flags_to_string(flags):
|
|
""" Prints module segment flags in readable form
|
|
"""
|
|
out = '('
|
|
if flags & 0x1 == 0x1:
|
|
out = out + ' contents'
|
|
if flags & 0x2 == 0x2:
|
|
out = out + ' alloc'
|
|
if flags & 0x4 == 0x4:
|
|
out = out + ' load'
|
|
if flags & 0x8 == 0x8:
|
|
out = out + ' readonly'
|
|
if flags & 0x10 == 0x10:
|
|
out = out + ' code'
|
|
if flags & 0x20 == 0x20:
|
|
out = out + ' data'
|
|
out = out + ' type=' + repr((flags>>8)&0xf)
|
|
out = out + ' pages=' + repr((flags>>16)&0xffff)
|
|
out = out + ' )'
|
|
return out
|
|
|
|
# Parsers
|
|
|
|
def parse_extended_manifest(reader):
|
|
""" Parses extended manifest from sof binary
|
|
"""
|
|
ext_mft = ExtendedManifest()
|
|
hdr = Component('ext_mft_hdr', 'Header', 0)
|
|
ext_mft.add_comp(hdr)
|
|
|
|
# Try to detect signature first
|
|
sig = reader.read_bytes(4).decode()
|
|
if sig != '$AE1':
|
|
reader.set_offset(0)
|
|
reader.info('info: Extended Manifest not found (sig = '+sig+')')
|
|
reader.ext_mft_length = 0
|
|
hdr.add_a(Auint('length', reader.ext_mft_length))
|
|
return ext_mft
|
|
|
|
reader.info('Extended Manifest (' + sig + ')', -4)
|
|
hdr.add_a(Astring('sig', sig))
|
|
|
|
# Next dword is the total length of the extended manifest
|
|
# (need to use it for further parsing)
|
|
reader.ext_mft_length = reader.read_dw()
|
|
hdr.add_a(Auint('length', reader.ext_mft_length))
|
|
hdr.add_a(Astring('ver', '{}.{}'.format(reader.read_w(), reader.read_w())))
|
|
hdr.add_a(Auint('entries', reader.read_dw()))
|
|
|
|
reader.ff_data(reader.ext_mft_length-16)
|
|
return ext_mft
|
|
|
|
def parse_cse_manifest(reader, add_module_entries):
|
|
""" Parses CSE manifest form sof binary
|
|
"""
|
|
cse_mft = CseManifest(reader.get_offset())
|
|
|
|
# Try to detect signature first
|
|
sig = reader.read_bytes(4).decode()
|
|
if sig != '$CPD':
|
|
reader.error('CSE Manifest NOT found ' + sig + ')', -4)
|
|
sys.exit(1)
|
|
reader.info('CSE Manifest (' + sig + ')', -4)
|
|
|
|
# Read the header
|
|
hdr = Component('cse_mft_hdr', 'Header', reader.get_offset())
|
|
cse_mft.add_comp(hdr)
|
|
hdr.add_a(Astring('sig', sig))
|
|
# read number of entries
|
|
nb_entries = reader.read_dw()
|
|
hdr.add_a(Adec('nb_entries', nb_entries))
|
|
# read version (1byte for header ver and 1 byte for entry ver)
|
|
ver = reader.read_w()
|
|
hdr.add_a(Ahex('header_version', ver))
|
|
header_length = reader.read_b()
|
|
hdr.add_a(Ahex('header_length', header_length))
|
|
hdr.add_a(Ahex('checksum', reader.read_b()))
|
|
hdr.add_a(Astring('partition_name', reader.read_bytes(4).decode()))
|
|
|
|
reader.set_offset(cse_mft.file_offset + header_length)
|
|
# Read entries
|
|
nb_index = 0
|
|
while nb_index < nb_entries:
|
|
entry_name = reader.read_bytes(12).decode()
|
|
entry_offset = reader.read_dw()
|
|
entry_length = reader.read_dw()
|
|
# reserved field
|
|
reader.read_dw()
|
|
|
|
hdr_entry = Component('cse_hdr_entry', 'Entry', reader.get_offset())
|
|
hdr_entry.add_a(Astring('entry_name', entry_name))
|
|
hdr_entry.add_a(Ahex('entry_offset', entry_offset))
|
|
hdr_entry.add_a(Ahex('entry_length', entry_length))
|
|
hdr.add_comp(hdr_entry)
|
|
|
|
if '.man' in entry_name:
|
|
entry = CssManifest(entry_name, entry_offset)
|
|
cur_off = reader.set_offset(reader.ext_mft_length + entry_offset)
|
|
parse_css_manifest(entry, reader,
|
|
reader.ext_mft_length + entry_offset + entry_length)
|
|
reader.set_offset(cur_off)
|
|
elif '.met' in entry_name:
|
|
cur_off = reader.set_offset(reader.ext_mft_length + entry_offset)
|
|
entry = parse_mft_extension(reader, 0)
|
|
entry.name = '{} ({})'.format(entry_name, entry.name)
|
|
reader.set_offset(cur_off)
|
|
else:
|
|
# override offset with precise one
|
|
cur_off = reader.set_offset(reader.ext_mft_length + 0x2000)
|
|
entry = parse_adsp_manifest(reader, entry_name, add_module_entries)
|
|
reader.set_offset(cur_off)
|
|
cse_mft.add_comp(entry)
|
|
|
|
nb_index += 1
|
|
|
|
return cse_mft
|
|
|
|
def parse_css_manifest(css_mft, reader, limit):
|
|
""" Parses CSS manifest from sof binary
|
|
"""
|
|
ver, = struct.unpack('I', reader.get_data(0, 4))
|
|
if ver == 4:
|
|
reader.info('CSS Manifest type 4')
|
|
return parse_css_manifest_4(css_mft, reader, limit)
|
|
|
|
reader.error('CSS Manifest NOT found or NOT recognized!')
|
|
sys.exit(1)
|
|
|
|
def parse_css_manifest_4(css_mft, reader, size_limit):
|
|
""" Parses CSS manifest type 4 from sof binary
|
|
"""
|
|
|
|
# CSS Header
|
|
hdr = Component('css_mft_hdr', 'Header', reader.get_offset())
|
|
css_mft.add_comp(hdr)
|
|
|
|
hdr.add_a(Auint('type', reader.read_dw()))
|
|
header_len_dw = reader.read_dw()
|
|
hdr.add_a(Auint('header_len_dw', header_len_dw))
|
|
hdr.add_a(Auint('header_version', reader.read_dw()))
|
|
hdr.add_a(Auint('reserved0', reader.read_dw(), 'red'))
|
|
hdr.add_a(Ahex('mod_vendor', reader.read_dw()))
|
|
hdr.add_a(Adate('date', hex(reader.read_dw())))
|
|
size = reader.read_dw()
|
|
hdr.add_a(Auint('size', size))
|
|
hdr.add_a(Astring('header_id', reader.read_bytes(4).decode()))
|
|
hdr.add_a(Auint('padding', reader.read_dw()))
|
|
hdr.add_a(Aversion('fw_version', reader.read_w(), reader.read_w(),
|
|
reader.read_w(), reader.read_w()))
|
|
hdr.add_a(Auint('svn', reader.read_dw()))
|
|
reader.read_bytes(18*4)
|
|
modulus_size = reader.read_dw()
|
|
hdr.add_a(Adec('modulus_size', modulus_size))
|
|
exponent_size = reader.read_dw()
|
|
hdr.add_a(Adec('exponent_size', exponent_size))
|
|
modulus = reader.read_bytes(modulus_size * 4)
|
|
hdr.add_a(Amodulus('modulus', modulus, KNOWN_KEYS.get(modulus, 'Other')))
|
|
hdr.add_a(Abytes('exponent', reader.read_bytes(exponent_size * 4)))
|
|
hdr.add_a(Abytes('signature', reader.read_bytes(modulus_size * 4)))
|
|
|
|
# Move right after the header
|
|
reader.set_offset(css_mft.file_offset + header_len_dw*4)
|
|
|
|
# Anything packed here is
|
|
# either an 'Extension' beginning with
|
|
# dw0 - extension type
|
|
# dw1 - extension length (in bytes)
|
|
# that could be parsed if extension type is recognized
|
|
#
|
|
# or series of 0xffffffff that should be skipped
|
|
ext_idx = 0
|
|
while reader.get_offset() < size_limit:
|
|
ext_type = reader.read_dw()
|
|
if ext_type == 0xffffffff:
|
|
continue
|
|
reader.set_offset(reader.get_offset() - 4)
|
|
css_mft.add_comp(parse_mft_extension(reader, ext_idx))
|
|
ext_idx += 1
|
|
|
|
return css_mft
|
|
|
|
def parse_mft_extension(reader, ext_id):
|
|
""" Parses mft extension from sof binary
|
|
"""
|
|
ext_type = reader.read_dw()
|
|
ext_len = reader.read_dw()
|
|
if ext_type == 15:
|
|
begin_off = reader.get_offset()
|
|
ext = PlatFwAuthExtension(ext_id, reader.get_offset()-8)
|
|
ext.add_a(Astring('name', reader.read_bytes(4).decode()))
|
|
ext.add_a(Auint('vcn', reader.read_dw()))
|
|
ext.add_a(Abytes('bitmap', reader.read_bytes(16), 'red'))
|
|
ext.add_a(Auint('svn', reader.read_dw()))
|
|
read_len = reader.get_offset() - begin_off
|
|
reader.ff_data(ext_len - read_len)
|
|
elif ext_type == 17:
|
|
ext = AdspMetadataFileExt(ext_id, reader.get_offset()-8)
|
|
ext.add_a(Auint('adsp_imr_type', reader.read_dw(), 'red'))
|
|
# skip reserved part
|
|
reader.read_bytes(16)
|
|
reader.read_dw()
|
|
reader.read_dw()
|
|
#
|
|
ext.add_a(Auint('version', reader.read_dw()))
|
|
ext.add_a(Abytes('sha_hash', reader.read_bytes(32)))
|
|
ext.add_a(Auint('base_offset', reader.read_dw()))
|
|
ext.add_a(Auint('limit_offset', reader.read_dw()))
|
|
ext.add_a(Abytes('attributes', reader.read_bytes(16)))
|
|
else:
|
|
ext = MftExtension(ext_id, 'Other Extension', reader.get_offset()-8)
|
|
reader.ff_data(ext_len-8)
|
|
ext.add_a(Auint('type', ext_type))
|
|
ext.add_a(Auint('length', ext_len))
|
|
return ext
|
|
|
|
def parse_adsp_manifest_hdr(reader):
|
|
""" Parses ADSP manifest hader from sof binary
|
|
"""
|
|
# Verify signature
|
|
try:
|
|
sig = reader.read_bytes(4).decode()
|
|
except UnicodeDecodeError:
|
|
print('\n' + reader.offset_to_string() + \
|
|
'\terror: Failed to decode signature, wrong position?')
|
|
sys.exit(1)
|
|
if sig != '$AM1':
|
|
reader.error('ADSP Manifest NOT found!', -4)
|
|
sys.exit(1)
|
|
reader.info('ADSP Manifest (' + sig + ')', -4)
|
|
|
|
hdr = Component('adsp_mft_hdr', 'ADSP Manifest Header',
|
|
reader.get_offset() -4)
|
|
hdr.add_a(Astring('sig', sig))
|
|
|
|
hdr.add_a(Auint('size', reader.read_dw()))
|
|
hdr.add_a(Astring('name', chararr_to_string(reader.read_bytes(8), 8)))
|
|
hdr.add_a(Auint('preload', reader.read_dw()))
|
|
hdr.add_a(Auint('fw_image_flags', reader.read_dw()))
|
|
hdr.add_a(Auint('feature_mask', reader.read_dw()))
|
|
hdr.add_a(Aversion('build_version', reader.read_w(), reader.read_w(),
|
|
reader.read_w(), reader.read_w()))
|
|
|
|
hdr.add_a(Adec('num_module_entries', reader.read_dw()))
|
|
hdr.add_a(Ahex('hw_buf_base_addr', reader.read_dw()))
|
|
hdr.add_a(Auint('hw_buf_length', reader.read_dw()))
|
|
hdr.add_a(Ahex('load_offset', reader.read_dw()))
|
|
|
|
return hdr
|
|
|
|
def parse_adsp_manifest_mod_entry(index, reader):
|
|
""" Parses ADSP manifest module entry from sof binary
|
|
"""
|
|
# Verify Mod Entry signature
|
|
try:
|
|
sig = reader.read_bytes(4).decode()
|
|
except UnicodeDecodeError:
|
|
print(reader.offset_to_string() + \
|
|
'\terror: Failed to decode ModuleEntry signature')
|
|
sys.exit(1)
|
|
if sig != '$AME':
|
|
reader.error('ModuleEntry signature NOT found!')
|
|
sys.exit(1)
|
|
reader.info('Module Entry signature found (' + sig + ')', -4)
|
|
|
|
mod = Component('mod_entry_'+repr(index), 'Module Entry',
|
|
reader.get_offset() -4)
|
|
mod.add_a(Astring('sig', sig))
|
|
|
|
mod.add_a(Astring('mod_name',
|
|
chararr_to_string(reader.read_bytes(8), 8)))
|
|
mod.add_a(Astring('uuid', reader.read_uuid()))
|
|
me_type = reader.read_dw()
|
|
mod.add_a(Astring('type',
|
|
hex(me_type) + ' ' + mod_type_to_string(me_type)))
|
|
mod.add_a(Abytes('hash', reader.read_bytes(32)))
|
|
mod.add_a(Ahex('entry_point', reader.read_dw()))
|
|
mod.add_a(Adec('cfg_offset', reader.read_w()))
|
|
mod.add_a(Adec('cfg_count', reader.read_w()))
|
|
mod.add_a(Auint('affinity_mask', reader.read_dw()))
|
|
mod.add_a(Adec('instance_max_count', reader.read_w()))
|
|
mod.add_a(Auint('instance_stack_size', reader.read_w()))
|
|
for i in range(0, 3):
|
|
seg_flags = reader.read_dw()
|
|
mod.add_a(Astring('seg_'+repr(i)+' flags',
|
|
hex(seg_flags) + ' ' + seg_flags_to_string(seg_flags)))
|
|
mod.add_a(Ahex('seg_'+repr(i)+' v_base_addr', reader.read_dw()))
|
|
mod.add_a(Ahex('seg_'+repr(i)+' file_offset', reader.read_dw()))
|
|
|
|
return mod
|
|
|
|
def parse_adsp_manifest(reader, name, add_module_entries):
|
|
""" Parses ADSP manifest from sof binary
|
|
"""
|
|
adsp_mft = AdspManifest(name, reader.get_offset())
|
|
adsp_mft.add_comp(parse_adsp_manifest_hdr(reader))
|
|
num_module_entries = adsp_mft.cdir['adsp_mft_hdr'].adir['num_module_entries'].val
|
|
for i in range(0, num_module_entries):
|
|
mod_entry = parse_adsp_manifest_mod_entry(i, reader)
|
|
if add_module_entries:
|
|
adsp_mft.add_comp(mod_entry)
|
|
|
|
return adsp_mft
|
|
|
|
def parse_fw_bin(path, verbose, add_module_entries):
|
|
""" Parses sof binary
|
|
"""
|
|
reader = BinReader(path, verbose)
|
|
|
|
parsed_bin = FwBin()
|
|
parsed_bin.add_a(Astring('file_name', reader.file_name))
|
|
parsed_bin.add_a(Auint('file_size', reader.file_size))
|
|
parsed_bin.add_comp(parse_extended_manifest(reader))
|
|
parsed_bin.add_comp(parse_cse_manifest(reader, add_module_entries))
|
|
|
|
if verbose:
|
|
print('Parsing finished')
|
|
return parsed_bin
|
|
|
|
class BinReader():
|
|
""" sof binary reader
|
|
"""
|
|
def __init__(self, path, verbose):
|
|
self.verbose = verbose
|
|
if self.verbose:
|
|
print('Reading SOF ri image ' + path)
|
|
self.file_name = path
|
|
# read the content
|
|
self.data = open(path, 'rb').read()
|
|
self.file_size = len(self.data)
|
|
if self.verbose:
|
|
print('File size ' + uint_to_string(self.file_size, True))
|
|
self.cur_offset = 0
|
|
|
|
def get_offset(self):
|
|
""" Retrieve the offset, the reader is at
|
|
"""
|
|
return self.cur_offset
|
|
|
|
def ff_data(self, delta_offset):
|
|
""" Forwards the read pointer by specified number of bytes
|
|
"""
|
|
self.cur_offset += delta_offset
|
|
|
|
def set_offset(self, offset):
|
|
""" Set current reader offset
|
|
"""
|
|
old_offset = self.cur_offset
|
|
self.cur_offset = offset
|
|
return old_offset
|
|
|
|
def get_data(self, beg, length):
|
|
""" Retrieves the data from beg to beg+length.
|
|
This one is good to peek the data w/o advancing the read pointer
|
|
"""
|
|
return self.data[self.cur_offset +beg : self.cur_offset +beg +length]
|
|
|
|
def read_bytes(self, count):
|
|
""" Reads the specified number of bytes from the stream
|
|
"""
|
|
bts = self.get_data(0, count)
|
|
self.ff_data(count)
|
|
return bts
|
|
|
|
def read_dw(self):
|
|
""" Reads a dword from the stream
|
|
"""
|
|
dword, = struct.unpack('I', self.get_data(0, 4))
|
|
self.ff_data(4)
|
|
return dword
|
|
|
|
def read_w(self):
|
|
""" Reads a word from the stream
|
|
"""
|
|
word, = struct.unpack('H', self.get_data(0, 2))
|
|
self.ff_data(2)
|
|
return word
|
|
|
|
def read_b(self):
|
|
""" Reads a byte from the stream
|
|
"""
|
|
byte, = struct.unpack('B', self.get_data(0, 1))
|
|
self.ff_data(1)
|
|
return byte
|
|
|
|
def read_uuid(self):
|
|
""" Reads a UUID from the stream and returns as string
|
|
"""
|
|
out = '{:08x}'.format(self.read_dw())
|
|
out += '-'+'{:04x}'.format(self.read_w())
|
|
out += '-'+'{:04x}'.format(self.read_w())
|
|
out += '-'+'{:02x}'.format(self.read_b()) + \
|
|
'{:02x}'.format(self.read_b()) + '-'
|
|
for _ in range(0, 6):
|
|
out += '{:02x}'.format(self.read_b())
|
|
return out
|
|
|
|
def offset_to_string(self, delta=0):
|
|
""" Retrieves readable representation of the current offset value
|
|
"""
|
|
return uint_to_string(self.cur_offset+delta)
|
|
|
|
def info(self, loginfo, off_delta=0, verb_info=True):
|
|
""" Prints 'info' log to the output, respects verbose mode
|
|
"""
|
|
if verb_info and not self.verbose:
|
|
return
|
|
print(self.offset_to_string(off_delta) + '\t' + loginfo)
|
|
|
|
def error(self, logerror, off_delta=0):
|
|
""" Prints 'error' log to the output
|
|
"""
|
|
print(self.offset_to_string(off_delta) + '\terror: ' + logerror)
|
|
|
|
# Data Model
|
|
|
|
class Attribute():
|
|
""" Attribute: base class with global formatting options
|
|
"""
|
|
no_colors = False
|
|
full_bytes = True
|
|
|
|
class Auint(Attribute):
|
|
""" Attribute : unsigned integer
|
|
"""
|
|
def __init__(self, name, val, color='none'):
|
|
self.name = name
|
|
self.val = val
|
|
self.color = color
|
|
|
|
def __str__(self):
|
|
if Attribute.no_colors:
|
|
return uint_to_string(self.val)
|
|
return '{}{}{}'.format(change_color(self.color),
|
|
uint_to_string(self.val),
|
|
change_color('none'))
|
|
|
|
class Ahex(Attribute):
|
|
""" Attribute : unsigned integer printed as hex
|
|
"""
|
|
def __init__(self, name, val, color='none'):
|
|
self.name = name
|
|
self.val = val
|
|
self.color = color
|
|
|
|
def __str__(self):
|
|
if Attribute.no_colors:
|
|
return hex(self.val)
|
|
return '{}{}{}'.format(change_color(self.color), hex(self.val),
|
|
change_color('none'))
|
|
|
|
class Adec(Attribute):
|
|
""" Attribute: integer printed as dec
|
|
"""
|
|
def __init__(self, name, val):
|
|
self.name = name
|
|
self.val = val
|
|
|
|
def __str__(self):
|
|
return repr(self.val)
|
|
|
|
class Abytes(Attribute):
|
|
""" Attribute: array of bytes
|
|
"""
|
|
def __init__(self, name, val, color='none'):
|
|
self.name = name
|
|
self.val = val
|
|
self.color = color
|
|
|
|
def __str__(self):
|
|
length = len(self.val)
|
|
if Attribute.no_colors:
|
|
out = ''
|
|
else:
|
|
out = '{}'.format(change_color(self.color))
|
|
if Attribute.full_bytes or length <= 16:
|
|
out += ' '.join(['{:02x}'.format(b) for b in self.val])
|
|
else:
|
|
out += ' '.join('{:02x}'.format(b) for b in self.val[:8])
|
|
out += ' ... '
|
|
out += ' '.join('{:02x}'.format(b) for b in self.val[length-8:length])
|
|
if not Attribute.no_colors:
|
|
out += '{}'.format(change_color('none'))
|
|
return out
|
|
|
|
class Adate(Attribute):
|
|
""" Attribute: Date in BCD format
|
|
"""
|
|
def __init__(self, name, val):
|
|
self.name = name
|
|
self.val = val
|
|
|
|
def __str__(self):
|
|
return date_to_string(self.val)
|
|
|
|
class Astring(Attribute):
|
|
""" Attribute: String
|
|
"""
|
|
def __init__(self, name, val):
|
|
self.name = name
|
|
self.val = val
|
|
|
|
def __str__(self):
|
|
return self.val
|
|
|
|
class Aversion(Attribute):
|
|
""" Attribute: version
|
|
"""
|
|
def __init__(self, name, major, minor, hotfix, build):
|
|
self.name = name
|
|
self.val = '{:d}.{:d}.{:d}.{:d}'.format(major, minor, hotfix, build)
|
|
|
|
def __str__(self):
|
|
return self.val
|
|
|
|
class Amodulus(Abytes):
|
|
""" Attribute: modulus from RSA public key
|
|
"""
|
|
def __init__(self, name, val, val_type):
|
|
super().__init__(name, val)
|
|
self.val_type = val_type
|
|
|
|
def __str__(self):
|
|
out = super().__str__()
|
|
if not Attribute.full_bytes:
|
|
if Attribute.no_colors:
|
|
out += ' ({})'.format(self.val_type)
|
|
else:
|
|
out += ' {}({}){}'.format(change_color('red'), self.val_type,
|
|
change_color('none'))
|
|
return out
|
|
|
|
class Component():
|
|
""" A component of sof binary
|
|
"""
|
|
def __init__(self, uid, name, file_offset):
|
|
self.uid = uid
|
|
self.name = name
|
|
self.file_offset = file_offset
|
|
self.attribs = []
|
|
self.adir = {}
|
|
self.max_attr_name_len = 0
|
|
self.components = []
|
|
self.cdir = {}
|
|
|
|
def add_a(self, attrib):
|
|
""" Adds an attribute
|
|
"""
|
|
self.max_attr_name_len = max(self.max_attr_name_len,
|
|
len(attrib.name))
|
|
self.attribs.append(attrib)
|
|
self.adir[attrib.name] = attrib
|
|
|
|
def add_comp(self, comp):
|
|
""" Adds a nested component
|
|
"""
|
|
self.components.append(comp)
|
|
self.cdir[comp.uid] = comp
|
|
|
|
def get_comp(self, comp_uid):
|
|
""" Retrieves a nested component by id
|
|
"""
|
|
for comp in self.components:
|
|
if comp.uid == comp_uid:
|
|
return comp
|
|
return None
|
|
|
|
def dump_info(self, pref):
|
|
""" Prints out the content (name, all attributes, and nested comps)
|
|
"""
|
|
print(pref + self.name)
|
|
for attrib in self.attribs:
|
|
print("{:} {:<{:}} {:}".format(pref, attrib.name,
|
|
self.max_attr_name_len, attrib))
|
|
self.dump_comp_info(pref)
|
|
|
|
def dump_attrib_info(self, pref, attr_name):
|
|
""" Prints out a single attribute
|
|
"""
|
|
attrib = self.adir[attr_name]
|
|
print("{:} {:<{:}} {:}".format(pref, attrib.name,
|
|
self.max_attr_name_len, attrib))
|
|
|
|
def dump_comp_info(self, pref, name_filter=''):
|
|
""" Prints out all nested components (filtered by name set to 'filter')
|
|
"""
|
|
for comp in self.components:
|
|
if comp.name == name_filter:
|
|
continue
|
|
print()
|
|
comp.dump_info(pref + ' ')
|
|
|
|
class ExtendedManifest(Component):
|
|
""" Extended manifest
|
|
"""
|
|
def __init__(self):
|
|
super(ExtendedManifest, self).__init__('ext_mft',
|
|
'Extended Manifest', 0)
|
|
|
|
def dump_info(self, pref):
|
|
hdr = self.cdir['ext_mft_hdr']
|
|
if hdr.adir['length'].val == 0:
|
|
return
|
|
out = '{}{}'.format(pref, self.name)
|
|
out += ' ver {}'.format(hdr.adir['ver'])
|
|
out += ' entries {}'.format(hdr.adir['entries'])
|
|
print(out)
|
|
self.dump_comp_info(pref, name_filter='Header')
|
|
|
|
class CseManifest(Component):
|
|
""" CSE Manifest
|
|
"""
|
|
def __init__(self, offset):
|
|
super(CseManifest, self).__init__('cse_mft', 'CSE Manifest', offset)
|
|
|
|
def dump_info(self, pref):
|
|
hdr = self.cdir['cse_mft_hdr']
|
|
print('{}{} ver {} checksum {} partition name {}'.
|
|
format(pref,
|
|
self.name, hdr.adir['header_version'],
|
|
hdr.adir['checksum'], hdr.adir['partition_name']))
|
|
self.dump_comp_info(pref, name_filter='Header')
|
|
|
|
class CssManifest(Component):
|
|
""" CSS Manifest
|
|
"""
|
|
def __init__(self, name, offset):
|
|
super(CssManifest, self).__init__('css_mft', name, offset)
|
|
|
|
def dump_info(self, pref):
|
|
hdr = self.cdir['css_mft_hdr']
|
|
out = '{}{} (CSS Manifest)'.format(pref, self.name)
|
|
out += ' type {}'.format(hdr.adir['type'])
|
|
out += ' ver {}'.format(hdr.adir['header_version'])
|
|
out += ' date {}'.format(hdr.adir['date'])
|
|
print(out)
|
|
print('{} Rsvd0 {}'.
|
|
format(pref, hdr.adir['reserved0']))
|
|
print('{} Modulus size (dwords) {}'.
|
|
format(pref, hdr.adir['modulus_size']))
|
|
print('{} {}'.format(pref, hdr.adir['modulus']))
|
|
print('{} Exponent size (dwords) {}'.
|
|
format(pref,
|
|
hdr.adir['exponent_size']))
|
|
print('{} {}'.format(pref, hdr.adir['exponent']))
|
|
print('{} Signature'.format(pref))
|
|
print('{} {}'.format(pref, hdr.adir['signature']))
|
|
# super().dump_info(pref)
|
|
self.dump_comp_info(pref, name_filter='Header')
|
|
|
|
class MftExtension(Component):
|
|
""" Manifest Extension
|
|
"""
|
|
def __init__(self, ext_id, name, offset):
|
|
super(MftExtension, self).__init__('mft_ext'+repr(ext_id), name,
|
|
offset)
|
|
|
|
def dump_info(self, pref):
|
|
print('{}{} type {} length {}'.
|
|
format(pref, self.name,
|
|
self.adir['type'], self.adir['length']))
|
|
|
|
class PlatFwAuthExtension(MftExtension):
|
|
""" Platform FW Auth Extension
|
|
"""
|
|
def __init__(self, ext_id, offset):
|
|
super(PlatFwAuthExtension,
|
|
self).__init__(ext_id, 'Plat Fw Auth Extension', offset)
|
|
|
|
def dump_info(self, pref):
|
|
out = '{}{}'.format(pref, self.name)
|
|
out += ' name {}'.format(self.adir['name'])
|
|
out += ' vcn {}'.format(self.adir['vcn'])
|
|
out += ' bitmap {}'.format(self.adir['bitmap'])
|
|
out += ' svn {}'.format(self.adir['svn'])
|
|
print(out)
|
|
|
|
class AdspMetadataFileExt(MftExtension):
|
|
""" ADSP Metadata File Extension
|
|
"""
|
|
def __init__(self, ext_id, offset):
|
|
super(AdspMetadataFileExt,
|
|
self).__init__(ext_id, 'ADSP Metadata File Extension',
|
|
offset)
|
|
|
|
def dump_info(self, pref):
|
|
out = '{}{}'.format(pref, self.name)
|
|
out += ' ver {}'.format(self.adir['version'])
|
|
out += ' base offset {}'.format(self.adir['base_offset'])
|
|
out += ' limit offset {}'.format(self.adir['limit_offset'])
|
|
print(out)
|
|
print('{} IMR type {}'.format(pref, self.adir['adsp_imr_type']))
|
|
print('{} Attributes'.format(pref))
|
|
print('{} {}'.format(pref, self.adir['attributes']))
|
|
|
|
class AdspManifest(Component):
|
|
""" ADSP Manifest
|
|
"""
|
|
def __init__(self, name, offset):
|
|
super(AdspManifest, self).__init__('adsp_mft', name, offset)
|
|
|
|
def dump_info(self, pref):
|
|
hdr = self.cdir['adsp_mft_hdr']
|
|
out = '{}{} (ADSP Manifest)'.format(pref, self.name)
|
|
out += ' name {}'.format(hdr.adir['name'])
|
|
out += ' build ver {}'.format(hdr.adir['build_version'])
|
|
out += ' feature mask {}'.format(hdr.adir['feature_mask'])
|
|
out += ' image flags {}'.format(hdr.adir['fw_image_flags'])
|
|
print(out)
|
|
print('{} HW buffers base address {} length {}'.
|
|
format(pref,
|
|
hdr.adir['hw_buf_base_addr'],
|
|
hdr.adir['hw_buf_length']))
|
|
print('{} Load offset {}'.format(pref,
|
|
hdr.adir['load_offset']))
|
|
self.dump_comp_info(pref, 'ADSP Manifest Header')
|
|
|
|
class FwBin(Component):
|
|
""" Parsed sof binary
|
|
"""
|
|
def __init__(self):
|
|
super(FwBin, self).__init__('bin', 'SOF Binary', 0)
|
|
|
|
def dump_info(self, pref):
|
|
""" Print out the content
|
|
"""
|
|
print('SOF Binary {} size {}'.format(
|
|
self.adir['file_name'], self.adir['file_size']))
|
|
self.dump_comp_info(pref)
|
|
|
|
def main(args):
|
|
""" main function
|
|
"""
|
|
Attribute.no_colors = args.no_colors
|
|
Attribute.full_bytes = args.full_bytes
|
|
|
|
fw_bin = parse_fw_bin(args.sof_ri_path, args.verbose, not args.headers)
|
|
fw_bin.dump_info('')
|
|
|
|
if __name__ == "__main__":
|
|
ARGS = parse_params()
|
|
main(ARGS)
|