IUCODE_TOOL(8)

💖 NAME 💖

Okay bestie, this is the iucode_tool manual 🌸, and the page is for iucode_tool, a tool for poking at Intel® IA‐32/X86‐64 microcode bundles 💅


🎀 SYNOPSIS 🎀

iucode_tool [options] [[-ttype] filename|dirname] ...

✨ DESCRIPTION ✨

okay so iucode_tool is a utility that can load Intel® processor microcode data from files in both text and binary microcode bundle formats 🫶

it can list out the microcodes inside those files, merge them, upload them to the kernel (which upgrades the microcode in the system processor cores ⚡), or write some of them out to a file in binary format so you can use them later 💜

iucode_tool loads every microcode from the files and directories you give it into memory so it can process them 🧠 Duplicated and outdated microcodes get discarded, no cap 💀 It can also read microcode data from standard input (stdin) if you pass it a file name of - (minus sign) 🧚

microcode data files are assumed to be in .dat text format if they have a .dat suffix, and in binary format otherwise 🦋 stdin is assumed to be in .dat text format too. the -t option changes the type of the files specified after it, and that includes stdin 🍓

if you give it a directory, every file whose name doesn't begin with a dot gets loaded, in an unspecified order (it's giving mystery 🙈). Nested directories are skipped, so don't expect it to dig deeper 😭

empty files and directories are ignored and skipped. no drama, just vibes 🌈

you can pick which microcodes get written out, listed, or uploaded to the kernel using the -S, -s, --date-before and --date-after options ✨ if you don't specify any of those, all microcodes get selected automatically 👑

you can upload the selected microcodes to the kernel, or write them out to a file in binary format, to a Linux early initramfs archive, to per-processor-signature files in a directory, or to per-microcode files in a directory. the options for that are -w, --write-earlyfw, -k, -K, and -W 🔥

iucode_tool labels microcodes in its output and error messages with an "n/k" notation, where "n" is the bundle number and "k" is the microcode number within that bundle 🎀 if you want to see how it works, the output of --list-all when you process multiple input files is the best example 🫶

for more info about Intel processor microcodes, check out the included documentation and the Intel manuals listed in the SEE ALSO section 📚💅

✨ OPTIONS ✨

