iPXE
Data Structures | Macros | Functions | Variables
ucode.c File Reference

Microcode updates. More...

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <ipxe/uaccess.h>
#include <ipxe/umalloc.h>
#include <ipxe/image.h>
#include <ipxe/cpuid.h>
#include <ipxe/msr.h>
#include <ipxe/mp.h>
#include <ipxe/timer.h>
#include <ipxe/ucode.h>

Go to the source code of this file.

Data Structures

union  ucode_vendor_id
 A CPU vendor string. More...
 
struct  ucode_vendor
 A CPU vendor. More...
 
struct  ucode_update
 A microcode update. More...
 
struct  ucode_summary
 A microcode update summary. More...
 

Macros

#define UCODE_MAX_HT   8
 Maximum number of hyperthread siblings. More...
 
#define UCODE_WAIT_MS   10
 Time to wait for a microcode update to complete. More...
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static const char * ucode_vendor_name (const union ucode_vendor_id *vendor)
 Get CPU vendor name (for debugging) More...
 
static int ucode_status (struct ucode_update *update, struct ucode_control *control, struct ucode_summary *summary, unsigned int id, int optional)
 Check status report. More...
 
static int ucode_update_all (struct image *image, struct ucode_update *update, struct ucode_summary *summary)
 Update microcode on all CPUs. More...
 
static void ucode_describe (struct image *image, size_t start, const struct ucode_vendor *vendor, const struct ucode_descriptor *desc, uint32_t platforms, struct ucode_update *update)
 Add descriptor to list (if applicable) More...
 
static int ucode_verify (struct image *image, size_t start, size_t len)
 Verify checksum. More...
 
static int ucode_parse_intel (struct image *image, size_t start, struct ucode_update *update)
 Parse Intel microcode image. More...
 
static int ucode_parse_amd (struct image *image, size_t start, struct ucode_update *update)
 Parse AMD microcode image. More...
 
static int ucode_parse (struct image *image, struct ucode_update *update)
 Parse microcode image. More...
 
static int ucode_exec (struct image *image)
 Execute microcode update. More...
 
static int ucode_probe (struct image *image)
 Probe microcode update image. More...
 
struct image_type ucode_image_type __image_type (PROBE_NORMAL)
 Microcode update image type. More...
 

Variables

static struct ucode_vendor ucode_intel
 Intel CPU vendor. More...
 
static struct ucode_vendor ucode_amd
 AMD CPU vendor. More...
 
static struct ucode_vendorucode_vendors []
 List of known CPU vendors. More...
 

Detailed Description

Microcode updates.

Definition in file ucode.c.

Macro Definition Documentation

◆ UCODE_MAX_HT

#define UCODE_MAX_HT   8

Maximum number of hyperthread siblings.

Microcode updates must not be performed on hyperthread siblings at the same time, since they share microcode storage.

Hyperthread siblings are always the lowest level of the CPU topology and correspond to the least significant bits of the APIC ID. We may therefore avoid collisions by performing the microcode updates in batches, with each batch targeting just one value for the least significant N bits of the APIC ID.

We assume that no CPUs exist with more than this number of hyperthread siblings. (This must be a power of two.)

Definition at line 60 of file ucode.c.

◆ UCODE_WAIT_MS

#define UCODE_WAIT_MS   10

Time to wait for a microcode update to complete.

Definition at line 63 of file ucode.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ ucode_vendor_name()

static const char* ucode_vendor_name ( const union ucode_vendor_id vendor)
static

Get CPU vendor name (for debugging)

Parameters
vendorCPU vendor
Return values
nameName

Definition at line 135 of file ucode.c.

135  {
136  static union {
137  union ucode_vendor_id vendor;
138  char text[ sizeof ( *vendor ) + 1 /* NUL */ ];
139  } u;
140 
141  /* Construct name */
142  memcpy ( &u.vendor, vendor, sizeof ( u.vendor ) );
143  u.text[ sizeof ( u.text ) - 1 ] = '\0';
144  return u.text;
145 }
static unsigned short vendor
Definition: davicom.c:128
A CPU vendor string.
Definition: ucode.c:66
void * memcpy(void *dest, const void *src, size_t len) __nonnull
union @17 u

References memcpy(), u, and vendor.

Referenced by ucode_describe(), and ucode_exec().

◆ ucode_status()

static int ucode_status ( struct ucode_update update,
struct ucode_control control,
struct ucode_summary summary,
unsigned int  id,
int  optional 
)
static

Check status report.

Parameters
updateMicrocode update
controlMicrocode update control
summaryMicrocode update summary
idAPIC ID
optionalStatus report is optional
Return values
rcReturn status code

Definition at line 157 of file ucode.c.

