Annotation of openbsd/fw_update/fw_install.sh, Revision 1.21
1.1 afresh1 1: #!/bin/ksh
2: set -e
3:
4: scan_dmesg() {
5: # no bsort for now
6: sed -n "$1" /var/run/dmesg.boot
7: }
8:
1.8 afresh1 9: # tmpdir, do_as, unpriv, and unpriv2 are from install.sub
10:
11: # Create a temporary directory based on the supplied directory name prefix.
12: tmpdir() {
13: local _i=1 _dir
14:
15: until _dir="${1?}.$_i.$RANDOM" && mkdir -- "$_dir" 2>/dev/null; do
16: ((++_i < 10000)) || return 1
17: done
18: echo "$_dir"
19: }
1.6 afresh1 20:
21: # Run a command ($2+) as unprivileged user ($1).
22: # Take extra care that after "cmd" no "user" processes exist.
23: #
24: # Optionally:
25: # - create "file" and chown it to "user"
26: # - after "cmd", chown "file" back to root
27: #
28: # Usage: do_as user [-f file] cmd
29: do_as() {
30: (( $# >= 2 )) || return
31:
32: local _file _rc _user=$1
33: shift
34:
35: if [[ $1 == -f ]]; then
36: _file=$2
37: shift 2
38: fi
39:
40: if [[ -n $_file ]]; then
41: >$_file
42: chown "$_user" "$_file"
43: fi
44:
45: doas -u "$_user" "$@"
46: _rc=$?
47:
48: while doas -u "$_user" kill -9 -1 2>/dev/null; do
49: echo "Processes still running for user $_user after: $@"
50: sleep 1
51: done
52:
53: [[ -n $_file ]] && chown root "$_file"
54:
55: return $_rc
56: }
57:
58: unpriv() {
59: do_as _sndio "$@"
60: }
61:
62: unpriv2() {
63: do_as _file "$@"
64: }
65:
1.20 afresh1 66: # "fail" needs to be replaced with the "ask_yn" loop like in the installer.
1.8 afresh1 67: _issue=
68: fail() {
69: echo $_issue >&2
70: exit 1
71: }
72:
1.7 afresh1 73: VNAME=$(sysctl -n kern.osrelease)
74: VERSION="${VNAME%.*}${VNAME#*.}"
75: FWDIR="$VNAME"
1.1 afresh1 76:
1.14 afresh1 77: # TODO: We need the firmware for the system we just installed
78: # not the one we booted from. For example:
79: # * booting from a snapshot bsd.rd that thinks it is the 7.0 release
80: # will install the firmware from the 7.0 directory instead of
81: # from the snapshots dir.
82: # If they're using sysupgrade, then the installer kernel will be correct.
83: # If we're doing this in the installer we can check what they picked
84: # for downloading sets and use that value.
85: # Otherwise, the fw_update after first boot will fix it up for us.
86:
1.7 afresh1 87: HTTP_FWDIR=$FWDIR
88: set -- $(scan_dmesg "/^OpenBSD $VNAME\([^ ]*\).*$/s//\1/p")
89: [[ $1 == -!(stable) ]] && HTTP_FWDIR=snapshots
90:
91: FWURL=http://firmware.openbsd.org/firmware/${HTTP_FWDIR}
92: FWPUB_KEY=${DESTDIR}/etc/signify/openbsd-${VERSION}-fw.pub
1.1 afresh1 93: PKGDIR=${DESTDIR}/var/db/pkg
1.20 afresh1 94: FWPATTERNS="file:${0%/*}/firmware_patterns"
1.1 afresh1 95:
1.20 afresh1 96: # TODO: support srclocal installation of firmware somehow
1.11 afresh1 97: fw_update() {
1.20 afresh1 98: local _src=$FWURL _tmpsrc _t=Get _cfile="/tmp/SHA256" _srclocal=false
99: local _f _r _remove _i _installed
1.15 afresh1 100: local _d _drivers=$(
1.11 afresh1 101: last=''
1.20 afresh1 102: ftp -D "Detecting" -Vmo- $FWPATTERNS |
1.15 afresh1 103: while read _d _m; do
1.11 afresh1 104: grep=grep
1.15 afresh1 105: [ "$last" = "$_d" ] && continue
106: [ "$_m" ] || _m="^$_d[0-9][0-9]* at "
107: [ "$_m" = "${_m#^}" ] && grep=fgrep
108: $grep -q "$_m" /var/run/dmesg.boot || continue
109: echo $_d
110: last=$_d
1.11 afresh1 111: done
112: )
113:
114: if [ -z "$_drivers" ]; then
115: echo "No devices found which need firmware files to be downloaded." >&2
116: return
117: fi
1.1 afresh1 118:
1.11 afresh1 119: if _tmpsrc=$( tmpdir "${DESTDIR}/tmp/fw_update" ); then
120: (
121: >$_tmpsrc/t &&
122: $_unpriv cat $_tmpsrc/t
123: ) >/dev/null 2>&1 ||
124: rm -r $_tmpsrc
125: fi
1.1 afresh1 126:
1.11 afresh1 127: [[ ! -d $_tmpsrc ]] &&
128: _issue="Cannot create prefetch area" && fail
1.1 afresh1 129:
1.16 afresh1 130: # Cleanup from previous runs.
131: rm -f $_cfile $_cfile.sig
132:
1.21 ! afresh1 133: _t=Get/Verify
1.17 afresh1 134:
1.11 afresh1 135: ! $_unpriv ftp -D "$_t" -Vmo - "$_src/SHA256.sig" >"$_cfile.sig" &&
136: _issue="Cannot fetch SHA256.sig" && fail
1.1 afresh1 137:
1.11 afresh1 138: # Verify signature file with public keys.
139: ! unpriv -f "$_cfile" \
140: signify -Vep $FWPUB_KEY -x "$_cfile.sig" -m "$_cfile" &&
141: _issue="Signature check of SHA256.sig failed" && fail
142:
1.15 afresh1 143: for _d in $_drivers; do
144: _f=$( sed -n "s/.*(\($_d-firmware-.*\.tgz\)).*/\1/p" "$_cfile" )
1.19 afresh1 145: _installed=$(
146: for fw in "${PKGDIR}/$_d-firmware"*; do
147: [ -e "$fw" ] || continue
148: echo ${fw##*/}
149: done
1.21 ! afresh1 150: )
1.15 afresh1 151:
152: for _i in $_installed; do
153: if [ "$_f" = "$_i.tgz" ]; then
154: echo "Firmware for $_d already installed ($_installed)"
1.11 afresh1 155: continue 2
1.1 afresh1 156: fi
157: done
158:
1.11 afresh1 159: rm -f /tmp/h /tmp/fail
160:
161: # Fetch firmware file and create a checksum by piping through
162: # sha256. Create a flag file in case ftp failed. Firmware
163: # from net is written to the prefetch area.
164: ( $_unpriv ftp -D "$_t" -Vmo - "$_src/$_f" || >/tmp/fail ) |
165: ( $_srclocal && unpriv2 sha256 -b >/tmp/h ||
166: unpriv2 -f /tmp/h sha256 -bph /tmp/h >"$_tmpsrc/$_f" )
167:
168: # Handle failed transfer.
169: if [[ -f /tmp/fail ]]; then
170: rm -f "$_tmpsrc/$_f"
171: _issue="Fetching of $_f failed!"
172: fail
173: fi
174:
175: # Verify firmware by comparing its checksum with SHA256.
176: if fgrep -qx "SHA256 ($_f) = $(</tmp/h)" "$_cfile"; then
177: #_unver=$(rmel $_f $_unver)
178: true
179: else
180: [[ -d "$_tmpsrc" ]] && rm -rf "$_tmpsrc"
181: _issue="Checksum test for $_f failed."
182: fail
183: fi
184:
185: # TODO: Check hash for files before deleting
1.18 afresh1 186: if [ "$_installed" ] && [ -e "${PKGDIR}/$_installed/+CONTENTS" ]; then
187: echo "Uninstalling $_installed"
188: cwd=${PKGDIR}/$_installed
1.11 afresh1 189:
190: set -A _remove -- "${cwd}/+CONTENTS" "${cwd}"
191:
192: while read c g; do
193: case $c in
1.13 afresh1 194: @cwd) cwd="${DESTDIR}/$g"
1.11 afresh1 195: ;;
196: @*) continue
197: ;;
198: *) set -A _remove -- "$cwd/$c" "${_remove[@]}"
199: ;;
200: esac
1.18 afresh1 201: done < "${PKGDIR}/$_installed/+CONTENTS"
1.11 afresh1 202:
1.21 ! afresh1 203: # We specifically rm -f here because not removing files/dirs
! 204: # is probably not worth failing over.
1.11 afresh1 205: for _r in "${_remove[@]}" ; do
206: if [ -d "$_r" ]; then
207: # Try hard not to actually remove recursively
208: # without rmdir on the install media.
209: [ "$_r/*" = $( echo "$_r"/* ) ] && rm -rf "$_r"
210: else
211: rm -f "$_r"
212: fi
213: done
214: fi
215:
1.21 ! afresh1 216: # TODO: Should we mark these so real fw_update can -Drepair?
1.11 afresh1 217: echo "Installing $_f"
1.13 afresh1 218: tar -zxphf "$_tmpsrc/$_f" -C "${DESTDIR}/etc" "firmware/*"
1.11 afresh1 219: mkdir -p ${PKGDIR}/${_f%.tgz}/
1.12 afresh1 220: tar -zxphf "$_tmpsrc/$_f" -C "${PKGDIR}/${_f%.tgz}" "+*"
1.11 afresh1 221: ed -s "${PKGDIR}/${_f%.tgz}/+CONTENTS" <<EOL
1.1 afresh1 222: /^@comment pkgpath/ -1a
223: @option manual-installation
224: @option firmware
225: @comment install-script
226: .
227: w
228: EOL
1.11 afresh1 229: done
230: }
1.1 afresh1 231:
1.11 afresh1 232: fw_update
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>