#!/bin/ksh # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version # 1.0 of the CDDL. # # A full copy of the text of the CDDL should have accompanied this # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # Copyright 2022 OmniOS Community Edition (OmniOSce) Association. # Copyright 2023 Oxide Computer Company # A simple update script that checks out the upstream AMD firmware # repository, extracts the microcode into separate files within the amd/ # directory, generates the required combined equivalence table and updates # the pkg(7) manifest. UPSTREAM=git://git.kernel.org UPSTREAM_PATH=/pub/scm/linux/kernel/git/firmware/linux-firmware.git # These are the GPG keys that AMD use to sign their CPU microcode updates # The first key is the current one and the second is one they have used for # older CPU families. GPGSERVER=keys.gnupg.net typeset -a GPGKEYS=( 0xFC7C6C505DAFCC14718357CAE4BE5339F328AE73 0x916A770823A7B27AADE01565A5E8DBC98C0108B4 ) function errexit { echo "$@" >&2 exit 1 } FW=platform/i86pc/ucode/AuthenticAMD export LC_ALL=C.UTF-8 set -e set -o pipefail mf=../../pkg/manifests/system-microcode-amd.p5m [[ -f $mf ]] || errexit "Run from usr/src/data/ucode" function find_cmd { typeset cmd="$1" typeset var=$(echo $cmd | tr '[:lower:]' '[:upper:]') typeset -n path="$var" path=$(whence -fp "$cmd") if (($? != 0)) || [ ! -x "$path" ]; then errexit "Cannot find executable '$cmd' in PATH" fi } # This script uses a few commands which are not part of illumos and are # expected to be available in the path. find_cmd git find_cmd gpg find_cmd pkgfmt find_cmd stat # Search for 'ucodeadm'. If you need to use an updated ucodeadm to handle this # firmware update, as is occasionally necessary, ensure it occurs earlier in # the path than /usr/sbin. find_cmd ucodeadm tmp=$(mktemp -d) [[ -n "$tmp" && -d "$tmp" ]] mkdir $tmp/out || errexit "Failed to create temporary directory" trap 'rm -rf $tmp' EXIT echo "** Adding AMD GPG signing keys to temporary keyring" mkdir -m 0700 $tmp/gnupg $GPG --homedir $tmp/gnupg --keyserver $GPGSERVER --receive-keys ${GPGKEYS[@]} echo "** Cloning $UPSTREAM$UPSTREAM_PATH" $GIT clone $UPSTREAM$UPSTREAM_PATH $tmp/ucode ver=`$GIT -C $tmp/ucode log -n1 --format=%ad --date=format:%Y%m%d amd-ucode` echo "** Updating to microcode version $ver" echo "** Verifying microcode signatures" for f in $tmp/ucode/amd-ucode/*.bin; do if [[ ! -f "$f.asc" ]]; then echo "Signature missing for ${f##*/}" exit 1 fi $GPG --homedir $tmp/gnupg --trust-model=always --verify $f{.asc,} done # Now that everything is in place and verified, begin modifying the tree. rm -f amd/*-* cp $tmp/ucode/LICENSE.amd-ucode amd/THIRDPARTYLICENSE echo AMD Processor Microcode Data Files > amd/THIRDPARTYLICENSE.descrip for f in $tmp/ucode/amd-ucode/*.bin; do bf=${f##*/} bf=${bf#microcode_} bf=${bf%.bin} [[ $bf = amd* ]] || errexit "$f does not look like a firmware file" echo "Converting $bf" mkdir $tmp/out/$bf cp $f $tmp/amd-fw $UCODEADM -l $tmp/amd-fw $UCODEADM -i -R $tmp/out/$bf $tmp/amd-fw rm -f $tmp/amd-fw done # Copy the firmware files into place cp $tmp/out/*/*-?? amd/ # Combine the equivalence tables from the different updates into one # Each equivalence-table file is a sequence of 16-byte records with a # 16-byte terminator which is all zeros. To merge, we just concatenate # the non-terminator records and then add 16 bytes from /dev/zero. { for f in $tmp/out/*/equivalence-table; do size=$($STAT -c %s $f) ((size -= 16)) dd if=$f bs=1 count=$size status=none done # Add terminator dd if=/dev/zero bs=1 count=16 status=none } > amd/equivalence-table $PKGFMT -u $mf mv $mf $mf.tmp egrep -v "file path=$FW" $mf.tmp > $mf rm -f $mf.tmp for f in amd/*; do bf=${f##*/} [[ $bf = THIRDPARTYLICENSE* ]] && continue [[ $bf = Makefile* ]] && continue echo "file path=$FW/$bf group=sys mode=0444 reboot-needed=true" >> $mf done sed -i "/pkg.fmri.*microcode\/amd@/s/@[0-9]*/@$ver/" $mf $PKGFMT -fv2 $mf