Quantcast
Channel: CodeSection,代码区,Python开发技术文章_教程 - CodeSec
Viewing all articles
Browse latest Browse all 9596

Python 3 Utilities for Parsing Intel Microcode

$
0
0

A recent issue on a linux platform with an Intel CPU prompted me to check to see if there was a microcode patch available from Intel to fix the issue. This blog post provides the source code for some of the python utilities I wrote to assist me in determining if a microcode update was available for my particular issue or not.

Intel distributes microcode updates in the form of a text file consisting of groups of big endian 32-bit integers represented as hexadecimals. As an example, here is a portion of one such file:

/* Fri Nov 4 16:09:13 CST 2016 */
/* m02f0a15.inc */
0x00000001, 0x00000015, 0x08212002, 0x00000f0a,
0x63e49a0c, 0x00000001, 0x00000002, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xffffffe9, 0x80e0e61a, 0x7cb2c607, 0xbe1e2fc9,
0xacaf1526, 0x31514e28, 0x9252d426, 0xb999ebf8,
0x8469bb8a, 0x95e72fd2, 0x5f7c5472, 0x254adcf0,
0xf706b236, 0x21ef3efb, 0x82d05526, 0x8b10bd77,
0x268ab8bd, 0x929739a5, 0x0f180e02, 0x3ad1cc5a,
0x23a10814, 0xbc4257f8, 0x026ded8d, 0x84bf45be,
0xe13e69f3, 0xbb0edf16, 0x85218fd2, 0x898af4e1,
0xcd635f26, 0x846ab0c6, 0x85a5d5cd, 0x077b4a16,
0x71514de0, 0xbff893a6, 0x47536ab0, 0x1fc4b546,
0x906f4b85, 0xc1f997d5, 0x0ba4b594, 0xa823eb50,

The first 16 integers (48 bytes) represent a standard microcode header which is fully documented in Section 9.11 (Microcode Update Facilities) of the Intel 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A: System Programming Guide, Part 1 .

Here is Table 9-6 from that section:


Python 3 Utilities for Parsing Intel Microcode
Python 3 Utilities for Parsing Intel Microcode

This table also details an extended header (> 48 bytes, starting with the field named Update Data ) which does not form part of this blog post.

Here is a simple Python script which converts the downloaded microcode.dat ASCII file and converts it into a little endian binary file suitable for use on a Linux system which supports loading microcode updates.

#!/usr/bin/python3
#
# Author: Finnbarr P. Murphy
# License: BSD
# Date: November 2016
# Usage: scriptname microcode.dat microcode.bin
#
import sys
import binascii
def convert2int(sval) :
sval = sval.replace('\t','').replace('0x','').replace(' ','')
return int.from_bytes(binascii.unhexlify(sval), 'little')
if len(sys.argv) != 3 :
print("ERROR: An input and output filename is required")
exit(1)
try :
infile = open(sys.argv[1], "r")
except IOError :
print("ERROR: Failed to open input file")
exit(1)
try :
outfile = open(sys.argv[2], "wb")
except IOError :
print("ERROR: Failed to open output file")
infile.close()
exit(2)
for line in infile :
if line[0] == '/' :
continue
hvals = line.split(',')
for hval in hvals :
if hval == '\r\n' or hval == '\n' or hval == '\r' :
continue
outfile.write(bytes.fromhex('%0.8X' % convert2int(hval)))
infile.close()
outfile.close()
exit(0)

Note that this script does not break the individual microcode updates into individual files as some tools such as iucode_tool do. This functionality could easily be added if desired.

The following script takes the downloaded file and outputs a line of information for each microcode header found in the file. Note that the script only parses the standard microcode header and not any extended headers. Functionality to parse any extended headers found in the file could easily be added if desired but I did not include such code as I had no need for this information.

