linux_bootloader/
measure.rs1use log::info;
2use uefi::{
3 cstr16,
4 proto::tcg::PcrIndex,
5 table::{runtime::VariableAttributes, Boot, SystemTable},
6};
7
8use crate::{
9 efivars::BOOT_LOADER_VENDOR_UUID, pe_section::pe_section_data, tpm::tpm_log_event_ascii,
10 uefi_helpers::PeInMemory, unified_sections::UnifiedSection,
11};
12
13const TPM_PCR_INDEX_KERNEL_IMAGE: PcrIndex = PcrIndex(11);
14
15pub unsafe fn measure_image(
16 system_table: &SystemTable<Boot>,
17 image: PeInMemory,
18) -> uefi::Result<u32> {
19 let runtime_services = system_table.runtime_services();
20 let boot_services = system_table.boot_services();
21
22 let pe_binary = unsafe { image.as_slice() };
28 let pe = goblin::pe::PE::parse(pe_binary).map_err(|_err| uefi::Status::LOAD_ERROR)?;
29
30 let mut measurements = 0;
31 for section in pe.sections {
32 let section_name = section.name().map_err(|_err| uefi::Status::UNSUPPORTED)?;
33 if let Ok(unified_section) = UnifiedSection::try_from(section_name) {
34 if unified_section.should_be_measured() {
37 if let Some(data) = pe_section_data(pe_binary, §ion) {
39 info!("Measuring section `{}`...", section_name);
40 if tpm_log_event_ascii(
41 boot_services,
42 TPM_PCR_INDEX_KERNEL_IMAGE,
43 data,
44 section_name,
45 )? {
46 measurements += 1;
47 }
48 }
49 }
50 }
51 }
52
53 if measurements > 0 {
54 runtime_services.set_variable(
57 cstr16!("StubPcrKernelImage"),
58 &BOOT_LOADER_VENDOR_UUID,
59 VariableAttributes::BOOTSERVICE_ACCESS | VariableAttributes::RUNTIME_ACCESS,
60 &TPM_PCR_INDEX_KERNEL_IMAGE.0.to_le_bytes(),
61 )?;
62 }
63
64 Ok(measurements)
65}