• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

Introducing cpupdate, a microcode tool for FreeBSD

Snurg

Aspiring Daemon

Thanks: 242
Messages: 698

#1
There is a new microcode updating utility. (Currently for Intel only. Although I'd add AMD and VIA support and write a man page, if there is sufficient interest to put it into base system or ports collection).
Code:
# cpupdate -h
Usage: cpupdate [-qwvviIAVh] [-<f|U> <microcodefile>] [-<u|c> <datadir>] [-x <dirname>]
  -i   show processor information
  -f   show version information of microcode file
  -u   update microcode using microcode files in <datadir>
  -U   update microcode using file <microcodefile>
  -w   write it: without this option cpupdate only simulates updating
  -c   Check integrity of microcode files in <datadir>. Vendor mode must be set!
  -IAV for -c option: set vendor mode to Intel/AMD/VIA [atm only Intel implemented]
  -x   extract microcode files from multi-blob intel-ucode files to <dirname>
  -q   quiet mode
  -v   verbose mode, -vv very verbose
  -h   show this help
#
First, why another CPU microcode updater?
The microcode updater in devcpu-data is rudimentary, has critical bugs and does not support the modern multi-blobbed Intel microcode data file format.
And, this new tool "cpupdate" has a number of useful functions which devcpu-data does not offer.

To stay below the tl;dr threshold, just a very short intro how to build and install:
Download the source and build it using make.
Then run its "show processor information" function to get information about your CPU and microcode release:
(example output shown for Xeon 56xx series with unpatched memory sinkhole bug)
Code:
# ./cpupdate -i
Found CPU(s) from Intel
Processor Core: 0
-> CPUID: 206c2  Family: 06  Model: 2C  Stepping: 02  uCodeRev: 0000001A
<other cores' output snipped>
#
(Note: Use the verbosity flags -v[v] to get more detailed infos)
(Note 2: The cpuctl kernel module is needed to use cpupdate. If it is not loaded you'll get an error message reminding to load it)
(Note 3: The examples assume the current working directory is the one where you built the program)

Go to platomav's microcode collection page, read it, and go to the Intel subdirectory.
Search for the CPUID string (in the above example '206c2') and download the newest microcode file you find for your CPU, if there is any. In the example the file "cpu206C2_plat03_ver0000001D_2015-08-04_PRD_F7DC758B.bin" matched the CPUID and contains microcode 0x1D, which should fix the memory sinkhole.
Your CPUID is probably different. So just hit ctrl-F, enter your CPUID, and let the browser search for a matching file.

(Note: If your computer vendor offers a BIOS update that updates the microcode, updating the BIOS is the preferred way - these microcodes are intended mainly for updating computers for which no updated BIOS is available. So, in case you cannot obtain that microcode revision by a BIOS update, download the microcode file.)

Then verify the integrity of the downloaded file:
Code:
% ./cpupdate -I -f /home/myname/Downloads/cpu206C2_plat03_ver0000001D_2015-08-04_PRD_F7DC758B.bin
  Blob 1 of 1 headers info:
    ucode rev  0x0000001d
-> Family: 06  Model: 2C  Stepping: 02
%
If there is no complaint (checksums etc) and the data matches the processor, then you can do the actual processor update with...
Code:
# ./cpupdate -w -U /home/myname/Downloads/cpu206C2_plat03_ver0000001D_2015-08-04_PRD_F7DC758B.bin
(Note: Remove the -w option to only simulate the update process; the output will reflect this accordingly.)
If you want to avoid having to configure every computer individually, just save the file in Intel's Family-Model-Stepping FF-MM-SS scheme, in this case "06-2c-02".
Then you can use just the directory containing the update files as parameter, like in the sample rc file:
Code:
# ./cpupdate -vv -w -u /usr/local/share/microcodes/intel-ucode
Found CPU(s) from Intel
/dev/cpuctl0 identification successful!
Update filename: 06-2c-02!
File /usr/local/share/microcodes/intel-ucode/06-2c-02 contains 1 update blobs
Updated core 0 from microcode revision 0x001a to 0x001d
<snipped other cores' output>
#
Finally, if all is to your satisfaction, you can make the update changes permanent by adding a rc script to /etc/rc.d and adding a line to /etc/rc.conf:
Code:
cpupdate_enable="YES"
A sample rc script (rc.cpupdate) is included in the github repo. Verify that it matches your preferences, edit it and place it in /etc/rc.d/cpupdate. In particular you probably will want to replace the -vv option with the -q option to avoid the program spamming the screen with messages about cpu microcode uploading.
In the sample script, the microcode files being placed in /usr/local/share/microcodes/intel-ucode, and the executable in /usr/local/sbin/cpupdate.
As cpupdate requires the cpuctl kernel module being loaded, add to /boot/loader.conf:
Code:
cpuctl_load="YES"
(Note 1: If you want to use a particular file, not matching the Intel naming convention, you would instead use the -U option together with the complete path and file name.
(Note 2: This rc config above is probably not the best way, as I am no rc expert, and as long no update removes cpu features, it should not matter when in the system startup process the microcode gets updated. Expert comments and advice very welcome!)

If you discover bugs, experience difficulties, have questions or suggestions, I would appreciate if you'd leave a comment.
 

julian@

New Member
Developer

Thanks: 1
Messages: 2

#4
might I suggest that the most useful thing you could do now is either extend it using libfetch to actually go get the firmware itself or supply scripts to do the work you suggest in terms of firmware fetching.