PATH := $(PATH):/sbin:/usr/sbin
IUCODE_TOOL := iucode_tool
IUC_FLAGS := -vv
IUC_QUIET_FLAGS := -q
IUC_FINAL_FLAGS := -vv --downgrade

# CUTDATE RANGE
# This filter selects what we consider to be old microcode which
# should still be shipped even if Intel dropped them.  Note that
# it is useless to ship microcodes for anything the distro doesn't
# really support anymore
#
# Watch out: check in the changelog, if this filter will add
# microcodes that look like they've been recalled, use IUC_EXCLUDE
# below to avoid shipping the probably recalled microcode.
# Last manual check: up to 2008-01-01
IUC_OLDIES_SELECT := "--date-before=2008-01-01"

# EXCLUDING MICROCODES:
# Always document reason.  See iucode_tool(8) for -s !<sig> syntax
# Recalls might require use of .fw overrides to retain old version,
# instead of exclusions.  Exclusions have the highest priority, and
# will remove microcode added by any other means, including override
# files (.fw files).
IUC_EXCLUDE :=

# 0x106c0: alpha hardware, seen in a very very old microcode data file
IUC_EXCLUDE += -s !0x106c0

# INCLUDING MICROCODES:
# This should be used to add a microcode from any of the microcode
# bundles, without the need for an override file. See iucode_tool(8)
# for -s <sig> syntax.  Always document the reason, as per IUC_EXCLUDE.
IUC_INCLUDE :=

# ##EXAMPLE ## DO NOT ENABLE##
# 0x106a5: Xeon X55xx: Intel recalled some errata fixes for unknown
# reasons, and then stopped shipping the microcode at rev 0x15.  HP ships
# the latest available revision of this microcode (0x16) on their
# DL360/DL380 G6/G7 servers.
#
# IUC_INCLUDE += -s 0x000106a5
# ##EXAMPLE##

# Keep sorting order predictable or things will break
export LC_COLLATE=C

MICROCODE_SOURCES   := $(sort $(wildcard microcode-*.dat microcode-*.bin))
MICROCODE_FINAL_SOURCES := microcode-oldies.pbin $(lastword $(MICROCODE_SOURCES))
MICROCODE_OVERRIDES := $(wildcard *.fw)
ifneq ($(MICROCODE_OVERRIDES),)
	MICROCODE_FINAL_SOURCES += microcode-overrides.pbin
endif

all: intel-microcode.bin intel-microcode-64.bin

#
# We have to build a list of microcode signatures for very old microcode
# that is likely to be droped as legacy from newer bundles, and then
# select the newest microcode available for each such signature.
# We can't just date-filter, as that would skip microcode revisions
# publised after the cut-date.
#
microcode-oldies.pbin: $(MICROCODE_SOURCES)
	@echo
	@echo Building microcode bundle for older and additional microcode
	@$(IUCODE_TOOL) $(IUC_FLAGS) --overwrite -w "$@" $^ $(IUC_INCLUDE) $$( \
		(for i in $^ ; do \
			$(IUCODE_TOOL) $(IUC_QUIET_FLAGS) $(IUC_OLDIES_SELECT) -l "$$i" | \
			sed -n -e '/sig/ { s/.*sig \(0x[0-9a-fA-F]\+\),.*/-s \1/ p }' ; \
		done ) | sort | uniq | xargs \
	)

# The microcode overrides are bundled together to sort out any
# duplication and revision level issues.
microcode-overrides.pbin: $(MICROCODE_OVERRIDES)
	@echo
	@echo Preprocessing microcode overrides...
	@$(IUCODE_TOOL) $(IUC_FLAGS) --overwrite -w "$@" $^

# Final target
intel-microcode.bin: $(MICROCODE_FINAL_SOURCES)
	@echo
	@echo Building final microcode bundle...
	@$(IUCODE_TOOL) $(IUC_FINAL_FLAGS) $(IUC_EXCLUDE) --overwrite -w "$@" $^

intel-microcode-64.bin: intel-microcode.bin
	@echo
	@echo Building stripped-down microcode bundle for x86-64 and x32...
	@$(IUCODE_TOOL) $(IUC_FINAL_FLAGS) $(shell sed -n -r -e '/^i.86/ { s/^[^ ]+ +/-s !/;s/ +\#.*//;p}' cpu-signatures.txt) $(IUC_EXCLUDE) --overwrite -w "$@" $^

distclean: clean
clean:
	rm -f intel-microcode-64.bin intel-microcode.bin microcode-overrides.pbin microcode-oldies.pbin

.PHONY: clean
