1#!/bin/ksh 2 3# This file and its contents are supplied under the terms of the 4# Common Development and Distribution License ("CDDL"), version 1.0. 5# You may only use this file in accordance with the terms of version 6# 1.0 of the CDDL. 7# 8# A full copy of the text of the CDDL should have accompanied this 9# source. A copy of the CDDL is also available via the Internet at 10# http://www.illumos.org/license/CDDL. 11 12# Copyright 2022 OmniOS Community Edition (OmniOSce) Association. 13# Copyright 2023 Oxide Computer Company 14 15# A simple update script that checks out the upstream AMD firmware 16# repository, extracts the microcode into separate files within the amd/ 17# directory, generates the required combined equivalence table and updates 18# the pkg(7) manifest. 19 20UPSTREAM=git://git.kernel.org 21UPSTREAM_PATH=/pub/scm/linux/kernel/git/firmware/linux-firmware.git 22 23# These are the GPG keys that AMD use to sign their CPU microcode updates 24# The first key is the current one and the second is one they have used for 25# older CPU families. 26GPGSERVER=keys.gnupg.net 27typeset -a GPGKEYS=( 28 0xFC7C6C505DAFCC14718357CAE4BE5339F328AE73 29 0x916A770823A7B27AADE01565A5E8DBC98C0108B4 30) 31 32function errexit { 33 echo "$@" >&2 34 exit 1 35} 36 37FW=platform/i86pc/ucode/AuthenticAMD 38 39export LC_ALL=C.UTF-8 40 41set -e 42set -o pipefail 43 44mf=../../pkg/manifests/system-microcode-amd.p5m 45[[ -f $mf ]] || errexit "Run from usr/src/data/ucode" 46 47function find_cmd { 48 typeset cmd="$1" 49 typeset var=$(echo $cmd | tr '[:lower:]' '[:upper:]') 50 typeset -n path="$var" 51 path=$(whence -fp "$cmd") 52 if (($? != 0)) || [ ! -x "$path" ]; then 53 errexit "Cannot find executable '$cmd' in PATH" 54 fi 55} 56 57# This script uses a few commands which are not part of illumos and are 58# expected to be available in the path. 59find_cmd git 60find_cmd gpg 61find_cmd pkgfmt 62find_cmd stat 63# Search for 'ucodeadm'. If you need to use an updated ucodeadm to handle this 64# firmware update, as is occasionally necessary, ensure it occurs earlier in 65# the path than /usr/sbin. 66find_cmd ucodeadm 67 68tmp=$(mktemp -d) 69[[ -n "$tmp" && -d "$tmp" ]] 70mkdir $tmp/out || errexit "Failed to create temporary directory" 71trap 'rm -rf $tmp' EXIT 72 73echo "** Adding AMD GPG signing keys to temporary keyring" 74mkdir -m 0700 $tmp/gnupg 75$GPG --homedir $tmp/gnupg --keyserver $GPGSERVER --receive-keys ${GPGKEYS[@]} 76 77echo "** Cloning $UPSTREAM$UPSTREAM_PATH" 78$GIT clone $UPSTREAM$UPSTREAM_PATH $tmp/ucode 79 80ver=`$GIT -C $tmp/ucode log -n1 --format=%ad --date=format:%Y%m%d amd-ucode` 81echo "** Updating to microcode version $ver" 82 83echo "** Verifying microcode signatures" 84for f in $tmp/ucode/amd-ucode/*.bin; do 85 if [[ ! -f "$f.asc" ]]; then 86 echo "Signature missing for ${f##*/}" 87 exit 1 88 fi 89 $GPG --homedir $tmp/gnupg --trust-model=always --verify $f{.asc,} 90done 91 92# Now that everything is in place and verified, begin modifying the tree. 93 94rm -f amd/*-* amd/container 95 96cp $tmp/ucode/LICENSE.amd-ucode amd/THIRDPARTYLICENSE 97echo AMD Processor Microcode Data Files > amd/THIRDPARTYLICENSE.descrip 98 99for f in $tmp/ucode/amd-ucode/*.bin; do 100 bf=${f##*/} 101 bf=${bf#microcode_} 102 bf=${bf%.bin} 103 [[ $bf = amd* ]] || errexit "$f does not look like a firmware file" 104 echo "Converting $bf" 105 mkdir $tmp/out/$bf 106 cp $f $tmp/amd-fw 107 $UCODEADM -l $tmp/amd-fw 108 $UCODEADM -i -R $tmp/out/$bf $tmp/amd-fw 109 rm -f $tmp/amd-fw 110done 111 112# Copy the combined container file from the old (pre-family-15h) microcode 113# file to 'container'. This file is only used by xVM. 114cp $tmp/out/amd/container amd/ 115 116# Copy the firmware files into place 117cp $tmp/out/*/*-?? amd/ 118 119# Combine the equivalence tables from the different updates into one 120# Each equivalence-table file is a sequence of 16-byte records with a 121# 16-byte terminator which is all zeros. To merge, we just concatenate 122# the non-terminator records and then add 16 bytes from /dev/zero. 123{ 124 for f in $tmp/out/*/equivalence-table; do 125 size=$($STAT -c %s $f) 126 ((size -= 16)) 127 dd if=$f bs=1 count=$size status=none 128 done 129 # Add terminator 130 dd if=/dev/zero bs=1 count=16 status=none 131} > amd/equivalence-table 132 133$PKGFMT -u $mf 134mv $mf $mf.tmp 135egrep -v "file path=$FW" $mf.tmp > $mf 136rm -f $mf.tmp 137 138for f in amd/*; do 139 bf=${f##*/} 140 [[ $bf = THIRDPARTYLICENSE* ]] && continue 141 [[ $bf = Makefile* ]] && continue 142 echo "file path=$FW/$bf group=sys mode=0444 reboot-needed=true" >> $mf 143done 144 145sed -i "/pkg.fmri.*microcode\/amd@/s/@[0-9]*/@$ver/" $mf 146 147$PKGFMT -fv2 $mf 148 149