]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
commands/bli: Set UINT32_MAX in LoaderTpm2ActivePcrBanks if TPM2 present but no banks...
authorLuca Boccassi <luca.boccassi@gmail.com>
Wed, 10 Dec 2025 23:47:53 +0000 (23:47 +0000)
committerDaniel Kiper <daniel.kiper@oracle.com>
Sun, 21 Dec 2025 15:41:46 +0000 (16:41 +0100)
The implementation in sd-boot was changed to return UINT32_MAX when
the EFI environment detects a working TPM2, but with an older firmware
that doesn't implement the protocol to get the list of active banks.
This allows distinguishing with the case where there is no working TPM2,
in which case userspace just gives up, and instead lets userspace try to
figure it out later.

Fixes: f326c5c47 (commands/bli: Set LoaderTpm2ActivePcrBanks runtime variable)
Signed-off-by: Luca Boccassi <luca.boccassi@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
grub-core/commands/efi/tpm.c

index 7b493c890b6b0abbcc55acccc39d1dccbf32fd7c..96b5090319e167e5332593a926cb161a950af1db 100644 (file)
@@ -39,7 +39,7 @@ static grub_uint8_t grub_tpm_version;
 
 static grub_int8_t tpm1_present = -1;
 static grub_int8_t tpm2_present = -1;
-static grub_int8_t tpm2_pcr_banks_reporting_present = -1;
+static grub_efi_int64_t tpm2_active_pcr_banks = -1;
 
 static grub_efi_boolean_t
 grub_tpm1_present (grub_efi_tpm_protocol_t *tpm)
@@ -90,34 +90,6 @@ grub_tpm2_present (grub_efi_tpm2_protocol_t *tpm)
   return (grub_efi_boolean_t) tpm2_present;
 }
 
-static grub_efi_boolean_t
-grub_tpm2_pcr_banks_reporting_present (grub_efi_tpm2_protocol_t *tpm)
-{
-  grub_efi_status_t status;
-  EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
-
-  caps.Size = (grub_uint8_t) sizeof (caps);
-
-  if (tpm2_pcr_banks_reporting_present != -1)
-    return (grub_efi_boolean_t) tpm2_pcr_banks_reporting_present;
-
-  if (!grub_tpm2_present (tpm))
-    return (grub_efi_boolean_t) (tpm2_pcr_banks_reporting_present = 0);
-
-  status = tpm->get_capability (tpm, &caps);
-
-  if (status != GRUB_EFI_SUCCESS || caps.StructureVersion.Major < 1
-      || (caps.StructureVersion.Major == 1 && caps.StructureVersion.Minor < 1))
-    tpm2_pcr_banks_reporting_present = 0;
-  else
-    tpm2_pcr_banks_reporting_present = 1;
-
-  grub_dprintf ("tpm", "tpm2 PCR banks reporting%s present\n",
-               tpm2_pcr_banks_reporting_present ? "" : " NOT");
-
-  return (grub_efi_boolean_t) tpm2_pcr_banks_reporting_present;
-}
-
 static grub_efi_boolean_t
 grub_tpm_handle_find (grub_efi_handle_t *tpm_handle,
                      grub_efi_uint8_t *protocol_version)
@@ -365,32 +337,45 @@ grub_tpm_present (void)
 grub_uint32_t
 grub_tpm2_active_pcr_banks (void)
 {
+  EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
   grub_efi_handle_t tpm_handle;
   grub_efi_uint8_t protocol_version;
   grub_efi_tpm2_protocol_t *tpm;
-  grub_efi_uint32_t active_pcr_banks = 0;
+  grub_efi_uint32_t active_pcr_banks;
+  grub_efi_status_t status;
+
+  if (tpm2_active_pcr_banks >= 0)
+    return (grub_uint32_t) tpm2_active_pcr_banks;
 
   if (!grub_tpm_handle_find (&tpm_handle, &protocol_version))
-    return 0;
+    return (grub_uint32_t) (tpm2_active_pcr_banks = 0);
 
   if (protocol_version == 1)
-    return 0; /* We report TPM2 status */
+    return (grub_uint32_t) (tpm2_active_pcr_banks = 0); /* We report TPM2 status. */
 
   tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid,
                                GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
   if (tpm == NULL)
     {
       grub_dprintf ("tpm", "Cannot open TPM2 protocol\n");
-      return 0;
+      return (grub_uint32_t) (tpm2_active_pcr_banks = 0);
     }
 
-  if (grub_tpm2_pcr_banks_reporting_present (tpm))
-    {
-      grub_efi_status_t status = tpm->get_active_pcr_banks (tpm, &active_pcr_banks);
+  if (!grub_tpm2_present (tpm))
+    return (grub_uint32_t) (tpm2_active_pcr_banks = 0);
 
-      if (status != GRUB_EFI_SUCCESS)
-       return 0; /* Assume none available if the call fails. */
-    }
+  caps.Size = (grub_uint8_t) sizeof (caps);
+  status = tpm->get_capability (tpm, &caps);
+  if (status != GRUB_EFI_SUCCESS)
+    return (grub_uint32_t) (tpm2_active_pcr_banks = 0);
+  if (caps.StructureVersion.Major < 1 ||
+      (caps.StructureVersion.Major == 1 && caps.StructureVersion.Minor < 1))
+    /* There's a working TPM2 but without querying protocol, let userspace figure it out. */
+    return (grub_uint32_t) (tpm2_active_pcr_banks = GRUB_UINT_MAX);
+
+  status = tpm->get_active_pcr_banks (tpm, &active_pcr_banks);
+  if (status != GRUB_EFI_SUCCESS)
+    return (grub_uint32_t) (tpm2_active_pcr_banks = 0); /* Assume none available if the call fails. */
 
-  return active_pcr_banks;
+  return (grub_uint32_t) (tpm2_active_pcr_banks = active_pcr_banks);
 }