#!/bin/ksh
set -e
scan_dmesg() {
# no bsort for now
sed -n "$1" /var/run/dmesg.boot
}
installed_firmware() {
for fw in ${PKGDIR}/$1-firmware*; do
[ -e "$fw" ] || continue
echo ${fw##*/}
done
}
set -A _KERNV -- $( scan_dmesg '/^OpenBSD \([1-9][0-9]*\.[0-9]\)\([^ ]*\) .*/ { s//\1 \2/p; q; }' )
VNAME=${_KERNV[0]}
OSDIR=$VNAME
if ((${#_KERNV[*]} > 1)) && [ "$_KERNV[1]" = "-current" -o "$_KERNV[1]" = "-beta" ]; then
OSDIR=snapshots
fi
FWURL=http://firmware.openbsd.org/firmware/${OSDIR}
PKGDIR=${DESTDIR}/var/db/pkg
PATTERNS="file:${0%/*}/firmware_patterns"
drivers=$(
last=''
ftp -D "Detecting" -Vmo- $PATTERNS |
while read d m; do
grep=fgrep
[ "$last" = "$d" ] && continue
[ "$m" ] || m="^$d[0-9][0-9]* at "
[ "$m" != "${m#^}" ] && grep=grep
$grep -q "$m" /var/run/dmesg.boot || continue
echo $d
last=$d
done
)
if [ -z "$drivers" ]; then
echo "No devices found which need firmware files to be downloaded." >&2
exit 0
fi
tmpdir=${DESTDIR}/tmp/fw_update
[ -e "$tmpdir" ] && rm -rf "$tmpdir"
mkdir -p "$tmpdir"
cd "$tmpdir"
# TODO: Drop privs during fetch and verify
ftp -D Get -Vm "$FWURL/SHA256.sig"
# Probably should bundle the firmware sigfile on the installer,
# although we can just get it from the recently installed system.
if [ "$DESTDIR" ]; then
sigfile=$( sed -n '/^untrusted comment: verify with \(.*\)$/ { s//\1/p; q; }' SHA256.sig )
if [ ! -e "/etc/signify/$sigfile" ] \
&& [ -e "${DESTDIR}/etc/signify/$sigfile" ]; then
cp -a "${DESTDIR}/etc/signify/$sigfile" "/etc/signify/$sigfile"
fi
fi
signify -Ve -x SHA256.sig -m - < SHA256.sig > SHA256
for d in $drivers; do
firmware=$( sed -n "s/.*(\($d-firmware-.*\.tgz\)).*/\1/p" SHA256 )
installed=$( installed_firmware $d )
for i in $installed; do
if [ "$firmware" = "$i.tgz" ]; then
echo "Firmware for $d already installed ($installed)"
continue 2
fi
done
mkdir $d
# TODO: Drop privs during fetch and verify
ftp -D "Get/Verify" -Vmo- "$FWURL/$firmware" | sha256 -bph "$d/h" > "$firmware"
fgrep -qx "SHA256 ($firmware) = $(<$d/h)" SHA256
# TODO: Check hash for files before deleting
if [ "$installed" ] && [ -e "${PKGDIR}/$installed/+CONTENTS" ]; then
echo "Uninstalling $installed"
cwd=${PKGDIR}/$installed
remove="${cwd}/+CONTENTS ${cwd}"
while read c g; do
case $c in
@cwd) cwd=$g
;;
@*) continue
;;
*) remove="$cwd/$c $remove"
;;
esac
done < "${PKGDIR}/$installed/+CONTENTS"
for r in $remove ; do
if [ -d "$r" ]; then
# Try hard not to actually remove recursively
# without rmdir on the install media.
[ "$r/*" = $( echo "$r"/* ) ] && rm -rf "$r"
else
rm -f "$r"
fi
done
fi
# TODO: Add some details about the install to +CONTENTS like pkg_add
# TODO: Or, maybe we save the firmware someplace and make pkg_add reinstall
echo "Installing $firmware"
tar -zxphf "$firmware" -C /etc "firmware/*"
mkdir -p ${PKGDIR}/${firmware%.tgz}/
tar -zxphf "$firmware" -C "${PKGDIR}/${firmware%.tgz}" "+*"
ed -s "${PKGDIR}/${firmware%.tgz}/+CONTENTS" <<EOL
/^@comment pkgpath/ -1a
@option manual-installation
@option firmware
@comment install-script
.
w
EOL
done