#!/usr/bin/python3
#
# Author: Finnbarr P. Murphy
# License: BSD
# Date: November 2016
# Usage: scriptname < microcode.dat
#
import sys
import binascii
import re
def CpuFamily(sig) :
fam = (sig >> 8) & 0xF
if fam == 0xF :
fam += (sig >> 20) & 0xFF
return fam
def CpuModel(sig) :
fam = CpuFamily(sig)
model = (sig >> 4) & 0xF
if fam >= 0x6 :
model += ((sig >> 16) & 0xF) << 4
return model
def CpuStepping(sig) :
return sig & 0xF
def convert2int(sval) :
sval = sval.replace('\t','').replace('0x','').replace(' ','')
# return int.from_bytes(binascii.unhexlify(sval), 'little')
return int(sval, 16)
ints = 0
outline = ""
total = 0
matched = 0
datestr = "[A-Z][a-z]{2}\ [A-Z][a-z]{2}\ \d{1,2}\ \d{2}:\d{2}:\d{2}\ [A-Z]{3}\ \d{4}"
for line in sys.stdin:
if line[0] == '/' :
if line[1] != '*' :
continue
line = line.replace('\n','').replace('\r','').replace('/*','').replace('*/','')
if not matched :
match = re.search(datestr, line)
if match is not None :
matched = 1
print("Release Date: {0}".format(line.strip()))
print("\nDate Sig F/M/S Flags Datasize Name\n")
continue
if outline :
print("{0} {1}".format(outline, name))
total += 1
outline = ""
name = line.upper().replace('.INC','')
ints = 0
continue
hvals = line.split(',')
for hval in hvals:
if hval == '\r\n' or hval == '\r' or hval == '\n' :
continue
if ints == 2 : # date
outline += "{0:s}-{1:s}-{2:s}".format(hval[7:], hval[3:5], hval[5:7])
elif ints == 3 : # signature
sig = convert2int(hval)
fms = " {0:d}/{1:d}/{2:d}".format(CpuFamily(sig), CpuModel(sig), CpuStepping(sig))
outline += fms.ljust(12)
elif ints == 6 : # processor flags
procflags = convert2int(hval)
outline += " {0:08b}".format(procflags)
elif ints == 7 : # data size
datasize = convert2int(hval)
if datasize == 0 :
datasize = 2000
outline += " 0x{0:06X}".format(datasize)
ints += 1
print("\nTotal: {0}".format(total))
exit(0)

Note that the above script does not elegantly handle any errors it encounters when invoked. I leave it up to you the reader to modify the script to make it more robust.

Here is the output generated by the above script when run against the latest Intel Linux microcode (November 4th, 2016) download:

