Inspect Intel Microcode Safely with iucode_tool
You will finish with a repeatable way to inspect Intel microcode, select entries for the processors on the current machine, and write a test early-initramfs archive without touching the boot configuration. The installed command is iucode_tool 2.3.1 from package iucode-tool 2.3.1-3build1.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about 20 minutes. You need an Intel microcode directory or another microcode bundle that you trust, a shell, and enough space under /tmp for test output. Reading and inspecting files is normally unprivileged. Installing firmware, rebuilding an initramfs or changing a boot entry needs elevated privileges and should follow your distribution's documented process.
1. Check the installed tool and inputs
Confirm the binary and package before relying on examples. This is a read-only check:
$ command -v iucode_tool
/usr/sbin/iucode_tool
$ iucode_tool --version | sed -n '1p'
iucode_tool 2.3.1
$ dpkg-query -W -f='${Package} ${Version}\n' iucode-tool
iucode-tool 2.3.1-3build1
The manpage installed with this version is dated 2018-01-28 and documents iucode_tool 2.3.1. Do not silently transfer a command to another release when its output or defaults matter.
Check that the source directory exists and contains files:
$ test -d /lib/firmware/intel-ucode && echo 'microcode directory found'
microcode directory found
$ find /lib/firmware/intel-ucode -maxdepth 1 -type f -printf '%f\n' | head
Replace that path with the directory supplied by your distribution if it is different. A directory input loads every non-hidden file in unspecified order; nested directories are skipped. Files ending in .dat are treated as Intel text format. Other names are treated as binary format unless you select a type with -t.
2. List what the bundle contains
Use --list for the selected entries, or --list-all when investigating every entry as it is read. Scanning the running system with --scan-system narrows the result to processor signatures detected here:
$ iucode_tool --scan-system --list /lib/firmware/intel-ucode
iucode_tool: system has processor(s) with signature 0x000906e9
selected microcodes:
007/001: sig 0x000906e9, pf_mask 0x2a, 2023-09-28, rev 0x00f8, size 108544
Your signature, date and revision will differ. The useful fields are the processor signature, platform mask, date, revision and size. The tool keeps the highest revision for a processor by default when several files provide one. The listing also identifies entries as bundle/entry, which helps trace an unexpected result back to an input file.
--scan-system is a selection operation, not an update. The default scan mode uses CPUID and selects all steppings for the detected processor type, family and model. --scan-system=exact asks kernel drivers to inspect every online processor and can require root. Use the exact mode only when a mixed-signature system makes the default selection insufficient.
Checkpoint: stop here if the input is unreadable, the processor signature is not covered, or the revision is not the one you expected. Nothing has been changed.
3. Select a signature or revision deliberately
Use -s when you know the signature. Hexadecimal signatures and masks need the 0x prefix. The following selects one signature and lists it:
$ iucode_tool -s 0x000906e9 --list /lib/firmware/intel-ucode
selected microcodes:
007/001: sig 0x000906e9, pf_mask 0x2a, 2023-09-28, rev 0x00f8, size 108544
To constrain by revision, append a comparison such as gt:0xf0. To constrain by date, use an ISO date:
$ iucode_tool -s 0x000906e9 --date-after=2020-01-01 --list /lib/firmware/intel-ucode
$ iucode_tool --scan-system --date-before=2025-01-01 --list /lib/firmware/intel-ucode
No output means that the filters matched nothing. That is different from a successful update. Selection options can be combined, and later -s options override earlier selections. A negated signature, such as -s !0x000906e9, deselects it. Keep complicated filters in a script or a change record so that a later operator can see exactly what was intended.
Do not add --downgrade casually. It keeps the version from the last matching file rather than the highest revision. The manual warns that downgrade mode is intended for entries with the same processor flags mask and does not cover every kernel selection corner case.
4. Write a disposable binary bundle
Before installing anything, make a destination under /tmp. The default is --no-overwrite, so an existing destination causes an error instead of being replaced:
$ work=$(mktemp -d /tmp/iucode-tool.XXXXXX)
$ iucode_tool --scan-system --write-to="$work/selected.bin" /lib/firmware/intel-ucode
$ ls -l "$work/selected.bin"
-rw-r--r-- 1 ... ... ... selected.bin
$ iucode_tool --list "$work/selected.bin"
selected microcodes:
007/001: sig 0x000906e9, pf_mask 0x2a, 2023-09-28, rev 0x00f8, size 108544
The exact owner, size and selected revision vary. Listing the output again is the important check. Output files are created with mode 0644 modified by the current umask. iucode_tool reads input into memory and writes selected microcode in binary format.
Do not use --overwrite on a valuable file merely to make a command convenient. It removes the old destination before writing, breaks hardlinks and loses the old file's permissions, ACLs and extended attributes. Writes are not atomic: interruption can leave a corrupt destination. Use a new path, verify it, then replace a production file using the distribution's normal atomic or package-managed procedure. If this test must be abandoned, remove only the temporary directory after checking its path:
$ test -n "$work" && case "$work" in /tmp/iucode-tool.*) rm -rf -- "$work";; esac
5. Prepare an early initramfs archive
Early loading is normally safer than a late update because the kernel sees the microcode before boot continues. iucode_tool can create the specially formatted early archive and handle the alignment required by the early loader:
$ work=$(mktemp -d /tmp/iucode-early.XXXXXX)
$ iucode_tool --scan-system --write-earlyfw="$work/early.cpio" /lib/firmware/intel-ucode
$ file "$work/early.cpio"
$ ls -lh "$work/early.cpio"
-rw-r--r-- 1 ... ... ... early.cpio
The archive is test output. Inspect it with the tools available on your system before integrating it. The normal early archive format is the default because it keeps the microcode data available to the regular initramfs as well. --mini-earlyfw saves space by using a 16-byte cpio block size and omitting parent-directory entries, which can confuse other tools and makes the data unavailable to the regular initramfs. Leave it out unless you have tested that trade-off.
Creating this file does not make the kernel use it. To deploy it, use your distribution's initramfs and boot-loader tooling, keep a known-good previous image, and plan a reboot window. Do not write directly into /boot during an exploratory test. If a boot image has already been replaced and the system fails to boot, select the previous kernel or initramfs from the boot loader, restore the saved image from a rescue environment, and rebuild it through the distribution tool.
6. Know the boundary between inspection and updating
The -K and --write-firmware options write files named for the Linux firmware loader, by default under /lib/firmware/intel-ucode. Test the operation in a temporary directory first:
$ work=$(mktemp -d /tmp/iucode-firmware.XXXXXX)
$ iucode_tool --scan-system --write-firmware="$work" /lib/firmware/intel-ucode
$ find "$work" -maxdepth 1 -type f -printf '%f\n' | sort
06-9e-0b
Do not use --kernel for a routine modern deployment. It uploads through /dev/cpu/microcode, an interface the manpage marks deprecated. A late firmware reload can also have processor feature implications. Prefer the operating system package and early-initramfs workflow, and consult the kernel and distribution documentation before any live update.
For diagnostics, remember that requested listings go to standard output while informational and error messages go to standard error. A pipeline that captures only standard output can miss the reason a selection failed. Use --verbose when needed, and preserve the exit status:
$ iucode_tool --scan-system --list /path/to/microcode 2>error.log
$ status=$?
$ printf 'iucode_tool status: %s\n' "$status"
$ sed -n '1,20p' error.log
Keep the original bundle. If an input is damaged, the default strict checks and --no-ignore-broken stop rather than silently skipping it. The recovery loader -tr is for recovering microcode from a binary container and can find entries that fail strict checks; use it only when you understand why recovery is needed and have verified the resulting listing.
Done means
- You confirmed iucode_tool 2.3.1 and identified the input directory or bundle.
- You listed matching signatures and checked the selected revision, date and platform mask.
- You tested output under
/tmpbefore considering a firmware or boot change. - You left the default highest-revision and strict-check behaviour in place unless you had a recorded reason to change it.
- You know that writing an early archive is not the same as installing or booting it.
- You kept a known-good microcode and initramfs recovery path before any privileged deployment.