Blame SOURCES/dracut_99microcode_ctl-fw_dir_override_module_init.sh

539655
#!/bin/bash
539655
4eb1a6
# Hack in additional firmware directories for supported caveats.
539655
#
539655
# SPDX-License-Identifier: CC0-1.0
539655
539655
check() {
539655
	return 0
539655
}
539655
539655
install() {
4eb1a6
	local FW_DIR=/lib/firmware
4eb1a6
	local DATA_DIR=/usr/share/microcode_ctl/ucode_with_caveats
4eb1a6
	local CFG_DIR="/etc/microcode_ctl/ucode_with_caveats"
4eb1a6
	local check_caveats=/usr/libexec/microcode_ctl/check_caveats
4eb1a6
4eb1a6
	local verbose_opt
4eb1a6
	local cc_out
4eb1a6
	local path
4eb1a6
	local ignored
4eb1a6
	local do_skip_host_only
4eb1a6
	local p
4eb1a6
539655
	verbose_opt=
539655
	[ 4 -gt "$stdloglvl" ] || verbose_opt="-v"
539655
539655
	# HACK: we override external fw_dir variable in order to get
539655
	#       an additional ucode based on the kernel version.
4eb1a6
	dinfo "  microcode_ctl module: mangling fw_dir"
539655
539655
	[ -z "$fw_dir_l" ] || {
4eb1a6
		dinfo "    microcode_ctl: avoid touching fw_dir as" \
539655
		      "it has been changed (fw_dir_l is '$fw_dir_l')"
539655
539655
		return 0
539655
	}
539655
4eb1a6
	# Reset fw_dir to avoid inclusion of kernel-version-specific directories
4eb1a6
	# populated with microcode for the late load
4eb1a6
	[ "x$fw_dir" != \
4eb1a6
	  "x/lib/firmware/updates /lib/firmware /lib/firmware/$kernel" ] || {
4eb1a6
		fw_dir="/lib/firmware/updates /lib/firmware"
4eb1a6
		dinfo "    microcode_ctl: reset fw_dir to \"${fw_dir}\""
4eb1a6
	}
539655
4eb1a6
	while read -d "/" -r i; do
539655
		dinfo "    microcode_ctl: processing data directory " \
539655
		      "\"$DATA_DIR/$i\"..."
4eb1a6
4eb1a6
		if ! cc_out=$($check_caveats -e -k "$kernel" -c "$i" $verbose_opt)
4eb1a6
		then
4eb1a6
			dinfo "    microcode_ctl: kernel version \"$kernel\"" \
4eb1a6
			      "failed early load check for \"$i\", skipping"
539655
			continue
4eb1a6
		fi
4eb1a6
4eb1a6
		path=$(printf "%s" "$cc_out" | sed -n 's/^paths //p')
4eb1a6
		[ -n "$path" ] || {
4eb1a6
			ignored=$(printf "%s" "$cc_out" | \
4eb1a6
					sed -n 's/^skip_cfgs //p')
4eb1a6
4eb1a6
			if [ -n "$ignored" ]; then
4eb1a6
				dinfo "    microcode_ctl: configuration" \
4eb1a6
				      "\"$i\" is ignored"
4eb1a6
			else
4eb1a6
				dinfo "    microcode_ctl: no microcode paths" \
4eb1a6
				      "are associated with \"$i\", skipping"
4eb1a6
			fi
4eb1a6
539655
			continue
539655
		}
539655
539655
		if [ "x" != "x$hostonly" ]; then
4eb1a6
			do_skip_host_only=0
4eb1a6
4eb1a6
			local sho_overrides="
4eb1a6
				$CFG_DIR/skip-host-only-check
4eb1a6
				$CFG_DIR/skip-host-only-check-$i
4eb1a6
				$FW_DIR/$kernel/skip-host-only-check
4eb1a6
				$FW_DIR/$kernel/skip-host-only-check-$i"
4eb1a6
4eb1a6
			for p in $(echo "$sho_overrides"); do
4eb1a6
				[ -e "$p" ] || continue
4eb1a6
4eb1a6
				do_skip_host_only=1
4eb1a6
				dinfo "    microcode_ctl: $i; skipping" \
4eb1a6
				      "Host-Only check, since \"$p\" exists."
4eb1a6
				break
4eb1a6
			done
4eb1a6
		else
4eb1a6
			do_skip_host_only=1
4eb1a6
		fi
4eb1a6
4eb1a6
		if [ 0 -eq "$do_skip_host_only" ]; then
4eb1a6
			local hostonly_passed=0
4eb1a6
			local ucode
4eb1a6
			local uvendor
4eb1a6
			local ucode_dir=""
4eb1a6
4eb1a6
			ucode=$(get_ucode_file)
4eb1a6
			uvendor=$(get_cpu_vendor)
4eb1a6
4eb1a6
			case "$uvendor" in
4eb1a6
			Intel)