okay so iucode_tool takes a whole bunch of options 💅 here's the full lineup, bestie 🫶

  • -q, --quiet — shhh 🤫 this inhibits the usual output
  • -v, --verbose — prints more info. use it more than once if you want even more 📢
  • -h, -?, --help — lists every available option and what it means 📖
  • --usage — gives you a quick summary of the options
  • -V, --version — shows the version of the program 🏷️

  • -t type — sets the file type for the files that come after it. type can be:
    • b — binary format. this is the same format the kernel driver and the BIOS/EFI use, and it's explained in detail in the Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 3A, section 9.11 🧠
    • d — Intel microcode .dat text format. this is the one Intel normally uses to distribute microcode data files 📄
    • r — recover microcode in binary format. it searches uncompressed generic binary files for microcodes in Intel microcode binary format so it can recover them 🛠️ heads up though: it can find microcode that won't pass strict checks, and that will make iucode_tool exit unless --no-strict-checks or --ignore-broken is in effect ⚠️
    • a (default) — iucode_tool looks at the file suffix to decide: .dat text format for files ending in .dat, binary otherwise. for stdin, .dat text format is assumed 🕵️

  • --downgrade — when a processor has multiple microcode versions across different files, this keeps the one from the file loaded last, no matter the revision levels. files always load in the order you typed them on the command line. it does nothing if only one file got loaded 🔄
  • --no-downgrade — same situation, but this one keeps the version with the highest revision level. this is the default vibe 📈

  • --strict-checks — the strict mode, and it's the default ✅ it refuses to load microcodes and microcode data files with unexpected size or metadata. it also refuses microcode entries that have the same metadata but different payloads 🚫
  • --no-strict-checks — less strict checks. only use this if you come across a data file with microcodes that have weird sizes or dodgy non-critical metadata (like invalid dates) and you still want to keep them 🫣 if you just want to skip those instead, use --ignore-broken

  • --ignore-broken — skips broken microcode entries while loading a data file, instead of aborting the whole program 🩹 if an entry has an unsupported format or a severely corrupted header, all the remaining data in the file gets ignored too. in that situation, -tr (recover microcode in binary format) is recommended, since it can skip over badly mangled microcode data 💀
  • --no-ignore-broken — aborts the program if a broken microcode shows up while loading a data file. this is the default 🛑

  • -s ! | [!]signature[,[pf_mask][,[lt:|eq:|gt:]revision]] — selects microcodes by the signature, processor flags mask (pf_mask), and revision you give it 🎯
    • if you specify a processor flags mask, it only selects microcodes that are suitable for at least one of the processor flag combinations in the mask 🏷️
    • if you specify a revision, you can put one of the prefixes eq:, lt: or gt: in front of it. with no prefix (or with eq:), it selects microcodes with that exact revision. with lt: it selects microcodes with a revision less than the one you gave, and with gt: it selects ones greater than it 🔢
    • you can use -s more than once to select more microcodes 🫶 it also works together with --scan-system. if the signature starts with a ! (exclamation mark), it deselects microcodes instead. order matters here, because later -s options override earlier ones, including --scan-system 🔀
    • when you write a signature or pf_mask, hexadecimal numbers need the 0x prefix and octal numbers need a 0 prefix. decimal numbers must not have leading zeros, or they'll be read as octal 🧮
    • the special notation -s! (with no signature parameter) tells iucode_tool to require explicit inclusion of microcode signatures, either with the non-negated form of -s or with --scan-system 🙅‍♀️

  • -S, --scan-system[=mode] — selects microcodes by scanning the online processors on your system for their signatures 🔍 you can only use this once, but it can be combined with -s to select even more microcodes. microcodes picked by --scan-system can still be deselected by a later -s !signature 🫠

the optional mode argument (only accepted by the long version of the option) picks the scanning strategy:

  • 0 or auto — currently the same as fast, but that might change in future versions if Intel ever deploys multi-signature systems beyond mixed-stepping. this is the default, kept for backwards compatibility with previous versions of iucode_tool 🔙
  • 1 or fast — uses the cpuid instruction to detect the signature of the processor iucode_tool is running on, then selects all steppings for that processor's type, family and model. supports mixed-stepping systems 🏃‍♀️
  • 2 or exact — uses kernel drivers to scan the signature of every online processor directly. this mode supports multi-signature systems. it'll be slow on big systems with lots of processors, and it probably needs special permissions (like running as the root user) 🐢 if the scan fails for any reason, it issues a warning as a fail-safe and considers all possible steppings for every signature it did manage to scan successfully ⚠️

  • --date-before=YYYY-MM-DD and --date-after=YYYY-MM-DD — limits the selected microcodes by a date range 📅 the date has to be in ISO format: four digits for the year, two for the month and day, and - (minus sign) as the separator. dates aren't range-checked, so you can use --date-after=2000-00-00 to select everything dated since January 1st, 2000 🗓️
  • --loose-date-filtering — when a date range is set, all revisions of a microcode get considered if any one of its revisions falls within the range. only the date range gets ignored here, every other filter still applies 🌊
  • --strict-date-filtering — when a date range is set, only microcodes that are within the range get selected. this is the default 🎯

  • -l, --list — lists the selected microcode signatures to standard output (stdout) 📋
  • -L, --list-all — lists all microcode signatures while they're being processed, also to standard output (stdout) 👀

  • -k[device], --kernel[=device] — uploads the selected microcodes to the kernel 🧠 you can optionally give the device path, and the default is /dev/cpu/microcode. heads up bestie: this update method is deprecated, and it'll eventually be removed from both the kernel and iucode_tool 💀
  • -K[directory], --write-firmware[=directory] — writes the selected microcodes using the file names the Linux kernel firmware loader expects 🐧 you can optionally pick the destination directory, and the default is /lib/firmware/intel-ucode 📂
  • -wfile, --write-to=file — writes the selected microcodes to a file in binary format 💾
  • --write-earlyfw=file — writes the selected microcodes to an early initramfs archive. this archive should be prepended to the regular initramfs, so the kernel can update processor microcode super early during system boot 🚀
  • -Wdirectory, --write-named-to=directory — writes the selected microcodes to the directory you specify, one microcode per file, in binary format 🗂️ the file names reflect the microcode signature, processor flags mask and revision 🏷️
  • --write-all-named-to=directory — writes every microcode to the directory you specify, one per file, in binary format 🌈 the file names reflect the microcode signature, processor flags mask and revision too. this is the only way to write out every revision of the same microcode 🫶

  • --overwrite — removes the destination file before writing, if it exists and isn't a directory 🗑️ the destination file doesn't get overwritten in-place. hardlinks get severed, and any existing access permissions, ACLs and other extended attributes of the old destination file are lost 💔
