Blame SPECS/gen_provides.sh

Packit Service 2ad00c
#! /bin/bash -efu
Packit Service 2ad00c
Packit Service 2ad00c
# Generator of RPM "Provides:" tags for Intel microcode files.
Packit Service 2ad00c
#
Packit Service 2ad00c
# SPDX-License-Identifier: CC0-1.0
Packit Service 2ad00c
Packit Service 2ad00c
IFS=$'\n'
Packit Service 2ad00c
UPDATED="intel-beta"
Packit Service 2ad00c
CODENAMES="codenames"
Packit Service 2ad00c
Packit Service 2ad00c
if [ "$#" -ge 1 ]; then
Packit Service 2ad00c
	CODENAMES="$1"
Packit Service 2ad00c
	shift
Packit Service 2ad00c
fi
Packit Service 2ad00c
Packit Service 2ad00c
# Match only FF-MM-SS ucode files under intel-ucode/intel-ucode-with-caveats
Packit Service 2ad00c
# directories.
Packit Service 2ad00c
for f in $(grep -E '/intel-ucode.*/[0-9a-f][0-9a-f]-[0-9a-f][0-9a-f]-[0-9a-f][0-9a-f]$'); do
Packit Service 2ad00c
	ucode=$(basename "$f")
Packit Service 2ad00c
	ucode_caveat="$(basename "$(dirname "$(dirname "$f")")")"
Packit Service 2ad00c
	ucode_fname="$ucode_caveat/$ucode"
Packit Service 2ad00c
	file_sz="$(stat -c "%s" "$f")"
Packit Service 2ad00c
	skip=0
Packit Service 2ad00c
	ext_hdr=0
Packit Service 2ad00c
	ext_sig_cnt=0
Packit Service 2ad00c
	ext_sig_pos=0
Packit Service 2ad00c
	next_skip=0
Packit Service 2ad00c
Packit Service 2ad00c
	# Microcode header format description:
Packit Service 2ad00c
	# https://gitlab.com/iucode-tool/iucode-tool/blob/master/intel_microcode.c
Packit Service 2ad00c
	while :; do
Packit Service 2ad00c
		[ "$skip" -lt "$file_sz" ] || break
Packit Service 2ad00c
Packit Service 2ad00c
		# Do we parse ext_sig table or another microcode header?
Packit Service 2ad00c
		if [ 0 != "$next_skip" ]; then
Packit Service 2ad00c
			# Check whether we should abort ext_sig table parsing
Packit Service 2ad00c
			[ \( "${skip}" -lt "${next_skip}" \) -a \
Packit Service 2ad00c
			  \( "${ext_sig_pos}" -lt "${ext_sig_cnt}" \) ] || {
Packit Service 2ad00c
				skip="${next_skip}"
Packit Service 2ad00c
				next_skip=0
Packit Service 2ad00c
				continue
Packit Service 2ad00c
			}
Packit Service 2ad00c
Packit Service 2ad00c
			# ext_sig, 12 bytes in size
Packit Service 2ad00c
			IFS=' ' read cpuid pf_mask <<- EOF
Packit Service 2ad00c
			$(hexdump -s "$skip" -n 8 \
Packit Service 2ad00c
				-e '"" 1/4 "%08x " 1/4 "%u" "\n"' "$f")
Packit Service 2ad00c
			EOF
Packit Service 2ad00c
Packit Service 2ad00c
			skip="$((skip + 12))"
Packit Service 2ad00c
			ext_sig_pos="$((ext_sig_pos + 1))"
Packit Service 2ad00c
		else
Packit Service 2ad00c
			# Microcode header, 48 bytes, last 3 fields reserved
Packit Service 2ad00c
			IFS=' ' read hdrver rev \
Packit Service 2ad00c
			       date_y date_d date_m \
Packit Service 2ad00c
			       cpuid cksum ldrver \
Packit Service 2ad00c
			       pf_mask datasz totalsz <<- EOF
