
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 ---
tools/microcode-tool | 1 + tools/microcode-tool.py | 165 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 166 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..2f6a5f4 --- /dev/null +++ b/tools/microcode-tool.py @@ -0,0 +1,165 @@ +#!/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 + +MICROCODE_DIR = 'arch/x86/dts/microcode' + +class Microcode: + 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): + 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): + print 'Date: %s' % date + for name in sorted(microcodes.keys()): + print '%-20s: model %s' % (name, microcodes[name].model) + +def FindMicrocode(microcodes, model): + # Allow a full name to be used + mcode = microcodes.get(model) + if mcode: + return mcode + + tried = [] + 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): + return mcode, tried + return None, tried + +def CreateFile(date, license, mcode, outfile): + 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' + words += '\t%#010x' % mcode.words[i] + + # 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') + 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, Commands: + + create Create microcode .dtsi file for a model + list List available models in microcode file + license Print the license + make Make a U-Boot .dtsi file""" + +(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) +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, tried = FindMicrocode(microcodes, model) + if not mcode: + parser.error("Unknown model '%s' (%s) - try 'list' to list" % + (model, ', '.join(tried))) + CreateFile(date, license, mcode, options.outfile) +else: + parser.error("Unknown command '%s'" % cmd)