Release Date: Fri Nov 4 16:09:13 CST 2016
Date Sig F/M/S Flags Datasize Name
2002-08-21 15/0/10 00000010 0x0007D0 M02F0A15
2004-08-26 15/2/5 00010000 0x0007D0 M10F252C
1999-06-28 6/5/3 00000001 0x0007D0 MU165310
2001-02-20 6/11/1 00100000 0x0007D0 MU16B11D
2003-06-04 15/2/7 00001000 0x0007D0 M08F2739
1999-05-05 6/6/10 00001000 0x0007D0 MU166A0D
2002-07-16 15/0/10 00000100 0x0007D0 M04F0A14
2000-03-06 6/10/1 00000100 0x0007D0 MU26A101
1999-05-25 6/5/0 00000010 0x0007D0 MU165041
2005-04-21 15/4/9 10111101 0x0007D0 MBDF4903
1999-09-21 6/8/1 00001000 0x0007D0 MU16810F
1998-06-10 6/3/2 00000000 0x0007D0 MU163202
2000-05-05 6/8/6 00000001 0x0007D0 MU168607
2004-11-09 6/9/5 00100000 0x0007D0 M2069507
1999-05-05 6/6/13 00100000 0x0007D0 MU166D07
1999-05-25 6/5/0 00001000 0x0007D0 MU165045
2004-08-11 15/2/9 00001000 0x0007D0 M08F292F
2004-10-17 6/13/6 00100000 0x0007D0 M206D618
2002-01-10 6/11/4 00010000 0x0007D0 MU16B401
2005-04-21 15/3/3 00001101 0x0007D0 M0DF330C
2000-01-10 6/10/0 00000100 0x0007D0 MU26A003
1999-05-20 6/5/3 00000100 0x0007D0 MU26530B
2000-05-04 6/8/6 00000010 0x0007D0 MU16860A
2006-07-14 15/6/8 00100010 0x0007D0 M22F6809
1999-05-05 6/6/5 00010000 0x0007D0 MU166503
2004-05-11 15/3/2 00001101 0x0007D0 M0DF320A
2004-11-09 6/9/5 00010000 0x0007D0 M1069507
2001-02-15 6/11/1 00010000 0x0007D0 MU16B11C
2000-05-04 6/8/6 00000100 0x0007D0 MU268602
2004-08-11 15/2/5 00000010 0x0007D0 M02F252A
2003-05-02 15/1/2 00000100 0x0007D0 M04F122E
1999-09-21 6/8/1 00000100 0x0007D0 MU268110
1999-09-21 6/8/1 00100000 0x0007D0 MU16810E
2004-08-11 15/2/9 00000100 0x0007D0 M04F292E
1999-05-25 6/5/0 00000001 0x0007D0 MU165040
2000-12-07 6/8/10 10000000 0x0007D0 MU168A05
2004-08-11 15/2/9 00000010 0x0007D0 M02F292D
1999-05-05 6/6/10 00000010 0x0007D0 MU166A0C
2005-12-14 15/4/10 01011100 0x0007D0 M5CF4A04
2002-01-11 6/11/4 00100000 0x0007D0 MU16B402
1999-05-18 6/5/3 00000010 0x0007D0 MU16530C
1999-10-15 6/8/3 00001000 0x0007D0 MU168308
1999-03-12 6/6/13 00001000 0x0007D0 MU166D06
2003-06-05 15/2/4 00000010 0x0007D0 M02F241F
2003-06-04 15/2/7 00000100 0x0007D0 M04F2737
1999-09-10 6/7/3 00000100 0x0007D0 MU26732E
1999-03-12 6/6/13 00000010 0x0007D0 MU166D05
2000-11-02 6/8/10 00010000 0x0007D0 MU168A01
1999-09-21 6/8/1 00000001 0x0007D0 MU16810D
1999-05-12 6/5/2 00000100 0x0007D0 MU26522B
2000-12-07 6/8/10 00100000 0x0007D0 MU168A04
2004-11-09 6/9/5 10000000 0x0007D0 M8069547
2000-05-04 6/8/6 10000000 0x0007D0 MU16860C
2003-06-04 15/2/7 00000010 0x0007D0 M02F2738
2005-04-21 15/4/3 10011101 0x0007D0 M9DF4305
1999-05-12 6/5/2 00000001 0x0007D0 MU16522A
2004-08-05 15/2/6 00000010 0x0007D0 M02F2610
2003-06-10 15/2/4 00010000 0x0007D0 M10F2421
2000-11-15 15/0/7 00000010 0x0007D0 2F0708
1999-05-17 6/5/2 00000010 0x0007D0 MU16522C
1999-05-18 6/5/3 00001000 0x0007D0 MU16530D
2002-07-16 15/0/10 00000001 0x0007D0 M01F0A13
1999-05-05 6/6/10 00100000 0x0007D0 MU166A0B
1999-10-15 6/8/3 00100000 0x0007D0 MU168307
1998-08-11 6/7/1 00000100 0x0007D0 MU267114
1999-09-21 6/8/1 00010000 0x0007D0 MU168111
2005-06-10 15/4/10 01011101 0x0007D0 M5DF4A02
2002-07-16 15/0/7 00000001 0x0007D0 M01F0712
2003-06-05 15/2/4 00000100 0x0007D0 M04F241E
1999-09-22 6/7/2 00000100 0x0007D0 MU267238
1999-05-05 6/6/0 00000001 0x0007D0 MU16600A
1999-05-25 6/5/1 00000001 0x0007D0 MU165140
2000-05-05 6/8/6 00010000 0x0007D0 MU168608
2004-08-11 15/2/5 00000001 0x0007D0 M01F2529
2004-08-11 15/2/5 00000100 0x0007D0 M04F252B
2010-10-03 6/15/11 00100000 0x000FD0 M206FBBA
2005-04-22 15/4/1 10111101 0x0013D0 MBDF4117
2010-10-03 6/15/11 00001000 0x000FD0 M086FBBB
2010-09-30 6/15/6 00000001 0x000FD0 M16F6D0
2009-08-25 6/28/10 00000100 0x0013D0 M04106CA107
2009-08-25 6/28/10 00000001 0x0013D0 M01106CA107
2010-09-29 6/23/7 00010000 0x000FD0 M101067770A
2010-10-03 6/15/11 10000000 0x000FD0 M806FBBA
2005-04-21 15/4/4 10011101 0x000BD0 M9DF4406
2005-04-21 15/4/7 10011101 0x000BD0 M9DF4703
2005-06-30 15/4/8 01011111 0x000BD0 M5FF4807
2005-12-15 15/6/4 00000001 0x000BD0 M01F6402
2010-10-04 6/22/1 10000000 0x000FD0 M801066144
2010-09-29 6/23/6 00000001 0x000FD0 M011067660F
2010-10-01 6/15/6 00000100 0x000FD0 M46F6D2
2010-09-29 6/23/6 10000000 0x000FD0 M801067660F
2005-12-15 15/6/2 00000100 0x000BD0 M04F620F
2010-10-02 6/15/13 00100000 0x000FD0 M206FDA4
2010-10-03 6/15/11 01000000 0x000FD0 M406FBBC
2010-10-02 6/15/13 00000001 0x000FD0 M16FDA4
2009-04-10 6/28/2 00000001 0x0013D0 M01106C2217
2010-10-03 6/15/11 00010000 0x000FD0 M106FBBA
2005-12-23 15/6/4 00110100 0x000BD0 M34F6404
2010-09-29 6/23/6 00010000 0x000FD0 M101067660F
2009-04-10 6/28/2 00000100 0x0013D0 M04106C2218
2009-08-25 6/28/10 00010000 0x0013D0 M10106CA107
2009-04-10 6/28/2 00001000 0x0013D0 M08106C2219
2010-10-02 6/15/13 10000000 0x000FD0 M806FDA4
2005-04-21 15/4/1 00000010 0x0013D0 M02F4116
2005-11-15 6/14/8 00100000 0x000FD0 M206E839
2010-10-03 6/15/11 00000001 0x000FD0 M016FBBA
2006-05-01 6/14/12 00100000 0x000FD0 M206EC54
2010-10-03 6/15/11 00000100 0x000FD0 M046FBBC
2009-08-25 6/28/10 00001000 0x0013D0 M08106CA107
2009-10-23 6/38/1 00000001 0x0013D0 M0120661104
2010-10-04 6/22/1 00000010 0x000FD0 M021066142
2010-10-02 6/15/2 00000001 0x000FD0 M16F25D
2006-04-26 15/6/5 00000001 0x0007D0 M01F6508
2010-10-01 6/15/6 00100000 0x000FD0 M206F6D1
2006-05-08 15/4/8 00000001 0x000BD0 M01F480C
2005-04-21 15/3/4 00011101 0x001BD0 M1DF3417
2010-10-02 6/15/7 00010000 0x000FD0 M106F76A
2006-09-12 6/14/12 10000000 0x000FD0 M806EC59
2010-10-02 6/15/2 00100000 0x000FD0 M206F25C
2010-10-02 6/15/7 01000000 0x000FD0 M406F76B
2008-01-15 15/4/8 00000010 0x000BD0 M02F480E
2011-07-18 6/38/1 00000010 0x0013D0 M0220661105_CV
2010-10-02 6/15/10 10000000 0x000FD0 M806FA95
2010-10-04 6/22/1 00000001 0x000FD0 M011066143
2013-08-20 6/30/5 00010011 0x001BD0 M13106E5_00000007
2014-05-29 6/62/4 11101101 0x0033D0 MED306E4_00000428
2010-09-28 6/23/10 10100000 0x001FD0 MA01067AA0B
2013-06-26 6/37/2 00010010 0x001FD0 M1220652_0000000E
2013-06-21 6/26/5 00000011 0x0027D0 M03106A5_00000019
2010-09-28 6/23/10 00010001 0x001FD0 M111067AA0B
2013-06-17 6/45/7 01101101 0x0043D0 M6D206D7_00000710
2013-06-28 6/37/5 10010010 0x000BD0 M9220655_00000004
2013-06-21 6/26/4 00000011 0x0037D0 M03106A4_00000012
2013-06-19 6/62/6 11101101 0x002BD0 MED306E6_00000600
2012-05-22 6/45/6 01101101 0x003FD0 M6D206D6_00000619
2013-06-12 6/42/7 00010010 0x0027D0 M12206A7_00000029
2014-05-29 6/62/7 11101101 0x003BD0 MED306E7_0000070D
2015-02-26 6/58/9 00010010 0x002FD0 M12306A9_0000001C
2016-10-07 6/79/1 11101111 0x0063D0 MEF406F1_0B00001F
2016-06-22 6/78/3 11000000 0x017BD0 MC0406E3_0000009D_0000009E
2016-04-29 6/61/4 11000000 0x0043D0 MC0306D4_00000024
2016-04-01 6/69/1 01110010 0x004FD0 M7240651_0000001F
2016-04-01 6/70/1 00110010 0x005FD0 M3240661_00000016
2016-04-29 6/71/1 00100010 0x002BD0 M2240671_00000016
2015-12-12 6/86/2 00010000 0x006FD0 M1050662_0000000F
2016-06-07 6/63/4 10000000 0x003BD0 M80306F4_0000000D
2016-06-22 6/94/3 00110110 0x017BD0 M36506E3_0000009D_0000009E
2016-03-16 6/60/3 00110010 0x0057D0 M32306C3_00000020
2016-10-07 6/63/2 01101111 0x007FD0 M6F306F2_00000039
2013-06-18 6/47/2 00000101 0x0033D0 M05206F2_00000037
2010-09-28 6/23/10 01000100 0x001FD0 M441067AA0B
2010-09-29 6/23/6 01000000 0x000FD0 M401067660F
2010-09-30 6/29/1 00001000 0x000FD0 M08106D129
2010-09-29 6/23/6 00000100 0x000FD0 M041067660F
2016-06-02 6/86/4 00010000 0x0053D0 M1050664_0F00000A
Total: 155

The first column is the individual microcode release date, the second column is the processor family, model and stepping which were extracted from the Processor Signature field, the third column represents processor type bits extracted from the Processor Flag field, the next column is the size of the microcode code in bytes, and the final column is the identification string used by Intel.

Well, that is all for now. The source code I have provided above should be enough to enable you to develop your own Python tool(s) to slice and dice the Intel microcode file in whatever manner you wish. Both scripts ware developed using Python 3.5 on windows 10 using the Subsystem for Linux; thus there is no guarantee that the code will work without modification on Python 2.7.

Enjoy the holiday season and Merry Christmas to all my readers.


Viewing all articles
Browse latest Browse all 9596

Trending Articles