2017-05-30 15:48:19 +00:00
|
|
|
#!/usr/bin/env python3
|
2023-04-21 10:03:11 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
import datetime
|
|
|
|
import io
|
2017-05-30 15:48:19 +00:00
|
|
|
import sys
|
2023-04-21 10:03:11 +00:00
|
|
|
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,
|
|
|
|
)
|
2023-06-28 08:51:30 +00:00
|
|
|
@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",
|
|
|
|
)
|
2023-04-21 10:03:11 +00:00
|
|
|
def main(
|
2023-06-28 08:51:30 +00:00
|
|
|
boardloader: Path,
|
|
|
|
bootloader: Path,
|
|
|
|
firmware: Path,
|
|
|
|
outfile: Path | None,
|
|
|
|
boardloader_start: str,
|
|
|
|
boardloader_end: str,
|
|
|
|
bootloader_start: str,
|
|
|
|
firmware_start: str,
|
2023-04-21 10:03:11 +00:00
|
|
|
) -> None:
|
2023-06-28 08:51:30 +00:00
|
|
|
boardloader_start = int(boardloader_start, 0)
|
|
|
|
boardloader_end = int(boardloader_end, 0)
|
|
|
|
bootloader_start = int(bootloader_start, 0)
|
|
|
|
firmware_start = int(firmware_start, 0)
|
|
|
|
|
2023-04-21 10:03:11 +00:00
|
|
|
if outfile is None:
|
|
|
|
today = datetime.date.today().strftime(r"%Y-%m-%d")
|
|
|
|
outfile = Path(f"combined-{today}.bin")
|
|
|
|
|
2023-06-28 08:51:30 +00:00
|
|
|
offset = boardloader_start
|
2023-04-21 10:03:11 +00:00
|
|
|
out_bytes = io.BytesIO()
|
2017-05-30 15:48:19 +00:00
|
|
|
|
2023-04-21 10:03:11 +00:00
|
|
|
# write boardloader
|
|
|
|
offset += out_bytes.write(boardloader.read_bytes())
|
2023-06-28 08:51:30 +00:00
|
|
|
if offset > boardloader_end:
|
2023-04-21 10:03:11 +00:00
|
|
|
raise Exception("Boardloader too big")
|
2017-06-13 14:50:03 +00:00
|
|
|
|
2023-04-21 10:03:11 +00:00
|
|
|
# zero-pad until next section:
|
2023-06-28 08:51:30 +00:00
|
|
|
offset += out_bytes.write(b"\x00" * (bootloader_start - offset))
|
|
|
|
assert offset == bootloader_start
|
2017-05-30 15:48:19 +00:00
|
|
|
|
2023-04-21 10:03:11 +00:00
|
|
|
# write bootlaoder
|
|
|
|
offset += out_bytes.write(bootloader.read_bytes())
|
2023-06-28 08:51:30 +00:00
|
|
|
if offset > firmware_start:
|
2023-04-21 10:03:11 +00:00
|
|
|
raise Exception("Bootloader too big")
|
2017-09-05 21:15:47 +00:00
|
|
|
|
2023-04-21 10:03:11 +00:00
|
|
|
# zero-pad until next section:
|
2023-06-28 08:51:30 +00:00
|
|
|
offset += out_bytes.write(b"\x00" * (firmware_start - offset))
|
|
|
|
assert offset == firmware_start
|
2017-05-30 15:48:19 +00:00
|
|
|
|
2023-04-21 10:03:11 +00:00
|
|
|
# write firmware
|
|
|
|
offset += out_bytes.write(firmware.read_bytes())
|
2017-05-30 15:48:19 +00:00
|
|
|
|
2023-04-21 10:03:11 +00:00
|
|
|
# write out contents
|
2023-06-28 08:51:30 +00:00
|
|
|
click.echo(f"Writing {outfile} ({offset - boardloader_start} bytes)")
|
2023-04-21 10:03:11 +00:00
|
|
|
outfile.write_bytes(out_bytes.getvalue())
|
2017-05-30 15:48:19 +00:00
|
|
|
|
|
|
|
|
2023-04-21 10:03:11 +00:00
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|