mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-19 12:58:13 +00:00
feat(core/tests): add core bootloader hashes to make gen and gen_check targets
[no changelog]
This commit is contained in:
parent
7275a5544e
commit
3bfc0b61e5
10
Makefile
10
Makefile
@ -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
|
||||||
|
@ -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()
|
Loading…
Reference in New Issue
Block a user