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
24FILE_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 */
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 */
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 */
111static 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 */
119static struct ucode_vendor ucode_amd = {
120 .id = { .string = "AuthenticAMD" },
121 .trigger_msr = MSR_UCODE_TRIGGER_AMD,
122};
123
124/** List of known CPU vendors */
125static struct ucode_vendor *ucode_vendors[] = {
127 &ucode_amd,
128};
129
130/**
131 * Get CPU vendor name (for debugging)
132 *
133 * @v vendor CPU vendor
134 * @ret name Name
135 */
136static const char * ucode_vendor_name ( const union ucode_vendor_id *vendor ) {
137 static union {
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 */
159static 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 */
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 */
231static 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++ ) {
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 */
322static 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 */
360static 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",
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 */
394static 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 */
498static 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 ;
543 ( offset + sizeof ( *equiv ) ) <= ( sizeof ( *hdr ) + hdr->len );
544 count++, offset += sizeof ( *equiv ) ) {
545 if ( ! equiv[count].signature )
546 break;
547 }
548 DBGC2 ( image, "UCODE %s+%#04zx has %d equivalence table entries\n",
549 image->name, start, count );
550
551 /* Parse available updates */
552 offset = ( sizeof ( *hdr ) + hdr->len );
553 used = 0;
554 while ( used < count ) {
555
556 /* Read patch header */
557 if ( ( offset + sizeof ( *phdr ) ) > remaining ) {
558 DBGC ( image, "UCODE %s+%#04zx truncated patch "
559 "header\n", image->name, start );
560 return -EINVAL;
561 }
562 phdr = ( image->data + start + offset );
563 offset += sizeof ( *phdr );
564
565 /* Validate patch header */
566 if ( phdr->type != AMD_UCODE_PATCH_TYPE ) {
567 DBGC ( image, "UCODE %s+%#04zx unsupported patch type "
568 "%d\n", image->name, start, phdr->type );
569 return -ENOTSUP;
570 }
571 if ( phdr->len < sizeof ( *patch ) ) {
572 DBGC ( image, "UCODE %s+%#04zx underlength patch\n",
573 image->name, start );
574 return -EINVAL;
575 }
576 if ( phdr->len > ( remaining - offset ) ) {
577 DBGC ( image, "UCODE %s+%#04zx truncated patch\n",
578 image->name, start );
579 return -EINVAL;
580 }
581
582 /* Read patch and construct descriptor */
583 patch = ( image->data + start + offset );
584 desc.version = patch->version;
585 desc.address = ( virt_to_phys ( image->data ) +
586 start + offset );
587 offset += phdr->len;
588
589 /* Parse equivalence table to find matching signatures */
590 for ( i = 0 ; i < count ; i++ ) {
591 if ( patch->id == equiv[i].id ) {
592 desc.signature = equiv[i].signature;
594 &desc, 0, update );
595 used++;
596 }
597 }
598 }
599
600 return offset;
601}
602
603/**
604 * Parse microcode image
605 *
606 * @v image Microcode image
607 * @v update Microcode update
608 * @ret rc Return status code
609 */
610static int ucode_parse ( struct image *image, struct ucode_update *update ) {
611 size_t start;
612 int len;
613
614 /* Attempt to parse concatenated microcode updates */
615 for ( start = 0 ; start < image->len ; start += len ) {
616
617 /* Attempt to parse as Intel microcode */
618 len = ucode_parse_intel ( image, start, update );
619 if ( len > 0 )
620 continue;
621
622 /* Attempt to parse as AMD microcode */
623 len = ucode_parse_amd ( image, start, update );
624 if ( len > 0 )
625 continue;
626
627 /* Not a recognised microcode format */
628 DBGC ( image, "UCODE %s+%zx not recognised\n",
629 image->name, start );
630 return -ENOEXEC;
631 }
632
633 return 0;
634}
635
636/**
637 * Execute microcode update
638 *
639 * @v image Microcode image
640 * @ret rc Return status code
641 */
642static int ucode_exec ( struct image *image ) {
643 struct ucode_update update;
644 struct ucode_vendor *vendor;
645 struct ucode_summary summary;
646 union ucode_vendor_id id;
648 uint32_t discard_a;
649 uint32_t discard_b;
651 uint32_t discard_d;
652 unsigned int check;
653 unsigned int i;
654 size_t len;
655 int rc;
656
657 /* Initialise update */
658 memset ( &update, 0, sizeof ( update ) );
659 cpuid ( CPUID_VENDOR_ID, 0, &discard_a, &id.dword[0], &id.dword[2],
660 &id.dword[1] );
661 cpuid ( CPUID_FEATURES, 0, &update.signature, &discard_b,
662 &discard_c, &discard_d );
663
664 /* Identify CPU vendor, if recognised */
665 for ( i = 0 ; i < ( sizeof ( ucode_vendors ) /
666 sizeof ( ucode_vendors[0] ) ) ; i++ ) {
668 if ( memcmp ( &id, &vendor->id, sizeof ( id ) ) == 0 )
669 update.vendor = vendor;
670 }
671
672 /* Identify platform, if applicable */
673 if ( update.vendor == &ucode_intel ) {
674 platform_id = rdmsr ( MSR_PLATFORM_ID );
675 update.platform =
677 }
678
679 /* Count number of matching update descriptors */
680 DBGC ( image, "UCODE %s applying to %s %#08x",
681 image->name, ucode_vendor_name ( &id ), update.signature );
682 if ( update.platform )
683 DBGC ( image, " (%#02x)", update.platform );
684 DBGC ( image, "\n" );
685 if ( ( rc = ucode_parse ( image, &update ) ) != 0 )
686 goto err_count;
687 DBGC ( image, "UCODE %s found %d matching update(s)\n",
688 image->name, update.count );
689
690 /* Allocate descriptors */
691 len = ( ( update.count + 1 /* terminator */ ) *
692 sizeof ( update.desc[0] ) );
693 update.desc = zalloc ( len );
694 if ( ! update.desc ) {
695 rc = -ENOMEM;
696 goto err_alloc;
697 }
698
699 /* Populate descriptors */
700 check = update.count;
701 update.count = 0;
702 if ( ( rc = ucode_parse ( image, &update ) ) != 0 )
703 goto err_parse;
704 assert ( check == update.count );
705
706 /* Perform update */
707 if ( ( rc = ucode_update_all ( image, &update, &summary ) ) != 0 )
708 goto err_update;
709
710 /* Print summary if directed to do so */
711 if ( image->cmdline && ( strstr ( image->cmdline, "-v" ) ) ) {
712 printf ( "Microcode: " );
713 if ( summary.low == summary.high ) {
714 printf ( "already version %#x", summary.low );
715 } else {
716 printf ( "updated version %#x->%#x",
717 summary.low, summary.high );
718 }
719 printf ( " (x%d)\n", summary.count );
720 }
721
722 err_update:
723 err_parse:
724 free ( update.desc );
725 err_alloc:
726 err_count:
727 return rc;
728}
729
730/**
731 * Probe microcode update image
732 *
733 * @v image Microcode image
734 * @ret rc Return status code
735 */
736static int ucode_probe ( struct image *image ) {
737 const union {
738 struct intel_ucode_header intel;
739 struct amd_ucode_header amd;
740 } *header;
741
742 /* Sanity check */
743 if ( image->len < sizeof ( *header ) ) {
744 DBGC ( image, "UCODE %s too short\n", image->name );
745 return -ENOEXEC;
746 }
747
748 /* Read first microcode image header */
749 header = image->data;
750
751 /* Check for something that looks like an Intel update
752 *
753 * Intel updates unfortunately have no magic signatures or
754 * other easily verifiable fields. We check a small selection
755 * of header fields that can be easily verified.
756 *
757 * We do not attempt to fully parse the update, since we want
758 * errors to be reported at the point of attempting to execute
759 * the image, and do not want to have a microcode image
760 * erroneously treated as a PXE boot executable.
761 */
762 if ( ( header->intel.hver == INTEL_UCODE_HVER ) &&
763 ( header->intel.lver == INTEL_UCODE_LVER ) &&
764 ( ( header->intel.date.century == 0x19 ) ||
765 ( ( header->intel.date.century >= 0x20 ) &&
766 ( header->intel.date.century <= 0x29 ) ) ) ) {
767 DBGC ( image, "UCODE %s+%#04zx looks like an Intel update\n",
768 image->name, ( ( size_t ) 0 ) );
769 return 0;
770 }
771
772 /* Check for AMD update signature */
773 if ( ( header->amd.magic == AMD_UCODE_MAGIC ) &&
774 ( header->amd.type == AMD_UCODE_EQUIV_TYPE ) ) {
775 DBGC ( image, "UCODE %s+%#04zx looks like an AMD update\n",
776 image->name, ( ( size_t ) 0 ) );
777 return 0;
778 }
779
780 return -ENOEXEC;
781}
782
783/** Microcode update image type */
784struct image_type ucode_image_type __image_type ( PROBE_NORMAL ) = {
785 .name = "ucode",
786 .probe = ucode_probe,
787 .exec = ucode_exec,
788};
struct golan_inbox_hdr hdr
Message header.
Definition CIB_PRM.h:0
u8 signature
CPU signature.
Definition CIB_PRM.h:7
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned int uint32_t
Definition stdint.h:12
unsigned long long uint64_t
Definition stdint.h:13
signed int int32_t
Definition stdint.h:17
unsigned char uint8_t
Definition stdint.h:10
long discard_c
Definition bigint.h:32
Assertions.
#define build_assert(condition)
Assert a condition at build time (after dead code elimination).
Definition assert.h:88
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
#define max(x, y)
Definition ath.h:41
uint16_t offset
Offset to command line.
Definition bzimage.h:3
x86 CPU feature detection
#define CPUID_FEATURES
Get standard features.
Definition cpuid.h:44
#define CPUID_VENDOR_ID
Get vendor ID and largest standard function.
Definition cpuid.h:41
static unsigned short vendor
Definition davicom.c:128
union @104331263140136355135267063077374276003064103115 u
ring len
Length.
Definition dwmac.h:226
uint8_t platform_id
Platform ID.
Definition eltorito.h:8
uint8_t id
Request identifier.
Definition ena.h:1
uint16_t ext
Extended status.
Definition ena.h:9
struct ena_llq_option header
Header locations.
Definition ena.h:5
uint8_t status
Status.
Definition ena.h:5
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
Error codes.
#define DBGC2(...)
Definition compiler.h:547
#define DBGC(...)
Definition compiler.h:530
uint32_t start
Starting offset.
Definition netvsc.h:1
static unsigned int count
Number of entries.
Definition dwmac.h:220
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define ENOENT
No such file or directory.
Definition errno.h:558
#define EINVAL
Invalid argument.
Definition errno.h:472
#define ENOEXEC
Exec format error.
Definition errno.h:563
#define ENOMEM
Not enough space.
Definition errno.h:578
#define EIO
Input/output error.
Definition errno.h:477
#define ENOTSUP
Operation not supported.
Definition errno.h:633
#define ERANGE
Result too large.
Definition errno.h:683
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:638
Executable images.
#define PROBE_NORMAL
Normal image probe priority.
Definition image.h:163
#define __image_type(probe_order)
An executable image type.
Definition image.h:177
Multiprocessor functions.
void mp_exec_boot(mp_func_t func, void *opaque)
Execute a multiprocessor function on the boot processor.
void mp_start_all(mp_func_t func, void *opaque)
Start a multiprocessor function on all application processors.
iPXE timers
User memory allocation.
static __always_inline void * umalloc(size_t size)
Allocate external memory.
Definition umalloc.h:57
static __always_inline void ufree(void *ptr)
Free external memory.
Definition umalloc.h:68
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
Access to external ("user") memory.
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
unsigned int mp_boot_cpuid(void)
Get boot CPU identifier.
Definition mp.c:43
unsigned int mp_max_cpuid(void)
Get maximum CPU identifier.
Definition mp.c:58
Model-specific registers.
uint32_t control
Control.
Definition myson.h:3
uint8_t checksum
Checksum.
Definition pnpbios.c:12
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
unsigned long int dword
Definition smc9000.h:40
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition string.c:324
An AMD microcode equivalence table entry.
Definition ucode.h:185
uint32_t signature
CPU signature.
Definition ucode.h:187
uint16_t id
Equivalence ID.
Definition ucode.h:191
An AMD microcode update file header.
Definition ucode.h:169
An AMD microcode patch header.
Definition ucode.h:197
uint32_t type
Patch type.
Definition ucode.h:199
uint32_t len
Patch length.
Definition ucode.h:201
An AMD microcode patch.
Definition ucode.h:205
int32_t version
Microcode version.
Definition ucode.h:209
uint16_t id
Equivalence ID.
Definition ucode.h:213
An executable image type.
Definition image.h:102
An executable image.
Definition image.h:24
const void * data
Read-only data.
Definition image.h:51
char * name
Name.
Definition image.h:38
size_t len
Length of raw file image.
Definition image.h:63
char * cmdline
Command line to pass to image.
Definition image.h:43
An Intel microcode update file extended header.
Definition ucode.h:149
uint32_t count
Extended signature count.
Definition ucode.h:151
An Intel microcode extended signature.
Definition ucode.h:159
An Intel microcode update file header.
Definition ucode.h:113
A microcode update control.
Definition ucode.h:45
A microcode update descriptor.
Definition ucode.h:75
A microcode update status report.
Definition ucode.h:89
A microcode update summary.
Definition ucode.c:101
unsigned int count
Number of CPUs processed.
Definition ucode.c:103
int32_t high
Highest observed microcode version.
Definition ucode.c:107
int32_t low
Lowest observed microcode version.
Definition ucode.c:105
A microcode update.
Definition ucode.c:87
uint32_t signature
Boot processor CPU signature.
Definition ucode.c:91
uint32_t platform
Platform ID.
Definition ucode.c:93
struct ucode_descriptor * desc
Update descriptors (if being populated).
Definition ucode.c:97
struct ucode_vendor * vendor
CPU vendor, if known.
Definition ucode.c:89
unsigned int count
Number of potentially relevant signatures found.
Definition ucode.c:95
A CPU vendor.
Definition ucode.c:75
uint32_t trigger_msr
Microcode load trigger MSR.
Definition ucode.c:79
uint8_t ver_high
Microcode version is reported via high dword.
Definition ucode.c:83
union ucode_vendor_id id
Vendor string.
Definition ucode.c:77
uint8_t ver_clear
Microcode version requires manual clear.
Definition ucode.c:81
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79
static int ucode_probe(struct image *image)
Probe microcode update image.
Definition ucode.c:736
static struct ucode_vendor ucode_amd
AMD CPU vendor.
Definition ucode.c:119
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
static struct ucode_vendor * ucode_vendors[]
List of known CPU vendors.
Definition ucode.c:125
#define UCODE_MAX_HT
Maximum number of hyperthread siblings.
Definition ucode.c:61
static int ucode_parse_intel(struct image *image, size_t start, struct ucode_update *update)
Parse Intel microcode image.
Definition ucode.c:394
static struct ucode_vendor ucode_intel
Intel CPU vendor.
Definition ucode.c:111
static const char * ucode_vendor_name(const union ucode_vendor_id *vendor)
Get CPU vendor name (for debugging).
Definition ucode.c:136
static int ucode_exec(struct image *image)
Execute microcode update.
Definition ucode.c:642
#define UCODE_WAIT_MS
Time to wait for a microcode update to complete.
Definition ucode.c:64
static int ucode_parse(struct image *image, struct ucode_update *update)
Parse microcode image.
Definition ucode.c:610
static int ucode_parse_amd(struct image *image, size_t start, struct ucode_update *update)
Parse AMD microcode image.
Definition ucode.c:498
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
static int ucode_verify(struct image *image, size_t start, size_t len)
Verify checksum.
Definition ucode.c:360
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
Microcode updates.
uint32_t apic_max
Maximum expected APIC ID.
Definition ucode.h:7
#define MSR_UCODE_TRIGGER_AMD
AMD microcode load trigger MSR.
Definition ucode.h:25
#define INTEL_UCODE_LVER
Intel microcode loader version number.
Definition ucode.h:140
uint32_t data_len
Microcode data size (or 0 to indicate 2000 bytes).
Definition ucode.h:15
#define INTEL_UCODE_DATA_LEN
Intel microcode default data length.
Definition ucode.h:143
#define INTEL_UCODE_HVER
Intel microcode header version number.
Definition ucode.h:137
#define UCODE_SIGNATURE_MASK
CPUID signature applicability mask.
Definition ucode.h:32
#define AMD_UCODE_MAGIC
AMD microcode magic signature.
Definition ucode.h:179
#define AMD_UCODE_EQUIV_TYPE
AMD microcode equivalence table type.
Definition ucode.h:182
#define AMD_UCODE_PATCH_TYPE
AMD patch type.
Definition ucode.h:219
#define INTEL_UCODE_ALIGN
Intel microcode file alignment.
Definition ucode.h:146
#define MSR_PLATFORM_ID
Platform ID MSR.
Definition ucode.h:16
#define MSR_UCODE_TRIGGER_INTEL
Intel microcode load trigger MSR.
Definition ucode.h:22
#define MSR_PLATFORM_ID_VALUE(value)
Extract platform ID from MSR value.
Definition ucode.h:19
#define UCODE_VERSION_MAX
Maximum possible microcode version.
Definition ucode.h:38
uint32_t platforms
Supported platforms.
Definition ucode.h:13
#define UCODE_VERSION_MIN
Minimum possible microcode version.
Definition ucode.h:35
A CPU vendor string.
Definition ucode.c:67
uint32_t dword[3]
CPUID registers.
Definition ucode.c:69
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition vsprintf.c:485