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 <assert.h>
35 #include <errno.h>
36 #include <ipxe/uaccess.h>
37 #include <ipxe/umalloc.h>
38 #include <ipxe/image.h>
39 #include <ipxe/cpuid.h>
40 #include <ipxe/msr.h>
41 #include <ipxe/mp.h>
42 #include <ipxe/timer.h>
43 #include <ipxe/ucode.h>
44 
45 /**
46  * Maximum number of hyperthread siblings
47  *
48  * Microcode updates must not be performed on hyperthread siblings at
49  * the same time, since they share microcode storage.
50  *
51  * Hyperthread siblings are always the lowest level of the CPU
52  * topology and correspond to the least significant bits of the APIC
53  * ID. We may therefore avoid collisions by performing the microcode
54  * updates in batches, with each batch targeting just one value for
55  * the least significant N bits of the APIC ID.
56  *
57  * We assume that no CPUs exist with more than this number of
58  * hyperthread siblings. (This must be a power of two.)
59  */
60 #define UCODE_MAX_HT 8
61 
62 /** Time to wait for a microcode update to complete */
63 #define UCODE_WAIT_MS 10
64 
65 /** A CPU vendor string */
67  /** CPUID registers */
69  /** Human-readable string */
70  uint8_t string[12];
71 };
72 
73 /** A CPU vendor */
74 struct ucode_vendor {
75  /** Vendor string */
77  /** Microcode load trigger MSR */
79  /** Microcode version requires manual clear */
81  /** Microcode version is reported via high dword */
83 };
84 
85 /** A microcode update */
86 struct ucode_update {
87  /** CPU vendor, if known */
89  /** Boot processor CPU signature */
91  /** Platform ID */
93  /** Number of potentially relevant signatures found */
94  unsigned int count;
95  /** Update descriptors (if being populated) */
97 };
98 
99 /** A microcode update summary */
101  /** Number of CPUs processed */
102  unsigned int count;
103  /** Lowest observed microcode version */
105  /** Highest observed microcode version */
107 };
108 
109 /** Intel CPU vendor */
110 static struct ucode_vendor ucode_intel = {
111  .id = { .string = "GenuineIntel" },
112  .ver_clear = 1,
113  .ver_high = 1,
114  .trigger_msr = MSR_UCODE_TRIGGER_INTEL,
115 };
116 
117 /** AMD CPU vendor */
118 static struct ucode_vendor ucode_amd = {
119  .id = { .string = "AuthenticAMD" },
120  .trigger_msr = MSR_UCODE_TRIGGER_AMD,
121 };
122 
123 /** List of known CPU vendors */
124 static struct ucode_vendor *ucode_vendors[] = {
125  &ucode_intel,
126  &ucode_amd,
127 };
128 
129 /**
130  * Get CPU vendor name (for debugging)
131  *
132  * @v vendor CPU vendor
133  * @ret name Name
134  */
135 static const char * ucode_vendor_name ( const union ucode_vendor_id *vendor ) {
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 }
146 
147 /**
148  * Check status report
149  *
150  * @v update Microcode update
151  * @v control Microcode update control
152  * @v summary Microcode update summary
153  * @v id APIC ID
154  * @v optional Status report is optional
155  * @ret rc Return status code
156  */
157 static int ucode_status ( struct ucode_update *update,
158  struct ucode_control *control,
159  struct ucode_summary *summary,
160  unsigned int id, int optional ) {
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 }
224 
225 /**
226  * Update microcode on all CPUs
227  *
228  * @v image Microcode image
229  * @v update Microcode update
230  * @v summary Microcode update summary to fill in
231  * @ret rc Return status code
232  */
233 static int ucode_update_all ( struct image *image,
234  struct ucode_update *update,
235  struct ucode_summary *summary ) {
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 }
312 
313 /**
314  * Add descriptor to list (if applicable)
315  *
316  * @v image Microcode image
317  * @v start Starting offset within image
318  * @v vendor CPU vendor
319  * @v desc Microcode descriptor
320  * @v platforms Supported platforms, or 0 for all platforms
321  * @v update Microcode update
322  */
323 static void ucode_describe ( struct image *image, size_t start,
324  const struct ucode_vendor *vendor,
325  const struct ucode_descriptor *desc,
326  uint32_t platforms, struct ucode_update *update ) {
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 }
352 
353 /**
354  * Verify checksum
355  *
356  * @v image Microcode image
357  * @v start Starting offset
358  * @v len Length
359  * @ret rc Return status code
360  */
361 static int ucode_verify ( struct image *image, size_t start, size_t len ) {
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 }
388 
389 /**
390  * Parse Intel microcode image
391  *
392  * @v image Microcode image
393  * @v start Starting offset within image
394  * @v update Microcode update
395  * @ret len Length consumed, or negative error
396  */
397 static int ucode_parse_intel ( struct image *image, size_t start,
398  struct ucode_update *update ) {
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 }
494 
495 /**
496  * Parse AMD microcode image
497  *
498  * @v image Microcode image
499  * @v start Starting offset within image
500  * @v update Microcode update
501  * @ret len Length consumed, or negative error
502  */
503 static int ucode_parse_amd ( struct image *image, size_t start,
504  struct ucode_update *update ) {
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 }
612 
613 /**
614  * Parse microcode image
615  *
616  * @v image Microcode image
617  * @v update Microcode update
618  * @ret rc Return status code
619  */
620 static int ucode_parse ( struct image *image, struct ucode_update *update ) {
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 }
645 
646 /**
647  * Execute microcode update
648  *
649  * @v image Microcode image
650  * @ret rc Return status code
651  */
652 static int ucode_exec ( struct image *image ) {
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 }
739 
740 /**
741  * Probe microcode update image
742  *
743  * @v image Microcode image
744  * @ret rc Return status code
745  */
746 static int ucode_probe ( struct image *image ) {
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 }
792 
793 /** Microcode update image type */
794 struct image_type ucode_image_type __image_type ( PROBE_NORMAL ) = {
795  .name = "ucode",
796  .probe = ucode_probe,
797  .exec = ucode_exec,
798 };
uint16_t id
Equivalence ID.
Definition: ucode.h:213
#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:503
static int ucode_parse_intel(struct image *image, size_t start, struct ucode_update *update)
Parse Intel microcode image.
Definition: ucode.c:397
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
userptr_t data
Raw file image.
Definition: image.h:41
#define CPUID_FEATURES
Get standard features.
Definition: cpuid.h:40
#define max(x, y)
Definition: ath.h:39
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 ucode_descriptor * desc
Update descriptors (if being populated)
Definition: ucode.c:96
#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:620
Error codes.
static struct ucode_vendor ucode_amd
AMD CPU vendor.
Definition: ucode.c:118
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: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
#define CPUID_VENDOR_ID
Get vendor ID and largest standard function.
Definition: cpuid.h:37
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
struct ucode_vendor * vendor
CPU vendor, if known.
Definition: ucode.c:88
uint32_t type
Patch type.
Definition: ucode.h:199
An executable image type.
Definition: image.h:76
#define ENOENT
No such file or directory.
Definition: errno.h:514
#define PROBE_NORMAL
Normal image probe priority.
Definition: image.h:137
unsigned long long uint64_t
Definition: stdint.h:13
userptr_t phys_to_user(unsigned long phys_addr)
Convert physical address to user pointer.
A microcode update.
Definition: ucode.c:86
A microcode update summary.
Definition: ucode.c:100
uint32_t data_len
Microcode data size (or 0 to indicate 2000 bytes)
Definition: ucode.h:26
iPXE timers
A CPU vendor string.
Definition: ucode.c:66
An executable image.
Definition: image.h:24
uint8_t ver_high
Microcode version is reported via high dword.
Definition: ucode.c:82
static int ucode_exec(struct image *image)
Execute microcode update.
Definition: ucode.c:652
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:287
Access to external ("user") memory.
uint8_t checksum
Checksum.
Definition: pnpbios.c:37
uint32_t platforms
Supported platforms.
Definition: ucode.h:24
unsigned int count
Number of CPUs processed.
Definition: ucode.c:102
static int ucode_probe(struct image *image)
Probe microcode update image.
Definition: ucode.c:746
char * name
Name of this image type.
Definition: image.h:78
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
char * cmdline
Command line to pass to image.
Definition: image.h:39
#define MSR_PLATFORM_ID
Platform ID MSR.
Definition: ucode.h:16
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.
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.
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:110
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)
Executable images.
#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 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
A microcode update control.
Definition: ucode.h:45
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
uint8_t id
Request identifier.
Definition: ena.h:12
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:624
uint8_t platform_id
Platform ID.
Definition: eltorito.h:20
size_t len
Length of raw file image.
Definition: image.h:43
uint32_t len
Patch length.
Definition: ucode.h:201
int32_t low
Lowest observed microcode version.
Definition: ucode.c:104
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:124
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:78
uint32_t signature
CPU signature.
Definition: ucode.h:187
Multiprocessor functions.
#define UCODE_VERSION_MAX
Maximum possible microcode version.
Definition: ucode.h:38
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:60
static int ucode_status(struct ucode_update *update, struct ucode_control *control, struct ucode_summary *summary, unsigned int id, int optional)
Check status report.
Definition: ucode.c:157
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
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
#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:135
uint16_t id
Equivalence ID.
Definition: ucode.h:191
int32_t version
Microcode version.
Definition: ucode.h:209
#define EIO
Input/output error.
Definition: errno.h:433
uint16_t count
Number of entries.
Definition: ena.h:22
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:74
struct ena_aq_header header
Header.
Definition: ena.h:12
union @17 u
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
#define INTEL_UCODE_LVER
Intel microcode loader version number.
Definition: ucode.h:140
union ucode_vendor_id id
Vendor string.
Definition: ucode.c:76
uint8_t string[12]
Human-readable string.
Definition: ucode.c:70
long discard_c
Definition: bigint.h:32
uint8_t ver_clear
Microcode version requires manual clear.
Definition: ucode.c:80
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
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
int32_t high
Highest observed microcode version.
Definition: ucode.c:106
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.
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33
uint32_t apic_max
Maximum expected APIC ID.
Definition: ucode.h:18
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