| #!/usr/bin/env python3 |
| # type: ignore[attr-defined] |
| |
| # |
| # Copyright (c) 2024, Arm Limited. All rights reserved. |
| # |
| # SPDX-License-Identifier: BSD-3-Clause |
| # |
| |
| """Module defining the Transfer List Compiler (TLC) command line interface.""" |
| |
| from pathlib import Path |
| |
| import click |
| |
| from tlc.tl import * |
| |
| |
| @click.group() |
| @click.version_option() |
| def cli(): |
| pass |
| |
| |
| @cli.command() |
| @click.argument("filename", type=click.Path(dir_okay=False)) |
| @click.option( |
| "-s", "--size", default=0x1000, type=int, help="Maximum size of the Transfer List" |
| ) |
| @click.option( |
| "--fdt", |
| type=click.Path(exists=True), |
| help="Path to flattened device tree (FDT).", |
| ) |
| @click.option( |
| "--entry", |
| type=(int, click.Path(exists=True)), |
| multiple=True, |
| help="A tag ID and the corresponding path to a binary blob in the form <id> <path-to-blob>.", |
| ) |
| @click.option( |
| "--flags", |
| default=TRANSFER_LIST_ENABLE_CHECKSUM, |
| show_default=True, |
| help="Settings for the TL's properties.", |
| ) |
| def create(filename, size, fdt, entry, flags): |
| """Create a new Transfer List.""" |
| tl = TransferList(size) |
| |
| entry = (*entry, (1, fdt)) if fdt else entry |
| |
| try: |
| for id, path in entry: |
| tl.add_transfer_entry_from_file(id, path) |
| except MemoryError as mem_excp: |
| raise MemoryError( |
| "TL max size exceeded, consider increasing with the option -s" |
| ) from mem_excp |
| |
| tl.write_to_file(filename) |
| |
| |
| @cli.command() |
| @click.argument("filename", type=click.Path(exists=True, dir_okay=False)) |
| @click.option( |
| "--fdt-offset", |
| is_flag=True, |
| help="Returns the offset of FDT in the TL if it is present.", |
| ) |
| @click.option( |
| "--header", |
| is_flag=True, |
| help="Print the Transfer List header.", |
| ) |
| @click.option( |
| "--entries", |
| is_flag=True, |
| help="Print the Transfer List entries.", |
| ) |
| def info(filename, fdt_offset, header, entries): |
| """Print the contents of an existing Transfer List. |
| |
| This command allows you to extract the data stored in a binary blob |
| representing a transfer list (TL). The transfer list must comply with the |
| version of the firmware handoff specification supported by this tool. |
| """ |
| tl = TransferList.fromfile(filename) |
| |
| if fdt_offset: |
| return print(tl.get_entry_data_offset(1)) |
| |
| if header and entries or not (header or entries): |
| print(tl, sep="") |
| if tl.entries: |
| print("----", tl.get_transfer_entries_str(), sep="\n") |
| elif entries: |
| print(tl.get_transfer_entries_str()) |
| elif header: |
| print(tl) |
| |
| |
| @cli.command() |
| @click.argument("filename", type=click.Path(exists=True, dir_okay=False)) |
| @click.option( |
| "--tags", |
| type=int, |
| multiple=True, |
| help="Tags to be removed from TL.", |
| ) |
| def remove(filename, tags): |
| """Remove Transfer Entries with given tags. |
| |
| Remove Transfer Entries with given tags from a Transfer List.""" |
| tl = TransferList.fromfile(filename) |
| |
| for tag in tags: |
| tl.remove_tag(tag) |
| tl.write_to_file(filename) |
| |
| |
| @cli.command() |
| @click.argument("filename", type=click.Path(exists=True, dir_okay=False)) |
| @click.option( |
| "--entry", |
| type=(int, click.Path(exists=True)), |
| multiple=True, |
| help="A tag ID and the corresponding path to a binary blob in the form <id> <path-to-blob>.", |
| ) |
| def add(filename, entry): |
| """Update an existing Transfer List with given images.""" |
| tl = TransferList.fromfile(filename) |
| |
| for id, path in entry: |
| tl.add_transfer_entry_from_file(id, path) |
| |
| tl.write_to_file(filename) |
| |
| |
| @cli.command() |
| @click.argument("filename", type=click.Path(exists=True, dir_okay=False)) |
| @click.option( |
| "-C", type=click.Path(exists=True), help="Output directory for extracted images." |
| ) |
| def unpack(filename, c): |
| """Unpack images from a Transfer List.""" |
| tl = TransferList.fromfile(filename) |
| pwd = Path(".") if not c else Path(c) |
| |
| for i, te in enumerate(tl.entries): |
| with open(pwd / f"te_{i}_{te.id}.bin", "wb") as f: |
| f.write(te.data) |
| |
| |
| @cli.command() |
| @click.argument("filename", type=click.Path(exists=True, dir_okay=False)) |
| def validate(filename): |
| """Validate the contents of an existing Transfer List.""" |
| TransferList.fromfile(filename) |
| print("Valid TL!") |