You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/core/tools/combine_firmware

104 lines
2.5 KiB

#!/usr/bin/env python3
from __future__ import annotations
import datetime
import io
import sys
from pathlib import Path
import click
@click.command()
@click.argument(
"boardloader",
type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path),
)
@click.argument(
"bootloader",
type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path),
)
@click.argument(
"firmware",
type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path),
)
@click.argument(
"outfile",
type=click.Path(dir_okay=False, writable=True, path_type=Path),
required=False,
)
@click.argument(
"boardloader_start",
type=click.STRING,
required=False,
default="0x08000000",
)
@click.argument(
"boardloader_end",
type=click.STRING,
required=False,
default="0x0800C000",
)
@click.argument(
"bootloader_start",
type=click.STRING,
required=False,
default="0x08020000",
)
@click.argument(
"firmware_start",
type=click.STRING,
required=False,
default="0x08040000",
)
def main(
boardloader: Path,
bootloader: Path,
firmware: Path,
outfile: Path | None,
boardloader_start: str,
boardloader_end: str,
bootloader_start: str,
firmware_start: str,
) -> None:
boardloader_start = int(boardloader_start, 0)
boardloader_end = int(boardloader_end, 0)
bootloader_start = int(bootloader_start, 0)
firmware_start = int(firmware_start, 0)
if outfile is None:
today = datetime.date.today().strftime(r"%Y-%m-%d")
outfile = Path(f"combined-{today}.bin")
offset = boardloader_start
out_bytes = io.BytesIO()
# write boardloader
offset += out_bytes.write(boardloader.read_bytes())
if offset > boardloader_end:
raise Exception("Boardloader too big")
# zero-pad until next section:
offset += out_bytes.write(b"\x00" * (bootloader_start - offset))
assert offset == bootloader_start
# write bootlaoder
offset += out_bytes.write(bootloader.read_bytes())
if offset > firmware_start:
raise Exception("Bootloader too big")
# zero-pad until next section:
offset += out_bytes.write(b"\x00" * (firmware_start - offset))
assert offset == firmware_start
# write firmware
offset += out_bytes.write(firmware.read_bytes())
# write out contents
click.echo(f"Writing {outfile} ({offset - boardloader_start} bytes)")
outfile.write_bytes(out_bytes.getvalue())
if __name__ == "__main__":
main()