ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
merge_ihex.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# SPDX-License-Identifier: MIT
3# Copyright (c) 2026 Brighton Sikarskie
4"""Merge two Intel HEX files into one.
5
6Used by the tz_nsc_cgc_usb two-project TrustZone build (#96) to combine the
7Secure image (at 0x0200_0000+) and the Non-Secure image (LMA 0x0208_0000) into
8a single flashable hex. The two address ranges do not overlap.
9
10Concatenates every record from both inputs EXCEPT the End-Of-File (type 01)
11records, then appends a single EOF. Extended-Linear-Address (type 04) records
12are preserved, so each input keeps positioning its own data.
13
14Usage:
15 merge_ihex.py <in_a.hex> <in_b.hex> <out.hex>
16
17out.hex may be the same path as in_a.hex (read fully first, then written).
18"""
19
20import sys
21from pathlib import Path
22
23# Expected argument count: script + in_a + in_b + out
24_EXPECTED_ARGC = 4
25
26
27def data_records(path: str) -> list[str]:
28 """Return all non-EOF records (stripped) from an Intel HEX file."""
29 out: list[str] = []
30 with Path(path).open(encoding="ascii") as fh:
31 for raw in fh:
32 line = raw.strip()
33 if not line or not line.startswith(":"):
34 continue
35 # Record type is bytes [7:9] of the line (after ':LLAAAA').
36 if line[7:9].upper() == "01": # EOF record -- drop.
37 continue
38 out.append(line)
39 return out
40
41
42def main() -> int:
43 """Concatenate the data records of two Intel HEX files into one image.
44
45 Merges RECORDS rather than text: each input's EOF record is dropped and a
46 single one is emitted at the end, so the result is a valid image instead
47 of two files with a terminator in the middle that most loaders stop at.
48
49 Returns 0 on success, 2 on a usage error, 1 on an unreadable input.
50 """
51 if len(sys.argv) != _EXPECTED_ARGC:
52 print("usage: merge_ihex.py <in_a.hex> <in_b.hex> <out.hex>", file=sys.stderr)
53 return 2
54 in_a, in_b, out = sys.argv[1], sys.argv[2], sys.argv[3]
55 try:
56 records = data_records(in_a) + data_records(in_b)
57 except OSError as exc:
58 print(f"merge_ihex: {exc}", file=sys.stderr)
59 return 1
60 with Path(out).open("w", encoding="ascii") as fh:
61 fh.writelines(rec + "\n" for rec in records)
62 fh.write(":00000001FF\n") # canonical EOF record.
63 print(f"merge_ihex: wrote {len(records)} records -> {out}")
64 return 0
65
66
67if __name__ == "__main__":
68 sys.exit(main())
void main(void)
The application entry point Reset_Handler hands control to.
Definition main.c:298