160  {
161  struct ucode_status status;
162  struct ucode_descriptor *desc;
163 
164  /* Sanity check */
165  assert ( id <= control->apic_max );
166 
167  /* Read status report */
168  copy_from_user ( &status, phys_to_user ( control->status ),
169  ( id * sizeof ( status ) ), sizeof ( status ) );
170 
171  /* Ignore empty optional status reports */
172  if ( optional && ( ! status.signature ) )
173  return 0;
174  DBGC ( update, "UCODE %#08x signature %#08x ucode %#08x->%#08x\n",
175  id, status.signature, status.before, status.after );
176 
177  /* Check CPU signature */
178  if ( ! status.signature ) {
179  DBGC2 ( update, "UCODE %#08x has no signature\n", id );
180  return -ENOENT;
181  }
182 
183  /* Check APIC ID is correct */
184  if ( status.id != id ) {
185  DBGC ( update, "UCODE %#08x wrong APIC ID %#08x\n",
186  id, status.id );
187  return -EINVAL;
188  }
189 
190  /* Check that maximum APIC ID was not exceeded */
191  if ( control->apic_unexpected ) {
192  DBGC ( update, "UCODE %#08x saw unexpected APIC ID %#08x\n",
193  id, control->apic_unexpected );
194  return -ERANGE;
195  }
196 
197  /* Check microcode was not downgraded */
198  if ( status.after < status.before ) {
199  DBGC ( update, "UCODE %#08x was downgraded %#08x->%#08x\n",
200  id, status.before, status.after );
201  return -ENOTTY;
202  }
203 
204  /* Check that expected updates (if any) were applied */
205  for ( desc = update->desc ; desc->signature ; desc++ ) {
206  if ( ( desc->signature == status.signature ) &&
207  ( status.after < desc->version ) ) {
208  DBGC ( update, "UCODE %#08x failed update %#08x->%#08x "
209  "(wanted %#08x)\n", id, status.before,
210  status.after, desc->version );
211  return -EIO;
212  }
213  }
214 
215  /* Update summary */
216  summary->count++;
217  if ( status.before < summary->low )
218  summary->low = status.before;
219  if ( status.after > summary->high )
220  summary->high = status.after;
221 
222  return 0;
223 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
struct ucode_descriptor * desc
Update descriptors (if being populated)
Definition: ucode.c:96
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
uint64_t desc
Microcode descriptor list physical address.
Definition: ucode.h:12
#define DBGC(...)
Definition: compiler.h:505
#define ENOENT
No such file or directory.
Definition: errno.h:514
userptr_t phys_to_user(unsigned long phys_addr)
Convert physical address to user pointer.
unsigned int count
Number of CPUs processed.
Definition: ucode.c:102
uint8_t status
Status.
Definition: ena.h:16
A microcode update descriptor.
Definition: ucode.h:75
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define ERANGE
Result too large.
Definition: errno.h:639
int32_t low
Lowest observed microcode version.
Definition: ucode.c:104
uint32_t control
Control.
Definition: myson.h:14
A microcode update status report.
Definition: ucode.h:89
#define DBGC2(...)
Definition: compiler.h:522
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
#define EIO
Input/output error.
Definition: errno.h:433
int32_t high
Highest observed microcode version.
Definition: ucode.c:106
uint32_t apic_max
Maximum expected APIC ID.
Definition: ucode.h:18

References apic_max, assert(), control, copy_from_user(), ucode_summary::count, DBGC, DBGC2, desc, ucode_update::desc, EINVAL, EIO, ENOENT, ENOTTY, ERANGE, ucode_summary::high, ucode_summary::low, phys_to_user(), and status.

◆ ucode_update_all()

static int ucode_update_all ( struct image image,
struct ucode_update update,
struct ucode_summary summary 
)
static

Update microcode on all CPUs.

Parameters
imageMicrocode image
updateMicrocode update
summaryMicrocode update summary to fill in
Return values
rcReturn status code

Definition at line 233 of file ucode.c.

235  {
236  struct ucode_control control;
237  struct ucode_vendor *vendor;
239  unsigned int max;
240  unsigned int i;
241  size_t len;
242  int rc;
243 
244  /* Initialise summary */
245  summary->count = 0;
246  summary->low = UCODE_VERSION_MAX;
247  summary->high = UCODE_VERSION_MIN;
248 
249  /* Allocate status reports */
250  max = mp_max_cpuid();
251  len = ( ( max + 1 ) * sizeof ( struct ucode_status ) );
252  status = umalloc ( len );
253  if ( ! status ) {
254  DBGC ( image, "UCODE %s could not allocate %d status reports\n",
255  image->name, ( max + 1 ) );
256  rc = -ENOMEM;
257  goto err_alloc;
258  }
259  memset_user ( status, 0, 0, len );
260 
261  /* Construct control structure */
262  memset ( &control, 0, sizeof ( control ) );
263  control.desc = virt_to_phys ( update->desc );
264  control.status = user_to_phys ( status, 0 );
265  vendor = update->vendor;
266  if ( vendor ) {
267  control.ver_clear = vendor->ver_clear;
268  control.ver_high = vendor->ver_high;
269  control.trigger_msr = vendor->trigger_msr;
270  } else {
271  assert ( update->count == 0 );
272  }
273  control.apic_max = max;
274 
275  /* Update microcode on boot processor */
277  if ( ( rc = ucode_status ( update, &control, summary,
278  mp_boot_cpuid(), 0 ) ) != 0 ) {
279  DBGC ( image, "UCODE %s failed on boot processor: %s\n",
280  image->name, strerror ( rc ) );
281  goto err_boot;
282  }
283 
284  /* Update microcode on application processors, avoiding
285  * simultaneous updates on hyperthread siblings.
286  */
287  build_assert ( ( UCODE_MAX_HT & ( UCODE_MAX_HT - 1 ) ) == 0 );
288  control.apic_mask = ( UCODE_MAX_HT - 1 );
289  for ( ; control.apic_test <= control.apic_mask ; control.apic_test++ ) {
291  mdelay ( UCODE_WAIT_MS );
292  }
293 
294  /* Check status reports */
295  summary->count = 0;
296  for ( i = 0 ; i <= max ; i++ ) {
297  if ( ( rc = ucode_status ( update, &control, summary,
298  i, 1 ) ) != 0 ) {
299  goto err_status;
300  }
301  }
302 
303  /* Success */
304  rc = 0;
305 
306  err_status:
307  err_boot:
308  ufree ( status );
309  err_alloc:
310  return rc;
311 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define max(x, y)
Definition: ath.h:39
struct ucode_descriptor * desc
Update descriptors (if being populated)
Definition: ucode.c:96
#define UCODE_VERSION_MIN
Minimum possible microcode version.
Definition: ucode.h:35
static unsigned short vendor
Definition: davicom.c:128
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
#define DBGC(...)
Definition: compiler.h:505
struct ucode_vendor * vendor
CPU vendor, if known.
Definition: ucode.c:88
A microcode update.
Definition: ucode.c:86
An executable image.
Definition: image.h:24
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:287
unsigned int count
Number of CPUs processed.
Definition: ucode.c:102
void mp_start_all(mp_func_t func, void *opaque)
Start a multiprocessor function on all application processors.
uint8_t status
Status.
Definition: ena.h:16
void memset_user(userptr_t userptr, off_t offset, int c, size_t len)
Fill user buffer with a constant byte.
#define ENOMEM
Not enough space.
Definition: errno.h:534
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define build_assert(condition)
Assert a condition at build time (after dead code elimination)
Definition: assert.h:76
A microcode update control.
Definition: ucode.h:45
unsigned int mp_max_cpuid(void)
Get maximum CPU identifier.
Definition: mp.c:58
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
int32_t low
Lowest observed microcode version.
Definition: ucode.c:104
uint32_t control
Control.
Definition: myson.h:14
unsigned int mp_boot_cpuid(void)
Get boot CPU identifier.
Definition: mp.c:43
#define UCODE_VERSION_MAX
Maximum possible microcode version.
Definition: ucode.h:38
A microcode update status report.
Definition: ucode.h:89
#define UCODE_MAX_HT
Maximum number of hyperthread siblings.
Definition: ucode.c:60
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition: timer.c:78
static __always_inline void ufree(userptr_t userptr)
Free external memory.
Definition: umalloc.h:65
uint32_t len
Length.
Definition: ena.h:14
static __always_inline userptr_t umalloc(size_t size)
Allocate external memory.
Definition: umalloc.h:54
A CPU vendor.
Definition: ucode.c:74
unsigned int count
Number of potentially relevant signatures found.
Definition: ucode.c:94
void mp_exec_boot(mp_func_t func, void *opaque)
Execute a multiprocessor function on the boot processor.
#define UCODE_WAIT_MS
Time to wait for a microcode update to complete.
Definition: ucode.c:63
char * name
Name.
Definition: image.h:34
int32_t high
Highest observed microcode version.
Definition: ucode.c:106
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33
void * memset(void *dest, int character, size_t len) __nonnull

References assert(), build_assert, control, ucode_update::count, ucode_summary::count, DBGC, ucode_update::desc, ENOMEM, ucode_summary::high, len, ucode_summary::low, max, mdelay(), memset(), memset_user(), mp_boot_cpuid(), mp_exec_boot(), mp_max_cpuid(), mp_start_all(), image::name, rc, status, strerror(), UCODE_MAX_HT, UCODE_VERSION_MAX, UCODE_VERSION_MIN, UCODE_WAIT_MS, ufree(), umalloc(), user_to_phys(), ucode_update::vendor, vendor, and virt_to_phys().

Referenced by ucode_exec().

◆ ucode_describe()

static void ucode_describe ( struct image image,
size_t  start,
const struct ucode_vendor vendor,
const struct ucode_descriptor desc,
uint32_t  platforms,
struct ucode_update update 
)
static

Add descriptor to list (if applicable)

Parameters
imageMicrocode image
startStarting offset within image
vendorCPU vendor
descMicrocode descriptor
platformsSupported platforms, or 0 for all platforms
updateMicrocode update

Definition at line 323 of file ucode.c.

326  {
327 
328  /* Dump descriptor information */
329  DBGC2 ( image, "UCODE %s+%#04zx %s %#08x", image->name, start,
330  ucode_vendor_name ( &vendor->id ), desc->signature );
331  if ( platforms )
332  DBGC2 ( image, " (%#02x)", platforms );
333  DBGC2 ( image, " version %#08x\n", desc->version );
334 
335  /* Check applicability */
336  if ( vendor != update->vendor )
337  return;
338  if ( ( desc->signature ^ update->signature ) & UCODE_SIGNATURE_MASK )
339  return;
340  if ( platforms && ( ! ( platforms & update->platform ) ) )
341  return;
342 
343  /* Add descriptor, if applicable */
344  if ( update->desc ) {
345  memcpy ( &update->desc[update->count], desc, sizeof ( *desc ) );
346  DBGC ( image, "UCODE %s+%#04zx found %s %#08x version %#08x\n",
348  desc->signature, desc->version );
349  }
350  update->count++;
351 }
struct ucode_descriptor * desc
Update descriptors (if being populated)
Definition: ucode.c:96
static unsigned short vendor
Definition: davicom.c:128
uint64_t desc
Microcode descriptor list physical address.
Definition: ucode.h:12
#define DBGC(...)
Definition: compiler.h:505
struct ucode_vendor * vendor
CPU vendor, if known.
Definition: ucode.c:88
An executable image.
Definition: image.h:24
uint32_t platforms
Supported platforms.
Definition: ucode.h:24
uint32_t start
Starting offset.
Definition: netvsc.h:12
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define DBGC2(...)
Definition: compiler.h:522
static const char * ucode_vendor_name(const union ucode_vendor_id *vendor)
Get CPU vendor name (for debugging)
Definition: ucode.c:135
unsigned int count
Number of potentially relevant signatures found.
Definition: ucode.c:94
uint32_t signature
Boot processor CPU signature.
Definition: ucode.c:90
uint32_t platform
Platform ID.
Definition: ucode.c:92
char * name
Name.
Definition: image.h:34
#define UCODE_SIGNATURE_MASK
CPUID signature applicability mask.
Definition: ucode.h:32

References ucode_update::count, DBGC, DBGC2, desc, ucode_update::desc, memcpy(), image::name, ucode_update::platform, platforms, ucode_update::signature, start, UCODE_SIGNATURE_MASK, ucode_vendor_name(), ucode_update::vendor, and vendor.

Referenced by ucode_parse_amd(), and ucode_parse_intel().

◆ ucode_verify()

static int ucode_verify ( struct image image,
size_t  start,
size_t  len 
)
static

Verify checksum.

Parameters
imageMicrocode image
startStarting offset
lenLength
Return values
rcReturn status code

Definition at line 361 of file ucode.c.

361  {
362  uint32_t checksum = 0;
363  uint32_t dword;
364  size_t offset;
365 
366  /* Check length is a multiple of dwords */
367  if ( ( len % sizeof ( dword ) ) != 0 ) {
368  DBGC ( image, "UCODE %s+%#04zx invalid length %#zx\n",
369  image->name, start, len );
370  return -EINVAL;
371  }
372 
373  /* Calculate checksum */
374  for ( offset = start ; len ;
375  offset += sizeof ( dword ), len -= sizeof ( dword ) ) {
377  sizeof ( dword ) );
378  checksum += dword;
379  }
380  if ( checksum != 0 ) {
381  DBGC ( image, "UCODE %s+%#04zx bad checksum %#08x\n",
382  image->name, start, checksum );
383  return -EINVAL;
384  }
385 
386  return 0;
387 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
userptr_t data
Raw file image.
Definition: image.h:41
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
#define DBGC(...)
Definition: compiler.h:505
An executable image.
Definition: image.h:24
uint8_t checksum
Checksum.
Definition: pnpbios.c:37
uint32_t start
Starting offset.
Definition: netvsc.h:12
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
unsigned int uint32_t
Definition: stdint.h:12
uint32_t len
Length.
Definition: ena.h:14
char * name
Name.
Definition: image.h:34
unsigned long int dword
Definition: smc9000.h:40

References checksum, copy_from_user(), image::data, DBGC, EINVAL, len, image::name, offset, and start.

Referenced by ucode_parse_intel().

◆ ucode_parse_intel()

static int ucode_parse_intel ( struct image image,
size_t  start,
struct ucode_update update 
)
static

Parse Intel microcode image.

Parameters
imageMicrocode image
startStarting offset within image
updateMicrocode update
Return values
lenLength consumed, or negative error

Definition at line 397 of file ucode.c.

398  {
399  struct intel_ucode_header hdr;
400  struct intel_ucode_ext_header exthdr;
401  struct intel_ucode_ext ext;
402  struct ucode_descriptor desc;
403  size_t remaining;
404  size_t offset;
405  size_t data_len;
406  size_t len;
407  unsigned int i;
408  int rc;
409 
410  /* Read header */
411  remaining = ( image->len - start );
412  if ( remaining < sizeof ( hdr ) ) {
413  DBGC ( image, "UCODE %s+%#04zx too small for Intel header\n",
414  image->name, start );
415  return -ENOEXEC;
416  }
417  copy_from_user ( &hdr, image->data, start, sizeof ( hdr ) );
418 
419  /* Determine lengths */
420  data_len = hdr.data_len;
421  if ( ! data_len )
423  len = hdr.len;
424  if ( ! len )
425  len = ( sizeof ( hdr ) + data_len );
426 
427  /* Verify a selection of fields */
428  if ( ( hdr.hver != INTEL_UCODE_HVER ) ||
429  ( hdr.lver != INTEL_UCODE_LVER ) ||
430  ( len < sizeof ( hdr ) ) ||
431  ( len > remaining ) ||
432  ( data_len > ( len - sizeof ( hdr ) ) ) ||
433  ( ( data_len % sizeof ( uint32_t ) ) != 0 ) ||
434  ( ( len % INTEL_UCODE_ALIGN ) != 0 ) ) {
435  DBGC2 ( image, "UCODE %s+%#04zx is not an Intel update\n",
436  image->name, start );
437  return -EINVAL;
438  }
439  DBGC2 ( image, "UCODE %s+%#04zx is an Intel update\n",
440  image->name, start );
441 
442  /* Verify checksum */
443  if ( ( rc = ucode_verify ( image, start, len ) ) != 0 )
444  return rc;
445 
446  /* Populate descriptor */
447  desc.signature = hdr.signature;
448  desc.version = hdr.version;
449  desc.address = user_to_phys ( image->data,
450  ( start + sizeof ( hdr ) ) );
451 
452  /* Add non-extended descriptor, if applicable */
453  ucode_describe ( image, start, &ucode_intel, &desc, hdr.platforms,
454  update );
455 
456  /* Construct extended descriptors, if applicable */
457  offset = ( sizeof ( hdr ) + data_len );
458  if ( offset <= ( len - sizeof ( exthdr ) ) ) {
459 
460  /* Read extended header */
461  copy_from_user ( &exthdr, image->data, ( start + offset ),
462  sizeof ( exthdr ) );
463  offset += sizeof ( exthdr );
464 
465  /* Read extended signatures */
466  for ( i = 0 ; i < exthdr.count ; i++ ) {
467 
468  /* Read extended signature */
469  if ( offset > ( len - sizeof ( ext ) ) ) {
470  DBGC ( image, "UCODE %s+%#04zx extended "
471  "signature overrun\n",
472  image->name, start );
473  return -EINVAL;
474  }
475  copy_from_user ( &ext, image->data, ( start + offset ),
476  sizeof ( ext ) );
477  offset += sizeof ( ext );
478 
479  /* Avoid duplicating non-extended descriptor */
480  if ( ( ext.signature == hdr.signature ) &&
481  ( ext.platforms == hdr.platforms ) ) {
482  continue;
483  }
484 
485  /* Construct descriptor, if applicable */
486  desc.signature = ext.signature;
488  ext.platforms, update );
489  }
490  }
491 
492  return len;
493 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
#define INTEL_UCODE_HVER
Intel microcode header version number.
Definition: ucode.h:137
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
userptr_t data
Raw file image.
Definition: image.h:41
An Intel microcode update file extended header.
Definition: ucode.h:149
static void ucode_describe(struct image *image, size_t start, const struct ucode_vendor *vendor, const struct ucode_descriptor *desc, uint32_t platforms, struct ucode_update *update)
Add descriptor to list (if applicable)
Definition: ucode.c:323
struct golan_inbox_hdr hdr
Message header.
Definition: CIB_PRM.h:28
#define ENOEXEC
Exec format error.
Definition: errno.h:519
An Intel microcode extended signature.
Definition: ucode.h:159
static int ucode_verify(struct image *image, size_t start, size_t len)
Verify checksum.
Definition: ucode.c:361
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
uint64_t desc
Microcode descriptor list physical address.
Definition: ucode.h:12
#define DBGC(...)
Definition: compiler.h:505
uint32_t data_len
Microcode data size (or 0 to indicate 2000 bytes)
Definition: ucode.h:26
An executable image.
Definition: image.h:24
uint32_t start
Starting offset.
Definition: netvsc.h:12
A microcode update descriptor.
Definition: ucode.h:75
static struct ucode_vendor ucode_intel
Intel CPU vendor.
Definition: ucode.c:110
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
An Intel microcode update file header.
Definition: ucode.h:113
size_t len
Length of raw file image.
Definition: image.h:43
unsigned int uint32_t
Definition: stdint.h:12
uint16_t ext
Extended status.
Definition: ena.h:20
uint32_t len
Length.
Definition: ena.h:14
#define DBGC2(...)
Definition: compiler.h:522
#define INTEL_UCODE_LVER
Intel microcode loader version number.
Definition: ucode.h:140
char * name
Name.
Definition: image.h:34
#define INTEL_UCODE_DATA_LEN
Intel microcode default data length.
Definition: ucode.h:143
#define INTEL_UCODE_ALIGN
Intel microcode file alignment.
Definition: ucode.h:146

References copy_from_user(), intel_ucode_ext_header::count, image::data, data_len, DBGC, DBGC2, desc, EINVAL, ENOEXEC, ext, hdr, INTEL_UCODE_ALIGN, INTEL_UCODE_DATA_LEN, INTEL_UCODE_HVER, INTEL_UCODE_LVER, len, image::len, image::name, offset, rc, start, ucode_describe(), ucode_intel, ucode_verify(), and user_to_phys().

Referenced by ucode_parse().

◆ ucode_parse_amd()

static int ucode_parse_amd ( struct image image,
size_t  start,
struct ucode_update update 
)
static

Parse AMD microcode image.

Parameters
imageMicrocode image
startStarting offset within image
updateMicrocode update
Return values
lenLength consumed, or negative error

Definition at line 503 of file ucode.c.

504  {
505  struct amd_ucode_header hdr;
506  struct amd_ucode_equivalence equiv;
507  struct amd_ucode_patch_header phdr;
508  struct amd_ucode_patch patch;
509  struct ucode_descriptor desc;
510  size_t remaining;
511  size_t offset;
512  unsigned int count;
513  unsigned int used;
514  unsigned int i;
515 
516  /* Read header */
517  remaining = ( image->len - start );
518  if ( remaining < sizeof ( hdr ) ) {
519  DBGC ( image, "UCODE %s+%#04zx too small for AMD header\n",
520  image->name, start );
521  return -ENOEXEC;
522  }
523  copy_from_user ( &hdr, image->data, start, sizeof ( hdr ) );
524 
525  /* Check header */
526  if ( hdr.magic != AMD_UCODE_MAGIC ) {
527  DBGC2 ( image, "UCODE %s+%#04zx is not an AMD update\n",
528  image->name, start );
529  return -ENOEXEC;
530  }
531  DBGC2 ( image, "UCODE %s+%#04zx is an AMD update\n",
532  image->name, start );
533  if ( hdr.type != AMD_UCODE_EQUIV_TYPE ) {
534  DBGC ( image, "UCODE %s+%#04zx unsupported equivalence table "
535  "type %d\n", image->name, start, hdr.type );
536  return -ENOTSUP;
537  }
538  if ( hdr.len > ( remaining - sizeof ( hdr ) ) ) {
539  DBGC ( image, "UCODE %s+%#04zx truncated equivalence table\n",
540  image->name, start );
541  return -EINVAL;
542  }
543 
544  /* Count number of equivalence table entries */
545  offset = sizeof ( hdr );
546  for ( count = 0 ; offset < ( sizeof ( hdr ) + hdr.len ) ;
547  count++, offset += sizeof ( equiv ) ) {
548  copy_from_user ( &equiv, image->data, ( start + offset ),
549  sizeof ( equiv ) );
550  if ( ! equiv.signature )
551  break;
552  }
553  DBGC2 ( image, "UCODE %s+%#04zx has %d equivalence table entries\n",
554  image->name, start, count );
555 
556  /* Parse available updates */
557  offset = ( sizeof ( hdr ) + hdr.len );
558  used = 0;
559  while ( used < count ) {
560 
561  /* Read patch header */
562  if ( ( offset + sizeof ( phdr ) ) > remaining ) {
563  DBGC ( image, "UCODE %s+%#04zx truncated patch "
564  "header\n", image->name, start );
565  return -EINVAL;
566  }
567  copy_from_user ( &phdr, image->data, ( start + offset ),
568  sizeof ( phdr ) );
569  offset += sizeof ( phdr );
570 
571  /* Validate patch header */
572  if ( phdr.type != AMD_UCODE_PATCH_TYPE ) {
573  DBGC ( image, "UCODE %s+%#04zx unsupported patch type "
574  "%d\n", image->name, start, phdr.type );
575  return -ENOTSUP;
576  }
577  if ( phdr.len < sizeof ( patch ) ) {
578  DBGC ( image, "UCODE %s+%#04zx underlength patch\n",
579  image->name, start );
580  return -EINVAL;
581  }
582  if ( phdr.len > ( remaining - offset ) ) {
583  DBGC ( image, "UCODE %s+%#04zx truncated patch\n",
584  image->name, start );
585  return -EINVAL;
586  }
587 
588  /* Read patch and construct descriptor */
589  copy_from_user ( &patch, image->data, ( start + offset ),
590  sizeof ( patch ) );
591  desc.version = patch.version;
592  desc.address = user_to_phys ( image->data, ( start + offset ) );
593  offset += phdr.len;
594 
595  /* Parse equivalence table to find matching signatures */
596  for ( i = 0 ; i < count ; i++ ) {
597  copy_from_user ( &equiv, image->data,
598  ( start + sizeof ( hdr ) +
599  ( i * ( sizeof ( equiv ) ) ) ),
600  sizeof ( equiv ) );
601  if ( patch.id == equiv.id ) {
602  desc.signature = equiv.signature;
604  &desc, 0, update );
605  used++;
606  }
607  }
608  }
609 
610  return offset;
611 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
userptr_t data
Raw file image.
Definition: image.h:41
static void ucode_describe(struct image *image, size_t start, const struct ucode_vendor *vendor, const struct ucode_descriptor *desc, uint32_t platforms, struct ucode_update *update)
Add descriptor to list (if applicable)
Definition: ucode.c:323
static struct ucode_vendor ucode_amd
AMD CPU vendor.
Definition: ucode.c:118
struct golan_inbox_hdr hdr
Message header.
Definition: CIB_PRM.h:28
An AMD microcode update file header.
Definition: ucode.h:169
#define AMD_UCODE_EQUIV_TYPE
AMD microcode equivalence table type.
Definition: ucode.h:182
#define ENOEXEC
Exec format error.
Definition: errno.h:519
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
uint64_t desc
Microcode descriptor list physical address.
Definition: ucode.h:12
#define DBGC(...)
Definition: compiler.h:505
An executable image.
Definition: image.h:24
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
uint32_t start
Starting offset.
Definition: netvsc.h:12
A microcode update descriptor.
Definition: ucode.h:75
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
An AMD microcode equivalence table entry.
Definition: ucode.h:185
size_t len
Length of raw file image.
Definition: image.h:43
An AMD microcode patch.
Definition: ucode.h:205
#define AMD_UCODE_PATCH_TYPE
AMD patch type.
Definition: ucode.h:219
An AMD microcode patch header.
Definition: ucode.h:197
#define DBGC2(...)
Definition: compiler.h:522
#define AMD_UCODE_MAGIC
AMD microcode magic signature.
Definition: ucode.h:179
uint16_t count
Number of entries.
Definition: ena.h:22
char * name
Name.
Definition: image.h:34

References AMD_UCODE_EQUIV_TYPE, AMD_UCODE_MAGIC, AMD_UCODE_PATCH_TYPE, copy_from_user(), count, image::data, DBGC, DBGC2, desc, EINVAL, ENOEXEC, ENOTSUP, hdr, amd_ucode_equivalence::id, amd_ucode_patch::id, image::len, amd_ucode_patch_header::len, image::name, offset, amd_ucode_equivalence::signature, start, amd_ucode_patch_header::type, ucode_amd, ucode_describe(), user_to_phys(), and amd_ucode_patch::version.

Referenced by ucode_parse().

◆ ucode_parse()

static int ucode_parse ( struct image image,
struct ucode_update update 
)
static

Parse microcode image.

Parameters
imageMicrocode image
updateMicrocode update
Return values
rcReturn status code

Definition at line 620 of file ucode.c.

620  {
621  size_t start;
622  int len;
623 
624  /* Attempt to parse concatenated microcode updates */
625  for ( start = 0 ; start < image->len ; start += len ) {
626 
627  /* Attempt to parse as Intel microcode */
628  len = ucode_parse_intel ( image, start, update );
629  if ( len > 0 )
630  continue;
631 
632  /* Attempt to parse as AMD microcode */
633  len = ucode_parse_amd ( image, start, update );
634  if ( len > 0 )
635  continue;
636 
637  /* Not a recognised microcode format */
638  DBGC ( image, "UCODE %s+%zx not recognised\n",
639  image->name, start );
640  return -ENOEXEC;
641  }
642 
643  return 0;
644 }
static int ucode_parse_amd(struct image *image, size_t start, struct ucode_update *update)
Parse AMD microcode image.
Definition: ucode.c:503
static int ucode_parse_intel(struct image *image, size_t start, struct ucode_update *update)
Parse Intel microcode image.
Definition: ucode.c:397
#define ENOEXEC
Exec format error.
Definition: errno.h:519
#define DBGC(...)
Definition: compiler.h:505
An executable image.
Definition: image.h:24
uint32_t start
Starting offset.
Definition: netvsc.h:12
size_t len
Length of raw file image.
Definition: image.h:43
uint32_t len
Length.
Definition: ena.h:14
char * name
Name.
Definition: image.h:34

References DBGC, ENOEXEC, len, image::len, image::name, start, ucode_parse_amd(), and ucode_parse_intel().

Referenced by ucode_exec().

◆ ucode_exec()

static int ucode_exec ( struct image image)
static

Execute microcode update.

Parameters
imageMicrocode image
Return values
rcReturn status code

Definition at line 652 of file ucode.c.

652  {
653  struct ucode_update update;
654  struct ucode_vendor *vendor;
655  struct ucode_summary summary;
656  union ucode_vendor_id id;
658  uint32_t discard_a;
659  uint32_t discard_b;
661  uint32_t discard_d;
662  unsigned int check;
663  unsigned int i;
664  size_t len;
665  int rc;
666 
667  /* Initialise update */
668  memset ( &update, 0, sizeof ( update ) );
669  cpuid ( CPUID_VENDOR_ID, 0, &discard_a, &id.dword[0], &id.dword[2],
670  &id.dword[1] );
671  cpuid ( CPUID_FEATURES, 0, &update.signature, &discard_b,
672  &discard_c, &discard_d );
673 
674  /* Identify CPU vendor, if recognised */
675  for ( i = 0 ; i < ( sizeof ( ucode_vendors ) /
676  sizeof ( ucode_vendors[0] ) ) ; i++ ) {
677  vendor = ucode_vendors[i];
678  if ( memcmp ( &id, &vendor->id, sizeof ( id ) ) == 0 )
679  update.vendor = vendor;
680  }
681 
682  /* Identify platform, if applicable */
683  if ( update.vendor == &ucode_intel ) {
684  platform_id = rdmsr ( MSR_PLATFORM_ID );
685  update.platform =
686  ( 1 << MSR_PLATFORM_ID_VALUE ( platform_id ) );
687  }
688 
689  /* Count number of matching update descriptors */
690  DBGC ( image, "UCODE %s applying to %s %#08x",
691  image->name, ucode_vendor_name ( &id ), update.signature );
692  if ( update.platform )
693  DBGC ( image, " (%#02x)", update.platform );
694  DBGC ( image, "\n" );
695  if ( ( rc = ucode_parse ( image, &update ) ) != 0 )
696  goto err_count;
697  DBGC ( image, "UCODE %s found %d matching update(s)\n",
698  image->name, update.count );
699 
700  /* Allocate descriptors */
701  len = ( ( update.count + 1 /* terminator */ ) *
702  sizeof ( update.desc[0] ) );
703  update.desc = zalloc ( len );
704  if ( ! update.desc ) {
705  rc = -ENOMEM;
706  goto err_alloc;
707  }
708 
709  /* Populate descriptors */
710  check = update.count;
711  update.count = 0;
712  if ( ( rc = ucode_parse ( image, &update ) ) != 0 )
713  goto err_parse;
714  assert ( check == update.count );
715 
716  /* Perform update */
717  if ( ( rc = ucode_update_all ( image, &update, &summary ) ) != 0 )
718  goto err_update;
719 
720  /* Print summary if directed to do so */
721  if ( image->cmdline && ( strstr ( image->cmdline, "-v" ) ) ) {
722  printf ( "Microcode: " );
723  if ( summary.low == summary.high ) {
724  printf ( "already version %#x", summary.low );
725  } else {
726  printf ( "updated version %#x->%#x",
727  summary.low, summary.high );
728  }
729  printf ( " (x%d)\n", summary.count );
730  }
731 
732  err_update:
733  err_parse:
734  free ( update.desc );
735  err_alloc:
736  err_count:
737  return rc;
738 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
#define CPUID_FEATURES
Get standard features.
Definition: cpuid.h:40
static int ucode_parse(struct image *image, struct ucode_update *update)
Parse microcode image.
Definition: ucode.c:620
static unsigned short vendor
Definition: davicom.c:128
#define CPUID_VENDOR_ID
Get vendor ID and largest standard function.
Definition: cpuid.h:37
#define DBGC(...)
Definition: compiler.h:505
unsigned long long uint64_t
Definition: stdint.h:13
A microcode update.
Definition: ucode.c:86
A microcode update summary.
Definition: ucode.c:100
A CPU vendor string.
Definition: ucode.c:66
An executable image.
Definition: image.h:24
char * cmdline
Command line to pass to image.
Definition: image.h:39
#define MSR_PLATFORM_ID
Platform ID MSR.
Definition: ucode.h:16
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition: string.c:309
#define ENOMEM
Not enough space.
Definition: errno.h:534
static struct ucode_vendor ucode_intel
Intel CPU vendor.
Definition: ucode.c:110
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define MSR_PLATFORM_ID_VALUE(value)
Extract platform ID from MSR value.
Definition: ucode.h:19
uint8_t id
Request identifier.
Definition: ena.h:12
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
uint8_t platform_id
Platform ID.
Definition: eltorito.h:20
static struct ucode_vendor * ucode_vendors[]
List of known CPU vendors.
Definition: ucode.c:124
unsigned int uint32_t
Definition: stdint.h:12
uint32_t len
Length.
Definition: ena.h:14
static const char * ucode_vendor_name(const union ucode_vendor_id *vendor)
Get CPU vendor name (for debugging)
Definition: ucode.c:135
A CPU vendor.
Definition: ucode.c:74
long discard_c
Definition: bigint.h:32
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
char * name
Name.
Definition: image.h:34
unsigned long int dword
Definition: smc9000.h:40
void * memset(void *dest, int character, size_t len) __nonnull
static int ucode_update_all(struct image *image, struct ucode_update *update, struct ucode_summary *summary)
Update microcode on all CPUs.
Definition: ucode.c:233

References assert(), image::cmdline, ucode_update::count, ucode_summary::count, CPUID_FEATURES, CPUID_VENDOR_ID, DBGC, ucode_update::desc, discard_c, ENOMEM, free, ucode_summary::high, id, len, ucode_summary::low, memcmp(), memset(), MSR_PLATFORM_ID, MSR_PLATFORM_ID_VALUE, image::name, ucode_update::platform, platform_id, printf(), rc, ucode_update::signature, strstr(), ucode_intel, ucode_parse(), ucode_update_all(), ucode_vendor_name(), ucode_vendors, ucode_update::vendor, vendor, and zalloc().

◆ ucode_probe()

static int ucode_probe ( struct image image)
static

Probe microcode update image.

Parameters
imageMicrocode image
Return values
rcReturn status code

Definition at line 746 of file ucode.c.

746  {
747  union {
748  struct intel_ucode_header intel;
749  struct amd_ucode_header amd;
750  } header;
751 
752  /* Sanity check */
753  if ( image->len < sizeof ( header ) ) {
754  DBGC ( image, "UCODE %s too short\n", image->name );
755  return -ENOEXEC;
756  }
757 
758  /* Read first microcode image header */
759  copy_from_user ( &header, image->data, 0, sizeof ( header ) );
760 
761  /* Check for something that looks like an Intel update
762  *
763  * Intel updates unfortunately have no magic signatures or
764  * other easily verifiable fields. We check a small selection
765  * of header fields that can be easily verified.
766  *
767  * We do not attempt to fully parse the update, since we want
768  * errors to be reported at the point of attempting to execute
769  * the image, and do not want to have a microcode image
770  * erroneously treated as a PXE boot executable.
771  */
772  if ( ( header.intel.hver == INTEL_UCODE_HVER ) &&
773  ( header.intel.lver == INTEL_UCODE_LVER ) &&
774  ( ( header.intel.date.century == 0x19 ) ||
775  ( ( header.intel.date.century >= 0x20 ) &&
776  ( header.intel.date.century <= 0x29 ) ) ) ) {
777  DBGC ( image, "UCODE %s+%#04zx looks like an Intel update\n",
778  image->name, ( ( size_t ) 0 ) );
779  return 0;
780  }
781 
782  /* Check for AMD update signature */
783  if ( ( header.amd.magic == AMD_UCODE_MAGIC ) &&
784  ( header.amd.type == AMD_UCODE_EQUIV_TYPE ) ) {
785  DBGC ( image, "UCODE %s+%#04zx looks like an AMD update\n",
786  image->name, ( ( size_t ) 0 ) );
787  return 0;
788  }
789 
790  return -ENOEXEC;
791 }
#define INTEL_UCODE_HVER
Intel microcode header version number.
Definition: ucode.h:137
userptr_t data
Raw file image.
Definition: image.h:41
An AMD microcode update file header.
Definition: ucode.h:169
#define AMD_UCODE_EQUIV_TYPE
AMD microcode equivalence table type.
Definition: ucode.h:182
#define ENOEXEC
Exec format error.
Definition: errno.h:519
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
#define DBGC(...)
Definition: compiler.h:505
An executable image.
Definition: image.h:24
An Intel microcode update file header.
Definition: ucode.h:113
size_t len
Length of raw file image.
Definition: image.h:43
#define AMD_UCODE_MAGIC
AMD microcode magic signature.
Definition: ucode.h:179
struct ena_aq_header header
Header.
Definition: ena.h:12
#define INTEL_UCODE_LVER
Intel microcode loader version number.
Definition: ucode.h:140
char * name
Name.
Definition: image.h:34

References AMD_UCODE_EQUIV_TYPE, AMD_UCODE_MAGIC, copy_from_user(), image::data, DBGC, ENOEXEC, header, INTEL_UCODE_HVER, INTEL_UCODE_LVER, image::len, and image::name.

◆ __image_type()

struct image_type ucode_image_type __image_type ( PROBE_NORMAL  )

Microcode update image type.

Variable Documentation

◆ ucode_intel

struct ucode_vendor ucode_intel
static
Initial value:
= {
.id = { .string = "GenuineIntel" },
.ver_clear = 1,
.ver_high = 1,
.trigger_msr = MSR_UCODE_TRIGGER_INTEL,
}
#define MSR_UCODE_TRIGGER_INTEL
Intel microcode load trigger MSR.
Definition: ucode.h:22

Intel CPU vendor.

Definition at line 110 of file ucode.c.

Referenced by ucode_exec(), and ucode_parse_intel().

◆ ucode_amd

struct ucode_vendor ucode_amd
static
Initial value:
= {
.id = { .string = "AuthenticAMD" },
.trigger_msr = MSR_UCODE_TRIGGER_AMD,
}
#define MSR_UCODE_TRIGGER_AMD
AMD microcode load trigger MSR.
Definition: ucode.h:25

AMD CPU vendor.

Definition at line 118 of file ucode.c.

Referenced by ucode_parse_amd().

◆ ucode_vendors

struct ucode_vendor* ucode_vendors[]
static
Initial value:
= {
}
static struct ucode_vendor ucode_amd
AMD CPU vendor.
Definition: ucode.c:118
static struct ucode_vendor ucode_intel
Intel CPU vendor.
Definition: ucode.c:110

List of known CPU vendors.

Definition at line 124 of file ucode.c.

Referenced by ucode_exec().