xref: /illumos-gate/usr/src/data/ucode/update.amd (revision d32f26ee)
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