blob: b6e1acc8c0727980a3bbf7c7c520cb50daaa330a [file] [log] [blame]
Jukka Rissanen0ff4c252017-09-13 10:43:30 +03001#!/usr/bin/env python3
2#
3# Copyright (c) 2017 Intel Corporation
Irfan Ahmadf3d513d2025-01-17 02:47:43 +05004# Copyright (c) 2025 Siemens AG
Jukka Rissanen0ff4c252017-09-13 10:43:30 +03005#
6# SPDX-License-Identifier: Apache-2.0
7
Ruslan Mstoi1bae7672020-06-01 12:30:19 +03008
9"""Convert a file to a list of hex characters
10
11The list of hex characters can then be included to a source file. Optionally,
12the output can be compressed.
13
14"""
Jukka Rissanen0ff4c252017-09-13 10:43:30 +030015
16import argparse
17import codecs
18import gzip
19import io
20
Anas Nashif72565532017-12-12 08:19:25 -050021
Jukka Rissanen0ff4c252017-09-13 10:43:30 +030022def parse_args():
23 global args
24
Anas Nashif72565532017-12-12 08:19:25 -050025 parser = argparse.ArgumentParser(
26 description=__doc__,
Jamie McCraeec704442023-01-04 16:08:36 +000027 formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False)
Jukka Rissanen0ff4c252017-09-13 10:43:30 +030028
29 parser.add_argument("-f", "--file", required=True, help="Input file")
Pieter De Gendtae8c7242023-09-13 16:22:42 +020030 parser.add_argument("-o", "--offset", type=lambda x: int(x, 0), default=0,
31 help="Byte offset in the input file")
32 parser.add_argument("-l", "--length", type=lambda x: int(x, 0), default=-1,
33 help="""Length in bytes to read from the input file.
34 Defaults to reading till the end of the input file.""")
Irfan Ahmadf3d513d2025-01-17 02:47:43 +050035 parser.add_argument("-m", "--format", default="list",
36 help="Output format: 'list' (default) or 'literal' (string literal)")
Jukka Rissanen0ff4c252017-09-13 10:43:30 +030037 parser.add_argument("-g", "--gzip", action="store_true",
Anas Nashif72565532017-12-12 08:19:25 -050038 help="Compress the file using gzip before output")
Marc Herbert3061c922019-03-21 14:40:45 -070039 parser.add_argument("-t", "--gzip-mtime", type=int, default=0,
Ruslan Mstoia8e06552020-06-01 14:29:46 +030040 nargs='?', const=None,
Marc Herbert3061c922019-03-21 14:40:45 -070041 help="""mtime seconds in the gzip header.
42 Defaults to zero to keep builds deterministic. For
43 current date and time (= "now") use this option
44 without any value.""")
Jukka Rissanen0ff4c252017-09-13 10:43:30 +030045 args = parser.parse_args()
46
Anas Nashif72565532017-12-12 08:19:25 -050047
Jukka Rissanen0ff4c252017-09-13 10:43:30 +030048def get_nice_string(list_or_iterator):
Irfan Ahmade30c1082025-01-23 00:26:04 +050049 # Convert into comma separated list form.
50 s = ", ".join("0x" + str(x) for x in list_or_iterator)
51
52 # Format the list to eight values per line.
53 return "\n".join(s[i:i+47] for i in range(0, len(s), 48))
Anas Nashif72565532017-12-12 08:19:25 -050054
Jukka Rissanen0ff4c252017-09-13 10:43:30 +030055
56def make_hex(chunk):
57 hexdata = codecs.encode(chunk, 'hex').decode("utf-8")
Anas Nashif72565532017-12-12 08:19:25 -050058 hexlist = map(''.join, zip(*[iter(hexdata)] * 2))
Jukka Rissanen0ff4c252017-09-13 10:43:30 +030059 print(get_nice_string(hexlist) + ',')
60
Anas Nashif72565532017-12-12 08:19:25 -050061
Irfan Ahmadf3d513d2025-01-17 02:47:43 +050062def make_string_literal(chunk):
63 hexdata = codecs.encode(chunk, 'hex').decode("utf-8")
64 hexlist = map(''.join, zip(*[iter(hexdata)] * 2))
65 print(''.join("\\x" + str(x) for x in hexlist), end='')
66
67
Jukka Rissanen0ff4c252017-09-13 10:43:30 +030068def main():
69 parse_args()
70
71 if args.gzip:
Marc Herbert195195a2019-03-21 14:24:00 -070072 with io.BytesIO() as content:
73 with open(args.file, 'rb') as fg:
Pieter De Gendtae8c7242023-09-13 16:22:42 +020074 fg.seek(args.offset)
Marc Herbert195195a2019-03-21 14:24:00 -070075 with gzip.GzipFile(fileobj=content, mode='w',
Marc Herbert3061c922019-03-21 14:40:45 -070076 mtime=args.gzip_mtime,
Marc Herbert195195a2019-03-21 14:24:00 -070077 compresslevel=9) as gz_obj:
Pieter De Gendtae8c7242023-09-13 16:22:42 +020078 gz_obj.write(fg.read(args.length))
Marc Herbert195195a2019-03-21 14:24:00 -070079
80 content.seek(0)
Irfan Ahmad8d42cd02025-02-18 05:02:28 +050081 if args.format == "literal":
82 print('"', end='')
83 for chunk in iter(lambda: content.read(1024), b''):
84 make_string_literal(chunk)
85 print('"', end='')
86 else:
87 for chunk in iter(lambda: content.read(1024), b''):
88 make_hex(chunk)
Jukka Rissanen0ff4c252017-09-13 10:43:30 +030089 else:
90 with open(args.file, "rb") as fp:
Pieter De Gendtae8c7242023-09-13 16:22:42 +020091 fp.seek(args.offset)
Irfan Ahmadf3d513d2025-01-17 02:47:43 +050092
93 if args.format == "literal":
94 if args.length < 0:
95 print('"', end='')
96 for chunk in iter(lambda: fp.read(1024), b''):
97 make_string_literal(chunk)
98 print('"', end='')
99 else:
100 print('"', end='')
101 remainder = args.length
102 for chunk in iter(lambda: fp.read(min(1024, remainder)), b''):
103 make_string_literal(chunk)
104 remainder = remainder - len(chunk)
105 print('"', end='')
106
Pieter De Gendtae8c7242023-09-13 16:22:42 +0200107 else:
Irfan Ahmadf3d513d2025-01-17 02:47:43 +0500108 if args.length < 0:
109 for chunk in iter(lambda: fp.read(1024), b''):
110 make_hex(chunk)
111 else:
112 remainder = args.length
113 for chunk in iter(lambda: fp.read(min(1024, remainder)), b''):
114 make_hex(chunk)
115 remainder = remainder - len(chunk)
Jukka Rissanen0ff4c252017-09-13 10:43:30 +0300116
Anas Nashif72565532017-12-12 08:19:25 -0500117
Jukka Rissanen0ff4c252017-09-13 10:43:30 +0300118if __name__ == "__main__":
119 main()