
1.) Introduction
This is something I’ve been wanting do do years ago, but the recent outcry regarding the Meltdown and Spectre hardware security holes have reminded me of this. Since fixing at least parts of the exploits also requires CPU microcode support (from here on: “µcode”), and not all operating systems and mainboards/machines might get them, this might be useful for the current situation as well. It can also be helpful if you wish to patch Intel Xeon support into a slightly older platform, where the manufacturer hasn’t done so already. This article does however not apply to modern UEFI-based systems.
So, instead of getting the required CPU µcodes from a donor BIOS, why not obtain the latest version from Intels’ [µcode package for Linux]? Oh, and it’s not really Linux-specific anyway.
I will show you how to extract and prepare the Intel µcodes and how to patch them so you can embed them into pretty much any somewhat modern AMI BIOS. AMI BIOSes are pretty widespread, but tools similar to the AMI-specific ones shown here might of course also exist for other BIOS brands.
The steps of this guide will be shown for both Linux/UNIX as well as Microsoft Windows.
All the tools used in this post can be found at the end of the article. You can also get all the currently released µcodes in one package there, so you don’t need to download all the archives from Intel (not all archives contain all µcodes…).
2.) Fetch and extract/convert Intels’ µcode package
You can get the µcodes directly from Intel, again, here’s the [link]. To unpack the .tgz archive on MS Windows, you may want to use [7-zip] (It’s a 2-step process with 7-zip, from .tgz to .tar and from .tar to the final files). For older releases, all you’ll get by doing this is a microcode.dat file, sometimes the file name will also contain a date. That’s all the µcodes assembled in one file in a text format. This is useless for patching the data into BIOS images, so we’ll need to extract the individual CPU µcodes and convert them into the proper binary format.
Newer releases might contain pre-built binary versions as well, but we’ll just continue to work with microcode.dat.
Update 2018-05-10: With the 2018-04-25 release of its CPU µcodes, Intel has no longer included microcode.dat, posing quite a problem for this solution and also for others, like VMware users who rely on the file for their CPU updates using the [VMware CPU Microcode Update Driver] fling. Luckily, a hacker going by the name Jacob Klein has written and published a little tool called “Intel Microcode.dat Converter”[1] which can reassemble microcode.dat from the binary files provided by Intel. Thanks for pointing this out to me go to Greg, who posted the information in a [comment] below.
You can find the corresponding discussion thread over at the [VMware labs] and Jacobs’ files [over here], including the source code.
Somewhat unfortunately, it’s a tool build in C# for the .Net 4.6.1 framework, so no dice on UNIX and Linux for now, but it’s still a saving grace! I’ve taken the liberty of removing the (seemingly unnecessary) System.Net.Http namespace reference from the project to be able to downgrade the code to .Net 4.0 Client Profile. With that, I managed to build fully Windows XP compatible versions (32- and 64-bit) of the tool. You can also just hack the binary header of Jacobs’ release with CFF Explorer, but this is the cleaner solution. My builds have been added to the download section at the end of the article.
If the original files by Jacob Klein ever vanish from the web, I’ll re-host those as well.
This is what the tool looks like in action:

Specifiy the folder where the µcodes have been extracted. That’s the one with subfolders like intel-ucode, intel-ucode-with-caveats, etc.
Be careful with the “Include “intel-ucode-with-caveats” files?” option, as those shouldn’t be considered safe. The “µcodes with caveats” do need operating system kernel patches to work properly, so you should only use those if you’re sure your OS kernel is prepared for them, or you might run into some serious problems afterwards! Hit that “Convert!” button, and you’ll be rewarded with a microcode.dat file:

