1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
|
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0+
# Copyright 2021 Google LLC
# Written by Simon Glass <sjg@chromium.org>
"""Support for ARM's Firmware Image Package (FIP) format
FIP is a format similar to FMAP[1] but with fewer features and an obscure UUID
instead of the region name.
It consists of a header and a table of entries, each pointing to a place in the
firmware image where something can be found.
[1] https://chromium.googlesource.com/chromiumos/third_party/flashmap/+/refs/heads/master/lib/fmap.h
If ATF updates, run this program to update the FIT_TYPE_LIST.
ARM Trusted Firmware is available at:
https://github.com/ARM-software/arm-trusted-firmware.git
"""
from argparse import ArgumentParser
import collections
import io
import os
import re
import struct
import sys
from uuid import UUID
OUR_FILE = os.path.realpath(__file__)
OUR_PATH = os.path.dirname(OUR_FILE)
# Bring in the patman and dtoc libraries (but don't override the first path
# in PYTHONPATH)
sys.path.insert(2, os.path.join(OUR_PATH, '..'))
# pylint: disable=C0413
from u_boot_pylib import command
from u_boot_pylib import tools
# The TOC header, at the start of the FIP
HEADER_FORMAT = '<IIQ'
HEADER_LEN = 0x10
HEADER_MAGIC = 0xaA640001
HEADER_SERIAL = 0x12345678
# The entry header (a table of these comes after the TOC header)
UUID_LEN = 16
ENTRY_FORMAT = f'<{UUID_LEN}sQQQ'
ENTRY_SIZE = 0x28
HEADER_NAMES = (
'name',
'serial',
'flags',
)
ENTRY_NAMES = (
'uuid',
'offset',
'size',
'flags',
)
# Set to True to enable output from running fiptool for debugging
VERBOSE = False
# Use a class so we can convert the bytes, making the table more readable
# pylint: disable=R0903
class FipType:
"""A FIP entry type that we understand"""
def __init__(self, name, desc, uuid_bytes):
"""Create up a new type
Args:
name (str): Short name for the type
desc (str): Longer description for the type
uuid_bytes (bytes): List of 16 bytes for the UUID
"""
self.name = name
self.desc = desc
self.uuid = bytes(uuid_bytes)
# This is taken from tbbr_config.c in ARM Trusted Firmware
FIP_TYPE_LIST = [
# ToC Entry UUIDs
FipType('scp-fwu-cfg', 'SCP Firmware Updater Configuration FWU SCP_BL2U',
[0x65, 0x92, 0x27, 0x03, 0x2f, 0x74, 0xe6, 0x44,
0x8d, 0xff, 0x57, 0x9a, 0xc1, 0xff, 0x06, 0x10]),
FipType('ap-fwu-cfg', 'AP Firmware Updater Configuration BL2U',
[0x60, 0xb3, 0xeb, 0x37, 0xc1, 0xe5, 0xea, 0x41,
0x9d, 0xf3, 0x19, 0xed, 0xa1, 0x1f, 0x68, 0x01]),
FipType('fwu', 'Firmware Updater NS_BL2U',
[0x4f, 0x51, 0x1d, 0x11, 0x2b, 0xe5, 0x4e, 0x49,
0xb4, 0xc5, 0x83, 0xc2, 0xf7, 0x15, 0x84, 0x0a]),
FipType('fwu-cert', 'Non-Trusted Firmware Updater certificate',
[0x71, 0x40, 0x8a, 0xb2, 0x18, 0xd6, 0x87, 0x4c,
0x8b, 0x2e, 0xc6, 0xdc, 0xcd, 0x50, 0xf0, 0x96]),
FipType('tb-fw', 'Trusted Boot Firmware BL2',
[0x5f, 0xf9, 0xec, 0x0b, 0x4d, 0x22, 0x3e, 0x4d,
0xa5, 0x44, 0xc3, 0x9d, 0x81, 0xc7, 0x3f, 0x0a]),
FipType('scp-fw', 'SCP Firmware SCP_BL2',
[0x97, 0x66, 0xfd, 0x3d, 0x89, 0xbe, 0xe8, 0x49,
0xae, 0x5d, 0x78, 0xa1, 0x40, 0x60, 0x82, 0x13]),
FipType('soc-fw', 'EL3 Runtime Firmware BL31',
[0x47, 0xd4, 0x08, 0x6d, 0x4c, 0xfe, 0x98, 0x46,
0x9b, 0x95, 0x29, 0x50, 0xcb, 0xbd, 0x5a, 0x00]),
FipType('tos-fw', 'Secure Payload BL32 (Trusted OS)',
[0x05, 0xd0, 0xe1, 0x89, 0x53, 0xdc, 0x13, 0x47,
0x8d, 0x2b, 0x50, 0x0a, 0x4b, 0x7a, 0x3e, 0x38]),
FipType('tos-fw-extra1', 'Secure Payload BL32 Extra1 (Trusted OS Extra1)',
[0x0b, 0x70, 0xc2, 0x9b, 0x2a, 0x5a, 0x78, 0x40,
0x9f, 0x65, 0x0a, 0x56, 0x82, 0x73, 0x82, 0x88]),
FipType('tos-fw-extra2', 'Secure Payload BL32 Extra2 (Trusted OS Extra2)',
[0x8e, 0xa8, 0x7b, 0xb1, 0xcf, 0xa2, 0x3f, 0x4d,
0x85, 0xfd, 0xe7, 0xbb, 0xa5, 0x02, 0x20, 0xd9]),
FipType('nt-fw', 'Non-Trusted Firmware BL33',
[0xd6, 0xd0, 0xee, 0xa7, 0xfc, 0xea, 0xd5, 0x4b,
0x97, 0x82, 0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4]),
FipType('rmm-fw', 'Realm Monitor Management Firmware',
[0x6c, 0x07, 0x62, 0xa6, 0x12, 0xf2, 0x4b, 0x56,
0x92, 0xcb, 0xba, 0x8f, 0x63, 0x36, 0x06, 0xd9]),
# Key certificates
FipType('rot-cert', 'Root Of Trust key certificate',
[0x86, 0x2d, 0x1d, 0x72, 0xf8, 0x60, 0xe4, 0x11,
0x92, 0x0b, 0x8b, 0xe7, 0x62, 0x16, 0x0f, 0x24]),
FipType('trusted-key-cert', 'Trusted key certificate',
[0x82, 0x7e, 0xe8, 0x90, 0xf8, 0x60, 0xe4, 0x11,
0xa1, 0xb4, 0x77, 0x7a, 0x21, 0xb4, 0xf9, 0x4c]),
FipType('scp-fw-key-cert', 'SCP Firmware key certificate',
[0x02, 0x42, 0x21, 0xa1, 0xf8, 0x60, 0xe4, 0x11,
0x8d, 0x9b, 0xf3, 0x3c, 0x0e, 0x15, 0xa0, 0x14]),
FipType('soc-fw-key-cert', 'SoC Firmware key certificate',
[0x8a, 0xb8, 0xbe, 0xcc, 0xf9, 0x60, 0xe4, 0x11,
0x9a, 0xd0, 0xeb, 0x48, 0x22, 0xd8, 0xdc, 0xf8]),
FipType('tos-fw-key-cert', 'Trusted OS Firmware key certificate',
[0x94, 0x77, 0xd6, 0x03, 0xfb, 0x60, 0xe4, 0x11,
0x85, 0xdd, 0xb7, 0x10, 0x5b, 0x8c, 0xee, 0x04]),
FipType('nt-fw-key-cert', 'Non-Trusted Firmware key certificate',
[0x8a, 0xd5, 0x83, 0x2a, 0xfb, 0x60, 0xe4, 0x11,
0x8a, 0xaf, 0xdf, 0x30, 0xbb, 0xc4, 0x98, 0x59]),
# Content certificates
FipType('tb-fw-cert', 'Trusted Boot Firmware BL2 certificate',
[0xd6, 0xe2, 0x69, 0xea, 0x5d, 0x63, 0xe4, 0x11,
0x8d, 0x8c, 0x9f, 0xba, 0xbe, 0x99, 0x56, 0xa5]),
FipType('scp-fw-cert', 'SCP Firmware content certificate',
[0x44, 0xbe, 0x6f, 0x04, 0x5e, 0x63, 0xe4, 0x11,
0xb2, 0x8b, 0x73, 0xd8, 0xea, 0xae, 0x96, 0x56]),
FipType('soc-fw-cert', 'SoC Firmware content certificate',
[0xe2, 0xb2, 0x0c, 0x20, 0x5e, 0x63, 0xe4, 0x11,
0x9c, 0xe8, 0xab, 0xcc, 0xf9, 0x2b, 0xb6, 0x66]),
FipType('tos-fw-cert', 'Trusted OS Firmware content certificate',
[0xa4, 0x9f, 0x44, 0x11, 0x5e, 0x63, 0xe4, 0x11,
0x87, 0x28, 0x3f, 0x05, 0x72, 0x2a, 0xf3, 0x3d]),
FipType('nt-fw-cert', 'Non-Trusted Firmware content certificate',
[0x8e, 0xc4, 0xc1, 0xf3, 0x5d, 0x63, 0xe4, 0x11,
0xa7, 0xa9, 0x87, 0xee, 0x40, 0xb2, 0x3f, 0xa7]),
FipType('sip-sp-cert', 'SiP owned Secure Partition content certificate',
[0x77, 0x6d, 0xfd, 0x44, 0x86, 0x97, 0x4c, 0x3b,
0x91, 0xeb, 0xc1, 0x3e, 0x02, 0x5a, 0x2a, 0x6f]),
FipType('plat-sp-cert', 'Platform owned Secure Partition content certificate',
[0xdd, 0xcb, 0xbf, 0x4a, 0xca, 0xd6, 0x11, 0xea,
0x87, 0xd0, 0x02, 0x42, 0xac, 0x13, 0x00, 0x03]),
# Dynamic configs
FipType('hw-config', 'HW_CONFIG',
[0x08, 0xb8, 0xf1, 0xd9, 0xc9, 0xcf, 0x93, 0x49,
0xa9, 0x62, 0x6f, 0xbc, 0x6b, 0x72, 0x65, 0xcc]),
FipType('tb-fw-config', 'TB_FW_CONFIG',
[0x6c, 0x04, 0x58, 0xff, 0xaf, 0x6b, 0x7d, 0x4f,
0x82, 0xed, 0xaa, 0x27, 0xbc, 0x69, 0xbf, 0xd2]),
FipType('soc-fw-config', 'SOC_FW_CONFIG',
[0x99, 0x79, 0x81, 0x4b, 0x03, 0x76, 0xfb, 0x46,
0x8c, 0x8e, 0x8d, 0x26, 0x7f, 0x78, 0x59, 0xe0]),
FipType('tos-fw-config', 'TOS_FW_CONFIG',
[0x26, 0x25, 0x7c, 0x1a, 0xdb, 0xc6, 0x7f, 0x47,
0x8d, 0x96, 0xc4, 0xc4, 0xb0, 0x24, 0x80, 0x21]),
FipType('nt-fw-config', 'NT_FW_CONFIG',
[0x28, 0xda, 0x98, 0x15, 0x93, 0xe8, 0x7e, 0x44,
0xac, 0x66, 0x1a, 0xaf, 0x80, 0x15, 0x50, 0xf9]),
FipType('fw-config', 'FW_CONFIG',
[0x58, 0x07, 0xe1, 0x6a, 0x84, 0x59, 0x47, 0xbe,
0x8e, 0xd5, 0x64, 0x8e, 0x8d, 0xdd, 0xab, 0x0e]),
] # end
FIP_TYPES = {ftype.name: ftype for ftype in FIP_TYPE_LIST}
def get_type_uuid(fip_type_or_uuid):
"""get_type_uuid() - Convert a type or uuid into both
This always returns a UUID, but may not return a type since it does not do
the reverse lookup.
Args:
fip_type_or_uuid (str or bytes): Either a string containing the name of
an entry (e.g. 'soc-fw') or a bytes(16) containing the UUID
Returns:
tuple:
str: fip type (None if not known)
bytes(16): uuid
Raises:
ValueError: An unknown type was requested
"""
if isinstance(fip_type_or_uuid, str):
fip_type = fip_type_or_uuid
lookup = FIP_TYPES.get(fip_type)
if not lookup:
raise ValueError(f"Unknown FIP entry type '{fip_type}'")
uuid = lookup.uuid
else:
fip_type = None
uuid = fip_type_or_uuid
return fip_type, uuid
# pylint: disable=R0903
class FipHeader:
"""Class to represent a FIP header"""
def __init__(self, name, serial, flags):
"""Set up a new header object
Args:
name (str): Name, i.e. HEADER_MAGIC
serial (str): Serial value, i.e. HEADER_SERIAL
flags (int64): Flags value
"""
self.name = name
self.serial = serial
self.flags = flags
# pylint: disable=R0903
class FipEntry:
"""Class to represent a single FIP entry
This is used to hold the information about an entry, including its contents.
Use the get_data() method to obtain the raw output for writing to the FIP
file.
"""
def __init__(self, uuid, offset, size, flags):
self.uuid = uuid
self.offset = offset
self.size = size
self.flags = flags
self.fip_type = None
self.data = None
self.valid = uuid != tools.get_bytes(0, UUID_LEN)
if self.valid:
# Look up the friendly name
matches = {val for (key, val) in FIP_TYPES.items()
if val.uuid == uuid}
if len(matches) == 1:
self.fip_type = matches.pop().name
@classmethod
def from_type(cls, fip_type_or_uuid, data, flags):
"""Create a FipEntry from a type name
Args:
cls (class): This class
fip_type_or_uuid (str or bytes): Name of the type to create, or
bytes(16) uuid
data (bytes): Contents of entry
flags (int64): Flags value
Returns:
FipEntry: Created 241
"""
fip_type, uuid = get_type_uuid(fip_type_or_uuid)
fent = FipEntry(uuid, None, len(data), flags)
fent.fip_type = fip_type
fent.data = data
return fent
def decode_fip(data):
"""Decode a FIP into a header and list of FIP entries
Args:
data (bytes): Data block containing the FMAP
Returns:
Tuple:
header: FipHeader object
List of FipArea objects
"""
fields = list(struct.unpack(HEADER_FORMAT, data[:HEADER_LEN]))
header = FipHeader(*fields)
fents = []
pos = HEADER_LEN
while True:
fields = list(struct.unpack(ENTRY_FORMAT, data[pos:pos + ENTRY_SIZE]))
fent = FipEntry(*fields)
if not fent.valid:
break
fent.data = data[fent.offset:fent.offset + fent.size]
fents.append(fent)
pos += ENTRY_SIZE
return header, fents
class FipWriter:
"""Class to handle writing a ARM Trusted Firmware's Firmware Image Package
Usage is something like:
fip = FipWriter(size)
fip.add_entry('scp-fwu-cfg', tools.read_file('something.bin'))
...
data = cbw.get_data()
Attributes:
"""
def __init__(self, flags, align):
self._fip_entries = []
self._flags = flags
self._align = align
def add_entry(self, fip_type, data, flags):
"""Add a new entry to the FIP
Args:
fip_type (str): Type to add, e.g. 'tos-fw-config'
data (bytes): Contents of entry
flags (int64): Entry flags
Returns:
FipEntry: entry that was added
"""
fent = FipEntry.from_type(fip_type, data, flags)
self._fip_entries.append(fent)
return fent
def get_data(self):
"""Obtain the full contents of the FIP
Thhis builds the FIP with headers and all required FIP entries.
Returns:
bytes: data resulting from building the FIP
"""
buf = io.BytesIO()
hdr = struct.pack(HEADER_FORMAT, HEADER_MAGIC, HEADER_SERIAL,
self._flags)
buf.write(hdr)
# Calculate the position fo the first entry
offset = len(hdr)
offset += len(self._fip_entries) * ENTRY_SIZE
offset += ENTRY_SIZE # terminating entry
for fent in self._fip_entries:
offset = tools.align(offset, self._align)
fent.offset = offset
offset += fent.size
# Write out the TOC
for fent in self._fip_entries:
hdr = struct.pack(ENTRY_FORMAT, fent.uuid, fent.offset, fent.size,
fent.flags)
buf.write(hdr)
# Write out the entries
for fent in self._fip_entries:
buf.seek(fent.offset)
buf.write(fent.data)
return buf.getvalue()
class FipReader():
"""Class to handle reading a Firmware Image Package (FIP)
Usage is something like:
fip = fip_util.FipReader(data)
fent = fip.get_entry('fwu')
self.WriteFile('ufwu.bin', fent.data)
blob = fip.get_entry(
bytes([0xe3, 0xb7, 0x8d, 0x9e, 0x4a, 0x64, 0x11, 0xec,
0xb4, 0x5c, 0xfb, 0xa2, 0xb9, 0xb4, 0x97, 0x88]))
self.WriteFile('blob.bin', blob.data)
"""
def __init__(self, data, read=True):
"""Set up a new FitReader
Args:
data (bytes): data to read
read (bool): True to read the data now
"""
self.fents = collections.OrderedDict()
self.data = data
if read:
self.read()
def read(self):
"""Read all the files in the FIP and add them to self.files"""
self.header, self.fents = decode_fip(self.data)
def get_entry(self, fip_type_or_uuid):
"""get_entry() - Find an entry by type or UUID
Args:
fip_type_or_uuid (str or bytes): Name of the type to create, or
bytes(16) uuid
Returns:
FipEntry: if found
Raises:
ValueError: entry type not found
"""
fip_type, uuid = get_type_uuid(fip_type_or_uuid)
for fent in self.fents:
if fent.uuid == uuid:
return fent
label = fip_type
if not label:
label = UUID(bytes=uuid)
raise ValueError(f"Cannot find FIP entry '{label}'")
def parse_macros(srcdir):
"""parse_macros: Parse the firmware_image_package.h file
Args:
srcdir (str): 'arm-trusted-firmware' source directory
Returns:
dict:
key: UUID macro name, e.g. 'UUID_TRUSTED_FWU_CERT'
value: list:
file comment, e.g. 'ToC Entry UUIDs'
macro name, e.g. 'UUID_TRUSTED_FWU_CERT'
uuid as bytes(16)
Raises:
ValueError: a line cannot be parsed
"""
re_uuid = re.compile('0x[0-9a-fA-F]{2}')
re_comment = re.compile(r'^/\* (.*) \*/$')
fname = os.path.join(srcdir, 'include/tools_share/firmware_image_package.h')
data = tools.read_file(fname, binary=False)
macros = collections.OrderedDict()
comment = None
for linenum, line in enumerate(data.splitlines()):
if line.startswith('/*'):
mat = re_comment.match(line)
if mat:
comment = mat.group(1)
else:
# Example: #define UUID_TOS_FW_CONFIG \
if 'UUID' in line:
macro = line.split()[1]
elif '{{' in line:
mat = re_uuid.findall(line)
if not mat or len(mat) != 16:
raise ValueError(
f'{fname}: Cannot parse UUID line {linenum + 1}: Got matches: {mat}')
uuid = bytes([int(val, 16) for val in mat])
macros[macro] = comment, macro, uuid
if not macros:
raise ValueError(f'{fname}: Cannot parse file')
return macros
def parse_names(srcdir):
"""parse_names: Parse the tbbr_config.c file
Args:
srcdir (str): 'arm-trusted-firmware' source directory
Returns:
tuple: dict of entries:
key: UUID macro, e.g. 'UUID_NON_TRUSTED_FIRMWARE_BL33'
tuple: entry information
Description of entry, e.g. 'Non-Trusted Firmware BL33'
UUID macro, e.g. 'UUID_NON_TRUSTED_FIRMWARE_BL33'
Name of entry, e.g. 'nt-fw'
Raises:
ValueError: the file cannot be parsed
"""
# Extract the .name, .uuid and .cmdline_name values
re_data = re.compile(r'\.name = "([^"]*)",\s*\.uuid = (UUID_\w*),\s*\.cmdline_name = "([^"]+)"',
re.S)
fname = os.path.join(srcdir, 'tools/fiptool/tbbr_config.c')
data = tools.read_file(fname, binary=False)
# Example entry:
# {
# .name = "Secure Payload BL32 Extra2 (Trusted OS Extra2)",
# .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
# .cmdline_name = "tos-fw-extra2"
# },
mat = re_data.findall(data)
if not mat:
raise ValueError(f'{fname}: Cannot parse file')
names = {uuid: (desc, uuid, name) for desc, uuid, name in mat}
return names
def create_code_output(macros, names):
"""create_code_output() - Create the new version of this Python file
Args:
macros (dict):
key (str): UUID macro name, e.g. 'UUID_TRUSTED_FWU_CERT'
value: list:
file comment, e.g. 'ToC Entry UUIDs'
macro name, e.g. 'UUID_TRUSTED_FWU_CERT'
uuid as bytes(16)
names (dict): list of entries, each
tuple: entry information
Description of entry, e.g. 'Non-Trusted Firmware BL33'
UUID macro, e.g. 'UUID_NON_TRUSTED_FIRMWARE_BL33'
Name of entry, e.g. 'nt-fw'
Returns:
str: Table of FipType() entries
"""
def _to_hex_list(data):
"""Convert bytes into C code
Args:
bytes to convert
Returns:
str: in the format '0x12, 0x34, 0x56...'
"""
# Use 0x instead of %# since the latter ignores the 0 modifier in
# Python 3.8.10
return ', '.join(['0x%02x' % byte for byte in data])
out = ''
last_comment = None
for comment, macro, uuid in macros.values():
name_entry = names.get(macro)
if not name_entry:
print(f"Warning: UUID '{macro}' is not mentioned in tbbr_config.c file")
continue
desc, _, name = name_entry
if last_comment != comment:
out += f' # {comment}\n'
last_comment = comment
out += """ FipType('%s', '%s',
[%s,
%s]),
""" % (name, desc, _to_hex_list(uuid[:8]), _to_hex_list(uuid[8:]))
return out
def parse_atf_source(srcdir, dstfile, oldfile):
"""parse_atf_source(): Parse the ATF source tree and update this file
Args:
srcdir (str): Path to 'arm-trusted-firmware' directory. Get this from:
https://github.com/ARM-software/arm-trusted-firmware.git
dstfile (str): File to write new code to, if an update is needed
oldfile (str): Python source file to compare against
Raises:
ValueError: srcdir readme.rst is missing or the first line does not
match what is expected
"""
# We expect a readme file
readme_fname = os.path.join(srcdir, 'readme.rst')
if not os.path.exists(readme_fname):
raise ValueError(
f"Expected file '{readme_fname}' - try using -s to specify the "
'arm-trusted-firmware directory')
readme = tools.read_file(readme_fname, binary=False)
first_line = 'Trusted Firmware-A'
if readme.splitlines()[0] != first_line:
raise ValueError(f"'{readme_fname}' does not start with '{first_line}'")
macros = parse_macros(srcdir)
names = parse_names(srcdir)
output = create_code_output(macros, names)
orig = tools.read_file(oldfile, binary=False)
re_fip_list = re.compile(r'(.*FIP_TYPE_LIST = \[).*?( ] # end.*)', re.S)
mat = re_fip_list.match(orig)
new_code = mat.group(1) + '\n' + output + mat.group(2) if mat else output
if new_code == orig:
print(f"Existing code in '{oldfile}' is up-to-date")
else:
tools.write_file(dstfile, new_code, binary=False)
print(f'Needs update, try:\n\tmeld {dstfile} {oldfile}')
def main(argv, oldfile):
"""Main program for this tool
Args:
argv (list): List of str command-line arguments
oldfile (str): Python source file to compare against
Returns:
int: 0 (exit code)
"""
parser = ArgumentParser(epilog='''Creates an updated version of this code,
with a table of FIP-entry types parsed from the arm-trusted-firmware source
directory''')
parser.add_argument(
'-D', '--debug', action='store_true',
help='Enabling debugging (provides a full traceback on error)')
parser.add_argument(
'-o', '--outfile', type=str, default='fip_util.py.out',
help='Output file to write new fip_util.py file to')
parser.add_argument(
'-s', '--src', type=str, default='.',
help='Directory containing the arm-trusted-firmware source')
args = parser.parse_args(argv)
if not args.debug:
sys.tracebacklimit = 0
parse_atf_source(args.src, args.outfile, oldfile)
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:], OUR_FILE)) # pragma: no cover
|