#!/bin/sh
#
# Adds (non-free-firmware) firmware to the debian-installer initrd used by the
# PXE installation to make sure it works on more hardware out of the
# box.

set -e

export TMPDIR=/var/tmp

echo Finding and downloading firmware .debs
# Find files. This requires non-free-firmware to be enabled as APT
# repository.
# Skip installer debs to avoid the b43 installers that conflict
# with each other.
# For bookworm, also exclude firmware-microbit-micropython{-dl}.
# For trixie, exclude various other 'huge' firmware packages and metadata packages.
# FIXME Review if this needs to be adjusted after trixie.
debnames="$(apt-cache search ^firmware-.* | grep -v installer \
                                  | grep -v firmware-micropython \
                                  | grep -v firmware-nvidia \
                                  | grep -v firmware-qcom \
                                  | grep -v firmware-marvell-prestera \
                                  | grep -v firmware-linux-nonfree \
                                  | grep -v firmware-linux \
                                  | grep -v fxload \
                                  | grep -v dfu-util \
                                  | grep -v ap51-flash \
                                  | cut -d" " -f1)"

# Allow caller to ask for extra debs using environment variable
debnames="$debnames $FIRMWAREDEBNAMES"

add_firmware_to_initrd() {
	initrd=$1

	tmpdir=$(mktemp -d)
	cd $tmpdir

	# Find firmware .deb files
	for name in $debnames ; do
		for deb in /var/cache/apt/archives/${name}_* ; do
			if [ -f $deb ] ; then
				debs="$debs $deb"
			fi
		done
	done

	echo Unpacking current initrd
	gunzip < $initrd | cpio --quiet -id

	echo Unpacking firmware files, overwriting any in the original initrd
	for deb in $debs ; do
		data_tarball="$(ar t $deb | grep data.tar.)"
		if ar p ${deb} ${data_tarball} > ${data_tarball} && tar axf ${data_tarball} ./usr/lib/firmware ; then
			:
			# and clean up...
			rm ${data_tarball}
		else
			echo "Ignoring $deb without /usr/lib/firmware/"
		fi
	done

	timestamp=$(date +%Y%m%dT%H:%M)
	echo Wrapping up new initrd
	echo $(pwd)
	echo ${initrd}.new
	find . | cpio --quiet -o -H newc | gzip -9 > $initrd.new &&
	    mv $initrd $initrd.old-$timestamp &&
	    mv $initrd.new $initrd
	    cd /
	    rm -rf $tmpdir
}

if [ "$1" ] ; then
	diroot="$1"
fi

# Path to where the d-i pxe boot images were unpacked
if [ -z "$diroot" ] ; then
	diroot=/srv/tftp/debian-installer
fi

# Retrieve .deb packages that we will extract firmware files from.
apt-get --download-only --no-install-recommends -y -q install $debnames

# We will use firmware files available for this host's Debian version for
# all Debian-Installer initrd files (also for older/newer D-I versions).
# For older D-I versions, this will likely work well.
# FIXME: For newer D-I versions, we need to find a better solution at some point
# (e.g. debootstrap a minimal system based on the D-I version and obtain the
# firmware files into that chroot, FTR: firmware packages are arch:all, so only
# one amd64 chroot for Debian version based downloads are sufficient).
for initrd in $diroot/*/*/initrd.gz ; do
	if [ -e $initrd ] ; then
		add_firmware_to_initrd "$initrd"
	else
		echo "Unable to open $initrd"
	fi
done
