#!/bin/bash
#
# Compare firmware listed in debian/*.lst with the firmware files
# specified by modules in udebs for the specified kernel version.
# List files to be removed (i.e. files in debian/*.lst but not
# requested by udeb modules) and files to be added (i.e. files
# requested by udeb modules but not in debian/*.lst).
#
# The lists generated by this tool are not definitive, as some
# modules omit the firmware modinfo or put some less-than-current
# firmware version there. Exercise good judgement.
#
# Example usage:
#
#   $ debian/list-udeb-updates linux 4.4.0-13.29
#   $ debian/list-udeb-updates linux-lts-utopic 3.16.0-67.87~14.04.1

shopt -s expand_aliases
alias errecho='>&2 echo'

if [ $# -ne 2 ]; then
	errecho "Usage: $0 <source-pkg> <kernel-version>"
	exit 1
fi

# Bail if the source package or version string isn't the format we expect
if ! (expr match "$1" '^linux$' &>/dev/null || expr match "$1" '^linux-hwe[a-z\-]*$' &>/dev/null ||
      expr match "$1" '^linux-[0-9]\+\.[0-9]\+$' &>/dev/null || expr match "$1" '^linux-hwe-[0-9]\+\.[0-9]\+$')
then
	errecho "Invalid source package $1"
	exit 1
fi
if ! expr match "$2" '\(^[0-9]\+\.[0-9]\+\.0-[0-9]\+\.[0-9.~]\+$\)' &>/dev/null
then
	errecho "Invalid version $2"
	exit 1
fi
VER=$(expr match "$2" '\(^[0-9]\+\.[0-9]\+\.0\)')
TMP=${2#"${VER}-"}
ABI=$(expr match "$TMP" '\([0-9]\+\)')
UPLOAD=$(expr match "$TMP" '[0-9]\+\.\([0-9.~]\+\)')

TMPDIR=$(mktemp -d)
if [ $? -ne 0 ]; then
	echo "Error creating temporary directory"
	exit 1
fi

function cleanup {
	rm -r "$TMPDIR"
}
trap cleanup EXIT

UDEBS="kernel-image-${VER}-${ABI}-*_${VER}-${ABI}.${UPLOAD}_*.udeb"
UDEBS+=",nic-modules-${VER}-${ABI}-*_${VER}-${ABI}.${UPLOAD}_*.udeb"
UDEBS+=",nic-usb-modules-${VER}-${ABI}-*_${VER}-${ABI}.${UPLOAD}_*.udeb"
UDEBS+=",scsi-modules-${VER}-${ABI}-*_${VER}-${ABI}.${UPLOAD}_*.udeb"
mkdir "$TMPDIR/udebs"
if ! wget --quiet -r -l1 --no-parent -nd -P "$TMPDIR/udebs/" -A "$UDEBS" "http://archive.ubuntu.com/ubuntu/pool/main/l/$1/"
then
	errecho "Error downloading udebs for kernel version $VERSION"
	exit 1
fi
if ! wget --quiet -r -l1 --no-parent -nd -P "$TMPDIR/udebs/" -A "$UDEBS" "http://ports.ubuntu.com/pool/main/l/$1/"
then
	errecho "Error downloading udebs for kernel version $VERSION"
	exit 1
fi

touch "$TMPDIR/fwlist.txt"

for f in $TMPDIR/udebs/*.udeb; do
	dpkg -x "$f" "$TMPDIR/extract"
	modules=$(find "$TMPDIR/extract" -name '*.ko')

	rm -f "$TMPDIR/fwlist.tmp"
	touch "$TMPDIR/fwlist.tmp"
	for m in $modules; do
		modinfo -F firmware $m >>"$TMPDIR/fwlist.tmp"
	done

	cat "$TMPDIR/fwlist.txt" "$TMPDIR/fwlist.tmp" | sort | uniq >"$TMPDIR/fwlist.new"
	mv "$TMPDIR/fwlist.new" "$TMPDIR/fwlist.txt"
	rm -rf "$TMPDIR/extract"
done

# Filter out any firmware files not actually in linux-firmware
find . -type f | sed 's/\.\///'|egrep -v "debian|\.git|WHENCE|LICEN" | sort >"$TMPDIR/fw-files.txt"
comm -12 "$TMPDIR/fw-files.txt" "$TMPDIR/fwlist.txt" >"$TMPDIR/fwlist.tmp"
mv "$TMPDIR/fwlist.tmp" "$TMPDIR/fwlist.txt"

cat debian/*.lst | sort | uniq >"$TMPDIR/current-fw.txt"

echo "Firmware to remove from udebs:"
echo ""
comm -23 "$TMPDIR/current-fw.txt" "$TMPDIR/fwlist.txt"

echo ""
echo "Firmware to add to udebs:"
echo ""
comm -13 "$TMPDIR/current-fw.txt" "$TMPDIR/fwlist.txt"
