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