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