#! /bin/bash -efu

# Trigger microcode reload with additional check for BDW-EP that can have
# microcode reloaded only in case kernel has specific patches.
#
# SPDX-License-Identifier: CC0-1.0

get_model_string()
{
	/usr/bin/printf "%s %02x-%02x-%02x" \
		$(/bin/sed -rn '1,/^$/{
			s/^vendor_id[[:space:]]*: (.*)$/\1/p;
			s/^cpu family[[:space:]]*: (.*)$/\1/p;
			s/^model[[:space:]]*: (.*)$/\1/p;
			s/^stepping[[:space:]]*: (.*)$/\1/p;
		}' /proc/cpuinfo)
}

CFG_BDW=intel-06-4f-01
CFG_SNB=intel-06-2d-07
CFG_SKL=intel-06-55-04
CHECK_CAVEATS=/usr/libexec/microcode_ctl/check_caveats
MC_FILE=/lib/firmware/microcode.dat

model="$(get_model_string)"

# Broadwell-EP/EX check
if [ "x${model}" = "xGenuineIntel 06-4f-01" ]; then
	cc_out=$("$CHECK_CAVEATS" -m -c "$CFG_BDW") || exit 1

	# Check that the configuration hasn't been skipped
	ok_cfgs=$(printf "%s" "$cc_out" | sed -n 's/^ok_cfgs //p')

	[ "x$ok_cfgs" = "x$CFG_BDW" ] || exit 1

	MC_FILE=/lib/firmware/microcode-06-4f-01.dat
fi

# Sandy Bridge-E/EN/EP check
if [ "x${model}" = "xGenuineIntel 06-2d-07" ]; then
	cc_out=$("$CHECK_CAVEATS" -m -c "$CFG_SNB" || :)

	# Check that the configuration hasn't been skipped
	ok_cfgs=$(printf "%s" "$cc_out" | sed -n 's/^ok_cfgs //p')

	# Contrary to BDW caveat, we have a fallback in microcode.dat
	[ "x$ok_cfgs" != "x$CFG_SNB" ] || {
		MC_FILE=/lib/firmware/microcode-06-2d-07.dat
	}
fi

# Skylake-SP/W/X check
if [ "x${model}" = "xGenuineIntel 06-55-04" ]; then
	cc_out=$("$CHECK_CAVEATS" -m -c "$CFG_SKL" || :)

	# Check that the configuration hasn't been skipped
	ok_cfgs=$(printf "%s" "$cc_out" | sed -n 's/^ok_cfgs //p')

	# Contrary to BDW caveat, we have a fallback in microcode.dat
	[ "x$ok_cfgs" != "x$CFG_SKL" ] || {
		MC_FILE=/lib/firmware/microcode-06-55-04.dat
	}
fi

/sbin/microcode_ctl -Qu -f "$MC_FILE"
