diff mbox

[U-Boot,1/8] x86: Add a script to process Intel microcode files

Message ID 1418602541-25144-2-git-send-email-sjg@chromium.org
State Superseded
Delegated to: Simon Glass
Headers show

Commit Message

Simon Glass Dec. 15, 2014, 12:15 a.m. UTC
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

Comments

Simon Glass Dec. 15, 2014, 2:51 a.m. UTC | #1
Hi,

On 14 December 2014 at 17:15, 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>
> ---
>
>  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]

This doesn't work - the endianness is wrong:

 val = mcode.words[i]
        if i > 12:
            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')
> +        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)
> --
> 2.2.0.rc0.207.ga3a616c
>

Regards,
Simon
Bin Meng Dec. 15, 2014, 5:24 a.m. UTC | #2
Hi Simon,

On Mon, Dec 15, 2014 at 8:15 AM, 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>
> ---
>
>  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)
> --
> 2.2.0.rc0.207.ga3a616c
>

Is there specific microcode file format this tool expects? I always
get 'error: You must specify a microcode file' message.

$ ./tools/microcode-tool.py create M0220661105.h
Usage: microcode-tool.py [options] 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


And what is the [options] parameters for?

Regards,
Bin
Simon Glass Dec. 15, 2014, 5:28 a.m. UTC | #3
Hi Bin,

On Dec 14, 2014 10:24 PM, "Bin Meng" <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Mon, Dec 15, 2014 at 8:15 AM, 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>
> > ---
> >
> >  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)
> > --
> > 2.2.0.rc0.207.ga3a616c
> >
>
> Is there specific microcode file format this tool expects? I always
> get 'error: You must specify a microcode file' message.
>
> $ ./tools/microcode-tool.py create M0220661105.h
> Usage: microcode-tool.py [options] 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
>
>
> And what is the [options] parameters for?

Use -h to see that. It needs the microcode.dat file. I need to update the
help. The output file goes in the right place automatically. Use the model
number of your chip as the model.

Regards,
Simon
diff mbox

Patch

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)