⚠️ the old file's permissions, ACLs and extended attributes are gone after this, so be careful.
  • --no-overwrite — aborts if the destination file already exists. this is the default 🛡️ also, do note that iucode_tool does not follow non-directory symlinks when writing files 🔗

  • --mini-earlyfw — optimizes the early initramfs cpio container for minimal size 🤏 it changes the cpio block size to 16 bytes and removes the header entries for the parent directories of the microcode data file. because of that, the microcode data file won't be available to the regular initramfs, and some tools might complain about the non-standard cpio block size 🙈 this usually shrinks the early initramfs by 736 bytes ✨
  • --normal-earlyfw — optimizes the early initramfs size for tool compatibility instead. this is the default 🫶 the microcode data file will also be available inside the regular initramfs 🎀

✨ NOTES ✨

okay so bestie, listen up 💅 iucode_tool reads all the data into memory before it does anything. it enforces a sanity limit of a maximum of 1GiB worth of binary microcode data per microcode data file 🫶

All informational and error messages go to standard error (stderr) 📣, while stuff you actually asked for, like the output from the list options, goes to standard output (stdout) 🖨️

iucode_tool creates files with permissions 0644 (rw-r--r--), modified by the current umask 🎀

Your selected microcode listing and microcode output files are sorted first by processor signature (ascending order) ⬆️, and then by processor flags mask (descending order) ⬇️. the sorting is giving organized 💜

When you select multiple revisions of a microcode, the older ones get skipped 🙈 Only the newest selected revision (or the last one in load order when the --downgrade option is active) gets written to a file or uploaded to the kernel 🦋

Intel microcode data files, in both binary and text formats, can be concatenated to make a bigger file that's still valid 🌈 iykyk

iucode_tool does not follow symlinks when writing microcode data files 🚫 By default it refuses to write the file and aborts. With the --overwrite option active, it removes the target symlink or file first (which breaks hardlinks!) and then writes the new file. not me being dramatic but hardlinks are gone 💀

iucode_tool does follow directory symlinks to find the directory it should write files into ✨

✨ Linux Notes ✨

Before Linux v4.4, the microcode update driver was split into two parts 🧩: the early microcode update driver (which grabs microcode data from the initramfs) and the late microcode update driver (which could be a module and got its data from the firmware subsystem). the two drivers were unified in Linux v4.4 💖

The microcode update driver needs to be present in the system at all times so microcode updates get reapplied on resume from suspend and CPU hotplug 🔥 Do not unload the microcode module unless you really know better 🙅‍♀️ Since Linux v4.4, the late microcode driver can't be a module anymore, so it's always present when enabled 👑

Updating microcode early is safer 🛡️ It can only be done at boot and it needs an initramfs, but it's strongly recommended bestie. late microcode updates (which read microcode data from /lib/firmware) cannot safely change visible processor features 😭