Packit Service 2ad00c
			$(hexdump -s "$skip" -n 36 \
Packit Service 2ad00c
				-e '"" 1/4 "%u " 1/4 "%#x " \
Packit Service 2ad00c
			               1/2 "%04x " 1/1 "%02x " 1/1 "%02x " \
Packit Service 2ad00c
				       1/4 "%08x " 1/4 "%x " 1/4 "%#x " \
Packit Service 2ad00c
				       1/4 "%u " 1/4 "%u " 1/4 "%u" "\n"' "$f")
Packit Service 2ad00c
			EOF
Packit Service 2ad00c
Packit Service 2ad00c
			[ 0 != "$datasz" ] || datasz=2000
Packit Service 2ad00c
			[ 0 != "$totalsz" ] || totalsz=2048
Packit Service 2ad00c
Packit Service 2ad00c
			# TODO: add some sanity/safety checks here.  As of now,
Packit Service 2ad00c
			#       there's a (pretty fragile) assumption that all
Packit Service 2ad00c
			#       the matched files are valid Intel microcode
Packit Service 2ad00c
			#       files in the expected format.
Packit Service 2ad00c
Packit Service 2ad00c
			# ext_sig table is after the microcode payload,
Packit Service 2ad00c
			# check for its presence
Packit Service 2ad00c
			if [ 48 -lt "$((totalsz - datasz))" ]; then
Packit Service 2ad00c
				next_skip="$((skip + totalsz))"
Packit Service 2ad00c
				skip="$((skip + datasz + 48))"
Packit Service 2ad00c
				ext_sig_pos=0
Packit Service 2ad00c
Packit Service 2ad00c
				# ext_sig table header, 20 bytes in size,
Packit Service 2ad00c
				# last 3 fields are reserved.
Packit Service 2ad00c
				IFS=' ' read ext_sig_cnt  <<- EOF
Packit Service 2ad00c
				$(hexdump -s "$skip" -n 4 \
Packit Service 2ad00c
					-e '"" 1/4 "%u" "\n"' "$f")
Packit Service 2ad00c
				EOF
Packit Service 2ad00c
Packit Service 2ad00c
				skip="$((skip + 20))"
Packit Service 2ad00c
			else
Packit Service 2ad00c
				skip="$((skip + totalsz))"
Packit Service 2ad00c
				next_skip=0
Packit Service 2ad00c
			fi
Packit Service 2ad00c
		fi
Packit Service 2ad00c
Packit Service 2ad00c
		#[ -n "$rev" ] || continue
Packit Service 2ad00c
Packit Service 2ad00c
		# Basic "Provides:" tag. Everything else is bells and whistles.
Packit Service 2ad00c
		# It's possible that microcode files for different platform_id's
Packit Service 2ad00c
		# and the same CPUID have the same version, that's why "sort -u"
Packit Service 2ad00c
		# in the end.
Packit Service 2ad00c
		printf "firmware(intel-ucode/%s) = %s\n" "$ucode" "$rev"
Packit Service 2ad00c
Packit Service 2ad00c
		# Generate extended "Provides:" tags with additional
Packit Service 2ad00c
		# information, which allow more precise matching.
Packit Service 2ad00c
		printf "iucode_date(fname:%s;cpuid:%s;pf_mask:0x%x) = %s.%s.%s\n" \
Packit Service 2ad00c
			"$ucode_fname" "$cpuid" "$pf_mask" "$date_y" "$date_m" "$date_d"
Packit Service 2ad00c
		printf "iucode_rev(fname:%s;cpuid:%s;pf_mask:0x%x) = %s\n" \
Packit Service 2ad00c
			"$ucode_fname" "$cpuid" "$pf_mask" "$rev"
Packit Service 2ad00c
Packit Service 2ad00c
		# Generate tags for each possible platform_id
Packit Service 2ad00c
		_pf=1
Packit Service 2ad00c
		_pf_mask="$pf_mask"
Packit Service 2ad00c
		while [ 0 -lt "$_pf_mask" ]; do
Packit Service 2ad00c
			[ 1 -ne "$((_pf_mask % 2))" ] || \
Packit Service 2ad00c
				# We try to provide a more specific firmware()
Packit Service 2ad00c
				# dependency here.  It has incorrect file name,
Packit Service 2ad00c
				# but allows constructing a required RPM
Packit Service 2ad00c
				# capability name by (directly) using
Packit Service 2ad00c
				# the contents of /proc/cpuinfo and
Packit Service 2ad00c
				# /sys/devices/system/cpu/cpu*/microcode/processor_flags
Packit Service 2ad00c
				# (except for a Deschutes CPU with sig 0x1632)
Packit Service 2ad00c
				printf "iucode_rev(fname:%s;platform_id:0x%x) = %s\n" \
Packit Service 2ad00c
					"$ucode_fname" "$_pf" "$rev"
Packit Service 2ad00c
Packit Service 2ad00c
			_pf_mask=$((_pf_mask / 2))
Packit Service 2ad00c
			_pf=$((_pf * 2))
Packit Service 2ad00c
		done
Packit Service 2ad00c
Packit Service 2ad00c
		# Generate tags with codename information, in case
Packit Service 2ad00c
		# it is available
Packit Service 2ad00c
		if [ -e "$CODENAMES" ]; then
Packit Service 2ad00c
			cpuid_up="$(echo "$cpuid" | tr 'a-z' 'A-Z')"
Packit Service 2ad00c
			cpuid_short="$(printf "%x" "0x$cpuid")"
Packit Service 2ad00c
			(grep '	'"$cpuid_up"'	' "$CODENAMES" || :; grep ';'"$cpuid_short"';' "$CODENAMES" || :) \
Packit Service 2ad00c
			| while IFS=$';\t' read segm int_fname codename stepping candidate_pf cpuid_cn cname variants rest; do
Packit Service 2ad00c
				[ "x${segm###}" = "x$segm" ] || continue
Packit Service 2ad00c
				[ -n "${segm}" ] || continue
Packit Service 2ad00c
				codename=$(echo "$codename" | tr ' (),' '_[];')
Packit Service 2ad00c
				candidate_pf=$(printf "%u" "0x${candidate_pf}")
Packit Service 2ad00c
				(IFS=','; for s in $stepping; do
Packit Service 2ad00c
					[ \( 0 -ne "$pf_mask" \) -a \
Packit Service 2ad00c
					  \( 0 -eq "$((candidate_pf & pf_mask))" \) ] || { \
Packit Service 2ad00c
						printf "iucode_rev(fname:%s;cpuid:%s;pf_mask:0x%x;segment:\"%s\";codename:\"%s\";stepping:\"%s\";pf_model:0x%x) = %s\n" \
Packit Service 2ad00c
							"$ucode_fname" "$cpuid" "$pf_mask" \
Packit Service 2ad00c
							"$segm" "$codename" "$s" "$candidate_pf" \
Packit Service 2ad00c
							"$rev";
Packit Service 2ad00c
						printf "iucode_date(fname:%s;cpuid:%s;pf_mask:0x%x;segment:\"%s\";codename:\"%s\";stepping:\"%s\";pf_model:0x%x) = %s.%s.%s\n" \
Packit Service 2ad00c
							"$ucode_fname" "$cpuid" "$pf_mask" \
Packit Service 2ad00c
							"$segm" "$codename" "$s" "$candidate_pf" \
Packit Service 2ad00c
							"$date_y" "$date_m" "$date_d";
Packit Service 2ad00c
						if [ "$cpuid_short" = "$cpuid_cn" -a -n "$variants" ]; then
Packit Service 2ad00c
							(IFS=','; for v in $variants; do
Packit Service 2ad00c
								v=$(echo "$v" | tr ' (),' '_[];')
Packit Service 2ad00c
								printf "iucode_rev(fname:%s;cpuid:%s;pf_mask:0x%x;segment:\"%s\";codename:\"%s_%s\";stepping:\"%s\";pf_model:0x%x) = %s\n" \
Packit Service 2ad00c
									"$ucode_fname" "$cpuid" "$pf_mask" \
Packit Service 2ad00c
									"$segm" "$codename" "$v" "$s" "$candidate_pf" \
Packit Service 2ad00c
									"$rev";
Packit Service 2ad00c
								printf "iucode_date(fname:%s;cpuid:%s;pf_mask:0x%x;segment:\"%s\";codename:\"%s_%s\";stepping:\"%s\";pf_model:0x%x) = %s.%s.%s\n" \
Packit Service 2ad00c
									"$ucode_fname" "$cpuid" "$pf_mask" \
Packit Service 2ad00c
									"$segm" "$codename" "$v" "$s" "$candidate_pf" \
Packit Service 2ad00c
									"$date_y" "$date_m" "$date_d";
Packit Service 2ad00c
							done)
Packit Service 2ad00c
						fi
Packit Service 2ad00c
					  }
Packit Service 2ad00c
				done)
Packit Service 2ad00c
			done
Packit Service 2ad00c
		fi
Packit Service 2ad00c
Packit Service 2ad00c
		# Kludge squared: generate additional "Provides:" tags
Packit Service 2ad00c
		# for the files in the overrides tarball (that a placed
Packit Service 2ad00c
		# in a separate caveat with a specific name)
Packit Service 2ad00c
		[ "x${ucode_caveat}" != "x${UPDATED}" ] || {
Packit Service 2ad00c
			printf "firmware_updated(intel-ucode/%s) = %s\n" \
Packit Service 2ad00c
				"$ucode" "$rev";
Packit Service 2ad00c
		}
Packit Service 2ad00c
	done
Packit Service 2ad00c
done | sort -u