After a few seconds, the conversion is done!
According to my brief extraction tests with the microdecode program, the resulting file seems to be perfectly fine! Still, no warranties of course. After having obtained microcode.dat, you can continue with the rest of this guide.
And thanks, Jacob, nice work! ![]()
End of update
2a.) On Linux or UNIX
We’ll use iucode_tool for that, as at least most Linux systems should have a package ready for that program. If you can by no means get or compile iucode_tool, you might compile microdecode from source on Linux or UNIX instead, see 2b.) and 8.)! I have tested this on CentOS 6.9 Linux, and microdecode compiles just fine. But let’s continue with iucode_tool:
To extract the µcodes, switch to the directory containing microcode.dat (after unpacking the .tgz file with tar -xzf) and run the following commands:
$ mkdir ./µcodes/ $ iucode_tool -t d -L --write-named-to="./µcodes/" "microcode.dat"; done
With that, you’ll get a lot of *.fw binary files in ./µcodes/. Those are in the regular Intel µcode format and come in different sizes depending on the CPU. The file names look similar to e.g. this: s000206C2_m00000003_r00000013.fw. The first “s” part contains the CPUID, the second “m” part shows the platform ID, and the “r” part denotes the µcode revision, all of it in hexadecimal notation.
2b.) On Windows
On Windows, we’ll use the microdecode command line tool. It’s a bit easier to use than iucode_tool, as it’s only purpose is really just µcode extraction and nothing else. Switch to the directory containing the unpacked microcode.dat, make sure microdecode.exe is in your search path (or in the same directory), and run the following command:
microdecode.exe microcodes.dat
This will result in a lot of *.bin files that are identical to the .fw files the *nix tool extracts. The file names will be similar to this: cpu000206c2_plat00000003_ver00000013_date20100907.bin. The first “cpu” part contains the CPUID like above, the second “plat” part contains the platform ID, and the “ver” part shows the µcode revision. Additionally, we also get the release date in the final “date” part.
3.) Identifying your CPU
You’ll likely know your CPU model if you’re reading this. But what you’ll need to know above that is your exact CPUID, stepping and the revision of CPU µcode you’re currently running. You can look up some of the information on cpu-worlds’ [CPUID database], but ultimately, you’ll need to fetch it from your local machine anyway.
Important background information: The CPUID is a 32-bit value structured as follows:

