#!/usr/bin/env python3# SPDX-License-Identifier: GPL-2.0import argparseimport reimport shutilimport subprocessimport sysimport os script = os.path.relpath(__file__) DESCRIPTION = f"""For Intel CPUs, update the microcode revisions that determineX86_BUG_OLD_MICROCODE. This script is intended to be run in response to releases of theofficial Intel microcode GitHub repository:https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files.git It takes the Intel microcode files as input and uses iucode-tool toextract the revision information. It prints the output in the formatexpected by intel-ucode-defs.h. Usage: ./{script} /path/to/microcode/files > /path/to/intel-ucode-defs.h Typically, someone at Intel would see a new public release, wait for atleast three months to ensure the update is stable, run this script torefresh the intel-ucode-defs.h file, and send a patch upstream to updatethe mainline and stable versions. Any exception to this process should be supported with an appropriatejustification.""" SIG_RE = re.compile(r'sig (0x[0-9a-fA-F]+)')PFM_RE = re.compile(r'pf_mask (0x[0-9a-fA-F]+)')REV_RE = re.compile(r'rev (0x[0-9a-fA-F]+)') # Functions to extract family, model, and steppingdef bits(val, bottom, top): mask = (1 << (top + 1 - bottom)) - 1 return (val >> bottom) & mask def family(sig): if bits(sig, 8, 11) == 0xf: return bits(sig, 8, 11) + bits(sig, 20, 27) return bits(sig, 8, 11) def model(sig): return bits(sig, 4, 7) | (bits(sig, 16, 19) << 4) def step(sig): return bits(sig, 0, 3) class Ucode: def __init__(self, sig, pfm, rev): self.family = family(sig) self.model = model(sig) self.steppings = 1 << step(sig) self.platforms = pfm self.rev = rev self.key = (self.family, self.model, self.steppings, self.platforms) def __eq__(self, other): return self.key == other.key def __hash__(self): return hash(self.key) def __str__(self): return "{ .flags = X86_CPU_ID_FLAG_ENTRY_VALID, .vendor = X86_VENDOR_INTEL, .family = 0x%x, .model = 0x%02x, .steppings = 0x%04x, .platform_mask = 0x%02x, .driver_data = 0x%x }," % \ (self.family, self.model, self.steppings, self.platforms, self.rev) def main(): parser = argparse.ArgumentParser(description=DESCRIPTION, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('ucode_files', nargs='+', help='Path(s) to the microcode files') args = parser.parse_args() # Process the microcode files using iucode-tool iucode_tool = shutil.which("iucode-tool") or shutil.which("iucode_tool") if iucode_tool is None: print("Error: iucode-tool not found, please install it", file=sys.stderr) sys.exit(1) cmd = [iucode_tool, '--list-all'] + args.ucode_files result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: print("Error: iucode-tool ran into an error, exiting", file=sys.stderr) if result.stderr: print(result.stderr, file=sys.stderr, end='') sys.exit(1) ucodes = set() # Parse the output of iucode-tool for line in result.stdout.splitlines(): sig_match = SIG_RE.search(line) pfm_match = PFM_RE.search(line) rev_match = REV_RE.search(line) if not (sig_match and pfm_match and rev_match): continue sig = int(sig_match.group(1), 16) pfm = int(pfm_match.group(1), 16) rev = int(rev_match.group(1), 16) debug_rev = bits(rev, 31, 31) if debug_rev != 0: print("Error: Debug ucode file found, exiting", file=sys.stderr) sys.exit(1) ucodes.add(Ucode(sig, pfm, rev)) if not ucodes: print("Error: No valid microcode files found, exiting", file=sys.stderr) sys.exit(1) # Sort and print the microcode entries print("/* SPDX-License-Identifier: GPL-2.0 */") print("/* Auto-generated by scripts/update-intel-ucode-defs.py */") for u in sorted(ucodes, key=lambda x: x.key): print(u) if __name__ == "__main__": main()
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
import argparse
import re
import shutil
import subprocess
import sys
import os
script = os.path.relpath(__file__)
DESCRIPTION = f"""
For Intel CPUs, update the microcode revisions that determine
X86_BUG_OLD_MICROCODE.
This script is intended to be run in response to releases of the
official Intel microcode GitHub repository:
https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files.git
It takes the Intel microcode files as input and uses iucode-tool to
extract the revision information. It prints the output in the format
expected by intel-ucode-defs.h.
Usage:
./{script} /path/to/microcode/files > /path/to/intel-ucode-defs.h
Typically, someone at Intel would see a new public release, wait for at
least three months to ensure the update is stable, run this script to
refresh the intel-ucode-defs.h file, and send a patch upstream to update
the mainline and stable versions.
Any exception to this process should be supported with an appropriate
justification.
"""
SIG_RE = re.compile(r'sig (0x[0-9a-fA-F]+)')
PFM_RE = re.compile(r'pf_mask (0x[0-9a-fA-F]+)')
REV_RE = re.compile(r'rev (0x[0-9a-fA-F]+)')
# Functions to extract family, model, and stepping
def bits(val, bottom, top):
mask = (1 << (top + 1 - bottom)) - 1
return (val >> bottom) & mask
def family(sig):
if bits(sig, 8, 11) == 0xf:
return bits(sig, 8, 11) + bits(sig, 20, 27)
return bits(sig, 8, 11)
def model(sig):
return bits(sig, 4, 7) | (bits(sig, 16, 19) << 4)
def step(sig):
return bits(sig, 0, 3)
class Ucode:
def __init__(self, sig, pfm, rev):
self.family = family(sig)
self.model = model(sig)
self.steppings = 1 << step(sig)
self.platforms = pfm
self.rev = rev
self.key = (self.family, self.model, self.steppings, self.platforms)
def __eq__(self, other):
return self.key == other.key
def __hash__(self):
return hash(self.key)
def __str__(self):
return "{ .flags = X86_CPU_ID_FLAG_ENTRY_VALID, .vendor = X86_VENDOR_INTEL, .family = 0x%x, .model = 0x%02x, .steppings = 0x%04x, .platform_mask = 0x%02x, .driver_data = 0x%x }," % \
(self.family, self.model, self.steppings, self.platforms, self.rev)
def main():
parser = argparse.ArgumentParser(description=DESCRIPTION,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('ucode_files', nargs='+', help='Path(s) to the microcode files')
args = parser.parse_args()
# Process the microcode files using iucode-tool
iucode_tool = shutil.which("iucode-tool") or shutil.which("iucode_tool")
if iucode_tool is None:
print("Error: iucode-tool not found, please install it", file=sys.stderr)
sys.exit(1)
cmd = [iucode_tool, '--list-all'] + args.ucode_files
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print("Error: iucode-tool ran into an error, exiting", file=sys.stderr)
if result.stderr:
print(result.stderr, file=sys.stderr, end='')
sys.exit(1)
ucodes = set()
# Parse the output of iucode-tool
for line in result.stdout.splitlines():
sig_match = SIG_RE.search(line)
pfm_match = PFM_RE.search(line)
rev_match = REV_RE.search(line)
if not (sig_match and pfm_match and rev_match):
continue
sig = int(sig_match.group(1), 16)
pfm = int(pfm_match.group(1), 16)
rev = int(rev_match.group(1), 16)
debug_rev = bits(rev, 31, 31)
if debug_rev != 0:
print("Error: Debug ucode file found, exiting", file=sys.stderr)
sys.exit(1)
ucodes.add(Ucode(sig, pfm, rev))
if not ucodes:
print("Error: No valid microcode files found, exiting", file=sys.stderr)
sys.exit(1)
# Sort and print the microcode entries
print("/* SPDX-License-Identifier: GPL-2.0 */")
print("/* Auto-generated by scripts/update-intel-ucode-defs.py */")
for u in sorted(ucodes, key=lambda x: x.key):
print(u)
if __name__ == "__main__":
main()