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