The binary structure of Intels’ 32-bit CPUID, 4 bits equal one hexadecimal character
The binary matrix is usually expressed as 4-bit hexadecimal characters. e.g. the binary CPUID 0000:0000:0000:0010:0000:0110:1100:0010bin would result in 000206C2hex.
3a.) On Linux/UNIX
On Linux, the required information can be grabbed from procfs. Like this, for example:
$ cat /proc/cpuinfo | grep -e "model" -e "stepping" -e "microcode" -e "cpu family" | sort | uniq cpu family : 6 microcode : 15 model : 44 model name : Intel(R) Core(TM) i7 CPU X 980 @ 3.33GHz stepping : 2
You have to be careful interpreting this information however, as it’s mostly decoded in decimal form. Modern kernels might show some of the data in hexadecimal, so be careful here!
But first, convert the decimals from /proc/cpuinfo to hexadecimal, where necessary, in this case we’ll do it for the µcode revision and the model number:
$ printf '%X\n' 15 F $ printf'%X\n' 44 2C
So, the model number is 2Chex. Here, the right part or Chex is the actual model number (CPUID bits 4..7) and 2hex is the extended family number (CPUID bits 16..19).
The µcode version here would be Fhex. Note that µcode versions can be wider than just 1 hexadecimal character as well. The stepping 2 is a number lower than 15, so we don’t need to convert it to hexadecimal.
To assemble our final string which is 8 hexadecimal characters wide, we walk through the bit mask on the image shown above step by step! All “reserved” parts are just filled with blanks:
- 0 (Bits 31..28, reserved)
- 0 (Bits 27..24, extended CPU family, zero for family 6)
- 0 (Bits 23..20, extended CPU family, zero for family 6)
- 2 (Bits 19..16, extended CPU model number)
- 0 (Bits 15..12, two reserved and two platform type bits, typically zero)
- 6 (Bits 11..8, CPU family code)
- C (Bits 7..4, CPU model number)
- 2 (Bits 3..0, CPU stepping ID)
As a result of this, our CPUID string looks as follows:
000206C2hex, currently running µcode revisionFhex.
Please note that information down, it’s needed in the next step.
Of course, if you’re running some other UNIX, you’d be needing different tools. On FreeBSD you may be able to work with the “cpuflags” tool, like this:
$ cpuflags x 2>& | grep "Origin"
For other UNICES, you’re on your own though.
3b.) On Windows
On Windows I’d recommend Ray Hinchcliffes’ [System Information Viewer], or “SIV” in short. It’s a pretty powerful freeware system information tool that will read out the stuff we need for the next steps (You can also use something like CPU-Z of course). See the following screenshot to learn what you need to look for:
From left to right, we need the following data as pointed out with those arrows: CPU family 6hex, CPU model 2Chex (you can ignore the decimal value “44”), stepping 2hex and µcode revision 13hex. Again, 2Chex is a combination of model number Chex and extended model number 2hex!
Just like on Linux, the final identification string needs to be assembled first. Luckily, SIV already does the decimal -> hexadecimal conversion for us. To assemble the entire CPUID, put everything together like this:
- 0 (Bits 31..28, reserved)
- 0 (Bits 27..24, extended CPU family, zero for family 6)
- 0 (Bits 23..20, extended CPU family, zero for family 6)
- 2 (Bits 19..16, extended CPU model number)
- 0 (Bits 15..12, two reserved and two platform type bits, usually zero)
- 6 (Bits 11..8, CPU family code)
- C (Bits 7..4, CPU model number)
- 2 (Bits 3..0, CPU stepping ID)
As a result of this, our CPUID string looks as follows:
000206C2hex, currently running µcode revision13hex.
The revision is the µcode version you’re currently running. Newer version will just have higher numbers, so that’s how you can compare them with what you extracted from Intels’ package.
Note that information down, as you’ll need it in the next step.
4.) Locating the correct µcodes
4a.) On Linux/Unix
Let’s continue to assume your CPUID string is 000206C2hex. Switch to the directory where you extracted the Intel µcode package for Linux and look for the correct µcode binaries (in my case I have them grouped in folders by date as well):
$ find . -iname "*000206C2*" ./20100914/µcodes/s000206C2_m00000003_r00000013.fw ./20100826/µcodes/s000206C2_m00000003_r0000000F.fw
Two versions are available: The newer 13hex and the older Fhex (in decimal that would amount to 19 vs. 15, higher is always newer).
4b.) On Windows
Like on Linux, let’s assume your CPUID string is 000206C2hex. Switch to the directory where your extracted Intel µcodes are, and look for the corresponding files:
DIR /B /S "*000206C2*" X:\BIOSMOD\AMI\µCodes\20100826\cpu000206c2_plat00000003_ver0000000f_date20100618.bin X:\BIOSMOD\AMI\µCodes\20100914\cpu000206c2_plat00000003_ver00000013_date20100907.bin
There you go, the newer 13hex and the older Fhex µcodes.
5.) What’s wrong with AMI MMTool: A detailed explanation
To embed the µcodes into an actual AMI BIOS image, AMIs’ MMTool “CPU Patch” function is required. It’s a Windows program, but given its simple nature, it will run fine with Wine on Linux and FreeBSD UNIX as well:
- AMI MMTool on Windows (click to enlarge)
- AMI MMTool on Linux via Wine (click to enlarge)
But if you attempt to embed Intels’ original binaries, it’ll fail right away:

