iPXE
ucode.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 /** @file
27  *
28  * Microcode updates
29  *
30  */
31 
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <errno.h>
37 #include <ipxe/uaccess.h>
38 #include <ipxe/umalloc.h>
39 #include <ipxe/image.h>
40 #include <ipxe/cpuid.h>
41 #include <ipxe/msr.h>
42 #include <ipxe/mp.h>
43 #include <ipxe/timer.h>
44 #include <ipxe/ucode.h>
45 
46 /**
47  * Maximum number of hyperthread siblings
48  *
49  * Microcode updates must not be performed on hyperthread siblings at
50  * the same time, since they share microcode storage.
51  *
52  * Hyperthread siblings are always the lowest level of the CPU
53  * topology and correspond to the least significant bits of the APIC
54  * ID. We may therefore avoid collisions by performing the microcode
55  * updates in batches, with each batch targeting just one value for
56  * the least significant N bits of the APIC ID.
57  *
58  * We assume that no CPUs exist with more than this number of
59  * hyperthread siblings. (This must be a power of two.)
60  */
61 #define UCODE_MAX_HT 8
62 
63 /** Time to wait for a microcode update to complete */
64 #define UCODE_WAIT_MS 10
65 
66 /** A CPU vendor string */
68  /** CPUID registers */
70  /** Human-readable string */
71  uint8_t string[12];
72 };
73 
74 /** A CPU vendor */
75 struct ucode_vendor {
76  /** Vendor string */
78  /** Microcode load trigger MSR */
80  /** Microcode version requires manual clear */
82  /** Microcode version is reported via high dword */
84 };
85 
86 /** A microcode update */
87 struct ucode_update {
88  /** CPU vendor, if known */
90  /** Boot processor CPU signature */
92  /** Platform ID */
94  /** Number of potentially relevant signatures found */
95  unsigned int count;
96  /** Update descriptors (if being populated) */
98 };
99 
100 /** A microcode update summary */
102  /** Number of CPUs processed */
103  unsigned int count;
104  /** Lowest observed microcode version */
106  /** Highest observed microcode version */
108 };
109 
110 /** Intel CPU vendor */
111 static struct ucode_vendor ucode_intel = {
112  .id = { .string = "GenuineIntel" },
113  .ver_clear = 1,
114  .ver_high = 1,
115  .trigger_msr = MSR_UCODE_TRIGGER_INTEL,
116 };
117 
118 /** AMD CPU vendor */
119 static struct ucode_vendor ucode_amd = {
120  .id = { .string = "AuthenticAMD" },
121  .trigger_msr = MSR_UCODE_TRIGGER_AMD,
122 };
123 
124 /** List of known CPU vendors */
125 static struct ucode_vendor *ucode_vendors[] = {
126  &ucode_intel,
127  &ucode_amd,
128 };
129 
130 /**
131  * Get CPU vendor name (for debugging)
132  *
133  * @v vendor CPU vendor
134  * @ret name Name
135  */
136 static const char * ucode_vendor_name ( const union ucode_vendor_id *vendor ) {
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 }
147 
148 /**
149  * Check status report
150  *
151  * @v update Microcode update
152  * @v control Microcode update control
153  * @v status Microcode update status
154  * @v summary Microcode update summary
155  * @v id APIC ID
156  * @v optional Status report is optional
157  * @ret rc Return status code
158  */
159 static int ucode_status ( const struct ucode_update *update,
160  const struct ucode_control *control,
161  const struct ucode_status *status,
162  struct ucode_summary *summary,
163  unsigned int id, int optional ) {
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 }
222 
223 /**
224  * Update microcode on all CPUs
225  *
226  * @v image Microcode image
227  * @v update Microcode update
228  * @v summary Microcode update summary to fill in
229  * @ret rc Return status code
230  */
231 static int ucode_update_all ( struct image *image,
232  const struct ucode_update *update,
233  struct ucode_summary *summary ) {
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 }
311 
312 /**
313  * Add descriptor to list (if applicable)
314  *
315  * @v image Microcode image
316  * @v start Starting offset within image
317  * @v vendor CPU vendor
318  * @v desc Microcode descriptor
319  * @v platforms Supported platforms, or 0 for all platforms
320  * @v update Microcode update
321  */
322 static void ucode_describe ( struct image *image, size_t start,
323  const struct ucode_vendor *vendor,
324  const struct ucode_descriptor *desc,
325  uint32_t platforms, struct ucode_update *update ) {
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 }
351 
352 /**
353  * Verify checksum
354  *
355  * @v image Microcode image
356  * @v start Starting offset
357  * @v len Length
358  * @ret rc Return status code
359  */
360 static int ucode_verify ( struct image *image, size_t start, size_t len ) {
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 }
385 
386 /**
387  * Parse Intel microcode image
388  *
389  * @v image Microcode image
390  * @v start Starting offset within image
391  * @v update Microcode update
392  * @ret len Length consumed, or negative error
393  */
394 static int ucode_parse_intel ( struct image *image, size_t start,
395  struct ucode_update *update ) {
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 }
489 
490 /**
491  * Parse AMD microcode image
492  *
493  * @v image Microcode image
494  * @v start Starting offset within image
495  * @v update Microcode update
496  * @ret len Length consumed, or negative error
497  */
498 static int ucode_parse_amd ( struct image *image, size_t start,
499  struct ucode_update *update ) {
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 }
601 
602 /**
603  * Parse microcode image
604  *
605  * @v image Microcode image
606  * @v update Microcode update
607  * @ret rc Return status code
608  */
609 static int ucode_parse ( struct image *image, struct ucode_update *update ) {
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 }
634 
635 /**
636  * Execute microcode update
637  *
638  * @v image Microcode image
639  * @ret rc Return status code
640  */
641 static int ucode_exec ( struct image *image ) {
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 }
728 
729 /**
730  * Probe microcode update image
731  *
732  * @v image Microcode image
733  * @ret rc Return status code
734  */
735 static int ucode_probe ( struct image *image ) {
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 }
781 
782 /** Microcode update image type */
783 struct image_type ucode_image_type __image_type ( PROBE_NORMAL ) = {
784  .name = "ucode",
785  .probe = ucode_probe,
786  .exec = ucode_exec,
787 };
uint16_t id
Equivalence ID.
Definition: ucode.h:213
static __always_inline void ufree(void *ptr)
Free external memory.
Definition: umalloc.h:67
#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
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
uint8_t checksum
Checksum.
Definition: pnpbios.c:37
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
#define max(x, y)
Definition: ath.h:40
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
struct ucode_descriptor * desc
Update descriptors (if being populated)
Definition: ucode.c:97
#define MSR_UCODE_TRIGGER_INTEL
Intel microcode load trigger MSR.
Definition: ucode.h:22
static int ucode_parse(struct image *image, struct ucode_update *update)
Parse microcode image.
Definition: ucode.c:609
Error codes.
const void * data
Read-only data.
Definition: image.h:50
static struct ucode_vendor ucode_amd
AMD CPU vendor.
Definition: ucode.c:119
Microcode updates.
struct golan_inbox_hdr hdr
Message header.
Definition: CIB_PRM.h:28
#define UCODE_VERSION_MIN
Minimum possible microcode version.
Definition: ucode.h:35
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 unsigned short vendor
Definition: davicom.c:128
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 CPUID_VENDOR_ID
Get vendor ID and largest standard function.
Definition: cpuid.h:40
#define DBGC(...)
Definition: compiler.h:505
struct ucode_vendor * vendor
CPU vendor, if known.
Definition: ucode.c:89
uint32_t type
Patch type.
Definition: ucode.h:199
An executable image type.
Definition: image.h:94
#define ENOENT
No such file or directory.
Definition: errno.h:514
#define PROBE_NORMAL
Normal image probe priority.
Definition: image.h:155
unsigned long long uint64_t
Definition: stdint.h:13
A microcode update.
Definition: ucode.c:87
A microcode update summary.
Definition: ucode.c:101
uint32_t data_len
Microcode data size (or 0 to indicate 2000 bytes)
Definition: ucode.h:26
iPXE timers
union @18 u
A CPU vendor string.
Definition: ucode.c:67
An executable image.
Definition: image.h:23
uint8_t ver_high
Microcode version is reported via high dword.
Definition: ucode.c:83
static int ucode_exec(struct image *image)
Execute microcode update.
Definition: ucode.c:641
uint32_t platforms
Supported platforms.
Definition: ucode.h:24
unsigned int count
Number of CPUs processed.
Definition: ucode.c:103
static int ucode_probe(struct image *image)
Probe microcode update image.
Definition: ucode.c:735
char * name
Name of this image type.
Definition: image.h:96
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
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
uint32_t start
Starting offset.
Definition: netvsc.h:12
void mp_start_all(mp_func_t func, void *opaque)
Start a multiprocessor function on all application processors.
struct ena_llq_option desc
Descriptor counts.
Definition: ena.h:20
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition: string.c:309
A microcode update descriptor.
Definition: ucode.h:75
#define ENOMEM
Not enough space.
Definition: errno.h:534
static struct ucode_vendor ucode_intel
Intel CPU vendor.
Definition: ucode.c:111
void * memcpy(void *dest, const void *src, size_t len) __nonnull
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
Assertions.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
Access to external ("user") memory.
Executable images.
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
#define MSR_PLATFORM_ID_VALUE(value)
Extract platform ID from MSR value.
Definition: ucode.h:19
static unsigned int count
Number of entries.
Definition: dwmac.h:225
An AMD microcode equivalence table entry.
Definition: ucode.h:185
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
An Intel microcode update file header.
Definition: ucode.h:113
#define ERANGE
Result too large.
Definition: errno.h:639
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
x86 CPU feature detection
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:661
uint8_t platform_id
Platform ID.
Definition: eltorito.h:20
size_t len
Length of raw file image.
Definition: image.h:55
uint32_t len
Patch length.
Definition: ucode.h:201
int32_t low
Lowest observed microcode version.
Definition: ucode.c:105
User memory allocation.
uint32_t control
Control.
Definition: myson.h:14
static struct ucode_vendor * ucode_vendors[]
List of known CPU vendors.
Definition: ucode.c:125
An AMD microcode patch.
Definition: ucode.h:205
unsigned int mp_boot_cpuid(void)
Get boot CPU identifier.
Definition: mp.c:43
unsigned char uint8_t
Definition: stdint.h:10
uint32_t count
Extended signature count.
Definition: ucode.h:151
unsigned int uint32_t
Definition: stdint.h:12
#define AMD_UCODE_PATCH_TYPE
AMD patch type.
Definition: ucode.h:219
uint32_t trigger_msr
Microcode load trigger MSR.
Definition: ucode.c:79
uint32_t signature
CPU signature.
Definition: ucode.h:187
Multiprocessor functions.
#define UCODE_VERSION_MAX
Maximum possible microcode version.
Definition: ucode.h:38
uint8_t status
Status.
Definition: ena.h:16
uint16_t ext
Extended status.
Definition: ena.h:20
A microcode update status report.
Definition: ucode.h:89
#define UCODE_MAX_HT
Maximum number of hyperthread siblings.
Definition: ucode.c:61
An AMD microcode patch header.
Definition: ucode.h:197
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition: timer.c:78
signed int int32_t
Definition: stdint.h:17
#define DBGC2(...)
Definition: compiler.h:522
#define AMD_UCODE_MAGIC
AMD microcode magic signature.
Definition: ucode.h:179
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
static const char * ucode_vendor_name(const union ucode_vendor_id *vendor)
Get CPU vendor name (for debugging)
Definition: ucode.c:136
uint16_t id
Equivalence ID.
Definition: ucode.h:191
static __always_inline void * umalloc(size_t size)
Allocate external memory.
Definition: umalloc.h:56
int32_t version
Microcode version.
Definition: ucode.h:209
#define EIO
Input/output error.
Definition: errno.h:433
struct image_type ucode_image_type __image_type(PROBE_NORMAL)
Microcode update image type.
#define MSR_UCODE_TRIGGER_AMD
AMD microcode load trigger MSR.
Definition: ucode.h:25
A CPU vendor.
Definition: ucode.c:75
struct ena_llq_option header
Header locations.
Definition: ena.h:16
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
#define INTEL_UCODE_LVER
Intel microcode loader version number.
Definition: ucode.h:140
union ucode_vendor_id id
Vendor string.
Definition: ucode.c:77
uint8_t string[12]
Human-readable string.
Definition: ucode.c:71
long discard_c
Definition: bigint.h:32
uint8_t ver_clear
Microcode version requires manual clear.
Definition: ucode.c:81
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
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
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.
Definition: ucode.c:159
u8 signature
CPU signature.
Definition: CIB_PRM.h:35
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
String functions.
int32_t high
Highest observed microcode version.
Definition: ucode.c:107
unsigned long int dword
Definition: smc9000.h:40
#define INTEL_UCODE_DATA_LEN
Intel microcode default data length.
Definition: ucode.h:143
#define UCODE_SIGNATURE_MASK
CPUID signature applicability mask.
Definition: ucode.h:32
#define INTEL_UCODE_ALIGN
Intel microcode file alignment.
Definition: ucode.h:146
Model-specific registers.
uint32_t apic_max
Maximum expected APIC ID.
Definition: ucode.h:18
void * memset(void *dest, int character, size_t len) __nonnull