1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-24 07:18:09 +00:00

feat(core/tests): add core bootloader hashes to make gen and gen_check targets

[no changelog]
This commit is contained in:
tychovrahe 2024-08-26 21:02:45 +02:00 committed by matejcik
parent 7275a5544e
commit 3bfc0b61e5
2 changed files with 52 additions and 32 deletions

View File

@ -148,6 +148,12 @@ vendorheader: ## generate vendor header
vendorheader_check: ## check that vendor header is up to date vendorheader_check: ## check that vendor header is up to date
./core/tools/generate_vendorheader.sh --quiet --check ./core/tools/generate_vendorheader.sh --quiet --check
gen: templates mocks icons protobuf ci_docs vendorheader solana_templates ## regenerate auto-generated files from sources bootloader_hashes: ## generate bootloader hashes
./core/tools/bootloader_hashes.py
gen_check: templates_check mocks_check icons_check protobuf_check ci_docs_check vendorheader_check solana_templates_check ## check validity of auto-generated files bootloader_hashes_check: ## check generated bootloader hashes
./core/tools/bootloader_hashes.py --check
gen: templates mocks icons protobuf ci_docs vendorheader solana_templates bootloader_hashes ## regenerate auto-generated files from sources
gen_check: templates_check mocks_check icons_check protobuf_check ci_docs_check vendorheader_check solana_templates_check bootloader_hashes_check ## check validity of auto-generated files

View File

@ -1,18 +1,29 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import click
from pathlib import Path from pathlib import Path
from hashlib import blake2s from hashlib import blake2s
from trezorlib.firmware.core import FirmwareImage from trezorlib.firmware.core import FirmwareImage, Model
ALIGNED_SIZE = 128 * 1024 ALIGNED_SIZE = 128 * 1024
HERE = Path(__file__).parent HERE = Path(__file__).parent
BOOTLOADERS = HERE / ".." / "models" BOOTLOADERS = HERE / ".." / "embed" / "models"
BL_CHECK = HERE / "bl_check.c" TEMPLATE = """\
#ifndef BOOTLOADER_HASHES_H
#define BOOTLOADER_HASHES_H
BL_CHECK_AUTO_BEGIN = "// --- BEGIN GENERATED BOOTLOADER SECTION ---\n" // Auto-generated file, do not edit.
BL_CHECK_AUTO_END = "// --- END GENERATED BOOTLOADER SECTION ---\n"
// clang-format off
{patterns}
// clang-format on
#endif
"""
PATTERN = """\ PATTERN = """\
// {name} version {version} // {name} version {version}
@ -21,7 +32,7 @@ PATTERN = """\
""" """
def aligned_digest(data: bytes, padding: bytes) -> bytes: def aligned_digest(fn: Path, data: bytes, padding: bytes) -> bytes:
"""Calculate digest of data, aligned to ALIGNED_SIZE with """Calculate digest of data, aligned to ALIGNED_SIZE with
the specified padding. the specified padding.
@ -46,7 +57,7 @@ def to_uint_array(data: bytes) -> str:
return ", ".join([f"0x{i:02x}" for i in data]) return ", ".join([f"0x{i:02x}" for i in data])
def bootloader_str(file: Path) -> str: def bootloader_str(file: Path, model: str) -> str:
"""From a given file, generate the relevant C definition strings from PATTERN. """From a given file, generate the relevant C definition strings from PATTERN.
Calculates the two padded hashes, one with 0x00 and the other 0xFF, and returns Calculates the two padded hashes, one with 0x00 and the other 0xFF, and returns
@ -55,14 +66,19 @@ def bootloader_str(file: Path) -> str:
data = file.read_bytes() data = file.read_bytes()
suffix = file.stem[len("bootloader_") :].upper() suffix = file.stem[len("bootloader_") :].upper()
bytes_00 = to_uint_array(aligned_digest(data, b"\x00")) bytes_00 = to_uint_array(aligned_digest(file, data, b"\x00"))
bytes_ff = to_uint_array(aligned_digest(data, b"\xff")) bytes_ff = to_uint_array(aligned_digest(file, data, b"\xff"))
try: bl = FirmwareImage.parse(data)
bl = FirmwareImage.parse(data) version_str = ".".join(str(x) for x in bl.header.version)
version_str = ".".join(str(x) for x in bl.header.version) if not isinstance(bl.header.hw_model, Model):
except Exception: raise ValueError(
version_str = "<unknown>" f"Model mismatch: {file.name} {model} (found {bytes(bl.header.hw_model).decode()})"
)
elif bl.header.hw_model.value != model.encode():
raise ValueError(
f"Model mismatch: {file.name} {model} (found {bl.header.hw_model.value})"
)
return PATTERN.format( return PATTERN.format(
name=file.name, name=file.name,
@ -73,7 +89,9 @@ def bootloader_str(file: Path) -> str:
) )
def main(): @click.command()
@click.option("-c", "--check", is_flag=True, help="Do not write, only check.")
def bootloader_hashes(check):
models = list(BOOTLOADERS.iterdir()) models = list(BOOTLOADERS.iterdir())
@ -87,26 +105,22 @@ def main():
header_file = path / "bootloader_hashes.h" header_file = path / "bootloader_hashes.h"
content = [] patterns = []
content.append("#ifndef BOOTLOADER_HASHES_H\n")
content.append("#define BOOTLOADER_HASHES_H\n")
content.append("\n")
content.append("// Auto-generated file, do not edit.\n")
content.append("\n")
content.append("// clang-format off\n")
bootloaders = sorted(path.glob("bootloader*.bin")) bootloaders = sorted(path.glob("bootloader*.bin"))
for bootloader in bootloaders: for bootloader in bootloaders:
if bootloader.is_file(): print(f"Processing {bootloader}")
print(f"Processing {bootloader}") patterns.append(bootloader_str(bootloader, model.name))
content.append(bootloader_str(bootloader))
content.append("// clang-format on\n") content = TEMPLATE.format(patterns="\n".join(patterns))
content.append("\n")
content.append("#endif\n")
header_file.write_text("".join(content)) if not check:
header_file.write_text(content)
else:
actual = header_file.read_text()
if content != actual:
raise click.ClickException(f"{header_file} differs from expected")
if __name__ == "__main__": if __name__ == "__main__":
main() bootloader_hashes()