4eb1a6
				ucode_dir="intel-ucode"
4eb1a6
				;;
4eb1a6
			AMD)
742279
				ucode_dir="amd-ucode"
4eb1a6
				;;
4eb1a6
			*)
4eb1a6
				dinfo "    microcode_ctl: unknown CPU" \
4eb1a6
				      "vendor: \"$uvendor\", bailing out of" \
4eb1a6
				      "Host-Only check"
4eb1a6
				continue
4eb1a6
				;;
4eb1a6
			esac
4eb1a6
4eb1a6
			# $path is a list of globs, so it needs special care
4eb1a6
			for p in $(printf "%s" "$path"); do
4eb1a6
				find "$DATA_DIR/$i" -path "$DATA_DIR/$i/$p" \
4eb1a6
					-print0 \
4eb1a6
				    | grep -zFxq \
4eb1a6
					"$DATA_DIR/$i/$ucode_dir/$ucode" \
4eb1a6
				    || continue
4eb1a6
4eb1a6
				dinfo "    microcode_ctl: $i: Host-Only" \
4eb1a6
				      "mode is enabled and" \
4eb1a6
				      "\"$ucode_dir/$ucode\" matches \"$p\""
4eb1a6
4eb1a6
				hostonly_passed=1
4eb1a6
				break
4eb1a6
			done
4eb1a6
4eb1a6
			[ 1 -eq "$hostonly_passed" ] || {
4eb1a6
				dinfo "    microcode_ctl: $i: Host-Only mode" \
4eb1a6
				      "is enabled and ucode name does not" \
4eb1a6
				      "match the expected one, skipping" \
4eb1a6
				      "caveat (\"$ucode\" not in \"$path\")"
539655
				continue
539655
			}
539655
		fi
539655
4eb1a6
		dinfo "      microcode_ctl: $i: caveats check for kernel" \
4eb1a6
		      "version \"$kernel\" passed, adding" \
4eb1a6
		      "\"$DATA_DIR/$i\" to fw_dir variable"
4eb1a6
		fw_dir="$DATA_DIR/$i $fw_dir"
742279
742279
	# The list of directories is reverse-sorted in order to preserve the
742279
	# "last wins" policy in case of presence of multiple microcode
742279
	# revisions.
742279
	#
742279
	# In case of hostonly == 0, all microcode revisions will be included,
742279
	# but since the microcode search is done with the "first wins" policy
742279
	# by the (early) microcode loading code, the correct microcode revision
742279
	# still has to be picked.
4eb1a6
	done <<-EOF
742279
	$(find "$DATA_DIR" -maxdepth 1 -mindepth 1 -type d -printf "%f/" \
742279
		| sort -r)
4eb1a6
	EOF
4eb1a6
4eb1a6
	dinfo "    microcode_ctl: final fw_dir: \"${fw_dir}\""
539655
}
539655