1#!/usr/bin/env python3
2# SPDX-License-Identifier: BSD-3-Clause
3#
4# Copyright (c) 2019, Intel Corporation. All rights reserved.
5#
6# Author: Marcin Maka <marcin.maka@linux.intel.com>
7
8""" Parses manifests included in sof binary and prints extracted metadata
9    in readable form.
10"""
11
12# pylint: disable=too-few-public-methods
13# pylint: disable=too-many-arguments
14# pylint: disable=too-many-instance-attributes
15# pylint: disable=invalid-name
16# pylint: disable=missing-function-docstring
17
18import sys
19import argparse
20import struct
21import io
22import pathlib
23import hashlib
24
25# Required for open(pathlib)
26assert sys.version_info >= (3, 6)
27
28# To extend the DSP memory layout list scroll down to DSP_MEM_SPACE_EXT
29
30# Public keys signatures recognized by parse_css_manifest()
31# - add a new one as array of bytes and append entry to KNOWN_KEYS below.
32#   you can use --full_bytes to dump the bytes in below format
33
34APL_INTEL_PROD_KEY = bytes([0x1f, 0xf4, 0x58, 0x74, 0x64, 0xd4, 0xae, 0x90,
35                            0x03, 0xb6, 0x71, 0x0d, 0xb5, 0xaf, 0x6d, 0xd6,
36                            0x96, 0xce, 0x28, 0x95, 0xd1, 0x5b, 0x40, 0x59,
37                            0xcd, 0xdf, 0x0c, 0x55, 0xd2, 0xc1, 0xbd, 0x58,
38                            0xc3, 0x0d, 0x83, 0xe2, 0xac, 0xfa, 0xe0, 0xcc,
39                            0x54, 0xf6, 0x5f, 0x72, 0xc2, 0x11, 0x05, 0x93,
40                            0x1d, 0xb7, 0xe4, 0x4f, 0xa4, 0x95, 0xf5, 0x84,
41                            0x77, 0x07, 0x24, 0x6e, 0x72, 0xce, 0x57, 0x41,
42                            0xf2, 0x0b, 0x49, 0x49, 0x0c, 0xe2, 0x76, 0xf8,
43                            0x19, 0xc7, 0x9f, 0xe1, 0xca, 0x77, 0x20, 0x1b,
44                            0x5d, 0x1d, 0xed, 0xee, 0x5c, 0x54, 0x1d, 0xf6,
45                            0x76, 0x14, 0xce, 0x6a, 0x24, 0x80, 0xc9, 0xce,
46                            0x2e, 0x92, 0xe9, 0x35, 0xc7, 0x1a, 0xe9, 0x97,
47                            0x7f, 0x25, 0x2b, 0xa8, 0xf3, 0xc1, 0x4d, 0x6b,
48                            0xae, 0xd9, 0xcd, 0x0c, 0xbb, 0x08, 0x6d, 0x2b,
49                            0x01, 0x44, 0xe2, 0xb9, 0x44, 0x4e, 0x4d, 0x5c,
50                            0xdf, 0x8a, 0x89, 0xa5, 0x3c, 0x27, 0xa0, 0x54,
51                            0xde, 0xc5, 0x5b, 0xde, 0x58, 0x10, 0x8c, 0xaa,
52                            0xc4, 0x37, 0x5b, 0x73, 0x58, 0xfb, 0xe3, 0xcf,
53                            0x57, 0xf5, 0x65, 0xd3, 0x19, 0x06, 0xed, 0x36,
54                            0x47, 0xb0, 0x91, 0x67, 0xec, 0xc1, 0xe1, 0x7b,
55                            0x4f, 0x85, 0x66, 0x61, 0x31, 0x99, 0xfc, 0x98,
56                            0x7a, 0x56, 0x70, 0x95, 0x85, 0x52, 0xa0, 0x30,
57                            0x37, 0x92, 0x11, 0x9e, 0x7f, 0x33, 0x44, 0xd3,
58                            0x81, 0xfd, 0x14, 0x74, 0x51, 0x1c, 0x01, 0x14,
59                            0xc8, 0x4b, 0xf6, 0xd6, 0xeb, 0x67, 0xef, 0xfc,
60                            0x0a, 0x5f, 0xcc, 0x31, 0x73, 0xf8, 0xa9, 0xe3,
61                            0xcb, 0xb4, 0x8b, 0x91, 0xa1, 0xf0, 0xb9, 0x6e,
62                            0x1f, 0xea, 0xd3, 0xa3, 0xe4, 0x0f, 0x96, 0x74,
63                            0x3c, 0x17, 0x5b, 0x68, 0x7c, 0x87, 0xfc, 0x90,
64                            0x10, 0x89, 0x23, 0xca, 0x5d, 0x17, 0x5b, 0xc1,
65                            0xb5, 0xc2, 0x49, 0x4e, 0x2a, 0x5f, 0x47, 0xc2])
66
67CNL_INTEL_PROD_KEY = bytes([0x41, 0xa0, 0x3e, 0x14, 0x1e, 0x7e, 0x29, 0x72,
68                            0x89, 0x97, 0xc2, 0xa7, 0x7d, 0xbc, 0x1d, 0x25,
69                            0xf4, 0x9a, 0xa8, 0xb7, 0x89, 0x10, 0x73, 0x31,
70                            0x58, 0xbd, 0x46, 0x55, 0x78, 0xcf, 0xd9, 0xe1,
71                            0x7d, 0xfa, 0x24, 0x23, 0xfa, 0x5c, 0x7c, 0xc9,
72                            0x3d, 0xc8, 0xb5, 0x74, 0x87, 0xa, 0x8c, 0xe7,
73                            0x33, 0xc2, 0x71, 0x26, 0xb1, 0x4d, 0x32, 0x45,
74                            0x23, 0x17, 0xcb, 0xa6, 0xa2, 0xd0, 0xcc, 0x9e,
75                            0x2b, 0xa6, 0x9, 0x42, 0x52, 0xf1, 0xe6, 0xbd,
76                            0x73, 0x92, 0x2a, 0xfb, 0x7f, 0xc4, 0x8d, 0x5,
77                            0xec, 0x69, 0x7f, 0xd4, 0xa2, 0x6c, 0x46, 0xd4,
78                            0x5d, 0x92, 0x1d, 0x17, 0x75, 0x39, 0x16, 0x4c,
79                            0x61, 0xa8, 0xda, 0x93, 0xd6, 0x26, 0x23, 0xa,
80                            0xc8, 0x2d, 0xcc, 0x81, 0xf4, 0xcc, 0x85, 0x42,
81                            0xaa, 0xa3, 0x15, 0x8, 0x62, 0x8f, 0x72, 0x9b,
82                            0x5f, 0x90, 0x2f, 0xd5, 0x94, 0xdc, 0xad, 0xf,
83                            0xa9, 0x8, 0x8c, 0x2e, 0x20, 0xf4, 0xdf, 0x12,
84                            0xf, 0xe2, 0x1e, 0xeb, 0xfb, 0xf7, 0xe9, 0x22,
85                            0xef, 0xa7, 0x12, 0x3d, 0x43, 0x3b, 0x62, 0x8e,
86                            0x2e, 0xeb, 0x78, 0x8, 0x6e, 0xd0, 0xb0, 0xea,
87                            0x37, 0x43, 0x16, 0xd8, 0x11, 0x5a, 0xb5, 0x5,
88                            0x60, 0xf2, 0x91, 0xa7, 0xaa, 0x7d, 0x7, 0x17,
89                            0xb7, 0x5b, 0xec, 0x45, 0xf4, 0x4a, 0xaf, 0x5c,
90                            0xa3, 0x30, 0x62, 0x8e, 0x4d, 0x63, 0x2, 0x2,
91                            0xed, 0x4b, 0x1f, 0x1b, 0x9a, 0x2, 0x29, 0x9,
92                            0xc1, 0x7a, 0xc5, 0xeb, 0xc7, 0xdb, 0xa1, 0x6f,
93                            0x61, 0x31, 0xfa, 0x7b, 0x3b, 0xe0, 0x6a, 0x1c,
94                            0xee, 0x55, 0xed, 0xf0, 0xf9, 0x7a, 0xaf, 0xaa,
95                            0xc7, 0x76, 0xf5, 0xfb, 0x6a, 0xbc, 0x65, 0xde,
96                            0x42, 0x3e, 0x1c, 0xdf, 0xcc, 0x69, 0x75, 0x1,
97                            0x38, 0x8, 0x66, 0x20, 0xea, 0x6, 0x91, 0xb8,
98                            0xcd, 0x1d, 0xfa, 0xfd, 0xe8, 0xa0, 0xba, 0x91])
99
100ICL_INTEL_PROD_KEY = bytes([0x63, 0xdf, 0x54, 0xe3, 0xc1, 0xe5, 0xd9, 0xd2,
101                            0xb8, 0xb5, 0x13, 0xb3, 0xec, 0xc2, 0x64, 0xb5,
102                            0x16, 0xb4, 0xfc, 0x56, 0x92, 0x67, 0x17, 0xc7,
103                            0x91, 0x7b, 0x3d, 0xb0, 0x22, 0xbf, 0x7f, 0x92,
104                            0x39, 0x35, 0xcc, 0x64, 0x1c, 0xad, 0x8, 0x75,
105                            0xe7, 0x67, 0xb, 0x8, 0xf8, 0x57, 0xdb, 0x9c,
106                            0xde, 0xab, 0xe, 0xbd, 0x27, 0x5f, 0x5, 0x51,
107                            0xcf, 0x6e, 0x3e, 0xc9, 0xdd, 0xe6, 0x51, 0x14,
108                            0x57, 0xe1, 0x8a, 0x23, 0xae, 0x7a, 0xa5, 0x5f,
109                            0xdc, 0x16, 0x13, 0x1b, 0x28, 0x3b, 0xab, 0xf1,
110                            0xc3, 0xb5, 0x73, 0xc0, 0x72, 0xd8, 0x86, 0x7a,
111                            0x76, 0x3a, 0x2, 0xbe, 0x2f, 0x3e, 0xfe, 0x93,
112                            0x83, 0xa1, 0xd, 0xa0, 0xfc, 0x26, 0x7f, 0x6b,
113                            0x2e, 0x5a, 0xfd, 0xac, 0x6b, 0x53, 0xd3, 0xb8,
114                            0xff, 0x5e, 0xc7, 0x5, 0x25, 0xff, 0xe7, 0x78,
115                            0x9c, 0x45, 0xe4, 0x17, 0xbd, 0xf4, 0x52, 0x4e,
116                            0x3c, 0xa2, 0xa, 0x4d, 0x54, 0xb5, 0x40, 0x30,
117                            0xb3, 0x48, 0xba, 0x6c, 0xfa, 0x63, 0xc0, 0x65,
118                            0x2e, 0xde, 0x9, 0x2e, 0xa1, 0x95, 0x85, 0xc0,
119                            0x78, 0xd9, 0x98, 0x64, 0x3c, 0x29, 0x2e, 0x48,
120                            0x66, 0x1e, 0xaf, 0x1d, 0xa0, 0x7c, 0x15, 0x3,
121                            0x7f, 0x9e, 0x5f, 0x38, 0xf5, 0xc1, 0xe1, 0xe9,
122                            0xbe, 0x77, 0xa2, 0x9c, 0x83, 0xf2, 0x25, 0x54,
123                            0x22, 0xfe, 0x29, 0x66, 0x5, 0xc2, 0xc9, 0x6b,
124                            0x8b, 0xa6, 0xa3, 0xf9, 0xb1, 0x6b, 0xaf, 0xe7,
125                            0x14, 0x77, 0xff, 0x17, 0xc9, 0x7c, 0x7c, 0x4e,
126                            0x83, 0x28, 0x2a, 0xe5, 0xc3, 0xcc, 0x6e, 0x25,
127                            0xa, 0x62, 0xbb, 0x97, 0x44, 0x86, 0x7c, 0xa2,
128                            0xd4, 0xf1, 0xd4, 0xf8, 0x8, 0x17, 0xf4, 0x6c,
129                            0xcc, 0x95, 0x99, 0xd4, 0x86, 0x37, 0x4, 0x9f,
130                            0x5, 0x76, 0x1b, 0x44, 0x55, 0x75, 0xd9, 0x32,
131                            0x35, 0xf1, 0xec, 0x4d, 0x93, 0x73, 0xe6, 0xc4])
132
133JSL_INTEL_PROD_KEY = bytes([0x6f, 0xe4, 0xd5, 0xc9, 0x52, 0xf4, 0x01, 0xc1,
134                            0x89, 0xc7, 0x2b, 0x16, 0x9b, 0xe6, 0x5d, 0x8e,
135                            0x91, 0x28, 0x63, 0x16, 0x4f, 0x7b, 0x18, 0x6e,
136                            0xa7, 0x89, 0x0c, 0xea, 0x24, 0x62, 0xc7, 0x94,
137                            0x75, 0x43, 0xfd, 0x6d, 0xa8, 0x67, 0x47, 0x36,
138                            0x50, 0xaf, 0x37, 0x46, 0x15, 0x82, 0x45, 0x4a,
139                            0xa3, 0x2e, 0xae, 0xa4, 0x1f, 0x92, 0x67, 0x4b,
140                            0x5e, 0x67, 0x7e, 0x02, 0xfc, 0x18, 0x6f, 0x68,
141                            0x0d, 0xe3, 0xc1, 0x00, 0xdf, 0xea, 0xed, 0x9f,
142                            0xdc, 0x61, 0xa0, 0xfd, 0x36, 0x61, 0x84, 0xa7,
143                            0x8c, 0x2a, 0x4b, 0x2c, 0x2d, 0xed, 0x8d, 0x0b,
144                            0x35, 0xe9, 0x79, 0x59, 0x3f, 0x22, 0xdc, 0x3c,
145                            0xd4, 0x43, 0x32, 0x22, 0xf0, 0xda, 0x0d, 0xa1,
146                            0x3a, 0xec, 0x47, 0x87, 0x5e, 0xa0, 0xd2, 0xaa,
147                            0xf8, 0x1c, 0x61, 0x08, 0x05, 0x64, 0xb4, 0xa8,
148                            0x75, 0xc8, 0x20, 0x34, 0xbf, 0x04, 0x10, 0x75,
149                            0x8c, 0xb7, 0x6d, 0x49, 0xde, 0x3d, 0x3c, 0x66,
150                            0x08, 0xfe, 0x67, 0xc8, 0x77, 0x04, 0x7c, 0xa5,
151                            0xf0, 0x9e, 0xe7, 0x5e, 0x70, 0xbf, 0xde, 0xf1,
152                            0xcb, 0x1c, 0xc0, 0x84, 0x4a, 0x89, 0x76, 0x37,
153                            0x4f, 0xad, 0x3b, 0x8f, 0x04, 0x91, 0xd0, 0x1b,
154                            0x0b, 0xa8, 0x20, 0x6e, 0x1e, 0x97, 0x1e, 0xff,
155                            0x1f, 0xef, 0xde, 0x7a, 0xd7, 0x93, 0x3c, 0xa9,
156                            0x46, 0xe5, 0x74, 0x66, 0x9c, 0x85, 0xfa, 0xaa,
157                            0x4a, 0xe4, 0x39, 0xc5, 0x33, 0xbb, 0x8e, 0xca,
158                            0x1f, 0xd9, 0x4c, 0xbc, 0xcd, 0x7c, 0xa1, 0x30,
159                            0xdb, 0x15, 0xed, 0xa1, 0x24, 0x9d, 0xcb, 0xf0,
160                            0xbe, 0xeb, 0x92, 0x60, 0xb0, 0xab, 0x60, 0xa0,
161                            0xcc, 0xd8, 0x04, 0xf9, 0xf1, 0xa0, 0x04, 0x98,
162                            0x6a, 0x20, 0xd8, 0x86, 0xff, 0xd4, 0x9d, 0x09,
163                            0xa1, 0x22, 0xce, 0x0a, 0x3e, 0x21, 0x27, 0xcd,
164                            0xf8, 0x7c, 0xb0, 0x09, 0x09, 0xc2, 0xa3, 0xcc])
165
166TGL_INTEL_PROD_KEY = bytes([0xd3, 0x72, 0x92, 0x99, 0x4e, 0xb9, 0xcd, 0x67,
167                            0x41, 0x86, 0x16, 0x77, 0x35, 0xa1, 0x34, 0x85,
168                            0x43, 0x96, 0xd9, 0x53, 0x76, 0x4d, 0xd0, 0x63,
169                            0x17, 0x72, 0x96, 0xee, 0xf6, 0xdc, 0x50, 0x53,
170                            0x4b, 0x4, 0xaa, 0xfe, 0x3d, 0xd7, 0x21, 0x29,
171                            0x79, 0x6, 0x76, 0xee, 0xb3, 0x70, 0x23, 0x8,
172                            0x26, 0xa8, 0x83, 0x3d, 0x70, 0x13, 0x9d, 0x65,
173                            0xcb, 0xd5, 0xc6, 0xf, 0x92, 0x93, 0x38, 0x29,
174                            0x19, 0xa6, 0x7c, 0xbf, 0xf1, 0x76, 0x75, 0x2,
175                            0x9e, 0x32, 0x8f, 0x1f, 0x5, 0xa6, 0x2d, 0x89,
176                            0x6d, 0x38, 0xba, 0x38, 0xd, 0xf1, 0xe9, 0xe8,
177                            0xed, 0xf7, 0x6c, 0x20, 0x8d, 0x91, 0xc, 0xf8,
178                            0xdd, 0x9a, 0x56, 0xd3, 0xf7, 0xbf, 0x3c, 0xda,
179                            0xc8, 0x5d, 0xb, 0xef, 0x20, 0x5a, 0xc1, 0x5f,
180                            0x91, 0x94, 0xee, 0x90, 0xb8, 0xfc, 0x2c, 0x31,
181                            0x75, 0xc3, 0x7e, 0x86, 0xf6, 0x4f, 0x45, 0x4c,
182                            0x64, 0xe1, 0xe9, 0xe5, 0xcd, 0xf0, 0xec, 0xef,
183                            0xa7, 0xbd, 0x31, 0x62, 0x40, 0xa8, 0x48, 0x52,
184                            0xd5, 0x23, 0xce, 0x4, 0x45, 0x2f, 0xb, 0x3d,
185                            0xe0, 0x7a, 0xcf, 0xe5, 0x2a, 0x45, 0x5e, 0x91,
186                            0x1d, 0x41, 0xa7, 0x40, 0x85, 0x34, 0xe, 0x50,
187                            0x45, 0x59, 0xbf, 0xd, 0xa6, 0x6, 0xf9, 0xf6,
188                            0xce, 0xa2, 0x76, 0x72, 0x0, 0x62, 0x73, 0x37,
189                            0x1a, 0xbe, 0xd2, 0xe3, 0x1b, 0x7b, 0x26, 0x7b,
190                            0x32, 0xaa, 0x79, 0xed, 0x59, 0x23, 0xb6, 0xdb,
191                            0x9f, 0x3c, 0x3d, 0x65, 0xf3, 0xbb, 0x4b, 0xb4,
192                            0x97, 0xaa, 0x2a, 0xae, 0x48, 0xf4, 0xc5, 0x59,
193                            0x8d, 0x82, 0x4a, 0xb, 0x15, 0x4d, 0xd5, 0x4,
194                            0xa6, 0xc1, 0x2d, 0x83, 0x19, 0xc4, 0xc6, 0x49,
195                            0xba, 0x0, 0x1b, 0x2b, 0x70, 0xb, 0x26, 0x7c,
196                            0xb8, 0x94, 0x18, 0xe4, 0x9a, 0xf6, 0x5a, 0x68,
197                            0x9d, 0x44, 0xd2, 0xed, 0xd5, 0x67, 0x42, 0x47,
198                            0x5f, 0x73, 0xc5, 0xa7, 0xe5, 0x87, 0xa9, 0x4d,
199                            0xae, 0xc1, 0xb, 0x2c, 0x46, 0x16, 0xd7, 0x4e,
200                            0xf0, 0xdc, 0x61, 0x58, 0x51, 0xb1, 0x2, 0xbc,
201                            0xca, 0x17, 0xb1, 0x1a, 0xa, 0x96, 0x3b, 0x25,
202                            0x1c, 0x63, 0x56, 0x65, 0x20, 0x6e, 0x1b, 0x21,
203                            0xb1, 0x94, 0x7a, 0xf5, 0xbf, 0x83, 0x21, 0x86,
204                            0x38, 0xf1, 0x66, 0x1a, 0xa, 0x75, 0x73, 0xa,
205                            0xe, 0xc7, 0x64, 0x68, 0xc7, 0xf9, 0xc3, 0x4a,
206                            0x73, 0xfb, 0x86, 0xa5, 0x7, 0xb8, 0x8b, 0xf0,
207                            0xa3, 0x3b, 0xa9, 0x8f, 0x33, 0xa7, 0xce, 0xfe,
208                            0x36, 0x60, 0xbd, 0x5, 0xf0, 0x9a, 0x30, 0xe5,
209                            0xe1, 0x43, 0x25, 0x1c, 0x1, 0x4a, 0xd4, 0x23,
210                            0x1e, 0x8f, 0xb9, 0xdd, 0xd8, 0xb2, 0x24, 0xef,
211                            0x36, 0x4d, 0x5b, 0x8f, 0xba, 0x4f, 0xe9, 0x48,
212                            0xe7, 0x51, 0x42, 0x59, 0x56, 0xa, 0x1c, 0xf,
213                            0x5d, 0x62, 0x4a, 0x80, 0x96, 0x31, 0xf8, 0xb5])
214
215EHL_INTEL_PROD_KEY = bytes([0xb5, 0xb0, 0xe2, 0x25, 0x3d, 0xc7, 0x54, 0x10,
216                            0xde, 0x3c, 0xc9, 0x24, 0x97, 0x74, 0xbc, 0x02,
217                            0x7d, 0x0b, 0xd6, 0x61, 0x2e, 0x35, 0x65, 0xed,
218                            0x78, 0xf6, 0x85, 0x73, 0x1f, 0x8c, 0xda, 0x8f,
219                            0x50, 0x79, 0xc7, 0x0c, 0x9e, 0xb4, 0x09, 0x3b,
220                            0xfc, 0x2e, 0x4e, 0xf3, 0x46, 0xfe, 0x3f, 0x20,
221                            0x9d, 0x8d, 0xf6, 0x3e, 0xc3, 0x46, 0x92, 0xf9,
222                            0xce, 0xbb, 0x7d, 0x0b, 0xb3, 0x45, 0x35, 0x76,
223                            0xbe, 0x19, 0x87, 0x21, 0x6c, 0x79, 0xfa, 0xf4,
224                            0xc8, 0x8e, 0x07, 0x26, 0x03, 0x0d, 0xe9, 0xe3,
225                            0x1e, 0x61, 0x7c, 0xd1, 0x45, 0x10, 0x61, 0x1c,
226                            0x79, 0x3f, 0x10, 0xa9, 0x42, 0x60, 0x2c, 0x7a,
227                            0x7a, 0x89, 0x1b, 0x54, 0xda, 0x0e, 0x54, 0x08,
228                            0x30, 0x0f, 0x6e, 0x37, 0xea, 0xb7, 0x58, 0xa0,
229                            0xaf, 0x4a, 0x94, 0x2c, 0x43, 0x50, 0x74, 0xed,
230                            0x16, 0xdc, 0x11, 0xa1, 0xd3, 0x6e, 0x54, 0xa6,
231                            0x56, 0xf9, 0x40, 0x8c, 0x3f, 0xa3, 0x74, 0xae,
232                            0x4f, 0x48, 0xc8, 0x79, 0x30, 0x5a, 0x99, 0x79,
233                            0x26, 0xe1, 0x52, 0x9b, 0xfe, 0x9e, 0xaf, 0x96,
234                            0xcc, 0xe6, 0x9a, 0x53, 0x2e, 0xe4, 0x40, 0xcc,
235                            0xad, 0x19, 0x8e, 0x23, 0x53, 0x63, 0xc8, 0xfd,
236                            0x96, 0xeb, 0x27, 0x9b, 0x3e, 0x49, 0x0d, 0x90,
237                            0xb0, 0x67, 0xb4, 0x05, 0x4a, 0x55, 0x5b, 0xb0,
238                            0xa5, 0x68, 0xb8, 0x60, 0xa4, 0x81, 0x6a, 0x3e,
239                            0x8c, 0xbc, 0x29, 0xcd, 0x85, 0x45, 0x3c, 0xf4,
240                            0x86, 0xf8, 0x9b, 0x69, 0xb5, 0xc5, 0xb9, 0xaa,
241                            0xc8, 0xed, 0x7d, 0x70, 0x45, 0xb6, 0xf6, 0x5b,
242                            0x48, 0x62, 0xf6, 0x68, 0xe8, 0xdd, 0x79, 0xda,
243                            0xb0, 0xe9, 0x3c, 0x8f, 0x01, 0x92, 0x80, 0x73,
244                            0x89, 0x7d, 0x9a, 0xaf, 0x31, 0x85, 0x75, 0x7c,
245                            0x89, 0xf3, 0x6c, 0x77, 0x95, 0x5b, 0xa9, 0xc5,
246                            0xe1, 0x33, 0xe0, 0x44, 0x81, 0x7e, 0x72, 0xa5,
247                            0xbb, 0x3d, 0x40, 0xb7, 0xc9, 0x77, 0xd8, 0xc3,
248                            0xe3, 0xef, 0x42, 0xae, 0x57, 0x91, 0x63, 0x0c,
249                            0x26, 0xac, 0x5e, 0x10, 0x51, 0x28, 0xe6, 0x61,
250                            0xad, 0x4d, 0xc4, 0x93, 0xb2, 0xe0, 0xb4, 0x31,
251                            0x60, 0x5a, 0x97, 0x0e, 0x80, 0x86, 0x91, 0xc9,
252                            0xcd, 0xfc, 0x97, 0xc3, 0x78, 0xbd, 0xca, 0xce,
253                            0xd3, 0x96, 0xee, 0x75, 0x81, 0xe0, 0x8b, 0x45,
254                            0x8e, 0x20, 0x4b, 0x98, 0x31, 0x0f, 0xf9, 0x66,
255                            0xb3, 0x04, 0xb7, 0x0d, 0xde, 0x68, 0x1e, 0x2a,
256                            0xe4, 0xec, 0x45, 0x2a, 0x0a, 0x24, 0x81, 0x82,
257                            0xcb, 0x86, 0xa0, 0x61, 0x7f, 0xe7, 0x96, 0x84,
258                            0x4b, 0x30, 0xc4, 0x7d, 0x5c, 0x1b, 0x2c, 0x1e,
259                            0x66, 0x68, 0x71, 0x1d, 0x39, 0x6c, 0x23, 0x07,
260                            0x6d, 0xf3, 0x3e, 0x64, 0xc3, 0x03, 0x97, 0x84,
261                            0x14, 0xd1, 0xf6, 0x50, 0xf4, 0x32, 0x5d, 0xae,
262                            0xad, 0x23, 0x46, 0x0c, 0x9f, 0xfc, 0x3e, 0xb9])
263
264ADL_INTEL_PROD_KEY = bytes([0xd3, 0x42, 0x11, 0x78, 0xf4, 0x4a, 0xa5, 0x85,
265                            0x4b, 0x78, 0x7a, 0x9b, 0xbd, 0x71, 0xc1, 0x84,
266                            0x0f, 0x54, 0xe4, 0x07, 0x47, 0x65, 0x9e, 0xdc,
267                            0x79, 0x85, 0x14, 0x52, 0x3c, 0xa1, 0xe1, 0x06,
268                            0x4c, 0x25, 0x31, 0x56, 0xb2, 0xba, 0x7c, 0xfd,
269                            0x3d, 0x2d, 0x87, 0x28, 0xf4, 0xb3, 0x19, 0xe9,
270                            0x38, 0xd9, 0x78, 0x3c, 0x45, 0x7d, 0xfa, 0x9c,
271                            0x58, 0x3a, 0xaf, 0xda, 0x4b, 0xe1, 0x94, 0xcc,
272                            0xb0, 0xdb, 0x41, 0x5d, 0x5f, 0xd5, 0xf9, 0xeb,
273                            0x53, 0xcc, 0xd7, 0x14, 0xab, 0xdb, 0x13, 0x20,
274                            0x26, 0x59, 0xc0, 0x7e, 0xaa, 0x14, 0x7f, 0x80,
275                            0x0f, 0x73, 0x9a, 0xb2, 0xc4, 0x8c, 0x8b, 0x0d,
276                            0x56, 0xd0, 0x7a, 0xd1, 0x52, 0xca, 0xaa, 0x96,
277                            0x28, 0x8e, 0x98, 0xad, 0x6e, 0xf6, 0x36, 0x1a,
278                            0x6e, 0xdd, 0xba, 0x4f, 0xd5, 0xb1, 0x06, 0xe6,
279                            0xc8, 0x5a, 0x06, 0x93, 0x06, 0x51, 0xd1, 0x44,
280                            0xe1, 0x87, 0x54, 0x49, 0x2f, 0xfd, 0xa5, 0x2b,
281                            0x86, 0xbe, 0xea, 0x59, 0xa9, 0x09, 0xf5, 0x1f,
282                            0x01, 0xa4, 0x7a, 0x0b, 0xd9, 0xd0, 0x73, 0x13,
283                            0x1a, 0x4a, 0xb3, 0xd5, 0x4d, 0x37, 0x06, 0x6b,
284                            0x84, 0x48, 0xce, 0xbb, 0x0b, 0x81, 0x71, 0xa1,
285                            0x97, 0x3f, 0x95, 0x64, 0x6b, 0xfd, 0xb0, 0x37,
286                            0x4e, 0xfd, 0xa5, 0x0b, 0x08, 0xb3, 0xd0, 0xbc,
287                            0xbe, 0x27, 0x64, 0x72, 0x89, 0xc7, 0xc8, 0x58,
288                            0x7e, 0x83, 0x8a, 0x0f, 0xf5, 0x56, 0xa7, 0x53,
289                            0x06, 0x24, 0xa1, 0x9e, 0x2c, 0xd2, 0x35, 0x86,
290                            0xdf, 0x6d, 0x68, 0xdd, 0x7a, 0x95, 0xbf, 0xf5,
291                            0x7a, 0xa4, 0x52, 0xf9, 0xc2, 0x03, 0xa8, 0xa1,
292                            0x63, 0x38, 0x1e, 0xc9, 0x2b, 0x1d, 0xcb, 0x55,
293                            0x04, 0x4b, 0xed, 0x53, 0x06, 0xb4, 0x96, 0xc8,
294                            0x84, 0x73, 0x66, 0x66, 0xbe, 0xb9, 0xca, 0xfc,
295                            0x8b, 0x81, 0xe2, 0xbd, 0x0b, 0x8e, 0xa3, 0x93,
296                            0x98, 0x82, 0x1d, 0x8e, 0x99, 0xf7, 0x29, 0x48,
297                            0x3d, 0xeb, 0x70, 0xda, 0x02, 0x6e, 0x2e, 0xc7,
298                            0x6c, 0x60, 0x7c, 0x3d, 0xff, 0x78, 0xdc, 0x95,
299                            0x4b, 0xec, 0x89, 0x7a, 0x97, 0x61, 0x32, 0x7e,
300                            0x00, 0x59, 0x1d, 0x1d, 0xbe, 0x3a, 0x55, 0xb8,
301                            0x2e, 0xa1, 0xb4, 0xf8, 0x6c, 0xad, 0x92, 0xbc,
302                            0x47, 0x27, 0xe8, 0x0e, 0xad, 0x80, 0xca, 0xca,
303                            0xb2, 0x92, 0x71, 0xaa, 0x19, 0x2b, 0x3a, 0x4e,
304                            0xbb, 0x01, 0x76, 0x9b, 0x6d, 0x42, 0xd3, 0xc4,
305                            0x2f, 0x29, 0x8f, 0x3f, 0xd2, 0xd1, 0xd9, 0xcb,
306                            0x48, 0xb3, 0x99, 0xce, 0x78, 0xfa, 0x29, 0x69,
307                            0xdc, 0x55, 0xde, 0xcf, 0xc0, 0xc9, 0x2f, 0xbe,
308                            0x67, 0x22, 0xb4, 0x02, 0x38, 0x18, 0xbd, 0xa6,
309                            0x98, 0xcf, 0xc9, 0x42, 0x8e, 0xdd, 0xbd, 0xa0,
310                            0xcc, 0x17, 0xb2, 0x12, 0xd3, 0x32, 0x0f, 0x1e,
311                            0x0c, 0x8e, 0x94, 0x8b, 0x7c, 0xbe, 0x79, 0xeb])
312
313ADL_N_INTEL_PROD_KEY = bytes([0xe1, 0x71, 0x6a, 0xed, 0xfa, 0x0b, 0x75, 0xb3,
314                              0xd3, 0x1a, 0x7b, 0xd9, 0xb8, 0x56, 0x43, 0x90,
315                              0x81, 0x9e, 0x6e, 0x4f, 0xb6, 0x94, 0xa2, 0x44,
316                              0x3c, 0xd7, 0x80, 0x98, 0x54, 0x48, 0xa2, 0xbb,
317                              0x4a, 0xd2, 0xeb, 0x25, 0x8d, 0x5b, 0x5c, 0x18,
318                              0x5d, 0x0c, 0xa8, 0x87, 0xb7, 0xb7, 0xec, 0xeb,
319                              0x49, 0xf9, 0x03, 0x14, 0x81, 0x13, 0x11, 0xe0,
320                              0xbb, 0x41, 0x84, 0x93, 0xa1, 0x09, 0x2e, 0xbf,
321                              0xa3, 0xe6, 0xc5, 0x80, 0x76, 0x86, 0x08, 0xf3,
322                              0x37, 0x21, 0xd6, 0xce, 0x7e, 0xf2, 0x47, 0x31,
323                              0xd0, 0x07, 0x6c, 0x98, 0x15, 0x1f, 0x93, 0x07,
324                              0x31, 0x57, 0xc6, 0x90, 0x53, 0xcf, 0x27, 0x2d,
325                              0x01, 0x89, 0x22, 0xc0, 0xe0, 0x00, 0x86, 0xf8,
326                              0x8c, 0x58, 0x94, 0x97, 0x2c, 0x09, 0x6a, 0x26,
327                              0xda, 0x6b, 0x0d, 0x1d, 0xcd, 0x8e, 0x7f, 0x0b,
328                              0xed, 0xaf, 0xeb, 0x14, 0x79, 0x8c, 0x1f, 0xec,
329                              0xe4, 0xc6, 0xd2, 0x39, 0x20, 0x26, 0x2b, 0xec,
330                              0xf3, 0x07, 0x89, 0xfd, 0x13, 0x6f, 0xa7, 0x58,
331                              0xe0, 0xa9, 0xb2, 0xaa, 0xab, 0x7f, 0x87, 0xfd,
332                              0x7c, 0xcb, 0x92, 0xc0, 0x54, 0x06, 0x46, 0xef,
333                              0xb0, 0xab, 0xfc, 0x52, 0xd7, 0x18, 0x82, 0x18,
334                              0xa2, 0x4a, 0xa6, 0xe8, 0xf6, 0x1e, 0xbe, 0xcd,
335                              0xf3, 0x94, 0x4f, 0xd8, 0xd8, 0x94, 0xa8, 0x26,
336                              0xb2, 0x25, 0x28, 0x12, 0x33, 0x07, 0x69, 0xf5,
337                              0x55, 0x2c, 0xcd, 0x94, 0x83, 0x42, 0xe3, 0x4e,
338                              0xf2, 0xe8, 0x49, 0x0a, 0x40, 0xe9, 0x03, 0x1a,
339                              0x05, 0x34, 0x45, 0xab, 0x82, 0x1f, 0xad, 0x0d,
340                              0x5d, 0x24, 0x08, 0x25, 0x49, 0x7d, 0xaa, 0x06,
341                              0x30, 0x3e, 0x25, 0xf4, 0x47, 0x94, 0xba, 0x20,
342                              0xd2, 0xc2, 0x1d, 0x20, 0x83, 0x3f, 0xb1, 0xc7,
343                              0x9c, 0x69, 0x05, 0x82, 0xf4, 0x9e, 0x70, 0x8e,
344                              0x06, 0x67, 0x9d, 0xe2, 0x8a, 0x25, 0x86, 0x95,
345                              0xaf, 0xe0, 0x41, 0x56, 0x68, 0x84, 0xa5, 0x91,
346                              0xdb, 0x8e, 0xc6, 0xa7, 0xd6, 0xcb, 0xb3, 0x1f,
347                              0x46, 0x53, 0xe5, 0x52, 0x4d, 0xb7, 0x3f, 0x0d,
348                              0x98, 0x13, 0x80, 0xc0, 0xd5, 0x9f, 0x21, 0x55,
349                              0xcf, 0x38, 0x1e, 0xcf, 0x4f, 0x58, 0xf7, 0x68,
350                              0x98, 0xda, 0x15, 0xd4, 0x54, 0x89, 0xea, 0xdf,
351                              0x52, 0x98, 0x97, 0x92, 0xd8, 0xcc, 0x4b, 0xdc,
352                              0xf7, 0x1b, 0xc4, 0xe5, 0xdb, 0x5d, 0xe7, 0xae,
353                              0x9e, 0x00, 0x77, 0x32, 0x4c, 0x5f, 0x3b, 0x11,
354                              0xa0, 0xcf, 0xbe, 0xc3, 0xe6, 0x84, 0xd8, 0xa6,
355                              0x58, 0x36, 0x90, 0xbc, 0xc5, 0x98, 0xdc, 0xff,
356                              0x48, 0x2f, 0xe7, 0xdd, 0x26, 0xa6, 0x4d, 0x15,
357                              0xe6, 0x39, 0x7e, 0x41, 0xd2, 0x7d, 0xb6, 0x8f,
358                              0xf8, 0xec, 0x54, 0xb0, 0xec, 0xad, 0x0c, 0x30,
359                              0x7b, 0x6f, 0x9c, 0x5a, 0xe1, 0x92, 0xf7, 0x48,
360                              0x63, 0x32, 0xad, 0xad, 0xe3, 0x34, 0x59, 0xcc])
361
362COMMUNITY_KEY = bytes([0x85, 0x00, 0xe1, 0x68, 0xaa, 0xeb, 0xd2, 0x07,
363                       0x1b, 0x7c, 0x5e, 0xed, 0xd6, 0xe7, 0xe5, 0xf9,
364                       0xc1, 0x0e, 0x47, 0xd4, 0x4c, 0xab, 0x8c, 0xf0,
365                       0xe8, 0xee, 0x8b, 0x40, 0x36, 0x35, 0x58, 0x8f,
366                       0xf4, 0x6f, 0xfc, 0xfd, 0x0f, 0xdd, 0x55, 0x8b,
367                       0x45, 0x8c, 0xf0, 0x47, 0xdc, 0xb4, 0xac, 0x21,
368                       0x3b, 0x4b, 0x20, 0xe6, 0x81, 0xb3, 0xcc, 0x90,
369                       0xd4, 0x5e, 0xf1, 0xa4, 0x9b, 0x68, 0x52, 0xc8,
370                       0xf1, 0x2d, 0xf9, 0xc4, 0x77, 0xc6, 0x4d, 0xa9,
371                       0x90, 0xc7, 0x10, 0xfd, 0x43, 0xc8, 0x4b, 0x6b,
372                       0x23, 0x5e, 0x92, 0xf5, 0x8f, 0xac, 0xd5, 0x7d,
373                       0x60, 0x27, 0x36, 0x7c, 0x21, 0x4e, 0x21, 0x99,
374                       0xde, 0xcb, 0xc0, 0x45, 0xf3, 0x04, 0x22, 0xb8,
375                       0x7d, 0x16, 0x68, 0x40, 0xf9, 0x5c, 0xf0, 0xb9,
376                       0x7e, 0x8c, 0x05, 0xb6, 0xfc, 0x28, 0xbb, 0x3d,
377                       0xd8, 0xff, 0xb6, 0xa4, 0xd4, 0x54, 0x27, 0x3b,
378                       0x1a, 0x42, 0x4e, 0xf5, 0xa6, 0xa8, 0x5e, 0x44,
379                       0xe2, 0x9e, 0xed, 0x68, 0x6a, 0x27, 0x60, 0x13,
380                       0x8d, 0x2f, 0x27, 0x70, 0xcd, 0x57, 0xc9, 0x18,
381                       0xa3, 0xb0, 0x30, 0xa1, 0xf4, 0xe6, 0x32, 0x12,
382                       0x89, 0x2a, 0xaf, 0x40, 0xa5, 0xfd, 0x52, 0xf1,
383                       0xaa, 0x8a, 0xa4, 0xef, 0x20, 0x3d, 0x10, 0xa3,
384                       0x70, 0xf2, 0x39, 0xc5, 0x05, 0x99, 0x22, 0x10,
385                       0x81, 0x83, 0x6e, 0x45, 0xa4, 0xf3, 0x5a, 0x9d,
386                       0x6a, 0xb8, 0x88, 0xfe, 0x69, 0x40, 0xd1, 0xb1,
387                       0xcb, 0x2a, 0xdb, 0x28, 0x05, 0xde, 0x54, 0xbf,
388                       0x3d, 0x86, 0x5f, 0x39, 0x8b, 0xc1, 0xf4, 0xaf,
389                       0x00, 0x61, 0x86, 0x01, 0xfa, 0x22, 0xac, 0xf6,
390                       0x2c, 0xa4, 0x17, 0x6a, 0xa7, 0xd8, 0x0a, 0x8c,
391                       0x9f, 0xbf, 0x1f, 0x62, 0xb2, 0x2e, 0x68, 0x52,
392                       0x3f, 0x82, 0x8f, 0xe5, 0x28, 0x4d, 0xdb, 0xb5,
393                       0x5a, 0x96, 0x28, 0x27, 0x19, 0xaf, 0x43, 0xb9])
394
395COMMUNITY_KEY2 = bytes([0x6b, 0x75, 0xed, 0x58, 0x20, 0x08, 0x85, 0x95,
396                        0xa0, 0x49, 0x8b, 0x9e, 0xbd, 0x5f, 0x34, 0x82,
397                        0x0a, 0x9d, 0x1e, 0x9a, 0xb6, 0x76, 0x43, 0x19,
398                        0xb7, 0x76, 0x45, 0x5b, 0x59, 0xab, 0xbb, 0xf3,
399                        0x9e, 0x72, 0xf2, 0x41, 0x24, 0x92, 0x97, 0xef,
400                        0x39, 0xc0, 0xed, 0xc4, 0x7a, 0x4e, 0xdb, 0xec,
401                        0xeb, 0xc7, 0x4c, 0xf6, 0x45, 0xbe, 0xb2, 0xe0,
402                        0x13, 0x6a, 0xdc, 0x06, 0x7a, 0x1c, 0xbd, 0x8d,
403                        0xd8, 0xd2, 0xd7, 0x82, 0x6d, 0xbe, 0x03, 0x76,
404                        0x3b, 0x6b, 0xb8, 0x2f, 0xcc, 0xbe, 0x30, 0x56,
405                        0x61, 0x87, 0x09, 0xdf, 0x44, 0x51, 0xf8, 0x82,
406                        0xc5, 0x78, 0x05, 0x45, 0x8c, 0xe3, 0x78, 0x0e,
407                        0xd3, 0x7a, 0xd4, 0xf4, 0xbe, 0x96, 0xde, 0xb8,
408                        0x3b, 0x78, 0x90, 0x8b, 0xd3, 0xdd, 0x0b, 0xdd,
409                        0xbe, 0x56, 0xf3, 0x9a, 0x34, 0xc9, 0x38, 0x47,
410                        0x8d, 0xc4, 0xbd, 0x5e, 0x68, 0xf8, 0x62, 0xc4,
411                        0x28, 0xdd, 0x00, 0x48, 0x93, 0xb5, 0xad, 0x74,
412                        0x52, 0xe5, 0xf3, 0xd2, 0x97, 0xde, 0xbc, 0x0a,
413                        0x85, 0x95, 0xe9, 0xfa, 0xd2, 0xac, 0xdc, 0xdc,
414                        0x59, 0x74, 0xfa, 0x57, 0xf2, 0xd3, 0x61, 0xc6,
415                        0x2b, 0x26, 0xde, 0x57, 0x50, 0xe2, 0x58, 0x6b,
416                        0x79, 0x65, 0x0b, 0x49, 0x2c, 0x59, 0x28, 0x25,
417                        0x64, 0x31, 0x93, 0x65, 0x9a, 0x0a, 0x88, 0x98,
418                        0x9a, 0x77, 0x00, 0x47, 0x8f, 0xa0, 0xc7, 0x6b,
419                        0x58, 0x90, 0xa9, 0xb5, 0x15, 0xff, 0x65, 0x7c,
420                        0x84, 0x02, 0xd4, 0xdd, 0x09, 0xf1, 0x25, 0xad,
421                        0xf9, 0x30, 0xaa, 0x34, 0x5b, 0x77, 0xef, 0xb2,
422                        0x75, 0x3d, 0x54, 0x9d, 0xcc, 0x0d, 0x11, 0xda,
423                        0x91, 0x01, 0x2e, 0x51, 0xdc, 0x0c, 0x8a, 0x92,
424                        0x71, 0x44, 0x9a, 0xd5, 0x69, 0x5d, 0x7a, 0xad,
425                        0xaf, 0xdf, 0x25, 0xea, 0x95, 0x21, 0xbb, 0x99,
426                        0x53, 0x89, 0xbc, 0x54, 0xca, 0xf3, 0x54, 0xf5,
427                        0xbb, 0x38, 0x27, 0x64, 0xce, 0xf2, 0x17, 0x25,
428                        0x75, 0x33, 0x1a, 0x2d, 0x19, 0x00, 0xff, 0x9b,
429                        0xd9, 0x4d, 0x0c, 0xb1, 0xa5, 0x55, 0x55, 0xa9,
430                        0x29, 0x8e, 0xfb, 0x82, 0x43, 0xeb, 0xfa, 0xc8,
431                        0x33, 0x76, 0xf3, 0x7d, 0xee, 0x95, 0xe1, 0x39,
432                        0xba, 0xa5, 0x4a, 0xd5, 0xb1, 0x8a, 0xa6, 0xff,
433                        0x8f, 0x4b, 0x45, 0x8c, 0xe9, 0x7b, 0x87, 0xae,
434                        0x8d, 0x32, 0x6e, 0x16, 0xe7, 0x9e, 0x85, 0x22,
435                        0x71, 0x3d, 0x17, 0xba, 0x54, 0xed, 0x73, 0x87,
436                        0xe5, 0x9d, 0xbf, 0xc0, 0xcd, 0x76, 0xfa, 0x83,
437                        0xd4, 0xc5, 0x30, 0xd1, 0xc7, 0x25, 0x49, 0x25,
438                        0x75, 0x4d, 0x0a, 0x4a, 0x2d, 0x13, 0x1c, 0x12,
439                        0x2e, 0x5d, 0x2a, 0xe2, 0xa9, 0xae, 0xbf, 0x8f,
440                        0xdf, 0x24, 0x76, 0xf5, 0x81, 0x1e, 0x09, 0x5d,
441                        0x63, 0x04, 0xaf, 0x24, 0x45, 0x87, 0xf4, 0x96,
442                        0x55, 0xd1, 0x7d, 0xc6, 0x0d, 0x79, 0x12, 0xa9])
443
444KNOWN_KEYS = {APL_INTEL_PROD_KEY : 'APL Intel prod key',
445              CNL_INTEL_PROD_KEY : 'CNL Intel prod key',
446              ICL_INTEL_PROD_KEY : 'ICL Intel prod key',
447              JSL_INTEL_PROD_KEY : 'JSL Intel prod key',
448              TGL_INTEL_PROD_KEY : 'TGL Intel prod key',
449              EHL_INTEL_PROD_KEY : 'EHL Intel prod key',
450              ADL_INTEL_PROD_KEY : 'ADL Intel prod key',
451              ADL_N_INTEL_PROD_KEY : 'ADL-N Intel prod key',
452              COMMUNITY_KEY : 'Community key',
453              COMMUNITY_KEY2 : 'Community 3k key'}
454
455def parse_params():
456    """ Parses parameters
457    """
458    parser = argparse.ArgumentParser(description='SOF Binary Info Utility')
459    parser.add_argument('-v', '--verbose', help='increase output verbosity',
460                        action='store_true')
461    parser.add_argument('--headers', help='display headers only',
462                        action='store_true')
463    parser.add_argument('--full_bytes', help='display full byte arrays',
464                        action='store_true')
465    parser.add_argument('--no_colors', help='disable colors in output',
466                        action='store_true')
467    parser.add_argument('--no_cse', help='disable cse manifest parsing',
468                        action='store_true')
469    parser.add_argument('--no_headers', help='skip information about headers',
470                        action='store_true')
471    parser.add_argument('--no_modules', help='skip information about modules',
472                        action='store_true')
473    parser.add_argument('--no_memory', help='skip information about memory',
474                        action='store_true')
475    parser.add_argument('--erase_vars', help='''
476    Replace the variable signature and any other variable element with constants
477    ''', type=pathlib.Path, dest='erased_vars_image')
478    parser.add_argument('sof_ri_path', help='path to fw binary file to parse')
479    parsed_args = parser.parse_args()
480
481    return parsed_args
482
483# Helper Functions
484
485def change_color(color):
486    """ Prints escape code to change text color
487    """
488    color_code = {'red':91, 'green':92, 'yellow':93, 'blue':94,
489                  'magenta':95, 'cyan':96, 'white':98, 'none':0}
490    return '\033[{}m'.format(color_code[color])
491
492def uint_to_string(uint, both=False):
493    """ Prints uint in readable form
494    """
495    if both:
496        return hex(uint) + ' (' + repr(uint) + ')'
497    return hex(uint)
498
499def date_to_string(date):
500    """ Prints BCD date in readable form
501    """
502    return date[2:6]+'/'+date[6:8]+'/'+date[8:10]
503
504def chararr_to_string(chararr, max_len):
505    """ Prints array of characters (null terminated or till max_len)
506        in readable form
507    """
508    out = ''
509    for i in range(0, max_len):
510        if chararr[i] == 0:
511            return out
512        out += '{:c}'.format(chararr[i])
513    return out
514
515def mod_type_to_string(mod_type):
516    """ Prints module type in readable form
517    """
518    out = '('
519    # type
520    if (mod_type & 0xf) == 0:
521        out += ' builtin'
522    elif (mod_type & 0xf) == 1:
523        out += ' loadable'
524    # Module that may be instantiated by fw on startup
525    if ((mod_type >> 4) & 0x1) == 1:
526        out += ' auto_start'
527    # Module designed to run with low latency scheduler
528    if ((mod_type >> 5) & 0x1) == 1:
529        out += ' LL'
530    # Module designed to run with edf scheduler
531    if ((mod_type >> 6) & 0x1) == 1:
532        out += ' DP'
533    out += ' )'
534    return out
535
536def seg_flags_to_string(flags):
537    """ Prints module segment flags in readable form
538    """
539    out = '('
540    if flags & 0x1 == 0x1:
541        out = out + ' contents'
542    if flags & 0x2 == 0x2:
543        out = out + ' alloc'
544    if flags & 0x4 == 0x4:
545        out = out + ' load'
546    if flags & 0x8 == 0x8:
547        out = out + ' readonly'
548    if flags & 0x10 == 0x10:
549        out = out + ' code'
550    if flags & 0x20 == 0x20:
551        out = out + ' data'
552    out = out + ' type=' + repr((flags>>8)&0xf)
553    out = out + ' pages=' + repr((flags>>16)&0xffff)
554    out = out + ' )'
555    return out
556
557# Parsers
558
559def parse_extended_manifest_ae1(reader):
560    ext_mft = ExtendedManifestAE1()
561    hdr = Component('ext_mft_hdr', 'Header', 0)
562    ext_mft.add_comp(hdr)
563
564    sig = reader.read_string(4)
565    reader.info('Extended Manifest (' + sig + ')', -4)
566    hdr.add_a(Astring('sig', sig))
567
568    # Next dword is the total length of the extended manifest
569    # (need to use it for further parsing)
570    reader.ext_mft_length = reader.read_dw()
571    hdr.add_a(Auint('length', reader.ext_mft_length))
572    hdr.add_a(Astring('ver', '{}.{}'.format(reader.read_w(), reader.read_w())))
573    hdr.add_a(Auint('entries', reader.read_dw()))
574
575    reader.ff_data(reader.ext_mft_length-16)
576    return ext_mft
577
578def parse_extended_manifest_xman(reader):
579    ext_mft = ExtendedManifestXMan()
580    hdr = Component('ext_mft_hdr', 'Header', 0)
581    ext_mft.add_comp(hdr)
582
583    sig = reader.read_string(4)
584    reader.info('Extended Manifest (' + sig + ')', -4)
585    hdr.add_a(Astring('sig', sig))
586
587    # Next dword is the total length of the extended manifest
588    # (need to use it for further parsing)
589    reader.ext_mft_length = reader.read_dw()
590    hdr_length = reader.read_dw()
591    hdr_ver = reader.read_dw()
592
593    major = hdr_ver >> 24
594    minor = (hdr_ver >> 12) & 0xFFF
595    patch = hdr_ver & 0xFFF
596
597    hdr.add_a(Auint('length', reader.ext_mft_length))
598    hdr.add_a(Astring('ver', '{}.{}.{}'.format(major, minor, patch)))
599    hdr.add_a(Auint('hdr_length', hdr_length))
600
601    reader.ff_data(reader.ext_mft_length-16)
602    return ext_mft
603
604def parse_extended_manifest(reader):
605    """ Parses extended manifest from sof binary
606    """
607
608    reader.info('Looking for Extended Manifest')
609    # Try to detect signature first
610    sig = reader.read_string(4)
611    reader.set_offset(0)
612    if sig == '$AE1':
613        ext_mft = parse_extended_manifest_ae1(reader)
614    elif sig == 'XMan':
615        ext_mft = parse_extended_manifest_xman(reader)
616    else:
617        ext_mft = ExtendedManifestAE1()
618        hdr = Component('ext_mft_hdr', 'Header', 0)
619        ext_mft.add_comp(hdr)
620        reader.info('info: Extended Manifest not found (sig = '+sig+')')
621        reader.ext_mft_length = 0
622        hdr.add_a(Auint('length', reader.ext_mft_length))
623
624    return ext_mft
625
626def parse_cse_manifest(reader):
627    """ Parses CSE manifest form sof binary
628    """
629    reader.info('Looking for CSE Manifest')
630    cse_mft = CseManifest(reader.get_offset())
631
632    # Try to detect signature first
633    sig = reader.read_string(4)
634    if sig != '$CPD':
635        raise Exception('CSE Manifest magic number NOT found, instead: ('
636                     + sig + ')', -4)
637    reader.info('CSE Manifest (' + sig + ')', -4)
638
639    # Read the header
640    hdr = Component('cse_mft_hdr', 'Header', reader.get_offset())
641    cse_mft.add_comp(hdr)
642    hdr.add_a(Astring('sig', sig))
643    # read number of entries
644    nb_entries = reader.read_dw()
645    reader.info('# of entries {}'.format(nb_entries))
646    hdr.add_a(Adec('nb_entries', nb_entries))
647    # read version (1byte for header ver and 1 byte for entry ver)
648    ver = reader.read_w()
649    hdr.add_a(Ahex('header_version', ver))
650    header_length = reader.read_b()
651    hdr.add_a(Ahex('header_length', header_length))
652    hdr.add_a(Ahex('checksum', reader.read_b()))
653    hdr.add_a(Astring('partition_name', reader.read_string(4)))
654
655    reader.set_offset(cse_mft.file_offset + header_length)
656    # Read entries
657    nb_index = 0
658    while nb_index < nb_entries:
659        reader.info('Reading CSE Manifest entry %d...' % nb_index)
660        entry_name = reader.read_string(12)
661        entry_offset = reader.read_dw()
662        entry_length = reader.read_dw()
663        # reserved field
664        reader.read_dw()
665
666        hdr_entry = Component('cse_hdr_entry', 'Entry', reader.get_offset())
667        hdr_entry.add_a(Astring('entry_name', entry_name))
668        hdr_entry.add_a(Ahex('entry_offset', entry_offset))
669        hdr_entry.add_a(Ahex('entry_length', entry_length))
670        hdr.add_comp(hdr_entry)
671
672        assert cse_mft.file_offset == reader.ext_mft_length
673        entry_file_offset = reader.ext_mft_length + entry_offset
674        reader.info('... CSE Entry name {} file offset 0x{:x} length {}'.format(entry_name,
675                    entry_file_offset, entry_length))
676
677        if '.man' in entry_name:
678            entry = CssManifest(entry_name, entry_file_offset)
679            cur_off = reader.set_offset(entry_file_offset)
680            parse_css_manifest(entry, reader,
681                               entry_file_offset + entry_length)
682            reader.set_offset(cur_off)
683        elif '.met' in entry_name:
684            cur_off = reader.set_offset(entry_file_offset)
685            entry = parse_mft_extension(reader, 0)
686            entry.name = '{} ({})'.format(entry_name, entry.name)
687            reader.set_offset(cur_off)
688        else:
689            # indicate the place, the entry is enumerated. mft parsed later
690            entry = Component('adsp_mft_cse_entry', entry_name, entry_file_offset)
691        cse_mft.add_comp(entry)
692
693        nb_index += 1
694
695    return cse_mft
696
697def parse_css_manifest(css_mft, reader, limit):
698    """ Parses CSS manifest from sof binary
699    """
700    reader.info('Parsing CSS Manifest')
701    ver, = struct.unpack('I', reader.get_data(0, 4))
702    if ver == 4:
703        reader.info('CSS Manifest type 4')
704        return parse_css_manifest_4(css_mft, reader, limit)
705
706    raise Exception('CSS Manifest NOT found or NOT recognized!')
707
708def parse_css_manifest_4(css_mft, reader, size_limit):
709    """ Parses CSS manifest type 4 from sof binary
710    """
711
712    reader.info('Parsing CSS Manifest type 4')
713    # CSS Header
714    hdr = Component('css_mft_hdr', 'Header', reader.get_offset())
715    css_mft.add_comp(hdr)
716
717    hdr.add_a(Auint('type', reader.read_dw()))
718    header_len_dw = reader.read_dw()
719    hdr.add_a(Auint('header_len_dw', header_len_dw))
720    hdr.add_a(Auint('header_version', reader.read_dw()))
721    hdr.add_a(Auint('reserved0', reader.read_dw(), 'red'))
722    hdr.add_a(Ahex('mod_vendor', reader.read_dw()))
723    date_start = reader.get_offset()
724    hdr.add_a(Auint('date_start', date_start))
725    hdr.add_a(Adate('date', hex(reader.read_dw())))
726    hdr.add_a(Auint('date_length', reader.get_offset() - date_start))
727    size = reader.read_dw()
728    hdr.add_a(Auint('size', size))
729    hdr.add_a(Astring('header_id', reader.read_string(4)))
730    hdr.add_a(Auint('padding', reader.read_dw()))
731    hdr.add_a(Aversion('fw_version', reader.read_w(), reader.read_w(),
732                       reader.read_w(), reader.read_w()))
733    hdr.add_a(Auint('svn', reader.read_dw()))
734    reader.read_bytes(18*4)
735    modulus_size = reader.read_dw()
736    hdr.add_a(Adec('modulus_size', modulus_size))
737    exponent_size = reader.read_dw()
738    hdr.add_a(Adec('exponent_size', exponent_size))
739    modulus = reader.read_bytes(modulus_size * 4)
740    hdr.add_a(Amodulus('modulus', modulus, KNOWN_KEYS.get(modulus, 'Unknown key')))
741    hdr.add_a(Abytes('exponent', reader.read_bytes(exponent_size * 4)))
742
743    sig_start = reader.get_offset()
744    hdr.add_a(Auint('signature_start', sig_start))
745    hdr.add_a(Abytes('signature', reader.read_bytes(modulus_size * 4)))
746    hdr.add_a(Auint('signature_length', reader.get_offset() - sig_start))
747
748    # Move right after the header
749    reader.set_offset(css_mft.file_offset + header_len_dw*4)
750
751    # Anything packed here is
752    #   either an 'Extension' beginning with
753    #     dw0 - extension type
754    #     dw1 - extension length (in bytes)
755    #   that could be parsed if extension type is recognized
756    #
757    #   or series of 0xffffffff that should be skipped
758    reader.info('Parsing CSS Manifest extensions, end at 0x{:x}'.format(size_limit))
759    ext_idx = 0
760    while reader.get_offset() < size_limit:
761        ext_type = reader.read_dw()
762        reader.info('Reading CSS extension type 0x{:x}:'.format(ext_type))
763        if ext_type == 0xffffffff:
764            continue
765        reader.set_offset(reader.get_offset() - 4)
766        css_mft.add_comp(parse_mft_extension(reader, ext_idx))
767        ext_idx += 1
768
769    assert reader.get_offset() == size_limit # wrong extension length
770
771    css_mft.length = reader.get_offset() - css_mft.file_offset
772    return css_mft
773
774def parse_mft_extension(reader, ext_id):
775    """ Parses mft extension from sof binary
776    """
777    begin_off = reader.get_offset()
778    ext_type = reader.read_dw()
779    ext_len = reader.read_dw()
780    if ext_type == 15:
781        reader.info("Plat Fw Auth extension")
782        ext = PlatFwAuthExtension(ext_id, reader.get_offset()-8)
783        ext.add_a(Astring('name', reader.read_string(4)))
784        ext.add_a(Auint('vcn', reader.read_dw()))
785        ext.add_a(Abytes('bitmap', reader.read_bytes(16), 'red'))
786        ext.add_a(Auint('svn', reader.read_dw()))
787        read_len = reader.get_offset() - begin_off
788        reader.ff_data(ext_len - read_len)
789    elif ext_type == 17:
790        reader.info("ADSP metadata file extension")
791        ext = AdspMetadataFileExt(ext_id, reader.get_offset()-8)
792        ext.add_a(Auint('adsp_imr_type', reader.read_dw(), 'red'))
793        # skip reserved part
794        reader.read_bytes(16)
795        reader.read_dw()
796        reader.read_dw()
797        #
798        ext.add_a(Auint('version', reader.read_dw()))
799        ext.add_a(Abytes('sha_hash', reader.read_bytes(32)))
800        ext.add_a(Auint('base_offset', reader.read_dw()))
801        ext.add_a(Auint('limit_offset', reader.read_dw()))
802        ext.add_a(Abytes('attributes', reader.read_bytes(16)))
803    else:
804        reader.info("Other extension")
805        ext = MftExtension(ext_id, 'Other Extension', reader.get_offset()-8)
806        reader.ff_data(ext_len-8)
807    ext.add_a(Auint('type', ext_type))
808    ext.add_a(Auint('length', ext_len))
809    reader.info("... end of extension")
810    return ext
811
812def parse_adsp_manifest_hdr(reader):
813    """ Parses ADSP manifest hader from sof binary
814    """
815    # Verify signature
816    try:
817        sig = reader.read_string(4)
818    except UnicodeDecodeError:
819        raise Exception('\n' + reader.offset_to_string() + \
820              '\terror: Failed to decode signature, wrong position?')
821    if sig != '$AM1':
822        raise Exception('ADSP Manifest NOT found!', -4)
823    reader.info('ADSP Manifest (' + sig + ')', -4)
824
825    hdr = Component('adsp_mft_hdr', 'ADSP Manifest Header',
826                    reader.get_offset() -4)
827    hdr.add_a(Astring('sig', sig))
828
829    hdr.add_a(Auint('size', reader.read_dw()))
830    hdr.add_a(Astring('name', chararr_to_string(reader.read_bytes(8), 8)))
831    hdr.add_a(Auint('preload', reader.read_dw()))
832    hdr.add_a(Auint('fw_image_flags', reader.read_dw()))
833    hdr.add_a(Auint('feature_mask', reader.read_dw()))
834    hdr.add_a(Aversion('build_version', reader.read_w(), reader.read_w(),
835                       reader.read_w(), reader.read_w()))
836
837    hdr.add_a(Adec('num_module_entries', reader.read_dw()))
838    hdr.add_a(Ahex('hw_buf_base_addr', reader.read_dw()))
839    hdr.add_a(Auint('hw_buf_length', reader.read_dw()))
840    hdr.add_a(Ahex('load_offset', reader.read_dw()))
841
842    return hdr
843
844def parse_adsp_manifest_mod_entry(index, reader):
845    """ Parses ADSP manifest module entry from sof binary
846    """
847    # Verify Mod Entry signature
848    try:
849        sig = reader.read_string(4)
850    except UnicodeDecodeError:
851        raise Exception(reader.offset_to_string() + \
852              '\terror: Failed to decode ModuleEntry signature')
853    if sig != '$AME':
854        raise Exception('ModuleEntry signature NOT found!')
855    reader.info('Module Entry signature found (' + sig + ')', -4)
856
857    mod = AdspModuleEntry('mod_entry_'+repr(index),
858                          reader.get_offset() -4)
859    mod.add_a(Astring('sig', sig))
860
861    mod.add_a(Astring('mod_name',
862                      chararr_to_string(reader.read_bytes(8), 8)))
863    mod.add_a(Astring('uuid', reader.read_uuid()))
864    me_type = reader.read_dw()
865    mod.add_a(Astring('type',
866                      hex(me_type) + ' ' + mod_type_to_string(me_type)))
867    mod.add_a(Abytes('hash', reader.read_bytes(32)))
868    mod.add_a(Ahex('entry_point', reader.read_dw()))
869    mod.add_a(Adec('cfg_offset', reader.read_w()))
870    mod.add_a(Adec('cfg_count', reader.read_w()))
871    mod.add_a(Auint('affinity_mask', reader.read_dw()))
872    mod.add_a(Adec('instance_max_count', reader.read_w()))
873    mod.add_a(Auint('instance_stack_size', reader.read_w()))
874    for i in range(0, 3):
875        seg_flags = reader.read_dw()
876        mod.add_a(Astring('seg_'+repr(i)+'_flags',
877                          hex(seg_flags) + ' ' + seg_flags_to_string(seg_flags)))
878        mod.add_a(Ahex('seg_'+repr(i)+'_v_base_addr', reader.read_dw()))
879        mod.add_a(Ahex('seg_'+repr(i)+'_size', ((seg_flags>>16)&0xffff)*0x1000))
880        mod.add_a(Ahex('seg_'+repr(i)+'_file_offset', reader.read_dw()))
881
882    return mod
883
884def parse_adsp_manifest(reader, name):
885    """ Parses ADSP manifest from sof binary
886    """
887    adsp_mft = AdspManifest(name, reader.get_offset())
888    adsp_mft.add_comp(parse_adsp_manifest_hdr(reader))
889    num_module_entries = adsp_mft.cdir['adsp_mft_hdr'].adir['num_module_entries'].val
890    for i in range(0, num_module_entries):
891        mod_entry = parse_adsp_manifest_mod_entry(i, reader)
892        adsp_mft.add_comp(mod_entry)
893
894    return adsp_mft
895
896def parse_fw_bin(path, no_cse, verbose):
897    """ Parses sof binary
898    """
899    reader = BinReader(path, verbose)
900
901    parsed_bin = FwBin()
902    parsed_bin.add_a(Astring('file_name', reader.file_name))
903    parsed_bin.add_a(Auint('file_size', reader.file_size))
904    parsed_bin.add_comp(parse_extended_manifest(reader))
905    if not no_cse:
906        parsed_bin.add_comp(parse_cse_manifest(reader))
907    reader.set_offset(reader.ext_mft_length + 0x2000)
908    parsed_bin.add_comp(parse_adsp_manifest(reader, 'cavs0015'))
909
910    reader.info('Parsing finished', show_offset = False)
911    return parsed_bin
912
913class BinReader():
914    """ sof binary reader
915    """
916    def __init__(self, path, verbose):
917        self.verbose = verbose
918        self.cur_offset = 0
919        self.ext_mft_length = 0
920        self.info(f'Reading SOF ri image {path}', show_offset=False)
921        self.file_name = path
922        # read the content
923        self.data = open(path, 'rb').read()
924        self.file_size = len(self.data)
925        self.info('File size ' + uint_to_string(self.file_size, True),
926                  show_offset=False)
927
928    def get_offset(self):
929        """ Retrieve the offset, the reader is at
930        """
931        return self.cur_offset
932
933    def ff_data(self, delta_offset):
934        """ Forwards the read pointer by specified number of bytes
935        """
936        self.cur_offset += delta_offset
937
938    def set_offset(self, offset):
939        """ Set current reader offset
940        """
941        old_offset = self.cur_offset
942        self.cur_offset = offset
943        return old_offset
944
945    def get_data(self, beg, length):
946        """ Retrieves the data from beg to beg+length.
947            This one is good to peek the data w/o advancing the read pointer
948        """
949        return self.data[self.cur_offset +beg : self.cur_offset +beg +length]
950
951    def read_bytes(self, count):
952        """ Reads the specified number of bytes from the stream
953        """
954        bts = self.get_data(0, count)
955        self.ff_data(count)
956        return bts
957
958    def read_dw(self):
959        """ Reads a dword from the stream
960        """
961        dword, = struct.unpack('I', self.get_data(0, 4))
962        self.ff_data(4)
963        return dword
964
965    def read_w(self):
966        """ Reads a word from the stream
967        """
968        word, = struct.unpack('H', self.get_data(0, 2))
969        self.ff_data(2)
970        return word
971
972    def read_b(self):
973        """ Reads a byte from the stream
974        """
975        byte, = struct.unpack('B', self.get_data(0, 1))
976        self.ff_data(1)
977        return byte
978
979    def read_string(self, size_in_file):
980        """ Reads a string from the stream, potentially padded with zeroes
981        """
982        return self.read_bytes(size_in_file).decode().rstrip('\0')
983
984    def read_uuid(self):
985        """ Reads a UUID from the stream and returns as string
986        """
987        out = '{:08x}'.format(self.read_dw())
988        out += '-'+'{:04x}'.format(self.read_w())
989        out += '-'+'{:04x}'.format(self.read_w())
990        out += '-'+'{:02x}'.format(self.read_b()) + \
991               '{:02x}'.format(self.read_b()) + '-'
992        for _ in range(0, 6):
993            out += '{:02x}'.format(self.read_b())
994        return out
995
996    def offset_to_string(self, delta=0):
997        """ Retrieves readable representation of the current offset value
998        """
999        return uint_to_string(self.cur_offset+delta)
1000
1001    def info(self, loginfo, off_delta=0, verb_info=True, show_offset=True):
1002        """ Prints 'info' log to the output, respects verbose mode
1003        """
1004        if verb_info and not self.verbose:
1005            return
1006        if show_offset:
1007            print(self.offset_to_string(off_delta) + '\t' + loginfo)
1008        else:
1009            print(loginfo)
1010
1011    def error(self, logerror, off_delta=0):
1012        """ Prints 'error' log to the output
1013        """
1014        print(self.offset_to_string(off_delta) + '\terror: ' + logerror,
1015              file=sys.stderr)
1016
1017# Data Model
1018
1019class Attribute():
1020    """ Attribute: base class with global formatting options
1021    """
1022    no_colors = False
1023    full_bytes = True
1024
1025class Auint(Attribute):
1026    """ Attribute : unsigned integer
1027    """
1028    def __init__(self, name, val, color='none'):
1029        self.name = name
1030        self.val = val
1031        self.color = color
1032
1033    def __str__(self):
1034        if Attribute.no_colors:
1035            return uint_to_string(self.val)
1036        return '{}{}{}'.format(change_color(self.color),
1037                               uint_to_string(self.val),
1038                               change_color('none'))
1039
1040class Ahex(Attribute):
1041    """ Attribute : unsigned integer printed as hex
1042    """
1043    def __init__(self, name, val, color='none'):
1044        self.name = name
1045        self.val = val
1046        self.color = color
1047
1048    def __str__(self):
1049        if Attribute.no_colors:
1050            return hex(self.val)
1051        return '{}{}{}'.format(change_color(self.color), hex(self.val),
1052                               change_color('none'))
1053
1054class Adec(Attribute):
1055    """ Attribute: integer printed as dec
1056    """
1057    def __init__(self, name, val):
1058        self.name = name
1059        self.val = val
1060
1061    def __str__(self):
1062        return repr(self.val)
1063
1064class Abytes(Attribute):
1065    """ Attribute: array of bytes
1066    """
1067    def __init__(self, name, val, color='none'):
1068        self.name = name
1069        self.val = val
1070        self.color = color
1071
1072    def __str__(self):
1073        length = len(self.val)
1074        if Attribute.no_colors:
1075            out = ''
1076        else:
1077            out = '{}'.format(change_color(self.color))
1078        if length <= 16:
1079            out += ' '.join(['{:02x}'.format(b) for b in self.val])
1080        elif Attribute.full_bytes:
1081            """ n is num pre row
1082                print 8 num pre line, useful for add more KEY
1083            """
1084            n = 8
1085            out += '\n'
1086            out += ',\n'.join([', '.join(['0x{:02x}'.format(b) for b in self.val[i:i + n]]) for i in range(0, length, n)])
1087        else:
1088            out += ' '.join('{:02x}'.format(b) for b in self.val[:8])
1089            out += ' ... '
1090            out += ' '.join('{:02x}'.format(b) for b in self.val[length-8:length])
1091        if not Attribute.no_colors:
1092            out += '{}'.format(change_color('none'))
1093        return out
1094
1095class Adate(Attribute):
1096    """ Attribute: Date in BCD format
1097    """
1098    def __init__(self, name, val):
1099        self.name = name
1100        self.val = val
1101
1102    def __str__(self):
1103        return date_to_string(self.val)
1104
1105class Astring(Attribute):
1106    """ Attribute: String
1107    """
1108    def __init__(self, name, val):
1109        self.name = name
1110        self.val = val
1111
1112    def __str__(self):
1113        return self.val
1114
1115class Aversion(Attribute):
1116    """ Attribute: version
1117    """
1118    def __init__(self, name, major, minor, hotfix, build):
1119        self.name = name
1120        self.val = '{:d}.{:d}.{:d}.{:d}'.format(major, minor, hotfix, build)
1121
1122    def __str__(self):
1123        return self.val
1124
1125class Amodulus(Abytes):
1126    """ Attribute: modulus from RSA public key
1127    """
1128    def __init__(self, name, val, val_type):
1129        super().__init__(name, val)
1130        self.val_type = val_type
1131
1132    def __str__(self):
1133        out = super().__str__()
1134        if not Attribute.full_bytes:
1135            if Attribute.no_colors:
1136                out += ' ({})'.format(self.val_type)
1137            else:
1138                out += ' {}({}){}'.format(change_color('red'), self.val_type,
1139                                          change_color('none'))
1140        return out
1141
1142class Component():
1143    """ A component of sof binary
1144    """
1145    def __init__(self, uid, name, file_offset):
1146        self.uid = uid
1147        self.name = name
1148        self.file_offset = file_offset
1149        self.attribs = []
1150        self.adir = {}
1151        self.max_attr_name_len = 0
1152        self.components = []
1153        self.cdir = {}
1154
1155    def add_a(self, attrib):
1156        """ Adds an attribute
1157        """
1158        self.max_attr_name_len = max(self.max_attr_name_len,
1159                                     len(attrib.name))
1160        self.attribs.append(attrib)
1161        self.adir[attrib.name] = attrib
1162
1163    def add_comp(self, comp):
1164        """ Adds a nested component
1165        """
1166        self.components.append(comp)
1167        self.cdir[comp.uid] = comp
1168
1169    def get_comp(self, comp_uid):
1170        """ Retrieves a nested component by id
1171        """
1172        for comp in self.components:
1173            if comp.uid == comp_uid:
1174                return comp
1175        return None
1176
1177    def dump_info(self, pref, comp_filter):
1178        """ Prints out the content (name, all attributes, and nested comps)
1179        """
1180        print(pref + self.name)
1181        for attrib in self.attribs:
1182            print("{:}  {:<{:}} {:}".format(pref, attrib.name,
1183                                            self.max_attr_name_len, attrib))
1184        self.dump_comp_info(pref, comp_filter)
1185
1186    def dump_attrib_info(self, pref, attr_name):
1187        """ Prints out a single attribute
1188        """
1189        attrib = self.adir[attr_name]
1190        print("{:}  {:<{:}} {:}".format(pref, attrib.name,
1191                                        self.max_attr_name_len, attrib))
1192
1193    def dump_comp_info(self, pref, comp_filter=''):
1194        """ Prints out all nested components (filtered by name set to 'filter')
1195        """
1196        for comp in self.components:
1197            if comp.name in comp_filter:
1198                continue
1199            print()
1200            comp.dump_info(pref + '  ', comp_filter)
1201
1202    def add_comp_to_mem_map(self, mem_map):
1203        for comp in self.components:
1204            comp.add_comp_to_mem_map(mem_map)
1205
1206class ExtendedManifestAE1(Component):
1207    """ Extended manifest
1208    """
1209    def __init__(self):
1210        super(ExtendedManifestAE1, self).__init__('ext_mft',
1211                                               'Extended Manifest', 0)
1212
1213    def dump_info(self, pref, comp_filter):
1214        hdr = self.cdir['ext_mft_hdr']
1215        if hdr.adir['length'].val == 0:
1216            return
1217        out = '{}{}'.format(pref, self.name)
1218        out += ' ver {}'.format(hdr.adir['ver'])
1219        out += ' entries {}'.format(hdr.adir['entries'])
1220        print(out)
1221        self.dump_comp_info(pref, comp_filter + ['Header'])
1222
1223class ExtendedManifestXMan(Component):
1224    """ Extended manifest
1225    """
1226    def __init__(self):
1227        super(ExtendedManifestXMan, self).__init__('ext_mft',
1228                                               'Extended Manifest', 0)
1229
1230    def dump_info(self, pref, comp_filter):
1231        hdr = self.cdir['ext_mft_hdr']
1232        if hdr.adir['length'].val == 0:
1233            return
1234        out = '{}{}'.format(pref, self.name)
1235        out += ' ver {}'.format(hdr.adir['ver'])
1236        out += ' length {}'.format(hdr.adir['length'].val)
1237        print(out)
1238        self.dump_comp_info(pref, comp_filter + ['Header'])
1239
1240class CseManifest(Component):
1241    """ CSE Manifest
1242    """
1243    def __init__(self, offset):
1244        super(CseManifest, self).__init__('cse_mft', 'CSE Manifest', offset)
1245
1246    def dump_info(self, pref, comp_filter):
1247        hdr = self.cdir['cse_mft_hdr']
1248        print('{}{} ver {} checksum {} partition name {}'.
1249              format(pref,
1250                     self.name, hdr.adir['header_version'],
1251                     hdr.adir['checksum'], hdr.adir['partition_name']))
1252        self.dump_comp_info(pref, comp_filter + ['Header'])
1253
1254class CssManifest(Component):
1255    """ CSS Manifest
1256    """
1257    def __init__(self, name, offset):
1258        super(CssManifest, self).__init__('css_mft', name, offset)
1259
1260    def dump_info(self, pref, comp_filter):
1261        hdr = self.cdir['css_mft_hdr']
1262        out = '{}{} (CSS Manifest)'.format(pref, self.name)
1263        out += ' type {}'.format(hdr.adir['type'])
1264        out += ' file offset {:#x} hdr_len {}'.format(
1265            self.file_offset, hdr.adir['header_len_dw'].val * 4
1266        )
1267        out += ' ver {}'.format(hdr.adir['header_version'])
1268        out += ' date {}'.format(hdr.adir['date'])
1269        print(out)
1270        print('{}  Rsvd0 {}'.
1271              format(pref, hdr.adir['reserved0']))
1272        print('{}  Modulus size (dwords) {}'.
1273              format(pref, hdr.adir['modulus_size']))
1274        print('{}    {}'.format(pref, hdr.adir['modulus']))
1275        print('{}  Exponent size (dwords) {}'.
1276              format(pref,
1277                     hdr.adir['exponent_size']))
1278        print('{}    {}'.format(pref, hdr.adir['exponent']))
1279        print('{}  Signature (file offset {}, length {})'.format(
1280            pref, hdr.adir['signature_start'], hdr.adir['signature_length']))
1281        print('{}    {}'.format(pref, hdr.adir['signature']))
1282        # super().dump_info(pref)
1283        self.dump_comp_info(pref, comp_filter + ['Header'])
1284
1285class MftExtension(Component):
1286    """ Manifest Extension
1287    """
1288    def __init__(self, ext_id, name, offset):
1289        super(MftExtension, self).__init__('mft_ext'+repr(ext_id), name,
1290                                           offset)
1291
1292    def dump_info(self, pref, comp_filter):
1293        print('{}{} type {} file offset 0x{:x} length {}'.
1294              format(pref, self.name,
1295                     self.adir['type'], self.file_offset, self.adir['length']))
1296
1297class PlatFwAuthExtension(MftExtension):
1298    """ Platform FW Auth Extension
1299    """
1300    def __init__(self, ext_id, offset):
1301        super(PlatFwAuthExtension,
1302              self).__init__(ext_id, 'Plat Fw Auth Extension', offset)
1303
1304    def dump_info(self, pref, comp_filter):
1305        super().dump_info(pref, comp_filter)
1306        out = '{}'.format(pref)
1307        out += ' name {}'.format(self.adir['name'])
1308        out += ' vcn {}'.format(self.adir['vcn'])
1309        out += ' bitmap {}'.format(self.adir['bitmap'])
1310        out += ' svn {}'.format(self.adir['svn'])
1311        print(out)
1312
1313class AdspMetadataFileExt(MftExtension):
1314    """ ADSP Metadata File Extension
1315    """
1316    def __init__(self, ext_id, offset):
1317        super(AdspMetadataFileExt,
1318              self).__init__(ext_id, 'ADSP Metadata File Extension',
1319                             offset)
1320
1321    def dump_info(self, pref, comp_filter):
1322        super().dump_info(pref, comp_filter)
1323        out = '{}'.format(pref)
1324        out += ' ver {}'.format(self.adir['version'])
1325        out += ' base offset {}'.format(self.adir['base_offset'])
1326        out += ' limit offset {}'.format(self.adir['limit_offset'])
1327        print(out)
1328        print('{}  IMR type {}'.format(pref, self.adir['adsp_imr_type']))
1329        print('{}  Attributes'.format(pref))
1330        print('{}    {}'.format(pref, self.adir['attributes']))
1331
1332class AdspManifest(Component):
1333    """ ADSP Manifest
1334    """
1335    def __init__(self, name, offset):
1336        super(AdspManifest, self).__init__('adsp_mft', name, offset)
1337
1338    def dump_info(self, pref, comp_filter):
1339        hdr = self.cdir['adsp_mft_hdr']
1340        out = '{}{} (ADSP Manifest) file offset 0x{:x}'.format(pref, self.name, self.file_offset)
1341        out += ' name {}'.format(hdr.adir['name'])
1342        out += ' build ver {}'.format(hdr.adir['build_version'])
1343        out += ' feature mask {}'.format(hdr.adir['feature_mask'])
1344        out += ' image flags {}'.format(hdr.adir['fw_image_flags'])
1345        print(out)
1346        print('{}  HW buffers base address {} length {}'.
1347              format(pref,
1348                     hdr.adir['hw_buf_base_addr'],
1349                     hdr.adir['hw_buf_length']))
1350        print('{}  Load offset {}'.format(pref,
1351                                          hdr.adir['load_offset']))
1352        self.dump_comp_info(pref, comp_filter + ['ADSP Manifest Header'])
1353
1354class AdspModuleEntry(Component):
1355    """ ADSP Module Entry
1356    """
1357    def __init__(self, uid, offset):
1358        super(AdspModuleEntry, self).__init__(uid, 'Module Entry', offset)
1359
1360    def dump_info(self, pref, comp_filter):
1361        print('{}{:9} {}'.format(pref, str(self.adir['mod_name']),
1362            self.adir['uuid']))
1363        print('{}  entry point {} type {}'.format(pref, self.adir['entry_point'],
1364            self.adir['type']))
1365        out = '{}  cfg offset {} count {} affinity {}'.format(pref,
1366            self.adir['cfg_offset'], self.adir['cfg_count'],
1367            self.adir['affinity_mask'])
1368        out += ' instance max count {} stack size {}'.format(
1369            self.adir['instance_max_count'], self.adir['instance_stack_size'])
1370        print(out)
1371        print('{}  .text   {} file offset {} flags {}'.format(pref,
1372            self.adir['seg_0_v_base_addr'], self.adir['seg_0_file_offset'],
1373            self.adir['seg_0_flags']))
1374        print('{}  .rodata {} file offset {} flags {}'.format(pref,
1375            self.adir['seg_1_v_base_addr'], self.adir['seg_1_file_offset'],
1376            self.adir['seg_1_flags']))
1377        print('{}  .bss    {} file offset {} flags {}'.format(pref,
1378            self.adir['seg_2_v_base_addr'], self.adir['seg_2_file_offset'],
1379            self.adir['seg_2_flags']))
1380
1381    def add_comp_to_mem_map(self, mem_map):
1382        mem_map.insert_segment(DspMemorySegment(
1383            self.adir['mod_name'].val + '.text',
1384            self.adir['seg_0_v_base_addr'].val,
1385            self.adir['seg_0_size'].val));
1386        mem_map.insert_segment(DspMemorySegment(
1387            self.adir['mod_name'].val + '.rodata',
1388            self.adir['seg_1_v_base_addr'].val,
1389            self.adir['seg_1_size'].val));
1390        mem_map.insert_segment(DspMemorySegment(
1391            self.adir['mod_name'].val + '.bss',
1392            self.adir['seg_2_v_base_addr'].val,
1393            self.adir['seg_2_size'].val));
1394
1395class FwBin(Component):
1396    """ Parsed sof binary
1397    """
1398    def __init__(self):
1399        super(FwBin, self).__init__('bin', 'SOF Binary', 0)
1400
1401    def dump_info(self, pref, comp_filter):
1402        """ Print out the content
1403        """
1404        print('SOF Binary {} size {}'.format(
1405            self.adir['file_name'], self.adir['file_size']))
1406        self.dump_comp_info(pref, comp_filter)
1407
1408    def populate_mem_map(self, mem_map):
1409        """ Adds modules' segments to the memory map
1410        """
1411        self.add_comp_to_mem_map(mem_map)
1412
1413# DSP Memory Layout
1414def get_mem_map(ri_path):
1415    """ Retrieves memory map for platform determined by the file name
1416    """
1417    for plat_name in DSP_MEM_SPACE_EXT:
1418        # use full firmware name for match
1419        if "sof-{}.ri".format(plat_name) in ri_path:
1420            return DSP_MEM_SPACE_EXT[plat_name]
1421
1422    # Widen the search and match anything in directory names like
1423    # `___/build_tgl_xcc/sof.ri`
1424    found = None
1425    for plat_name in DSP_MEM_SPACE_EXT:
1426        if plat_name in ri_path:
1427            if found and len(found) > len(plat_name):
1428                continue
1429            found = plat_name
1430
1431    return DSP_MEM_SPACE_EXT[found] if found else DspMemory(
1432        'No platform found in name "{}"'.format(ri_path)
1433        + "; unknown memory layout.", [])
1434
1435def add_lmap_mem_info(ri_path, mem_map):
1436    """ Optional lmap processing
1437    """
1438    lmap_path = ri_path[0:ri_path.rfind('.')] + '.lmap'
1439    try:
1440        with open(lmap_path) as lmap:
1441            it_lines = iter(lmap.readlines())
1442            for line in it_lines:
1443                if 'Sections:' in line:
1444                    next(it_lines)
1445                    break;
1446            for line in it_lines:
1447                tok = line.split()
1448                mem_map.insert_segment(DspMemorySegment(tok[1],
1449                    int(tok[3], 16), int(tok[2], 16)))
1450                next(it_lines)
1451
1452    except FileNotFoundError:
1453        return
1454
1455class DspMemorySegment(object):
1456    """ Single continuous memory space
1457    """
1458    def __init__(self, name, base_address, size):
1459        self.name = name
1460        self.base_address = base_address
1461        self.size = size
1462        self.used_size = 0
1463        self.inner_segments = []
1464
1465    def is_inner(self, segment):
1466        return self.base_address <= segment.base_address and \
1467            segment.base_address + segment.size <= self.base_address + self.size
1468
1469    def insert_segment(self, segment):
1470        for seg in self.inner_segments:
1471            if seg.is_inner(segment):
1472                seg.insert_segment(segment)
1473                return
1474        self.inner_segments.append(segment)
1475        self.used_size += segment.size
1476
1477    def dump_info(self, pref):
1478        free_size = self.size - self.used_size
1479        out = '{}{:<35} 0x{:x}'.format(pref, self.name, self.base_address)
1480        if self.used_size > 0:
1481            out += ' ({} + {}  {:.2f}% used)'.format(self.used_size, free_size,
1482                self.used_size*100/self.size)
1483        else:
1484            out += ' ({})'.format(free_size)
1485        print(out)
1486        for seg in self.inner_segments:
1487            seg.dump_info(pref + '  ')
1488
1489class DspMemory(object):
1490    """ Dsp Memory, all top-level segments
1491    """
1492    def __init__(self, platform_name, segments):
1493        self.platform_name = platform_name
1494        self.segments = segments
1495
1496    def insert_segment(self, segment):
1497        """ Inserts segment
1498        """
1499        for seg in self.segments:
1500            if seg.is_inner(segment):
1501                seg.insert_segment(segment)
1502                return
1503
1504    def dump_info(self):
1505        if not self.segments:
1506            print(self.platform_name) # "no platform found"
1507            return
1508
1509        print("Memory layout for: " + self.platform_name)
1510        for seg in self.segments:
1511            seg.dump_info('  ')
1512
1513# Layouts of DSP memory for known platforms
1514
1515APL_MEMORY_SPACE = DspMemory('Intel Apollolake',
1516    [
1517        DspMemorySegment('imr', 0xa0000000, 4*1024*1024),
1518        DspMemorySegment('l2 hpsram', 0xbe000000, 8*64*1024),
1519        DspMemorySegment('l2 lpsram', 0xbe800000, 2*64*1024)
1520    ])
1521
1522CNL_MEMORY_SPACE = DspMemory('Intel Cannonlake',
1523    [
1524        DspMemorySegment('imr', 0xb0000000, 8*0x1024*0x1024),
1525        DspMemorySegment('l2 hpsram', 0xbe000000, 48*64*1024),
1526        DspMemorySegment('l2 lpsram', 0xbe800000, 1*64*1024)
1527    ])
1528
1529ICL_MEMORY_SPACE = DspMemory('Intel Icelake',
1530    [
1531        DspMemorySegment('imr', 0xb0000000, 8*1024*1024),
1532        DspMemorySegment('l2 hpsram', 0xbe000000, 47*64*1024),
1533        DspMemorySegment('l2 lpsram', 0xbe800000, 1*64*1024)
1534    ])
1535
1536TGL_LP_MEMORY_SPACE = DspMemory('Intel Tigerlake-LP',
1537    [
1538        DspMemorySegment('imr', 0xb0000000,16*1024*1024),
1539        DspMemorySegment('l2 hpsram', 0xbe000000, 46*64*1024),
1540        DspMemorySegment('l2 lpsram', 0xbe800000, 1*64*1024)
1541    ])
1542
1543JSL_MEMORY_SPACE = DspMemory('Intel Jasperlake',
1544    [
1545        DspMemorySegment('imr', 0xb0000000, 8*1024*1024),
1546        DspMemorySegment('l2 hpsram', 0xbe000000, 16*64*1024),
1547        DspMemorySegment('l2 lpsram', 0xbe800000, 1*64*1024)
1548    ])
1549
1550TGL_H_MEMORY_SPACE = DspMemory('Intel Tigerlake-H',
1551    [
1552        DspMemorySegment('imr', 0xb0000000, 16*1024*1024),
1553        DspMemorySegment('l2 hpsram', 0xbe000000, 30*64*1024),
1554        DspMemorySegment('l2 lpsram', 0xbe800000, 1*64*1024)
1555    ])
1556
1557DSP_MEM_SPACE_EXT = {
1558    'apl' : APL_MEMORY_SPACE,
1559    'glk' : APL_MEMORY_SPACE,
1560
1561    'cnl' : CNL_MEMORY_SPACE,
1562    'cfl' : CNL_MEMORY_SPACE,
1563    'cml' : CNL_MEMORY_SPACE,
1564
1565    'icl' : ICL_MEMORY_SPACE,
1566
1567    'jsl' : JSL_MEMORY_SPACE,
1568
1569    'tgl' : TGL_LP_MEMORY_SPACE,
1570    'ehl' : TGL_LP_MEMORY_SPACE,
1571    'adl' : TGL_LP_MEMORY_SPACE,
1572    'rpl' : TGL_LP_MEMORY_SPACE,
1573
1574    'tgl-h' : TGL_H_MEMORY_SPACE,
1575    'adl-s' : TGL_H_MEMORY_SPACE,
1576    'rpl-s' : TGL_H_MEMORY_SPACE,
1577}
1578
1579
1580def getCssManifest(parsed_fw):
1581    "Also known as 'ADSP.man'"
1582    cse_mft = parsed_fw.cdir['cse_mft']
1583    return cse_mft.cdir['css_mft']
1584
1585
1586def Erase(input_reader, start, length, padding):
1587
1588    padding = padding * (length // len(padding) + 1)
1589    output_bytes = input_reader.read(start)
1590
1591    # Skip and replace with padding
1592    input_reader.seek(length, 1)
1593    output_bytes += padding[:length]
1594
1595    output_bytes += input_reader.read()
1596
1597    input_reader.seek(0)
1598    return io.BytesIO(output_bytes)
1599
1600
1601def EraseSignature(signed_input, parsed_fw):
1602
1603    hdr = getCssManifest(parsed_fw).cdir['css_mft_hdr']
1604
1605    return Erase(signed_input,
1606                 hdr.adir['signature_start'].val,
1607                 hdr.adir['signature_length'].val,
1608                 b'Erased signature. ')
1609
1610
1611def EraseCssManifestDate(dated_input, parsed_fw):
1612
1613    hdr = getCssManifest(parsed_fw).cdir['css_mft_hdr']
1614
1615    return Erase(dated_input,
1616                 hdr.adir['date_start'].val,
1617                 hdr.adir['date_length'].val,
1618                 b'\x11' * 6) # = 1111/11/11
1619
1620
1621def EraseCssManifest(image_input, parsed_fw):
1622
1623    css_man = getCssManifest(parsed_fw)
1624
1625    return Erase(image_input, css_man.file_offset,
1626                 css_man.length, b"Erased CSS manifest. ")
1627
1628
1629def EraseImrType(image_input, parsed_fw):
1630
1631    cse_mft = parsed_fw.cdir['cse_mft']
1632    adsp_meta_ext = cse_mft.cdir['mft_ext0']
1633
1634    # IMR type is the very first field after extension type and length
1635    imr_start = adsp_meta_ext.file_offset + 4 + 4
1636
1637    # Health check: re-read the imr_type to make sure the offset is
1638    # still correct, no copy/paste/diverge.
1639    true_imr_type = adsp_meta_ext.adir['adsp_imr_type'].val
1640    image_input.seek(imr_start)
1641    imr_type, = struct.unpack("<I", image_input.read(4))
1642    assert imr_type == true_imr_type
1643    image_input.seek(0)
1644
1645    return Erase(image_input, imr_start, 4, b'IMRt')
1646
1647
1648def EraseVariables(input_path, parsed_fw, output_path):
1649    """This is not smart but it gets the current job done. This entire
1650    script should be re-written and based on a more advanced framework
1651    like Construct, then a hierarchical, diffoscope-like diff should be
1652    easy to implement on top.
1653    """
1654    with open(input_path, 'rb') as reader:
1655
1656        if True:
1657            # Massive erasure required to compare .ri files produced by
1658            # different tools (e.g. rimage vs MEU)
1659            cse_mft = parsed_fw.cdir['cse_mft']
1660            adsp_mft = parsed_fw.cdir['adsp_mft']
1661
1662            cse_plus_padding_len = adsp_mft.file_offset - cse_mft.file_offset
1663
1664            reader = Erase(reader, cse_mft.file_offset,
1665                           cse_plus_padding_len,
1666                           b'Erased CSE manifest + padding. ')
1667
1668        else:
1669            # This is much smaller and enough to deal with date and
1670            # random salt when signing with the same tool
1671            reader = EraseCssManifestDate(reader, parsed_fw)
1672            reader = EraseSignature(reader, parsed_fw)
1673
1674        with open(output_path, 'wb') as output:
1675            for chunk in reader:
1676                output.write(chunk)
1677
1678    assert input_path.stat().st_size == output_path.stat().st_size
1679
1680    with open(output_path, 'rb') as output:
1681        return hashlib.sha256(output.read()).hexdigest()
1682
1683
1684def main(args):
1685    """ main function
1686    """
1687    if sys.stdout.isatty():
1688        Attribute.no_colors = args.no_colors
1689    else:
1690        Attribute.no_colors = True
1691
1692    Attribute.full_bytes = args.full_bytes
1693
1694    fw_bin = parse_fw_bin(args.sof_ri_path, args.no_cse, args.verbose)
1695
1696    comp_filter = []
1697    if args.headers or args.no_modules:
1698        comp_filter.append('Module Entry')
1699    if args.no_headers:
1700        comp_filter.append('CSE Manifest')
1701    fw_bin.dump_info('', comp_filter)
1702    if not args.no_memory:
1703        mem = get_mem_map(args.sof_ri_path)
1704        fw_bin.populate_mem_map(mem)
1705        add_lmap_mem_info(args.sof_ri_path, mem)
1706        print()
1707        mem.dump_info()
1708
1709    if args.erased_vars_image:
1710        chk256 = EraseVariables(pathlib.Path(args.sof_ri_path), fw_bin,
1711                       args.erased_vars_image)
1712        print('sha256sum {0}\n{1} {0}'.format(args.erased_vars_image, chk256))
1713
1714
1715if __name__ == "__main__":
1716    ARGS = parse_params()
1717    main(ARGS)
1718