MMTool failing to import Intel µcodes directly
If you extract existing µcodes from a given BIOS image and compare them with the same µcode revision in Intels’ format, you’ll notice a size difference:
$ ls -al ./06C2-Rev13.bin 20100914/µcodes/s000206C2_m00000003_r00000013.fw -rw-rw-r-- 1 thrawn users 8192 Jan 10 14:04 ./06C2-Rev13.bin -rw-r--r-- 1 thrawn users 7168 Jan 10 14:26 20100914/out/s000206C2_m00000003_r00000013.fw
Intels’ µcode file in this case is 7168 bytes or 7kiB in size, but the stuff we extracted from that AMI BIOS is 8192 bytes or 8kiB in size. So what’s the deal here? At first I had no idea at all and thought that they’d just be encoded differently in the AMI BIOS or something. But it turns out that that is not the case. If you open both files in a hex editor of your choice, you’ll notice something at the end of the file that came from the AMI BIOS:
- Intel µcode format (click to enlarge)
- The file from the AMI BIOS has a zero padding at the end! (click to enlarge)
The final 1kiB is just binary zeroes! So how do we fix that? In essence, the entire procedure is like this:
- Extract µcodes from the target AMI BIOS image using MMTool.
- Look at how large that file is (in bytes).
- Look at how large the desired Intel µcode file “for Linux” is for your exact CPU.
- Calculate the difference in bytes.
- Fill the end of the Intel file with as many binary zeroes as there are missing bytes.
- Save that file and try to load it into your BIOS image using MMTools’ “CPU Patch” function.
Alright, let’s do it!
6.) Patching those µcodes for AMI MMTool and patching the BIOS itself
First, extract some random µcode from your BIOS using AMI MMTools’ “CPU Patch” function. Look at the file and note down its’ size in bytes. Also, you may want to look at the extracted µcode to see whether it has a lot of zeroes at the end. In my case, as said, the µcodes in that AMI BIOS are 8192 bytes, or 8kiB large, while Intel’s µcode is 7kiB in size. 8192 – 7168 = 1024, so again, the difference is 1024 bytes or 1kiB.
Please triple-check this stuff, as a wrong padding will break the µcode! Of course MMTool should warn you if something’s wrong, but it doesn’t hurt to make sure it’s safe from the start.
6a.) On Linux/UNIX
Let’s make this easy, generate a 1kiB zero padding file for future use on similar µcode files:
$ dd bs=1 count=1024 if=/dev/zero of=./1kiB-zeropadding.bin 1024+0 records in 1024+0 records out 1024 bytes (1.0 kB) copied, 0.00383825 s, 267 kB/s
And now, append the zeroes to the end of the file, generating a new file in the process, so we don’t touch the originals:
$ cat ./20100914/µcodes/s000206C2_m00000003_r00000013.fw ./1kiB-zeropadding.bin > ./0206C2-rev13.bin
That file 0206C2-rev13.bin is now the final µcode file for patching into the target BIOS. As an example, I’ll patch those µcodes for Xeon X5600 processors into an ancient BIOS version 0402 of an ASUS P6T Deluxe mainboard:
- MMTool on Linux with an unpatched BIOS (click to enlarge)
- MMTool on Linux: Patch successful (click to enlarge)
Save that file, and you’re done modifying your BIOS with µcodes from Intels’ Linux package!
6b.) On Windows
On MS Windows there is no dd command by default, but we have a another preinstalled utility for creating our 1kiB zero padding file: fsutil! Like this:
fsutil File CreateNew .\1kiB-zeropadding.bin 1024
We don’t have a cat command on Windows either, but we can use a binary copy for file concatenation, no need to install any additional tools. We’ll attach the zero padding to the end of the Intel µcode and write the result to a new file, so we’re not altering the originals:
COPY /B .\20100914\cpu000206c2_plat00000003_ver00000013_date20100907.bin + .\1kiB-zeropadding.bin .\0206C2-rev13.bin
That file 0206C2-rev13.bin is now the final µcode file for patching into the target BIOS. As an example, I’ll patch those µcodes for Xeon X5600 processors into an ancient BIOS version 0402 of an ASUS P6T Deluxe mainboard:
- MMTool on Windows with an unpatched BIOS (click to enlarge)
- MMTool on Windows: Patch successful (click to enlarge)
Save that file, and you’re done modifying your BIOS with µcodes from Intels’ Linux package!
7.) Flashing the modified BIOS
This step depends on your system. You may be able to flash from within the BIOS itself (e.g. from floppy disk or USB pen drive), or from within MS Windows or by using some bootable medium.
In any case, your BIOS image is ready now, and can be flashed at your convenience. After the update, re-check your µcode revision as shown in 3.). Your CPU should now be running the updated µcode!
8.) Downloads
Some of the programs used in this article can be downloaded here:
- [AMI MMTool v3.22]
- [microdecode], compiled by myself, contains 32-bit and 64-bit versions of the tool as well as the source code and license file. Compiles on Linux/UNIX as well.
- Intel Microcode.dat Converter[1], [32-bit XP XIN build][64-bit XP x64 XIN build]; A tool required for releases without Microcode.dat, like the 2018-04-25 one. See [this comment].
- [Intel µcodes], everything from 2009-03-30 up to 2018-01-08 as available on the Intel web site at the moment.
9.) Hopefully you haven’t bricked your mainboard
…all of this without any kind of guarantees of course! ![]()
[1] The Intel Microcode.dat Converter is © Jacob Klein and has been published under a not otherwise specific license at the VMware Labs









