#!/bin/sh
#
# Find missing firmware files requested by the kernel, and install the
# binary packages with the files.  Fetch them the from the non-free section
# if that is needed.
#
# This script was copied from auto-addfirmware from the debian-edu-config
# package and extended here.

dist=$(lsb_release -cs)
arch=$(dpkg --print-architecture)
mirror=http://http.debian.net/debian
aptsourcelist=/etc/apt/sources.list.d/isenkram-autoinstall-firmware.list

loginfo() {
    echo "info: $@" 1>&2
}

add_contrib_nonfree() {
    cat <<EOF > $aptsourcelist
deb $mirror $dist contrib non-free
deb-src $mirror $dist contrib non-free
EOF
    chmod a+r $aptsourcelist
}

# Find firmware files requested by loaded kernel drivers.
for fwfile in $(for module in $(awk '{print $1}' /proc/modules) ; do modinfo $module 2>/dev/null |awk '/^firmware:/ {print $2}'; done|sort -u); do
    if [ ! -e /lib/firmware/$fwfile ] ; then
	fwfiles="${fwfiles:+$fwfiles }$fwfile"
    fi
done

if [ -z "$fwfiles" ] ; then
    loginfo "did not find any firmware files requested by loaded kernel modules.  exiting"
    exit 1
fi
loginfo "some kernel driver requested extra firmware files:" $fwfiles

tmpdir=$(mktemp -d)
cd $tmpdir || exit 1

cleanup() {
    cd /
    rm -rf $tmpdir
}

# Try to fetch updated data, but use local copy too just in case this
# fail.

# "" is main in Wheezy.
for section in "" "contrib" "non-free"; do
    if [ -z "$section" ] ; then
	url="$mirror/dists/$dist/Contents-$arch.gz"
    else
	url="$mirror/dists/$dist/$section/Contents-$arch.gz"
    fi
    loginfo "fetching $url"
    GET $url | gunzip | grep ^lib/firmware > Fw-Contents-$arch-$dist-$section
done

datafiles=""
for f in Fw-Contents-$arch-$dist-* \
    /usr/share/isenkram/Fw-Contents-$arch-$dist-* ; do
    if [ -s "$f" ] ; then
	datafiles="$datafiles $f"
    fi
done

loginfo "locating packages with the requested firmware files"
binpkginfos=""
binpkgs=""
for fwfile in $fwfiles ; do
    fwfilere=$(echo $fwfile | sed -e 's%/%\\/%g' -e 's/\./\\./g')
    binpkginfo="$(awk "/^lib\/firmware\/$fwfilere/ {print \$2}" $datafiles)"
    if [ -z "$binpkginfo" ] ; then
	# Special case for b43 where the firmware is undistributable
	# by Debian.
	case "$fwfile" in
	    b43/*)
		add_contrib_nonfree
		binpkgs="${binpkgs:+$binpkgs }firmware-b43-installer"
		;;
	esac
    else
	binpkginfos="$binpkginfos $binpkginfo"
    fi
done

binpkgs="${binpkgs:+$binpkgs }$(
for binpkginfo in $binpkginfos ; do
    echo $binpkginfo |  while IFS=/ read section srcpkg binpkg ; do
        echo $binpkg
# Enable the non-free section if it is needed
	if LC_ALL=C apt-cache show $binpkg 2>&1 | \
               grep -q 'E: No packages found' \
           && ( [ non-free = "$section" ] \
               || [ contrib = "$section" ] ) ; then 
	    add_contrib_nonfree
	fi
    done
done)"

if [ -e $aptsourcelist ] ; then
    # Fetch updated package lists
    loginfo "Updating APT sources after adding non-free APT source"
    apt-get -qq update
fi

if [ "$binpkgs" ] ; then
    if [ "-l" = "$1" ] ; then
	echo $binpkgs | tr " " "\n"
    else
        # Install firmware packages
	loginfo "trying to install $binpkgs"
	apt-get -qq install -y $binpkgs
    fi
else
    loginfo "No new firmware package with requested firmware detected."
fi
cleanup
