<xi:include href="version-info.xml" xpointer="v240"/></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>LoaderTpm2ActivePcrBanks</varname></term>
+
+ <listitem><para>Hexadecimal string representation of a bitmask with values defined by the TCG EFI
+ Protocol Specification for TPM 2.0 as EFI_TCG2_BOOT_HASH_ALG_*. If no TPM2 support or no active
+ banks were detected, will be set to <constant>0</constant>. Set by the boot loader. Use
+ <citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ to view this data.</para>
+
+ <xi:include href="version-info.xml" xpointer="v258"/></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>LoaderImageIdentifier</varname></term>
<xi:include href="version-info.xml" xpointer="v250"/></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>LoaderTpm2ActivePcrBanks</varname></term>
+
+ <listitem><para>Hexadecimal string representation of a bitmask with values defined by the TCG EFI
+ Protocol Specification for TPM 2.0 as EFI_TCG2_BOOT_HASH_ALG_*. If no TPM2 support or no active
+ banks were detected, will be set to <constant>0</constant>. Set by the boot loader. Use
+ <citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ to view this data.</para>
+
+ <xi:include href="version-info.xml" xpointer="v258"/></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>LoaderImageIdentifier</varname></term>
EFI_LOADER_FEATURE_REPORT_URL |
EFI_LOADER_FEATURE_TYPE1_UKI |
EFI_LOADER_FEATURE_TYPE1_UKI_URL |
+ EFI_LOADER_FEATURE_TPM2_ACTIVE_PCR_BANKS |
0;
assert(loaded_image);
#include "device-path-util.h"
#include "efi-efivars.h"
#include "export-vars.h"
+#include "measure.h"
#include "part-discovery.h"
#include "url-discovery.h"
#include "util.h"
s = xasprintf("UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
efivar_set_str16(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareType", s, 0);
}
+
+ /* ditto for LoaderTpm2ActivePcrBanks */
+ if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderTpm2ActivePcrBanks", NULL, NULL) != EFI_SUCCESS) {
+ uint32_t active_pcr_banks = tpm_get_active_pcr_banks();
+ _cleanup_free_ char16_t *s = NULL;
+ s = xasprintf("0x%08x", active_pcr_banks);
+ efivar_set_str16(MAKE_GUID_PTR(LOADER), u"LoaderTpm2ActivePcrBanks", s, 0);
+ }
}
return tcg2_interface_check();
}
+uint32_t tpm_get_active_pcr_banks(void) {
+ uint32_t active_pcr_banks = 0;
+ EFI_TCG2_PROTOCOL *tpm2;
+ EFI_STATUS err;
+
+ tpm2 = tcg2_interface_check();
+ if (!tpm2)
+ return 0;
+
+ err = tpm2->GetActivePcrBanks(tpm2, &active_pcr_banks);
+ if (err != EFI_SUCCESS) {
+ log_warning_status(err, "Failed to get TPM2 active PCR banks, assuming none: %m");
+ return 0;
+ }
+
+ return active_pcr_banks;
+}
+
static EFI_STATUS tcg2_log_ipl_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
EFI_TCG2_PROTOCOL *tpm2;
EFI_STATUS err = EFI_SUCCESS;
#if ENABLE_TPM
bool tpm_present(void);
+uint32_t tpm_get_active_pcr_banks(void);
/* Routines for boot-time TPM PCR measurement as well as submitting an event log entry about it. The latter
* can be done with two different event log record types. For old stuff we use EV_IPL (which is legacy, and
return false;
}
+static inline uint32_t tpm_get_active_pcr_banks(void) {
+ return 0;
+}
+
static inline EFI_STATUS tpm_log_ipl_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
if (ret_measured)
*ret_measured = false;
uint64_t DataToHashLen,
EFI_TCG2_EVENT *EfiTcgEvent);
void *SubmitCommand;
- void *GetActivePcrBanks;
+ EFI_STATUS (EFIAPI *GetActivePcrBanks)(
+ EFI_TCG2_PROTOCOL *This,
+ uint32_t *ActivePcrBanks);
void *SetActivePcrBanks;
void *GetResultOfSetActivePcrBanks;
};
{ EFI_LOADER_FEATURE_REPORT_URL, "Loader reports network boot URL" },
{ EFI_LOADER_FEATURE_TYPE1_UKI, "Support Type #1 uki field" },
{ EFI_LOADER_FEATURE_TYPE1_UKI_URL, "Support Type #1 uki-url field" },
+ { EFI_LOADER_FEATURE_TPM2_ACTIVE_PCR_BANKS, "Loader reports TPM2 active PCR banks" },
};
static const struct {
uint64_t flag;
#define EFI_LOADER_FEATURE_REPORT_URL (UINT64_C(1) << 15)
#define EFI_LOADER_FEATURE_TYPE1_UKI (UINT64_C(1) << 16)
#define EFI_LOADER_FEATURE_TYPE1_UKI_URL (UINT64_C(1) << 17)
+#define EFI_LOADER_FEATURE_TPM2_ACTIVE_PCR_BANKS (UINT64_C(1) << 18)
/* Features of the stub, i.e. systemd-stub */
#define EFI_STUB_FEATURE_REPORT_BOOT_PARTITION (UINT64_C(1) << 0)
#include "fd-util.h"
#include "fileio.h"
#include "log.h"
+#include "parse-util.h"
#include "sort-util.h"
#include "stat-util.h"
#include "stdio-util.h"
#endif
}
+#if ENABLE_EFI
+static int loader_has_tpm2(void) {
+ _cleanup_free_ char *active_pcr_banks = NULL;
+ uint32_t active_pcr_banks_value;
+ int r;
+
+ r = efi_get_variable_string(EFI_LOADER_VARIABLE_STR("LoaderTpm2ActivePcrBanks"), &active_pcr_banks);
+ if (r < 0) {
+ if (r != -ENOENT)
+ log_debug_errno(r, "Failed to read LoaderTpm2ActivePcrBanks variable: %m");
+ return r;
+ }
+
+ r = safe_atou32_full(active_pcr_banks, 16, &active_pcr_banks_value);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to parse LoaderTpm2ActivePcrBanks variable: %m");
+
+ return active_pcr_banks_value != 0;
+}
+#endif
+
bool efi_has_tpm2(void) {
#if ENABLE_EFI
static int cache = -1;
if (!is_efi_boot())
return (cache = false);
+ /* Secondly, check if the loader told us, as that is the most accurate source of information
+ * regarding the firmware's setup */
+ r = loader_has_tpm2();
+ if (r >= 0)
+ return (cache = r);
+
/* Then, check if the ACPI table "TPM2" exists, which is the TPM2 event log table, see:
* https://trustedcomputinggroup.org/wp-content/uploads/TCG_ACPIGeneralSpecification_v1.20_r8.pdf
- * This table exists whenever the firmware knows ACPI and is hooked up to TPM2. */
+ * This table exists whenever the firmware knows ACPI and is hooked up to TPM2.
+ * Note that in some cases, for example with EDK2 2025.2 with the default arm64 config, this ACPI
+ * table is present even if TPM2 support is not enabled in the firmware. */
if (access("/sys/firmware/acpi/tables/TPM2", F_OK) >= 0)
return (cache = true);
if (errno != ENOENT)