#!/usr/bin/python3 import re import sys import subprocess from pathlib import Path # pylint: disable=invalid-name ### Sanity/usage checks if len(sys.argv) != 3: print("E: need 2 arguments", file=sys.stderr) sys.exit(1) arch = sys.argv[1] if arch not in ['armhf', 'arm64']: print("E: unsupported arch %s" % arch, file=sys.stderr) sys.exit(1) suite = sys.argv[2] if suite not in ['bookworm', 'trixie', 'forky', 'sid']: print("E: unsupported suite %s" % suite, file=sys.stderr) sys.exit(1) target_yaml = 'raspi_%s_%s.yaml' % (arch, suite) ### Setting variables based on suite and version starts here # Arch, kernel, DTB: if arch == 'armhf': arch = 'armhf' linux = 'linux-image-armmp' dtb = '/usr/lib/linux-image-*-armmp/bcm*rpi*.dtb' elif arch == 'arm64': linux = 'linux-image-arm64' dtb = '/usr/lib/linux-image-*-arm64/broadcom/bcm*rpi*.dtb' # wireless/bluetooth firmware: if arch != 'armhf': wireless_firmware = 'firmware-brcm80211' bluetooth_firmware = 'bluez-firmware' else: wireless_firmware = '' bluetooth_firmware = '' # Pi 4 on buster required some backports. Let's keep variables around, ready to # be used whenever we need to pull specific things from backports. backports_enable = False backports_suite = '%s-backports' % suite # Serial console: if arch == 'armhf': serial = 'ttyAMA0,115200' elif arch == 'arm64': serial = 'ttyS1,115200' # CMA fixup: extra_chroot_shell_cmds = [] if arch == 'arm64': extra_chroot_shell_cmds = [ "sed -i 's/cma=64M //' /boot/firmware/cmdline.txt", ] # Hostname: hostname = 'rpi-%s' % arch # Nothing yet! extra_root_shell_cmds = [] ### The following prepares substitutions based on variables set earlier # Enable backports with a reason, or add commented-out entry: if backports_enable: backports_stanza = """ %s deb http://deb.debian.org/debian/ %s main non-free-firmware """ % (backports_enable, backports_suite) else: # ugh backports_stanza = """ # Backports are _not_ enabled by default. # Enable them by uncommenting the following line: # deb http://deb.debian.org/debian %s main non-free-firmware """ % backports_suite # Enable updates and security for everyone but sid: if suite != 'sid': updates_stanza = 'deb http://deb.debian.org/debian %s-updates main non-free-firmware' % suite security_stanza = 'deb http://security.debian.org/debian-security %s-security main non-free-firmware' % suite else: updates_stanza = '' security_stanza = '' gitcommit = subprocess.getoutput("git show -s --pretty='format:%C(auto)%h (%s, %ad)' --date=short ") buildtime = subprocess.getoutput("date --utc +'%Y-%m-%d %H:%M'") ### Write results: def align_replace(text, pattern, replacement): """ This helper lets us keep the indentation of the matched pattern with the upcoming replacement, across multiple lines. Naive implementation, please make it more pythonic! """ lines = text.splitlines() for i, line in enumerate(lines): m = re.match(r'^(\s+)%s' % pattern, line) if m: indent = m.group(1) del lines[i] for r in replacement: lines.insert(i, '%s%s' % (indent, r)) i = i + 1 break return '\n'. join(lines) + '\n' with open('raspi_master.yaml', 'r') as in_file: with open(target_yaml, 'w') as out_file: in_text = in_file.read() out_text = in_text \ .replace('__RELEASE__', suite) \ .replace('__ARCH__', arch) \ .replace('__LINUX_IMAGE__', linux) \ .replace('__DTB__', dtb) \ .replace('__WIRELESS_FIRMWARE__', wireless_firmware) \ .replace('__BLUETOOTH_FIRMWARE__', bluetooth_firmware) \ .replace('__SERIAL_CONSOLE__', serial) \ .replace('__HOST__', hostname) \ .replace('__GITCOMMIT__', gitcommit) \ .replace('__BUILDTIME__', buildtime) out_text = align_replace(out_text, '__EXTRA_ROOT_SHELL_CMDS__', extra_root_shell_cmds) out_text = align_replace(out_text, '__EXTRA_CHROOT_SHELL_CMDS__', extra_chroot_shell_cmds) out_text = align_replace(out_text, '__UPDATES_', updates_stanza.splitlines()) out_text = align_replace(out_text, '__BACKPORTS__', backports_stanza.splitlines()) out_text = align_replace(out_text, '__SECURITY__', security_stanza.splitlines()) # Try not to keep lines where the placeholder was replaced # with nothing at all (including on a "list item" line): filtered = [x for x in out_text.splitlines() if not re.match(r'^\s+$', x) and not re.match(r'^\s+-\s*$', x)] out_file.write('\n'.join(filtered) + "\n")