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

Microcode updates. More...

#include <stdlib.h>
#include <stdio.h>
#include <string.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 (const struct ucode_update *update, const struct ucode_control *control, const struct ucode_status *status, struct ucode_summary *summary, unsigned int id, int optional)
 Check status report. More...
 
static int ucode_update_all (struct image *image, const 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 61 of file ucode.c.

◆ UCODE_WAIT_MS

#define UCODE_WAIT_MS   10

Time to wait for a microcode update to complete.

Definition at line 64 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 136 of file ucode.c.

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

References memcpy(), u, and vendor.

Referenced by ucode_describe(), and ucode_exec().

◆ ucode_status()

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

Check status report.

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

Definition at line 159 of file ucode.c.

163  {
164  struct ucode_descriptor *desc;
165 
166  /* Sanity check */
167  assert ( id <= control->apic_max );
168 
169  /* Ignore empty optional status reports */
170  if ( optional && ( ! status->signature ) )
171  return 0;
172  DBGC ( update, "UCODE %#08x signature %#08x ucode %#08x->%#08x\n",
173  id, status->signature, status->before, status->after );
174 
175  /* Check CPU signature */
176  if ( ! status->signature ) {
177  DBGC2 ( update, "UCODE %#08x has no signature\n", id );
178  return -ENOENT;
179  }
180 
181  /* Check APIC ID is correct */
182  if ( status->id != id ) {
183  DBGC ( update, "UCODE %#08x wrong APIC ID %#08x\n",
184  id, status->id );
185  return -EINVAL;
186  }
187 
188  /* Check that maximum APIC ID was not exceeded */
189  if ( control->apic_unexpected ) {
190  DBGC ( update, "UCODE %#08x saw unexpected APIC ID %#08x\n",
191  id, control->apic_unexpected );
192  return -ERANGE;
193  }
194 
195  /* Check microcode was not downgraded */
196  if ( status->after < status->before ) {
197  DBGC ( update, "UCODE %#08x was downgraded %#08x->%#08x\n",
198  id, status->before, status->after );
199  return -ENOTTY;
200  }
201 
202  /* Check that expected updates (if any) were applied */
203  for ( desc = update->desc ; desc->signature ; desc++ ) {
204  if ( ( desc->signature == status->signature ) &&
205  ( status->after < desc->version ) ) {
206  DBGC ( update, "UCODE %#08x failed update %#08x->%#08x "
207  "(wanted %#08x)\n", id, status->before,
208  status->after, desc->version );
209  return -EIO;
210  }
211  }
212 
213  /* Update summary */
214  summary->count++;
215  if ( status->before < summary->low )
216  summary->low = status->before;
217  if ( status->after > summary->high )
218  summary->high = status->after;
219 
220  return 0;
221 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
struct ucode_descriptor * desc
Update descriptors (if being populated)
Definition: ucode.c:97
#define DBGC(...)
Definition: compiler.h:505
#define ENOENT
No such file or directory.
Definition: errno.h:514
unsigned int count
Number of CPUs processed.
Definition: ucode.c:103
struct ena_llq_option desc
Descriptor counts.
Definition: ena.h:20
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:105
uint32_t control
Control.
Definition: myson.h:14
uint8_t status
Status.
Definition: ena.h:16
#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:107
uint32_t apic_max
Maximum expected APIC ID.
Definition: ucode.h:18

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

◆ ucode_update_all()

static int ucode_update_all ( struct image image,
const 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 231 of file ucode.c.

233  {
234  struct ucode_control control;
235  struct ucode_vendor *vendor;
236  struct ucode_status *status;
237  unsigned int max;
238  unsigned int id;
239  size_t len;
240  int rc;
241 
242  /* Initialise summary */
243  summary->count = 0;
244  summary->low = UCODE_VERSION_MAX;
245  summary->high = UCODE_VERSION_MIN;
246 
247  /* Allocate status reports */
248  max = mp_max_cpuid();
249  len = ( ( max + 1 ) * sizeof ( *status ) );
250  status = umalloc ( len );
251  if ( ! status ) {
252  DBGC ( image, "UCODE %s could not allocate %d status reports\n",
253  image->name, ( max + 1 ) );
254  rc = -ENOMEM;
255  goto err_alloc;
256  }
257  memset ( status, 0, len );
258 
259  /* Construct control structure */
260  memset ( &control, 0, sizeof ( control ) );
261  control.desc = virt_to_phys ( update->desc );
262  control.status = virt_to_phys ( status );
263  vendor = update->vendor;
264  if ( vendor ) {
265  control.ver_clear = vendor->ver_clear;
266  control.ver_high = vendor->ver_high;
267  control.trigger_msr = vendor->trigger_msr;
268  } else {
269  assert ( update->count == 0 );
270  }
271  control.apic_max = max;
272 
273  /* Update microcode on boot processor */
275  id = mp_boot_cpuid();
276  if ( ( rc = ucode_status ( update, &control, &status[id],
277  summary, id, 0 ) ) != 0 ) {
278  DBGC ( image, "UCODE %s failed on boot processor: %s\n",
279  image->name, strerror ( rc ) );
280  goto err_boot;
281  }
282 
283  /* Update microcode on application processors, avoiding
284  * simultaneous updates on hyperthread siblings.
285  */
286  build_assert ( ( UCODE_MAX_HT & ( UCODE_MAX_HT - 1 ) ) == 0 );
287  control.apic_mask = ( UCODE_MAX_HT - 1 );
288  for ( ; control.apic_test <= control.apic_mask ; control.apic_test++ ) {
290  mdelay ( UCODE_WAIT_MS );
291  }
292 
293  /* Check status reports */
294  summary->count = 0;
295  for ( id = 0 ; id <= max ; id++ ) {
296  if ( ( rc = ucode_status ( update, &control, &status[id],
297  summary, id, 1 ) ) != 0 ) {
298  goto err_status;
299  }
300  }
301 
302  /* Success */
303  rc = 0;
304 
305  err_status:
306  err_boot:
307  ufree ( status );
308  err_alloc:
309  return rc;
310 }
static __always_inline void ufree(void *ptr)
Free external memory.
Definition: umalloc.h:67
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define max(x, y)
Definition: ath.h:40
struct ucode_descriptor * desc
Update descriptors (if being populated)
Definition: ucode.c:97
#define UCODE_VERSION_MIN
Minimum possible microcode version.
Definition: ucode.h:35
static unsigned short vendor
Definition: davicom.c:128
#define DBGC(...)
Definition: compiler.h:505
struct ucode_vendor * vendor
CPU vendor, if known.
Definition: ucode.c:89
A microcode update.
Definition: ucode.c:87
An executable image.
Definition: image.h:23
unsigned int count
Number of CPUs processed.
Definition: ucode.c:103
void mp_start_all(mp_func_t func, void *opaque)
Start a multiprocessor function on all application processors.
#define ENOMEM
Not enough space.
Definition: errno.h:534
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
ring len
Length.
Definition: dwmac.h:231
#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
uint8_t id
Request identifier.
Definition: ena.h:12
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:105
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
uint8_t status
Status.
Definition: ena.h:16
A microcode update status report.
Definition: ucode.h:89
#define UCODE_MAX_HT
Maximum number of hyperthread siblings.
Definition: ucode.c:61
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition: timer.c:78
static __always_inline void * umalloc(size_t size)
Allocate external memory.
Definition: umalloc.h:56
A CPU vendor.
Definition: ucode.c:75
unsigned int count
Number of potentially relevant signatures found.
Definition: ucode.c:95
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:64
char * name
Name.
Definition: image.h:37
int32_t high
Highest observed microcode version.
Definition: ucode.c:107
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, id, len, ucode_summary::low, max, mdelay(), memset(), 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(), ucode_update::vendor, and vendor.

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 322 of file ucode.c.

325  {
326 
327  /* Dump descriptor information */
328  DBGC2 ( image, "UCODE %s+%#04zx %s %#08x", image->name, start,
329  ucode_vendor_name ( &vendor->id ), desc->signature );
330  if ( platforms )
331  DBGC2 ( image, " (%#02x)", platforms );
332  DBGC2 ( image, " version %#08x\n", desc->version );
333 
334  /* Check applicability */
335  if ( vendor != update->vendor )
336  return;
337  if ( ( desc->signature ^ update->signature ) & UCODE_SIGNATURE_MASK )
338  return;
339  if ( platforms && ( ! ( platforms & update->platform ) ) )
340  return;
341 
342  /* Add descriptor, if applicable */
343  if ( update->desc ) {
344  memcpy ( &update->desc[update->count], desc, sizeof ( *desc ) );
345  DBGC ( image, "UCODE %s+%#04zx found %s %#08x version %#08x\n",
347  desc->signature, desc->version );
348  }
349  update->count++;
350 }
struct ucode_descriptor * desc
Update descriptors (if being populated)
Definition: ucode.c:97
static unsigned short vendor
Definition: davicom.c:128
#define DBGC(...)
Definition: compiler.h:505
struct ucode_vendor * vendor
CPU vendor, if known.
Definition: ucode.c:89
An executable image.
Definition: image.h:23
uint32_t platforms
Supported platforms.
Definition: ucode.h:24
uint32_t start
Starting offset.
Definition: netvsc.h:12
struct ena_llq_option desc
Descriptor counts.
Definition: ena.h:20
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:136
unsigned int count
Number of potentially relevant signatures found.
Definition: ucode.c:95
uint32_t signature
Boot processor CPU signature.
Definition: ucode.c:91
uint32_t platform
Platform ID.
Definition: ucode.c:93
char * name
Name.
Definition: image.h:37
#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 360 of file ucode.c.

360  {
361  const uint32_t *dword;
363  unsigned int count;
364 
365  /* Check length is a multiple of dwords */
366  if ( ( len % sizeof ( *dword ) ) != 0 ) {
367  DBGC ( image, "UCODE %s+%#04zx invalid length %#zx\n",
368  image->name, start, len );
369  return -EINVAL;
370  }
371  dword = ( image->data + start );
372 
373  /* Calculate checksum */
374  count = ( len / sizeof ( *dword ) );
375  for ( checksum = 0 ; count ; count-- )
376  checksum += *(dword++);
377  if ( checksum != 0 ) {
378  DBGC ( image, "UCODE %s+%#04zx bad checksum %#08x\n",
379  image->name, start, checksum );
380  return -EINVAL;
381  }
382 
383  return 0;
384 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
uint8_t checksum
Checksum.
Definition: pnpbios.c:37
const void * data
Read-only data.
Definition: image.h:50
#define DBGC(...)
Definition: compiler.h:505
An executable image.
Definition: image.h:23
uint32_t start
Starting offset.
Definition: netvsc.h:12
ring len
Length.
Definition: dwmac.h:231
static unsigned int count
Number of entries.
Definition: dwmac.h:225
unsigned int uint32_t
Definition: stdint.h:12
char * name
Name.
Definition: image.h:37
unsigned long int dword
Definition: smc9000.h:40

References checksum, count, image::data, DBGC, EINVAL, len, image::name, 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 394 of file ucode.c.

395  {
396  const struct intel_ucode_header *hdr;
397  const struct intel_ucode_ext_header *exthdr;
398  const struct intel_ucode_ext *ext;
399  struct ucode_descriptor desc;
400  size_t remaining;
401  size_t offset;
402  size_t data_len;
403  size_t len;
404  unsigned int i;
405  int rc;
406 
407  /* Read header */
408  remaining = ( image->len - start );
409  if ( remaining < sizeof ( *hdr ) ) {
410  DBGC ( image, "UCODE %s+%#04zx too small for Intel header\n",
411  image->name, start );
412  return -ENOEXEC;
413  }
414  hdr = ( image->data + start );
415 
416  /* Determine lengths */
417  data_len = hdr->data_len;
418  if ( ! data_len )
420  len = hdr->len;
421  if ( ! len )
422  len = ( sizeof ( *hdr ) + data_len );
423 
424  /* Verify a selection of fields */
425  if ( ( hdr->hver != INTEL_UCODE_HVER ) ||
426  ( hdr->lver != INTEL_UCODE_LVER ) ||
427  ( len < sizeof ( *hdr ) ) ||
428  ( len > remaining ) ||
429  ( data_len > ( len - sizeof ( *hdr ) ) ) ||
430  ( ( data_len % sizeof ( uint32_t ) ) != 0 ) ||
431  ( ( len % INTEL_UCODE_ALIGN ) != 0 ) ) {
432  DBGC2 ( image, "UCODE %s+%#04zx is not an Intel update\n",
433  image->name, start );
434  return -EINVAL;
435  }
436  DBGC2 ( image, "UCODE %s+%#04zx is an Intel update\n",
437  image->name, start );
438 
439  /* Verify checksum */
440  if ( ( rc = ucode_verify ( image, start, len ) ) != 0 )
441  return rc;
442 
443  /* Populate descriptor */
444  desc.signature = hdr->signature;
445  desc.version = hdr->version;
446  desc.address = ( virt_to_phys ( image->data ) + start +
447  sizeof ( *hdr ) );
448 
449  /* Add non-extended descriptor, if applicable */
450  ucode_describe ( image, start, &ucode_intel, &desc, hdr->platforms,
451  update );
452 
453  /* Construct extended descriptors, if applicable */
454  offset = ( sizeof ( *hdr ) + data_len );
455  if ( offset <= ( len - sizeof ( *exthdr ) ) ) {
456 
457  /* Read extended header */
458  exthdr = ( image->data + start + offset );
459  offset += sizeof ( *exthdr );
460 
461  /* Read extended signatures */
462  for ( i = 0 ; i < exthdr->count ; i++ ) {
463 
464  /* Read extended signature */
465  if ( offset > ( len - sizeof ( *ext ) ) ) {
466  DBGC ( image, "UCODE %s+%#04zx extended "
467  "signature overrun\n",
468  image->name, start );
469  return -EINVAL;
470  }
471  ext = ( image->data + start + offset );
472  offset += sizeof ( *ext );
473 
474  /* Avoid duplicating non-extended descriptor */
475  if ( ( ext->signature == hdr->signature ) &&
476  ( ext->platforms == hdr->platforms ) ) {
477  continue;
478  }
479 
480  /* Construct descriptor, if applicable */
481  desc.signature = ext->signature;
483  ext->platforms, update );
484  }
485  }
486 
487  return len;
488 }
#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
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:322
const void * data
Read-only data.
Definition: image.h:50
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:360
#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:23
uint32_t start
Starting offset.
Definition: netvsc.h:12
struct ena_llq_option desc
Descriptor counts.
Definition: ena.h:20
A microcode update descriptor.
Definition: ucode.h:75
static struct ucode_vendor ucode_intel
Intel CPU vendor.
Definition: ucode.c:111
ring len
Length.
Definition: dwmac.h:231
An Intel microcode update file header.
Definition: ucode.h:113
size_t len
Length of raw file image.
Definition: image.h:55
uint32_t count
Extended signature count.
Definition: ucode.h:151
unsigned int uint32_t
Definition: stdint.h:12
uint16_t ext
Extended status.
Definition: ena.h:20
#define DBGC2(...)
Definition: compiler.h:522
#define INTEL_UCODE_LVER
Intel microcode loader version number.
Definition: ucode.h:140
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
char * name
Name.
Definition: image.h:37
#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 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, image::len, len, image::name, offset, rc, start, ucode_describe(), ucode_intel, and ucode_verify().

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 498 of file ucode.c.

499  {
500  const struct amd_ucode_header *hdr;
501  const struct amd_ucode_equivalence *equiv;
502  const struct amd_ucode_patch_header *phdr;
503  const struct amd_ucode_patch *patch;
504  struct ucode_descriptor desc;
505  size_t remaining;
506  size_t offset;
507  unsigned int count;
508  unsigned int used;
509  unsigned int i;
510 
511  /* Read header */
512  remaining = ( image->len - start );
513  if ( remaining < sizeof ( *hdr ) ) {
514  DBGC ( image, "UCODE %s+%#04zx too small for AMD header\n",
515  image->name, start );
516  return -ENOEXEC;
517  }
518  hdr = ( image->data + start );
519 
520  /* Check header */
521  if ( hdr->magic != AMD_UCODE_MAGIC ) {
522  DBGC2 ( image, "UCODE %s+%#04zx is not an AMD update\n",
523  image->name, start );
524  return -ENOEXEC;
525  }
526  DBGC2 ( image, "UCODE %s+%#04zx is an AMD update\n",
527  image->name, start );
528  if ( hdr->type != AMD_UCODE_EQUIV_TYPE ) {
529  DBGC ( image, "UCODE %s+%#04zx unsupported equivalence table "
530  "type %d\n", image->name, start, hdr->type );
531  return -ENOTSUP;
532  }
533  if ( hdr->len > ( remaining - sizeof ( *hdr ) ) ) {
534  DBGC ( image, "UCODE %s+%#04zx truncated equivalence table\n",
535  image->name, start );
536  return -EINVAL;
537  }
538 
539  /* Count number of equivalence table entries */
540  offset = sizeof ( *hdr );
541  equiv = ( image->data + start + offset );
542  for ( count = 0 ; offset < ( sizeof ( *hdr ) + hdr->len ) ;
543  count++, offset += sizeof ( *equiv ) ) {
544  if ( ! equiv[count].signature )
545  break;
546  }
547  DBGC2 ( image, "UCODE %s+%#04zx has %d equivalence table entries\n",
548  image->name, start, count );
549 
550  /* Parse available updates */
551  offset = ( sizeof ( *hdr ) + hdr->len );
552  used = 0;
553  while ( used < count ) {
554 
555  /* Read patch header */
556  if ( ( offset + sizeof ( *phdr ) ) > remaining ) {
557  DBGC ( image, "UCODE %s+%#04zx truncated patch "
558  "header\n", image->name, start );
559  return -EINVAL;
560  }
561  phdr = ( image->data + start + offset );
562  offset += sizeof ( *phdr );
563 
564  /* Validate patch header */
565  if ( phdr->type != AMD_UCODE_PATCH_TYPE ) {
566  DBGC ( image, "UCODE %s+%#04zx unsupported patch type "
567  "%d\n", image->name, start, phdr->type );
568  return -ENOTSUP;
569  }
570  if ( phdr->len < sizeof ( *patch ) ) {
571  DBGC ( image, "UCODE %s+%#04zx underlength patch\n",
572  image->name, start );
573  return -EINVAL;
574  }
575  if ( phdr->len > ( remaining - offset ) ) {
576  DBGC ( image, "UCODE %s+%#04zx truncated patch\n",
577  image->name, start );
578  return -EINVAL;
579  }
580 
581  /* Read patch and construct descriptor */
582  patch = ( image->data + start + offset );
583  desc.version = patch->version;
584  desc.address = ( virt_to_phys ( image->data ) +
585  start + offset );
586  offset += phdr->len;
587 
588  /* Parse equivalence table to find matching signatures */
589  for ( i = 0 ; i < count ; i++ ) {
590  if ( patch->id == equiv[i].id ) {
591  desc.signature = equiv[i].signature;
593  &desc, 0, update );
594  used++;
595  }
596  }
597  }
598 
599  return offset;
600 }
uint16_t id
Equivalence ID.
Definition: ucode.h:213
#define EINVAL
Invalid argument.
Definition: errno.h:428
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:322
const void * data
Read-only data.
Definition: image.h:50
static struct ucode_vendor ucode_amd
AMD CPU vendor.
Definition: ucode.c:119
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
#define DBGC(...)
Definition: compiler.h:505
uint32_t type
Patch type.
Definition: ucode.h:199
An executable image.
Definition: image.h:23
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
uint32_t start
Starting offset.
Definition: netvsc.h:12
struct ena_llq_option desc
Descriptor counts.
Definition: ena.h:20
A microcode update descriptor.
Definition: ucode.h:75
static unsigned int count
Number of entries.
Definition: dwmac.h:225
An AMD microcode equivalence table entry.
Definition: ucode.h:185
size_t len
Length of raw file image.
Definition: image.h:55
uint32_t len
Patch length.
Definition: ucode.h:201
An AMD microcode patch.
Definition: ucode.h:205
#define AMD_UCODE_PATCH_TYPE
AMD patch type.
Definition: ucode.h:219
uint32_t signature
CPU signature.
Definition: ucode.h:187
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
int32_t version
Microcode version.
Definition: ucode.h:209
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
u8 signature
CPU signature.
Definition: CIB_PRM.h:35
char * name
Name.
Definition: image.h:37

References AMD_UCODE_EQUIV_TYPE, AMD_UCODE_MAGIC, AMD_UCODE_PATCH_TYPE, 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, signature, amd_ucode_equivalence::signature, start, amd_ucode_patch_header::type, ucode_amd, ucode_describe(), 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 609 of file ucode.c.

609  {
610  size_t start;
611  int len;
612 
613  /* Attempt to parse concatenated microcode updates */
614  for ( start = 0 ; start < image->len ; start += len ) {
615 
616  /* Attempt to parse as Intel microcode */
617  len = ucode_parse_intel ( image, start, update );
618  if ( len > 0 )
619  continue;
620 
621  /* Attempt to parse as AMD microcode */
622  len = ucode_parse_amd ( image, start, update );
623  if ( len > 0 )
624  continue;
625 
626  /* Not a recognised microcode format */
627  DBGC ( image, "UCODE %s+%zx not recognised\n",
628  image->name, start );
629  return -ENOEXEC;
630  }
631 
632  return 0;
633 }
static int ucode_parse_amd(struct image *image, size_t start, struct ucode_update *update)
Parse AMD microcode image.
Definition: ucode.c:498
static int ucode_parse_intel(struct image *image, size_t start, struct ucode_update *update)
Parse Intel microcode image.
Definition: ucode.c:394
#define ENOEXEC
Exec format error.
Definition: errno.h:519
#define DBGC(...)
Definition: compiler.h:505
An executable image.
Definition: image.h:23
uint32_t start
Starting offset.
Definition: netvsc.h:12
ring len
Length.
Definition: dwmac.h:231
size_t len
Length of raw file image.
Definition: image.h:55
char * name
Name.
Definition: image.h:37

References DBGC, ENOEXEC, image::len, 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 641 of file ucode.c.

641  {
642  struct ucode_update update;
643  struct ucode_vendor *vendor;
644  struct ucode_summary summary;
645  union ucode_vendor_id id;
647  uint32_t discard_a;
648  uint32_t discard_b;
650  uint32_t discard_d;
651  unsigned int check;
652  unsigned int i;
653  size_t len;
654  int rc;
655 
656  /* Initialise update */
657  memset ( &update, 0, sizeof ( update ) );
658  cpuid ( CPUID_VENDOR_ID, 0, &discard_a, &id.dword[0], &id.dword[2],
659  &id.dword[1] );
660  cpuid ( CPUID_FEATURES, 0, &update.signature, &discard_b,
661  &discard_c, &discard_d );
662 
663  /* Identify CPU vendor, if recognised */
664  for ( i = 0 ; i < ( sizeof ( ucode_vendors ) /
665  sizeof ( ucode_vendors[0] ) ) ; i++ ) {
666  vendor = ucode_vendors[i];
667  if ( memcmp ( &id, &vendor->id, sizeof ( id ) ) == 0 )
668  update.vendor = vendor;
669  }
670 
671  /* Identify platform, if applicable */
672  if ( update.vendor == &ucode_intel ) {
673  platform_id = rdmsr ( MSR_PLATFORM_ID );
674  update.platform =
675  ( 1 << MSR_PLATFORM_ID_VALUE ( platform_id ) );
676  }
677 
678  /* Count number of matching update descriptors */
679  DBGC ( image, "UCODE %s applying to %s %#08x",
680  image->name, ucode_vendor_name ( &id ), update.signature );
681  if ( update.platform )
682  DBGC ( image, " (%#02x)", update.platform );
683  DBGC ( image, "\n" );
684  if ( ( rc = ucode_parse ( image, &update ) ) != 0 )
685  goto err_count;
686  DBGC ( image, "UCODE %s found %d matching update(s)\n",
687  image->name, update.count );
688 
689  /* Allocate descriptors */
690  len = ( ( update.count + 1 /* terminator */ ) *
691  sizeof ( update.desc[0] ) );
692  update.desc = zalloc ( len );
693  if ( ! update.desc ) {
694  rc = -ENOMEM;
695  goto err_alloc;
696  }
697 
698  /* Populate descriptors */
699  check = update.count;
700  update.count = 0;
701  if ( ( rc = ucode_parse ( image, &update ) ) != 0 )
702  goto err_parse;
703  assert ( check == update.count );
704 
705  /* Perform update */
706  if ( ( rc = ucode_update_all ( image, &update, &summary ) ) != 0 )
707  goto err_update;
708 
709  /* Print summary if directed to do so */
710  if ( image->cmdline && ( strstr ( image->cmdline, "-v" ) ) ) {
711  printf ( "Microcode: " );
712  if ( summary.low == summary.high ) {
713  printf ( "already version %#x", summary.low );
714  } else {
715  printf ( "updated version %#x->%#x",
716  summary.low, summary.high );
717  }
718  printf ( " (x%d)\n", summary.count );
719  }
720 
721  err_update:
722  err_parse:
723  free ( update.desc );
724  err_alloc:
725  err_count:
726  return rc;
727 }
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:43
static int ucode_parse(struct image *image, struct ucode_update *update)
Parse microcode image.
Definition: ucode.c:609
static unsigned short vendor
Definition: davicom.c:128
#define CPUID_VENDOR_ID
Get vendor ID and largest standard function.
Definition: cpuid.h:40
#define DBGC(...)
Definition: compiler.h:505
unsigned long long uint64_t
Definition: stdint.h:13
A microcode update.
Definition: ucode.c:87
A microcode update summary.
Definition: ucode.c:101
A CPU vendor string.
Definition: ucode.c:67
An executable image.
Definition: image.h:23
char * cmdline
Command line to pass to image.
Definition: image.h:42
#define MSR_PLATFORM_ID
Platform ID MSR.
Definition: ucode.h:16
static int ucode_update_all(struct image *image, const struct ucode_update *update, struct ucode_summary *summary)
Update microcode on all CPUs.
Definition: ucode.c:231
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:111
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
ring len
Length.
Definition: dwmac.h:231
#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:661
uint8_t platform_id
Platform ID.
Definition: eltorito.h:20
static struct ucode_vendor * ucode_vendors[]
List of known CPU vendors.
Definition: ucode.c:125
unsigned int uint32_t
Definition: stdint.h:12
static const char * ucode_vendor_name(const union ucode_vendor_id *vendor)
Get CPU vendor name (for debugging)
Definition: ucode.c:136
A CPU vendor.
Definition: ucode.c:75
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:37
unsigned long int dword
Definition: smc9000.h:40
void * memset(void *dest, int character, size_t len) __nonnull

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 735 of file ucode.c.

735  {
736  const union {
737  struct intel_ucode_header intel;
738  struct amd_ucode_header amd;
739  } *header;
740 
741  /* Sanity check */
742  if ( image->len < sizeof ( *header ) ) {
743  DBGC ( image, "UCODE %s too short\n", image->name );
744  return -ENOEXEC;
745  }
746 
747  /* Read first microcode image header */
748  header = image->data;
749 
750  /* Check for something that looks like an Intel update
751  *
752  * Intel updates unfortunately have no magic signatures or
753  * other easily verifiable fields. We check a small selection
754  * of header fields that can be easily verified.
755  *
756  * We do not attempt to fully parse the update, since we want
757  * errors to be reported at the point of attempting to execute
758  * the image, and do not want to have a microcode image
759  * erroneously treated as a PXE boot executable.
760  */
761  if ( ( header->intel.hver == INTEL_UCODE_HVER ) &&
762  ( header->intel.lver == INTEL_UCODE_LVER ) &&
763  ( ( header->intel.date.century == 0x19 ) ||
764  ( ( header->intel.date.century >= 0x20 ) &&
765  ( header->intel.date.century <= 0x29 ) ) ) ) {
766  DBGC ( image, "UCODE %s+%#04zx looks like an Intel update\n",
767  image->name, ( ( size_t ) 0 ) );
768  return 0;
769  }
770 
771  /* Check for AMD update signature */
772  if ( ( header->amd.magic == AMD_UCODE_MAGIC ) &&
773  ( header->amd.type == AMD_UCODE_EQUIV_TYPE ) ) {
774  DBGC ( image, "UCODE %s+%#04zx looks like an AMD update\n",
775  image->name, ( ( size_t ) 0 ) );
776  return 0;
777  }
778 
779  return -ENOEXEC;
780 }
#define INTEL_UCODE_HVER
Intel microcode header version number.
Definition: ucode.h:137
const void * data
Read-only data.
Definition: image.h:50
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
#define DBGC(...)
Definition: compiler.h:505
An executable image.
Definition: image.h:23
An Intel microcode update file header.
Definition: ucode.h:113
size_t len
Length of raw file image.
Definition: image.h:55
#define AMD_UCODE_MAGIC
AMD microcode magic signature.
Definition: ucode.h:179
struct ena_llq_option header
Header locations.
Definition: ena.h:16
#define INTEL_UCODE_LVER
Intel microcode loader version number.
Definition: ucode.h:140
char * name
Name.
Definition: image.h:37

References AMD_UCODE_EQUIV_TYPE, AMD_UCODE_MAGIC, 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 111 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 119 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:119
static struct ucode_vendor ucode_intel
Intel CPU vendor.
Definition: ucode.c:111

List of known CPU vendors.

Definition at line 125 of file ucode.c.

Referenced by ucode_exec().