summaryrefslogtreecommitdiffstats
path: root/debian/initramfs.hook
blob: 45812b0552ae03f75bc3352f732d84b689ba33b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#!/bin/sh
# intel-microcode initramfs-tools hook script version 3
# Copyright (C) 2012-2016 Henrique de Moraes Holschuh <hmh@debian.org>
# Released under the GNU GPL v2 or later license
#
# Generates a copy of the Intel microcode (by default tailored to the
# running system), and installs it in the early initramfs.
#
# iucode_tool v1.0 or later is required.
#

PREREQ=""
IUCODE_CONFIG=/etc/default/intel-microcode

prereqs()
{
   echo "$PREREQ"
}

case $1 in
prereqs)
   prereqs
   exit 0
   ;;
esac

. /usr/share/initramfs-tools/hook-functions

verbose()
{
	if [ "${verbose}" = "y" ] ; then
		echo "intel-microcode: $*"
	fi
	:
}

if [ "${verbose}" = "y" ] ; then
	IUCODE_TOOL_OPTIONS="-l"
else
	IUCODE_TOOL_OPTIONS="-q"
fi

IUCODE_TOOL=$(command -v iucode_tool)
if [ -z "${IUCODE_TOOL}" ] && [ -x /usr/sbin/iucode_tool ] ; then
	IUCODE_TOOL=/usr/sbin/iucode_tool
fi

IUCODE_FW_DIR=/usr/lib/firmware/intel-ucode
if [ "$MODULES" = "most" ]; then
	IUCODE_TOOL_INITRAMFS=early
	IUCODE_TOOL_SCANCPUS=no
else
	IUCODE_TOOL_INITRAMFS=auto
	IUCODE_TOOL_SCANCPUS=yes
fi
IUCODE_TOOL_EXTRA_OPTIONS=

[ -r ${IUCODE_CONFIG} ] && . ${IUCODE_CONFIG}

[ -z "${IUCODE_TOOL_INITRAMFS}" ] && IUCODE_TOOL_INITRAMFS=no

case "${IUCODE_TOOL_INITRAMFS}" in
    no|0)
	verbose "intel-microcode: disabled by ${IUCODE_CONFIG}"
	exit 0
	;;
    auto|early)
	;;
    yes|1)
	IUCODE_TOOL_INITRAMFS=early
	echo "W: intel-microcode: initramfs mode not supported, using early initramfs mode" >&2
	;;
    *)
	echo "E: intel-microcode: invalid IUCODE_TOOL_INITRAMFS, using automatic mode" >&2
	IUCODE_TOOL_INITRAMFS=auto
esac

# don't do anything unless there's an Intel processor in the system in auto mode
if [ "${IUCODE_TOOL_INITRAMFS}" = "auto" ] ; then
	grep -q "^vendor_id[[:blank:]]*:[[:blank:]]*.*GenuineIntel" /proc/cpuinfo || {
		verbose "no Intel processors detected, nothing to do"
		exit 0
	}
fi

# we require iucode_tool, but something is broken
if [ ! -x "${IUCODE_TOOL}" ] ; then
	echo "E: intel-microcode: cannot run iucode_tool!" >&2
	exit 0
fi

# Blacklist all kernel versions before v3.10, as they don't support early
# initramfs mode.
#
# This doesn't blacklist early 3.10 kernels in the LTS branches, we don't have
# enough information at the initramfs-tools layer, due to the way Debian and
# Ubuntu version kernel packages.
if dpkg --compare-versions "${version}" lt 3.10 ; then
       echo "E: intel-microcode: unsupported kernel version!" >&2
       exit 0
fi

if [ "${IUCODE_TOOL_SCANCPUS}" != "yes" ] ; then
	verbose "adding microcode for either all or selected Intel processor models"
else
	verbose "adding microcode for currently online and selected Intel processors"
	grep -q cpu/cpuid /proc/devices || modprobe -q cpuid
	IUCODE_TOOL_OPTIONS="${IUCODE_TOOL_OPTIONS} --scan-system"
fi

# paranoia
[ -z "${DESTDIR}" ] && {
	echo "E: intel-microcode: DESTDIR empty!" >&2
	exit 1
}
[ -z "${IUCODE_FW_DIR}" ] && {
	echo "E: intel-microcode: IUCODE_FW_DIR empty!" >&2
	exit 1
}

# include the microcode module in the initramfs for logging purposes, but
# ensure it will have no microcode data files to load.  This is also a safety
# net: we don't want it to be acidentally loaded outside the initramfs.
#
# This shouldn't be expensive, as the in-kernel firmware loader is quite
# fast at detecting missing data files and doesn't wait for them.
#
# note: force_load will load a blacklisted module. We depend on that behavior.
#
# For 4.4 and later kernels, the microcode driver cannot be a module and will
# be built-in.
dpkg --compare-versions "${version}" lt 4.4 && {
    [ -d "${DESTDIR}${IUCODE_FW_DIR}" ] && rm -fr "${DESTDIR}${IUCODE_FW_DIR}"

    manual_add_modules microcode && {
        # force_load has broken semanthics when the .ko file is missing
        find "${DESTDIR}/${MODULESDIR}" -type f -print | grep -qc '/microcode\.ko$' && {
            verbose "modular microcode driver detected"
            force_load microcode
        }
    }
}

# generate early initramfs image and prepend
verbose "using early initramfs microcode update mode..."
EFW=$(mktemp "${TMPDIR:-/var/tmp}/mkinitramfs-EFW_XXXXXXXXXX") || {
	echo "E: intel-microcode: cannot create temporary file" >&2
	exit 1
    }
( find /usr/share/misc -maxdepth 1 -type f -name 'intel-microcode*' -print0 ;
  find "${IUCODE_FW_DIR}" -maxdepth 0 -type d -print0 ) 2>/dev/null \
| xargs -0 -r -x ${IUCODE_TOOL} ${IUCODE_TOOL_OPTIONS} \
		--write-earlyfw="${EFW}" --overwrite \
		${IUCODE_TOOL_EXTRA_OPTIONS} \
&& prepend_earlyinitramfs "${EFW}" && {
	rm "${EFW}"
	exit 0
}

# usually we get here when initramfs-tools is missing prepend_earlyinitramfs()
# or when iucode_tool does not support --write-earlyfw, i.e. when old versions
# of these tools are installed.

rm "${EFW}" || true

echo "E: intel-microcode: failed to create or prepend the early initramfs to the initramfs" >&2

: