@@ -341,6 +341,146 @@ static void dt_filenames_free(char16_t **dt_filenames, size_t n_dt) {
341
341
free (dt_filenames );
342
342
}
343
343
344
+ static EFI_STATUS ucode_merge_and_measure_addons (
345
+ void * * ucode_bases_addon_global ,
346
+ size_t * ucode_sizes_addon_global ,
347
+ size_t n_ucode_addons_global ,
348
+ void * * ucode_bases_addon_uki ,
349
+ size_t * ucode_sizes_addon_uki ,
350
+ size_t n_ucode_addons_uki ,
351
+ void * ucode_section_base ,
352
+ size_t ucode_section_size ,
353
+ void * * ret_ucode_base ,
354
+ size_t * ret_ucode_size ,
355
+ bool * ret_sections_measured ) {
356
+
357
+ int sections_measured = -1 ;
358
+ EFI_STATUS err ;
359
+
360
+ assert (ret_ucode_base );
361
+ assert (ret_ucode_size );
362
+ assert (ret_sections_measured );
363
+
364
+ _cleanup_pages_ Pages global_addons_combined_pages = {}, uki_addons_combined_pages = {}, all_ucode_combined_pages = {};
365
+ void * global_addons_combined_base = NULL , * uki_addons_combined_base = NULL ;
366
+ size_t global_addons_combined_size = 0 , uki_addons_combined_size = 0 , all_ucode_combined_size = 0 ;
367
+
368
+ if (n_ucode_addons_global == 0 && n_ucode_addons_uki == 0 && ucode_section_size == 0 ) {
369
+ return EFI_SUCCESS ;
370
+ }
371
+
372
+ /* Order of ucode merging (and measurements):
373
+ * 1. UKI embedded .ucode section
374
+ * 2. Global addons
375
+ * 3. UKI addons
376
+ */
377
+
378
+ /* .ucode section from UKI is already measured as part of the full UKI measurements */
379
+ /* Measure global addons */
380
+ for (size_t i = 0 ; i < n_ucode_addons_global ; i ++ ) {
381
+ bool m = false;
382
+ /* First measure the name of the section */
383
+ (void ) tpm_log_event_ascii (
384
+ TPM2_PCR_KERNEL_BOOT ,
385
+ POINTER_TO_PHYSICAL_ADDRESS (unified_sections [UNIFIED_SECTION_UCODE ]),
386
+ strsize8 (unified_sections [UNIFIED_SECTION_UCODE ]), /* including NUL byte */
387
+ unified_sections [UNIFIED_SECTION_UCODE ],
388
+ & m );
389
+
390
+ sections_measured = sections_measured < 0 ? m : (sections_measured && m );
391
+
392
+ /* Then measure the data of the section */
393
+ (void ) tpm_log_event_ascii (
394
+ TPM2_PCR_KERNEL_BOOT ,
395
+ POINTER_TO_PHYSICAL_ADDRESS (ucode_bases_addon_global [i ]),
396
+ ucode_sizes_addon_global [i ],
397
+ unified_sections [UNIFIED_SECTION_UCODE ],
398
+ & m );
399
+
400
+ sections_measured = sections_measured < 0 ? m : (sections_measured && m );
401
+ }
402
+ /* Merge global addons */
403
+ if (n_ucode_addons_global == 1 ) {
404
+ global_addons_combined_base = ucode_bases_addon_global [0 ];
405
+ global_addons_combined_size = ucode_sizes_addon_global [0 ];
406
+ } else if (n_ucode_addons_global > 1 ) {
407
+ err = combine_initrds (* ucode_bases_addon_global , ucode_sizes_addon_global , n_ucode_addons_global , & global_addons_combined_pages , & global_addons_combined_size );
408
+ if (err != EFI_SUCCESS )
409
+ return err ;
410
+ global_addons_combined_base = PHYSICAL_ADDRESS_TO_POINTER (global_addons_combined_pages .addr );
411
+ }
412
+
413
+
414
+ /* Measure UKI addons */
415
+ for (size_t i = 0 ; i < n_ucode_addons_uki ; i ++ ) {
416
+ bool m = false;
417
+ /* First measure the name of the section */
418
+ (void ) tpm_log_event_ascii (
419
+ TPM2_PCR_KERNEL_BOOT ,
420
+ POINTER_TO_PHYSICAL_ADDRESS (unified_sections [UNIFIED_SECTION_UCODE ]),
421
+ strsize8 (unified_sections [UNIFIED_SECTION_UCODE ]), /* including NUL byte */
422
+ unified_sections [UNIFIED_SECTION_UCODE ],
423
+ & m );
424
+
425
+ sections_measured = sections_measured < 0 ? m : (sections_measured && m );
426
+
427
+ /* Then measure the data of the section */
428
+ (void ) tpm_log_event_ascii (
429
+ TPM2_PCR_KERNEL_BOOT ,
430
+ POINTER_TO_PHYSICAL_ADDRESS (ucode_bases_addon_uki [i ]),
431
+ ucode_sizes_addon_uki [i ],
432
+ unified_sections [UNIFIED_SECTION_UCODE ],
433
+ & m );
434
+
435
+ sections_measured = sections_measured < 0 ? m : (sections_measured && m );
436
+ }
437
+ /* Merge UKI addons */
438
+ if (n_ucode_addons_uki == 1 ) {
439
+ uki_addons_combined_base = ucode_bases_addon_uki [0 ];
440
+ uki_addons_combined_size = ucode_sizes_addon_uki [0 ];
441
+ } else if (n_ucode_addons_uki > 1 ) {
442
+ err = combine_initrds (* ucode_bases_addon_uki , ucode_sizes_addon_uki , n_ucode_addons_uki , & uki_addons_combined_pages , & uki_addons_combined_size );
443
+ if (err != EFI_SUCCESS )
444
+ return err ;
445
+ uki_addons_combined_base = PHYSICAL_ADDRESS_TO_POINTER (uki_addons_combined_pages .addr );
446
+ }
447
+
448
+ /* Merge the combined global addons, combined UKI addons, and ucode section from UKI */
449
+ err = combine_initrds (
450
+ (const void * const []) {
451
+ ucode_section_base ,
452
+ global_addons_combined_base ,
453
+ uki_addons_combined_base ,
454
+ },
455
+ (const size_t []) {
456
+ ucode_section_size ,
457
+ global_addons_combined_size ,
458
+ uki_addons_combined_size ,
459
+ },
460
+ 3 ,
461
+ & all_ucode_combined_pages ,
462
+ & all_ucode_combined_size
463
+ );
464
+ if (err != EFI_SUCCESS )
465
+ return err ;
466
+
467
+ * ret_ucode_base = PHYSICAL_ADDRESS_TO_POINTER (all_ucode_combined_pages .addr );
468
+ * ret_ucode_size = all_ucode_combined_size ;
469
+ all_ucode_combined_pages .n_pages = 0 ;
470
+ * ret_sections_measured = sections_measured ;
471
+
472
+ return EFI_SUCCESS ;
473
+ }
474
+
475
+ static void ucode_bases_free (void * * ucode_bases , size_t n_ucode ) {
476
+ assert (ucode_bases || n_ucode == 0 );
477
+
478
+ for (size_t i = 0 ; i < n_ucode ; ++ i )
479
+ free (ucode_bases [i ]);
480
+
481
+ free (ucode_bases );
482
+ }
483
+
344
484
static EFI_STATUS load_addons (
345
485
EFI_HANDLE stub_image ,
346
486
EFI_LOADED_IMAGE_PROTOCOL * loaded_image ,
@@ -350,15 +490,18 @@ static EFI_STATUS load_addons(
350
490
void * * * ret_dt_bases ,
351
491
size_t * * ret_dt_sizes ,
352
492
char16_t * * * ret_dt_filenames ,
353
- size_t * ret_n_dt ) {
493
+ size_t * ret_n_dt ,
494
+ void * * * ret_ucode_bases ,
495
+ size_t * * ret_ucode_sizes ,
496
+ size_t * ret_n_ucode ) {
354
497
355
- _cleanup_free_ size_t * dt_sizes = NULL ;
498
+ _cleanup_free_ size_t * dt_sizes = NULL , * ucode_sizes = NULL ;
356
499
_cleanup_ (strv_freep ) char16_t * * items = NULL ;
357
500
_cleanup_ (file_closep ) EFI_FILE * root = NULL ;
358
501
_cleanup_free_ char16_t * cmdline = NULL ;
359
- size_t n_items = 0 , n_allocated = 0 , n_dt = 0 ;
502
+ size_t n_items = 0 , n_allocated = 0 , n_dt = 0 , n_ucode = 0 ;
360
503
char16_t * * dt_filenames = NULL ;
361
- void * * dt_bases = NULL ;
504
+ void * * dt_bases = NULL , * * ucode_bases = NULL ;
362
505
EFI_STATUS err ;
363
506
364
507
assert (stub_image );
@@ -367,12 +510,15 @@ static EFI_STATUS load_addons(
367
510
assert (!!ret_dt_bases == !!ret_dt_sizes );
368
511
assert (!!ret_dt_bases == !!ret_n_dt );
369
512
assert (!!ret_dt_filenames == !!ret_n_dt );
513
+ assert (!!ret_ucode_bases == !!ret_ucode_sizes );
514
+ assert (!!ret_ucode_bases == !!ret_n_ucode );
370
515
371
516
if (!loaded_image -> DeviceHandle )
372
517
return EFI_SUCCESS ;
373
518
374
519
CLEANUP_ARRAY (dt_bases , n_dt , dt_bases_free );
375
520
CLEANUP_ARRAY (dt_filenames , n_dt , dt_filenames_free );
521
+ CLEANUP_ARRAY (ucode_bases , n_ucode , ucode_bases_free );
376
522
377
523
err = open_volume (loaded_image -> DeviceHandle , & root );
378
524
if (err == EFI_UNSUPPORTED )
@@ -424,11 +570,11 @@ static EFI_STATUS load_addons(
424
570
425
571
err = pe_memory_locate_sections (loaded_addon -> ImageBase , unified_sections , addrs , szs );
426
572
if (err != EFI_SUCCESS ||
427
- (szs [UNIFIED_SECTION_CMDLINE ] == 0 && szs [UNIFIED_SECTION_DTB ] == 0 )) {
573
+ (szs [UNIFIED_SECTION_CMDLINE ] == 0 && szs [UNIFIED_SECTION_DTB ] == 0 && szs [ UNIFIED_SECTION_UCODE ] == 0 )) {
428
574
if (err == EFI_SUCCESS )
429
575
err = EFI_NOT_FOUND ;
430
576
log_error_status (err ,
431
- "Unable to locate embedded .cmdline/.dtb sections in %ls, ignoring: %m" ,
577
+ "Unable to locate embedded .cmdline/.dtb/.ucode sections in %ls, ignoring: %m" ,
432
578
items [i ]);
433
579
continue ;
434
580
}
@@ -475,6 +621,21 @@ static EFI_STATUS load_addons(
475
621
476
622
++ n_dt ;
477
623
}
624
+
625
+ if (ret_ucode_bases && szs [UNIFIED_SECTION_UCODE ] > 0 ) {
626
+ ucode_sizes = xrealloc (ucode_sizes ,
627
+ n_ucode * sizeof (size_t ),
628
+ (n_ucode + 1 ) * sizeof (size_t ));
629
+ ucode_sizes [n_ucode ] = szs [UNIFIED_SECTION_UCODE ];
630
+
631
+ ucode_bases = xrealloc (ucode_bases ,
632
+ n_ucode * sizeof (void * ),
633
+ (n_ucode + 1 ) * sizeof (void * ));
634
+ ucode_bases [n_ucode ] = xmemdup ((uint8_t * )loaded_addon -> ImageBase + addrs [UNIFIED_SECTION_UCODE ],
635
+ ucode_sizes [n_ucode ]);
636
+
637
+ ++ n_ucode ;
638
+ }
478
639
}
479
640
480
641
if (ret_cmdline && !isempty (cmdline ))
@@ -486,6 +647,11 @@ static EFI_STATUS load_addons(
486
647
* ret_dt_sizes = TAKE_PTR (dt_sizes );
487
648
* ret_n_dt = n_dt ;
488
649
}
650
+ if (ret_ucode_bases && n_ucode > 0 ) {
651
+ * ret_ucode_bases = TAKE_PTR (ucode_bases );
652
+ * ret_ucode_sizes = TAKE_PTR (ucode_sizes );
653
+ * ret_n_ucode = n_ucode ;
654
+ }
489
655
490
656
return EFI_SUCCESS ;
491
657
}
@@ -496,8 +662,11 @@ static EFI_STATUS run(EFI_HANDLE image) {
496
662
void * * dt_bases_addons_global = NULL , * * dt_bases_addons_uki = NULL ;
497
663
char16_t * * dt_filenames_addons_global = NULL , * * dt_filenames_addons_uki = NULL ;
498
664
_cleanup_free_ size_t * dt_sizes_addons_global = NULL , * dt_sizes_addons_uki = NULL ;
499
- size_t linux_size , initrd_size , ucode_size , dt_size , n_dts_addons_global = 0 , n_dts_addons_uki = 0 ;
500
- EFI_PHYSICAL_ADDRESS linux_base , initrd_base , ucode_base , dt_base ;
665
+ void * * ucode_bases_addons_global = NULL , * * ucode_bases_addons_uki = NULL ;
666
+ _cleanup_free_ size_t * ucode_sizes_addons_global = NULL , * ucode_sizes_addons_uki = NULL ;
667
+ size_t linux_size , initrd_size , dt_size , n_dts_addons_global = 0 , n_dts_addons_uki = 0 , ucode_size = 0 , n_ucode_addons_global = 0 , n_ucode_addons_uki = 0 ;
668
+ EFI_PHYSICAL_ADDRESS linux_base , initrd_base , dt_base ;
669
+ void * ucode_base = NULL ;
501
670
_cleanup_ (devicetree_cleanup ) struct devicetree_state dt_state = {};
502
671
EFI_LOADED_IMAGE_PROTOCOL * loaded_image ;
503
672
size_t addrs [_UNIFIED_SECTION_MAX ] = {}, szs [_UNIFIED_SECTION_MAX ] = {};
@@ -533,6 +702,8 @@ static EFI_STATUS run(EFI_HANDLE image) {
533
702
CLEANUP_ARRAY (dt_bases_addons_uki , n_dts_addons_uki , dt_bases_free );
534
703
CLEANUP_ARRAY (dt_filenames_addons_global , n_dts_addons_global , dt_filenames_free );
535
704
CLEANUP_ARRAY (dt_filenames_addons_uki , n_dts_addons_uki , dt_filenames_free );
705
+ CLEANUP_ARRAY (ucode_bases_addons_global , n_ucode_addons_global , ucode_bases_free );
706
+ CLEANUP_ARRAY (ucode_bases_addons_uki , n_ucode_addons_uki , ucode_bases_free );
536
707
537
708
if (szs [UNIFIED_SECTION_UNAME ] > 0 )
538
709
uname = xstrndup8 ((char * )loaded_image -> ImageBase + addrs [UNIFIED_SECTION_UNAME ],
@@ -549,7 +720,10 @@ static EFI_STATUS run(EFI_HANDLE image) {
549
720
& dt_bases_addons_global ,
550
721
& dt_sizes_addons_global ,
551
722
& dt_filenames_addons_global ,
552
- & n_dts_addons_global );
723
+ & n_dts_addons_global ,
724
+ & ucode_bases_addons_global ,
725
+ & ucode_sizes_addons_global ,
726
+ & n_ucode_addons_global );
553
727
if (err != EFI_SUCCESS )
554
728
log_error_status (err , "Error loading global addons, ignoring: %m" );
555
729
@@ -565,7 +739,10 @@ static EFI_STATUS run(EFI_HANDLE image) {
565
739
& dt_bases_addons_uki ,
566
740
& dt_sizes_addons_uki ,
567
741
& dt_filenames_addons_uki ,
568
- & n_dts_addons_uki );
742
+ & n_dts_addons_uki ,
743
+ & ucode_bases_addons_uki ,
744
+ & ucode_sizes_addons_uki ,
745
+ & n_ucode_addons_uki );
569
746
if (err != EFI_SUCCESS )
570
747
log_error_status (err , "Error loading UKI-specific addons, ignoring: %m" );
571
748
}
@@ -735,6 +912,23 @@ static EFI_STATUS run(EFI_HANDLE image) {
735
912
& m );
736
913
parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m );
737
914
915
+ /* Handle ucode */
916
+ err = ucode_merge_and_measure_addons (
917
+ ucode_bases_addons_global ,
918
+ ucode_sizes_addons_global ,
919
+ n_ucode_addons_global ,
920
+ ucode_bases_addons_uki ,
921
+ ucode_sizes_addons_uki ,
922
+ n_ucode_addons_uki ,
923
+ szs [UNIFIED_SECTION_UCODE ] != 0 ? PHYSICAL_ADDRESS_TO_POINTER (POINTER_TO_PHYSICAL_ADDRESS (loaded_image -> ImageBase ) + addrs [UNIFIED_SECTION_UCODE ]) : NULL ,
924
+ szs [UNIFIED_SECTION_UCODE ],
925
+ & ucode_base ,
926
+ & ucode_size ,
927
+ & m );
928
+ if (err != EFI_SUCCESS )
929
+ return err ;
930
+ parameters_measured = parameters_measured < 0 ? m : (parameters_measured && m );
931
+
738
932
if (parameters_measured > 0 )
739
933
(void ) efivar_set_uint_string (MAKE_GUID_PTR (LOADER ), u"StubPcrKernelParameters" , TPM2_PCR_KERNEL_CONFIG , 0 );
740
934
if (sysext_measured )
@@ -785,17 +979,14 @@ static EFI_STATUS run(EFI_HANDLE image) {
785
979
initrd_size = szs [UNIFIED_SECTION_INITRD ];
786
980
initrd_base = initrd_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS (loaded_image -> ImageBase ) + addrs [UNIFIED_SECTION_INITRD ] : 0 ;
787
981
788
- ucode_size = szs [UNIFIED_SECTION_UCODE ];
789
- ucode_base = ucode_size != 0 ? POINTER_TO_PHYSICAL_ADDRESS (loaded_image -> ImageBase ) + addrs [UNIFIED_SECTION_UCODE ] : 0 ;
790
-
791
982
_cleanup_pages_ Pages initrd_pages = {};
792
983
if (ucode_base || credential_initrd || global_credential_initrd || sysext_initrd || confext_initrd || pcrsig_initrd || pcrpkey_initrd ) {
793
984
/* If we have generated initrds dynamically or there is a microcode initrd, combine them with the built-in initrd. */
794
985
err = combine_initrds (
795
986
(const void * const []) {
796
987
/* Microcode must always be first as kernel only scans uncompressed cpios
797
988
* and later initrds might be compressed. */
798
- PHYSICAL_ADDRESS_TO_POINTER ( ucode_base ) ,
989
+ ucode_base ,
799
990
PHYSICAL_ADDRESS_TO_POINTER (initrd_base ),
800
991
credential_initrd ,
801
992
global_credential_initrd ,
0 commit comments