Message ID | 1418706162-31354-2-git-send-email-sjg@chromium.org |
---|---|
State | Superseded |
Delegated to: | Simon Glass |
Headers | show |
Hi Simon, On Tue, Dec 16, 2014 at 1:02 PM, Simon Glass <sjg@chromium.org> wrote: > Intel delivers microcode updates in a microcode.dat file which must be > split up into individual files for each CPU. Add a tool which performs > this task. It can list available microcode updates for each model and > produce a new microcode update in U-Boot's .dtsi format. > > Signed-off-by: Simon Glass <sjg@chromium.org> > --- > > Changes in v2: > - Add function comments > - Fix problem with specifying the full microcode filename > - Allow 'list' command to display a list of matching microcode chunks > - Print a message when generating microcode > - Expand the help a little > - Print an error when an ambiguous microcode model is given > > tools/microcode-tool | 1 + > tools/microcode-tool.py | 245 ++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 246 insertions(+) > create mode 120000 tools/microcode-tool > create mode 100755 tools/microcode-tool.py > > diff --git a/tools/microcode-tool b/tools/microcode-tool > new file mode 120000 > index 0000000..8be8507 > --- /dev/null > +++ b/tools/microcode-tool > @@ -0,0 +1 @@ > +microcode-tool.py > \ No newline at end of file > diff --git a/tools/microcode-tool.py b/tools/microcode-tool.py > new file mode 100755 > index 0000000..5dbb0db > --- /dev/null > +++ b/tools/microcode-tool.py > @@ -0,0 +1,245 @@ > +#!/usr/bin/env python > +# > +# Copyright (c) 2014 Google, Inc > +# > +# SPDX-License-Identifier: GPL-2.0+ > +# > +# > +# Intel microcode update tool > + > +from optparse import OptionParser > +import os > +import re > +import struct > +import sys > + > +MICROCODE_DIR = 'arch/x86/dts/microcode' > + > +class Microcode: > + """Holds information about the microcode for a particular model of CPU. > + > + Attributes: > + name: Name of the CPU this microcode is for, including any version > + information (e.g. 'm12206a7_00000029') > + model: Model code string (this is cpuid(1).eax, e.g. '206a7') > + words: List of hex words containing the microcode. The first 16 words > + are the public header. > + """ > + def __init__(self, name, data): > + self.name = name > + # Convert data into a list of hex words > + self.words = [] > + for value in ''.join(data).split(','): > + hexval = value.strip() > + if hexval: > + self.words.append(int(hexval, 0)) > + > + # The model is in the 4rd hex word > + self.model = '%x' % self.words[3] > + > +def ParseFile(fname): > + """Parse a micrcode.dat file and return the component parts > + > + Args: > + fname: Filename to parse > + Returns: > + 3-Tuple: > + date: String containing date from the file's header > + license: List of text lines for the license file > + microcodes: List of Microcode objects from the file > + """ > + re_date = re.compile('/\* *(.* [0-9]{4}) *\*/$') > + re_license = re.compile('/[^-*+] *(.*)$') > + re_name = re.compile('/\* *(.*)\.inc *\*/', re.IGNORECASE) > + microcodes = {} > + license = [] > + date = '' > + data = [] > + name = None > + with open(fname) as fd: > + for line in fd: > + line = line.rstrip() > + m_date = re_date.match(line) > + m_license = re_license.match(line) > + m_name = re_name.match(line) > + if m_name: > + if name: > + microcodes[name] = Microcode(name, data) > + name = m_name.group(1).lower() > + data = [] > + elif m_license: > + license.append(m_license.group(1)) > + elif m_date: > + date = m_date.group(1) > + else: > + data.append(line) > + if name: > + microcodes[name] = Microcode(name, data) > + return date, license, microcodes > + > +def List(date, microcodes, model): > + """List the available microcode chunks > + > + Args: > + date: Date of the microcode file > + microcodes: Dict of Microcode objects indexed by name > + model: Model string to search for, or None > + """ > + print 'Date: %s' % date > + if model: > + mcode_list, tried = FindMicrocode(microcodes, model.lower()) > + print 'Matching models %s:' % (', '.join(tried)) > + else: > + print 'All models:' > + mcode_list = [microcodes[m] for m in microcodes.keys()] > + for mcode in mcode_list: > + print '%-20s: model %s' % (mcode.name, mcode.model) > + > +def FindMicrocode(microcodes, model): > + """Find all the microcode chunks which match the given model. > + > + This model is something like 306a9 (the value returned in eax from > + cpuid(1) when running on Intel CPUs). But we allow a partial match, > + omitting the last 1 or two characters to allow many families to have the > + same microcode. > + > + If the model name is ambiguous we return a list of matches. > + > + Args: > + microcodes: Dict of Microcode objects indexed by name > + model: String containing model name to find > + Returns: > + Tuple: > + List of matching Microcode objects > + List of abbreviations we tried > + """ > + # Allow a full name to be used > + mcode = microcodes.get(model) > + if mcode: > + return [mcode], [] > + > + tried = [] > + found = [] > + for i in range(3): > + abbrev = model[:-i] if i else model > + tried.append(abbrev) > + for mcode in microcodes.values(): > + if mcode.model.startswith(abbrev): > + found.append(mcode) > + if found: > + break > + return found, tried > + > +def CreateFile(date, license, mcode, outfile): > + """Create a microcode file in U-Boot's .dtsi format > + > + Args: > + date: String containing date of original microcode file > + license: List of text lines for the license file > + mcode: Microcode object to write > + outfile: Filename to write to ('-' for stdout) > + """ > + out = '''/*%s > + * --- > + * This is a device tree fragment. Use #include to add these properties to a > + * node. > + */ > + > +compatible = "intel,microcode"; > +intel,header-version = <%d>; > +intel,update-revision = <%#x>; > +intel,date-code = <%#x>; > +intel,processor-signature = <%#x>; > +intel,checksum = <%#x>; > +intel,loader-revision = <%d>; > +intel,processor-flags = <%#x>; > + > +/* The first 48-bytes are the public header which repeats the above data */ > +data = <%s > +\t>;''' > + words = '' > + for i in range(len(mcode.words)): > + if not (i & 3): > + words += '\n' > + val = mcode.words[i] > + # Change each word so it will be little-endian in the FDT > + # This data is needed before RAM is available on some platforms so we > + # cannot do an endianness swap on boot. > + val = struct.unpack("<I", struct.pack(">I", val))[0] > + words += '\t%#010x' % val > + > + # Take care to avoid adding a space before a tab > + text = '' > + for line in license: > + if line[0] == '\t': > + text += '\n *' + line > + else: > + text += '\n * ' + line > + args = [text] > + args += [mcode.words[i] for i in range(7)] > + args.append(words) > + if outfile == '-': > + print out % tuple(args) > + else: > + if not outfile: > + outfile = os.path.join(MICROCODE_DIR, mcode.name + '.dtsi') > + print >>sys.stderr, "Writing micrcode for '%s' to '%s'" % ( > + mcode.name, outfile) > + with open(outfile, 'w') as fd: > + print >>fd, out % tuple(args) > + > + > +commands = 'create,license,list'.split(',') > +parser = OptionParser() > +parser.add_option('-d', '--mcfile', type='string', action='store', > + help='Name of microcode.dat file') > +parser.add_option('-m', '--model', type='string', action='store', > + help='Model name to extract') > +parser.add_option('-o', '--outfile', type='string', action='store', > + help='Filename to use for output (- for stdout), default is' > + ' %s/<name>.dtsi' % MICROCODE_DIR) > +parser.usage += """ command > + > +Process an Intel microcode file (use -h for help). Commands: > + > + create Create microcode .dtsi file for a model > + list List available models in microcode file > + license Print the license > + > +Typical usage: > + > + ./tools/microcode-tool -d microcode.dat -m 306a create > + > +This will find the appropriate file and write it to %s.""" % MICROCODE_DIR > + > +(options, args) = parser.parse_args() > +if not args: > + parser.error('Please specify a command') > +cmd = args[0] > +if cmd not in commands: > + parser.error("Unknown command '%s'" % cmd) > + > +if not options.mcfile: > + parser.error('You must specify a microcode file') > +date, license, microcodes = ParseFile(options.mcfile) > + > +if cmd == 'list': > + List(date, microcodes, options.model) > +elif cmd == 'license': > + print '\n'.join(license) > +elif cmd == 'create': > + if not options.model: > + parser.error('You must specify a model to create') > + model = options.model.lower() > + mcode_list, tried = FindMicrocode(microcodes, model) > + if not mcode_list: > + parser.error("Unknown model '%s' (%s) - try 'list' to list" % > + (model, ', '.join(tried))) > + if len(mcode_list) > 1: > + parser.error("Ambiguous model '%s' (%s) matched %s - try 'list' to list" > + " or specify a particular file" % > + (model, ', '.join(tried), > + ', '.join([m.name for m in mcode_list]))) > + CreateFile(date, license, mcode_list[0], options.outfile) > +else: > + parser.error("Unknown command '%s'" % cmd) > -- $ ./tools/microcode-tool -d microcode.dat -m m0220661105_cv create Writing micrcode for 'm0220661105_cv' to 'arch/x86/dts/microcode/m0220661105_cv.dtsi' Traceback (most recent call last): File "./tools/microcode-tool", line 243, in <module> CreateFile(date, license, mcode_list[0], options.outfile) File "./tools/microcode-tool", line 188, in CreateFile with open(outfile, 'w') as fd: IOError: [Errno 2] No such file or directory: 'arch/x86/dts/microcode/m0220661105_cv.dtsi' My understanding is that when calling microcode-tool without '-o' option, a default dtsi file will be created in arch/x86/dts/microcode/ directory with the model number as the file name. However testing above shows some python error. Could you please either print some user friendly message, or just create a default dtsi file? Regards, Bin
Hi Bin, On 16 December 2014 at 01:04, Bin Meng <bmeng.cn@gmail.com> wrote: > Hi Simon, > > On Tue, Dec 16, 2014 at 1:02 PM, Simon Glass <sjg@chromium.org> wrote: >> Intel delivers microcode updates in a microcode.dat file which must be >> split up into individual files for each CPU. Add a tool which performs >> this task. It can list available microcode updates for each model and >> produce a new microcode update in U-Boot's .dtsi format. >> >> Signed-off-by: Simon Glass <sjg@chromium.org> >> --- >> >> Changes in v2: >> - Add function comments >> - Fix problem with specifying the full microcode filename >> - Allow 'list' command to display a list of matching microcode chunks >> - Print a message when generating microcode >> - Expand the help a little >> - Print an error when an ambiguous microcode model is given >> >> tools/microcode-tool | 1 + >> tools/microcode-tool.py | 245 ++++++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 246 insertions(+) >> create mode 120000 tools/microcode-tool >> create mode 100755 tools/microcode-tool.py >> >> diff --git a/tools/microcode-tool b/tools/microcode-tool >> new file mode 120000 >> index 0000000..8be8507 >> --- /dev/null >> +++ b/tools/microcode-tool >> @@ -0,0 +1 @@ >> +microcode-tool.py >> \ No newline at end of file >> diff --git a/tools/microcode-tool.py b/tools/microcode-tool.py >> new file mode 100755 >> index 0000000..5dbb0db >> --- /dev/null >> +++ b/tools/microcode-tool.py >> @@ -0,0 +1,245 @@ >> +#!/usr/bin/env python >> +# >> +# Copyright (c) 2014 Google, Inc >> +# >> +# SPDX-License-Identifier: GPL-2.0+ >> +# >> +# >> +# Intel microcode update tool >> + >> +from optparse import OptionParser >> +import os >> +import re >> +import struct >> +import sys >> + >> +MICROCODE_DIR = 'arch/x86/dts/microcode' >> + >> +class Microcode: >> + """Holds information about the microcode for a particular model of CPU. >> + >> + Attributes: >> + name: Name of the CPU this microcode is for, including any version >> + information (e.g. 'm12206a7_00000029') >> + model: Model code string (this is cpuid(1).eax, e.g. '206a7') >> + words: List of hex words containing the microcode. The first 16 words >> + are the public header. >> + """ >> + def __init__(self, name, data): >> + self.name = name >> + # Convert data into a list of hex words >> + self.words = [] >> + for value in ''.join(data).split(','): >> + hexval = value.strip() >> + if hexval: >> + self.words.append(int(hexval, 0)) >> + >> + # The model is in the 4rd hex word >> + self.model = '%x' % self.words[3] >> + >> +def ParseFile(fname): >> + """Parse a micrcode.dat file and return the component parts >> + >> + Args: >> + fname: Filename to parse >> + Returns: >> + 3-Tuple: >> + date: String containing date from the file's header >> + license: List of text lines for the license file >> + microcodes: List of Microcode objects from the file >> + """ >> + re_date = re.compile('/\* *(.* [0-9]{4}) *\*/$') >> + re_license = re.compile('/[^-*+] *(.*)$') >> + re_name = re.compile('/\* *(.*)\.inc *\*/', re.IGNORECASE) >> + microcodes = {} >> + license = [] >> + date = '' >> + data = [] >> + name = None >> + with open(fname) as fd: >> + for line in fd: >> + line = line.rstrip() >> + m_date = re_date.match(line) >> + m_license = re_license.match(line) >> + m_name = re_name.match(line) >> + if m_name: >> + if name: >> + microcodes[name] = Microcode(name, data) >> + name = m_name.group(1).lower() >> + data = [] >> + elif m_license: >> + license.append(m_license.group(1)) >> + elif m_date: >> + date = m_date.group(1) >> + else: >> + data.append(line) >> + if name: >> + microcodes[name] = Microcode(name, data) >> + return date, license, microcodes >> + >> +def List(date, microcodes, model): >> + """List the available microcode chunks >> + >> + Args: >> + date: Date of the microcode file >> + microcodes: Dict of Microcode objects indexed by name >> + model: Model string to search for, or None >> + """ >> + print 'Date: %s' % date >> + if model: >> + mcode_list, tried = FindMicrocode(microcodes, model.lower()) >> + print 'Matching models %s:' % (', '.join(tried)) >> + else: >> + print 'All models:' >> + mcode_list = [microcodes[m] for m in microcodes.keys()] >> + for mcode in mcode_list: >> + print '%-20s: model %s' % (mcode.name, mcode.model) >> + >> +def FindMicrocode(microcodes, model): >> + """Find all the microcode chunks which match the given model. >> + >> + This model is something like 306a9 (the value returned in eax from >> + cpuid(1) when running on Intel CPUs). But we allow a partial match, >> + omitting the last 1 or two characters to allow many families to have the >> + same microcode. >> + >> + If the model name is ambiguous we return a list of matches. >> + >> + Args: >> + microcodes: Dict of Microcode objects indexed by name >> + model: String containing model name to find >> + Returns: >> + Tuple: >> + List of matching Microcode objects >> + List of abbreviations we tried >> + """ >> + # Allow a full name to be used >> + mcode = microcodes.get(model) >> + if mcode: >> + return [mcode], [] >> + >> + tried = [] >> + found = [] >> + for i in range(3): >> + abbrev = model[:-i] if i else model >> + tried.append(abbrev) >> + for mcode in microcodes.values(): >> + if mcode.model.startswith(abbrev): >> + found.append(mcode) >> + if found: >> + break >> + return found, tried >> + >> +def CreateFile(date, license, mcode, outfile): >> + """Create a microcode file in U-Boot's .dtsi format >> + >> + Args: >> + date: String containing date of original microcode file >> + license: List of text lines for the license file >> + mcode: Microcode object to write >> + outfile: Filename to write to ('-' for stdout) >> + """ >> + out = '''/*%s >> + * --- >> + * This is a device tree fragment. Use #include to add these properties to a >> + * node. >> + */ >> + >> +compatible = "intel,microcode"; >> +intel,header-version = <%d>; >> +intel,update-revision = <%#x>; >> +intel,date-code = <%#x>; >> +intel,processor-signature = <%#x>; >> +intel,checksum = <%#x>; >> +intel,loader-revision = <%d>; >> +intel,processor-flags = <%#x>; >> + >> +/* The first 48-bytes are the public header which repeats the above data */ >> +data = <%s >> +\t>;''' >> + words = '' >> + for i in range(len(mcode.words)): >> + if not (i & 3): >> + words += '\n' >> + val = mcode.words[i] >> + # Change each word so it will be little-endian in the FDT >> + # This data is needed before RAM is available on some platforms so we >> + # cannot do an endianness swap on boot. >> + val = struct.unpack("<I", struct.pack(">I", val))[0] >> + words += '\t%#010x' % val >> + >> + # Take care to avoid adding a space before a tab >> + text = '' >> + for line in license: >> + if line[0] == '\t': >> + text += '\n *' + line >> + else: >> + text += '\n * ' + line >> + args = [text] >> + args += [mcode.words[i] for i in range(7)] >> + args.append(words) >> + if outfile == '-': >> + print out % tuple(args) >> + else: >> + if not outfile: >> + outfile = os.path.join(MICROCODE_DIR, mcode.name + '.dtsi') >> + print >>sys.stderr, "Writing micrcode for '%s' to '%s'" % ( >> + mcode.name, outfile) >> + with open(outfile, 'w') as fd: >> + print >>fd, out % tuple(args) >> + >> + >> +commands = 'create,license,list'.split(',') >> +parser = OptionParser() >> +parser.add_option('-d', '--mcfile', type='string', action='store', >> + help='Name of microcode.dat file') >> +parser.add_option('-m', '--model', type='string', action='store', >> + help='Model name to extract') >> +parser.add_option('-o', '--outfile', type='string', action='store', >> + help='Filename to use for output (- for stdout), default is' >> + ' %s/<name>.dtsi' % MICROCODE_DIR) >> +parser.usage += """ command >> + >> +Process an Intel microcode file (use -h for help). Commands: >> + >> + create Create microcode .dtsi file for a model >> + list List available models in microcode file >> + license Print the license >> + >> +Typical usage: >> + >> + ./tools/microcode-tool -d microcode.dat -m 306a create >> + >> +This will find the appropriate file and write it to %s.""" % MICROCODE_DIR >> + >> +(options, args) = parser.parse_args() >> +if not args: >> + parser.error('Please specify a command') >> +cmd = args[0] >> +if cmd not in commands: >> + parser.error("Unknown command '%s'" % cmd) >> + >> +if not options.mcfile: >> + parser.error('You must specify a microcode file') >> +date, license, microcodes = ParseFile(options.mcfile) >> + >> +if cmd == 'list': >> + List(date, microcodes, options.model) >> +elif cmd == 'license': >> + print '\n'.join(license) >> +elif cmd == 'create': >> + if not options.model: >> + parser.error('You must specify a model to create') >> + model = options.model.lower() >> + mcode_list, tried = FindMicrocode(microcodes, model) >> + if not mcode_list: >> + parser.error("Unknown model '%s' (%s) - try 'list' to list" % >> + (model, ', '.join(tried))) >> + if len(mcode_list) > 1: >> + parser.error("Ambiguous model '%s' (%s) matched %s - try 'list' to list" >> + " or specify a particular file" % >> + (model, ', '.join(tried), >> + ', '.join([m.name for m in mcode_list]))) >> + CreateFile(date, license, mcode_list[0], options.outfile) >> +else: >> + parser.error("Unknown command '%s'" % cmd) >> -- > > $ ./tools/microcode-tool -d microcode.dat -m m0220661105_cv create > Writing micrcode for 'm0220661105_cv' to > 'arch/x86/dts/microcode/m0220661105_cv.dtsi' > Traceback (most recent call last): > File "./tools/microcode-tool", line 243, in <module> > CreateFile(date, license, mcode_list[0], options.outfile) > File "./tools/microcode-tool", line 188, in CreateFile > with open(outfile, 'w') as fd: > IOError: [Errno 2] No such file or directory: > 'arch/x86/dts/microcode/m0220661105_cv.dtsi' > > My understanding is that when calling microcode-tool without '-o' > option, a default dtsi file will be created in arch/x86/dts/microcode/ > directory with the model number as the file name. However testing > above shows some python error. Could you please either print some user > friendly message, or just create a default dtsi file? I think it just needs to create the directory automatically. In my tree it already has this directory. The message seems OK to me though. I'll fix up the script a bit more. Regards, Simon
diff --git a/tools/microcode-tool b/tools/microcode-tool new file mode 120000 index 0000000..8be8507 --- /dev/null +++ b/tools/microcode-tool @@ -0,0 +1 @@ +microcode-tool.py \ No newline at end of file diff --git a/tools/microcode-tool.py b/tools/microcode-tool.py new file mode 100755 index 0000000..5dbb0db --- /dev/null +++ b/tools/microcode-tool.py @@ -0,0 +1,245 @@ +#!/usr/bin/env python +# +# Copyright (c) 2014 Google, Inc +# +# SPDX-License-Identifier: GPL-2.0+ +# +# +# Intel microcode update tool + +from optparse import OptionParser +import os +import re +import struct +import sys + +MICROCODE_DIR = 'arch/x86/dts/microcode' + +class Microcode: + """Holds information about the microcode for a particular model of CPU. + + Attributes: + name: Name of the CPU this microcode is for, including any version + information (e.g. 'm12206a7_00000029') + model: Model code string (this is cpuid(1).eax, e.g. '206a7') + words: List of hex words containing the microcode. The first 16 words + are the public header. + """ + def __init__(self, name, data): + self.name = name + # Convert data into a list of hex words + self.words = [] + for value in ''.join(data).split(','): + hexval = value.strip() + if hexval: + self.words.append(int(hexval, 0)) + + # The model is in the 4rd hex word + self.model = '%x' % self.words[3] + +def ParseFile(fname): + """Parse a micrcode.dat file and return the component parts + + Args: + fname: Filename to parse + Returns: + 3-Tuple: + date: String containing date from the file's header + license: List of text lines for the license file + microcodes: List of Microcode objects from the file + """ + re_date = re.compile('/\* *(.* [0-9]{4}) *\*/$') + re_license = re.compile('/[^-*+] *(.*)$') + re_name = re.compile('/\* *(.*)\.inc *\*/', re.IGNORECASE) + microcodes = {} + license = [] + date = '' + data = [] + name = None + with open(fname) as fd: + for line in fd: + line = line.rstrip() + m_date = re_date.match(line) + m_license = re_license.match(line) + m_name = re_name.match(line) + if m_name: + if name: + microcodes[name] = Microcode(name, data) + name = m_name.group(1).lower() + data = [] + elif m_license: + license.append(m_license.group(1)) + elif m_date: + date = m_date.group(1) + else: + data.append(line) + if name: + microcodes[name] = Microcode(name, data) + return date, license, microcodes + +def List(date, microcodes, model): + """List the available microcode chunks + + Args: + date: Date of the microcode file + microcodes: Dict of Microcode objects indexed by name + model: Model string to search for, or None + """ + print 'Date: %s' % date + if model: + mcode_list, tried = FindMicrocode(microcodes, model.lower()) + print 'Matching models %s:' % (', '.join(tried)) + else: + print 'All models:' + mcode_list = [microcodes[m] for m in microcodes.keys()] + for mcode in mcode_list: + print '%-20s: model %s' % (mcode.name, mcode.model) + +def FindMicrocode(microcodes, model): + """Find all the microcode chunks which match the given model. + + This model is something like 306a9 (the value returned in eax from + cpuid(1) when running on Intel CPUs). But we allow a partial match, + omitting the last 1 or two characters to allow many families to have the + same microcode. + + If the model name is ambiguous we return a list of matches. + + Args: + microcodes: Dict of Microcode objects indexed by name + model: String containing model name to find + Returns: + Tuple: + List of matching Microcode objects + List of abbreviations we tried + """ + # Allow a full name to be used + mcode = microcodes.get(model) + if mcode: + return [mcode], [] + + tried = [] + found = [] + for i in range(3): + abbrev = model[:-i] if i else model + tried.append(abbrev) + for mcode in microcodes.values(): + if mcode.model.startswith(abbrev): + found.append(mcode) + if found: + break + return found, tried + +def CreateFile(date, license, mcode, outfile): + """Create a microcode file in U-Boot's .dtsi format + + Args: + date: String containing date of original microcode file + license: List of text lines for the license file + mcode: Microcode object to write + outfile: Filename to write to ('-' for stdout) + """ + out = '''/*%s + * --- + * This is a device tree fragment. Use #include to add these properties to a + * node. + */ + +compatible = "intel,microcode"; +intel,header-version = <%d>; +intel,update-revision = <%#x>; +intel,date-code = <%#x>; +intel,processor-signature = <%#x>; +intel,checksum = <%#x>; +intel,loader-revision = <%d>; +intel,processor-flags = <%#x>; + +/* The first 48-bytes are the public header which repeats the above data */ +data = <%s +\t>;''' + words = '' + for i in range(len(mcode.words)): + if not (i & 3): + words += '\n' + val = mcode.words[i] + # Change each word so it will be little-endian in the FDT + # This data is needed before RAM is available on some platforms so we + # cannot do an endianness swap on boot. + val = struct.unpack("<I", struct.pack(">I", val))[0] + words += '\t%#010x' % val + + # Take care to avoid adding a space before a tab + text = '' + for line in license: + if line[0] == '\t': + text += '\n *' + line + else: + text += '\n * ' + line + args = [text] + args += [mcode.words[i] for i in range(7)] + args.append(words) + if outfile == '-': + print out % tuple(args) + else: + if not outfile: + outfile = os.path.join(MICROCODE_DIR, mcode.name + '.dtsi') + print >>sys.stderr, "Writing micrcode for '%s' to '%s'" % ( + mcode.name, outfile) + with open(outfile, 'w') as fd: + print >>fd, out % tuple(args) + + +commands = 'create,license,list'.split(',') +parser = OptionParser() +parser.add_option('-d', '--mcfile', type='string', action='store', + help='Name of microcode.dat file') +parser.add_option('-m', '--model', type='string', action='store', + help='Model name to extract') +parser.add_option('-o', '--outfile', type='string', action='store', + help='Filename to use for output (- for stdout), default is' + ' %s/<name>.dtsi' % MICROCODE_DIR) +parser.usage += """ command + +Process an Intel microcode file (use -h for help). Commands: + + create Create microcode .dtsi file for a model + list List available models in microcode file + license Print the license + +Typical usage: + + ./tools/microcode-tool -d microcode.dat -m 306a create + +This will find the appropriate file and write it to %s.""" % MICROCODE_DIR + +(options, args) = parser.parse_args() +if not args: + parser.error('Please specify a command') +cmd = args[0] +if cmd not in commands: + parser.error("Unknown command '%s'" % cmd) + +if not options.mcfile: + parser.error('You must specify a microcode file') +date, license, microcodes = ParseFile(options.mcfile) + +if cmd == 'list': + List(date, microcodes, options.model) +elif cmd == 'license': + print '\n'.join(license) +elif cmd == 'create': + if not options.model: + parser.error('You must specify a model to create') + model = options.model.lower() + mcode_list, tried = FindMicrocode(microcodes, model) + if not mcode_list: + parser.error("Unknown model '%s' (%s) - try 'list' to list" % + (model, ', '.join(tried))) + if len(mcode_list) > 1: + parser.error("Ambiguous model '%s' (%s) matched %s - try 'list' to list" + " or specify a particular file" % + (model, ', '.join(tried), + ', '.join([m.name for m in mcode_list]))) + CreateFile(date, license, mcode_list[0], options.outfile) +else: + parser.error("Unknown command '%s'" % cmd)
Intel delivers microcode updates in a microcode.dat file which must be split up into individual files for each CPU. Add a tool which performs this task. It can list available microcode updates for each model and produce a new microcode update in U-Boot's .dtsi format. Signed-off-by: Simon Glass <sjg@chromium.org> --- Changes in v2: - Add function comments - Fix problem with specifying the full microcode filename - Allow 'list' command to display a list of matching microcode chunks - Print a message when generating microcode - Expand the help a little - Print an error when an ambiguous microcode model is given tools/microcode-tool | 1 + tools/microcode-tool.py | 245 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 246 insertions(+) create mode 120000 tools/microcode-tool create mode 100755 tools/microcode-tool.py