uhd/mpm/python/usrp_mpm/bootgen_wrapper.py
Jörg Hofrichter d4828aa208 mpm: add bootgen_wrapper script
Provide the following two functions by wrapping the "bootgen"
command line tool:

verify: verify the validity of the signature of the .bin file.

extract_bitstream: extract the FPGA bitstream from the .bin file.
This works if the .bin file includes the FPGA bitstream as a
single partition.
2026-08-10 16:40:53 +02:00

58 lines
2.0 KiB
Python
Executable File

#!/usr/bin/env python3
#
# Copyright 2026 Ettus Research, a National Instruments Company
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
"""Utility functions provided by wrapping the "bootgen" tool.
verify: Verify the signature of a .bin file.
extract_bitstream: Extract the FPGA bitstream from a .bin file.
"""
import shutil
import subprocess
import tempfile
from pathlib import Path
def verify(input, arch):
"""Verify the signature of the .bin file."""
proc = subprocess.run(["bootgen", "-arch", arch, "-verify", input], capture_output=True)
if proc.returncode != 0:
stderr = proc.stderr.decode().splitlines()[0]
raise RuntimeError(
f'FPGA bitstream (.bin file) verification using bootgen failed: "{stderr}"'
)
def extract_bitstream(input, output, arch):
"""Extract the FPGA bitstream from the bootgen generated .bin file."""
temp_dir = tempfile.TemporaryDirectory()
proc = subprocess.run(
["bootgen", "-arch", arch, "-dump", input, "-dump_dir", temp_dir.name], capture_output=True
)
if proc.returncode != 0:
if proc.stderr.decode().startswith("[ERROR] : Boot Header not found"):
# The file is already a FPGA bitstream in .bin file format, just copy it
try:
shutil.copyfile(input, output)
except shutil.SameFileError:
# in-place conversion is allowed
pass
else:
stderr = proc.stderr.decode().splitlines()[0]
raise RuntimeError(
f'Could not extract bitstream from .bin file, bootgen returned "{stderr}"'
)
else:
extracted_bins = list(Path(temp_dir.name).glob("*.bin"))
num_bins = len(extracted_bins)
if num_bins == 0:
raise RuntimeError("Could not find extracted .bin file in bootgen dump output")
elif num_bins > 1:
raise RuntimeError(
f"Invalid .bin file: found {num_bins} partitions but expected only one."
)
shutil.move(str(extracted_bins[0]), output)