Early microcode updates have been available since Linux v3.9 🌸 They can safely change visible processor features (like the microcode updates that disabled Intel TSX instructions on Intel Haswell cores). They need an uncompressed initramfs image with the microcode update data in /kernel/x86/microcode/GenuineIntel.bin. This uncompressed initramfs image must come before any compressed initramfs image(s), and it has a special name: early initramfs 🧚

The microcode update data inside the early initramfs image must be aligned to a 16‐byte boundary, because of a bug in several versions of the Linux kernel early microcode update driver 🙈 This needs special steps when you create the initramfs archive with the microcode data, and it gets handled automatically by the iucode_tool --write-earlyfw option 🎀

Since Linux v4.2, you can also build a kernel with the microcode update data as built‐in firmware, using the CONFIG_FIRMWARE_IN_KERNEL facility 🧠 This feature isn't mature yet as of Linux v4.2.8, v4.4.11, v4.5.5 and v4.6, and it might not work in every case 💀

The /dev/cpu/microcode update interface has been deprecated, so don't use it 🚫 It has one special requirement: each write syscall must contain whole microcode(s). You can still access it through iucode_tool --kernel 🦋

Up to Linux v3.5, late microcode updates had to be triggered per‐core, by writing the number 1 to /sys/devices/system/cpu/*/microcode/reload for every cpu 🌈 Depending on the kernel version, you either have to trigger it on every core (to avoid a dangerous situation where some cores are using outdated microcode), or the kernel only accepts the request for the boot processor and uses it to trigger an update on all system processor cores 😵‍💫

Since Linux v3.6, the late microcode update driver has a new interface that explicitly triggers an update for every core at once when the number 1 is written to /sys/devices/system/cpu/microcode/reload ⭐ main character energy for the kernel fr fr

✨ EXAMPLES ✨

Updating files in /lib/firmware/intel‐ucode

iucode_tool -K/lib/firmware/intel‐ucode \
            /lib/firmware/intel‐ucode \
            /tmp/file-with-new-microcodes.bin

Processing several compressed files at once

zcat intel-microcode*.dat.gz | iucode_tool -l -
zcat intel-microcode*.bin.gz | iucode_tool -l -tb -

Selecting microcodes and creating an early initramfs

iucode_tool --scan-system \
            --write-earlyfw=/tmp/early.cpio \
            /lib/firmware/intel-ucode
iucode_tool -s 0x106a5 -s 0x106a4 -l /lib/firmware/intel-ucode

Using the recovery loader to load and to update microcode in an early initramfs

iucode_tool -L -tr /boot/intel-ucode.img
iucode_tool -Ll -S --write-earlyfw=/boot/intel-ucode.img.new \
            -tr /boot/intel-ucode.img -tb /lib/firmware/intel-ucode && \
       mv /boot/intel-ucode.img.new /boot/intel-ucode.img

✨ BUGS ✨

Microcode with negative revision numbers isn't special‐cased 🙃 so it won't be preferred over regular microcode.

The downgrade mode should only be used for microcodes with the same processor flags mask 🎀 It can't handle the corner cases where changing a processor flags mask would be required to force the kernel to load a lower revision of a microcode. iucode_tool will issue a warning when that happens ⚠️ So far this hasn't been a relevant limitation, since changes to the processor flags mask of post‐launch, production microcode updates are super rare ✨

The loader version microcode metadata field is ignored by iucode_tool 🤷‍♀️ This shouldn't cause problems as long as the same signature never needs more than a single type of loader.

Files are not replaced atomically! If iucode_tool gets interrupted while writing to a file, that file will be corrupted 💀 handle with care bestie

✨ SEE ALSO ✨

The Intel 64 and IA‐32 Architectures Software Developer's Manual, Volume 3A: System Programming Guide, Part 1 (order number 253668), section 9.11 📖🩷

✨ AUTHOR ✨

Henrique de Moraes Holschuh <hmh@hmh.eng.br> 👑🫶


bestie that's the whole thing 🦋 you're officially an iucode_tool expert now, go slay the microcode 💅🌸 IUCODE_TOOL 2.3.1, last updated 2018‐01‐28, forever iconic ✨🎀