]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
analyze: add "identify-tpm2" command that shows TPM2 chip information
authorLennart Poettering <lennart@amutable.com>
Tue, 3 Mar 2026 11:28:22 +0000 (12:28 +0100)
committerLennart Poettering <lennart@amutable.com>
Wed, 4 Mar 2026 07:28:29 +0000 (08:28 +0100)
man/systemd-analyze.xml
shell-completion/bash/systemd-analyze
src/analyze/analyze-has-tpm2.c
src/analyze/analyze-has-tpm2.h
src/analyze/analyze.c

index e64f9be57ee7f5edd4748c6ff362f5b46f078338..6a022916664f6d022914a4f9b2bae4cba2f7327c 100644 (file)
       <arg choice="opt" rep="repeat">OPTIONS</arg>
       <arg choice="plain">has-tpm2</arg>
     </cmdsynopsis>
+    <cmdsynopsis>
+      <command>systemd-analyze</command>
+      <arg choice="opt" rep="repeat">OPTIONS</arg>
+      <arg choice="plain">identify-tpm2</arg>
+    </cmdsynopsis>
     <cmdsynopsis>
       <command>systemd-analyze</command>
       <arg choice="opt" rep="repeat">OPTIONS</arg>
@@ -1028,6 +1033,26 @@ default         ignore      -         -</programlisting>
       <xi:include href="version-info.xml" xpointer="v257"/>
     </refsect2>
 
+    <refsect2>
+      <title><command>systemd-analyze identify-tpm2</command></title>
+
+      <para>Shows vendor information about the TPM 2.0 device discovered.</para>
+
+      <example>
+        <title>Example Output</title>
+
+        <programlisting>  Family Indicator: 2.0
+             Level: 0
+          Revision: 1.59
+Specification Date: Mon 2023-01-09
+      Manufacturer: STM
+     Vendor String: ST33KTPM2XSPI
+  Firmware Version: 9.258</programlisting>
+      </example>
+
+      <xi:include href="version-info.xml" xpointer="v260"/>
+    </refsect2>
+
     <refsect2>
       <title><command>systemd-analyze pcrs <optional><replaceable>PCR</replaceable>…</optional></command></title>
 
index a863af7affd768d0862b9f5e097bd455688b7a15..b194c74b63836f0049d640e7c8c3f0ed90a27765 100644 (file)
@@ -77,7 +77,7 @@ _systemd_analyze() {
     )
 
     local -A VERBS=(
-        [STANDALONE]='time blame unit-files unit-paths exit-status compare-versions timestamp timespan pcrs nvpcrs srk has-tpm2 smbios11 chid image-policy'
+        [STANDALONE]='time blame unit-files unit-paths exit-status compare-versions timestamp timespan pcrs nvpcrs srk has-tpm2 identify-tpm2 smbios11 chid image-policy'
         [CRITICAL_CHAIN]='critical-chain'
         [DOT]='dot'
         [DUMP]='dump'
index 3e13be9f160fdb5bcf77d1c57405f4b5bdae27bb..a63c44ebc649e6744f34d2f96a951e083ddcbd2a 100644 (file)
@@ -2,8 +2,130 @@
 
 #include "analyze.h"
 #include "analyze-has-tpm2.h"
+#include "format-table.h"
+#include "log.h"
+#include "string-util.h"
+#include "time-util.h"
 #include "tpm2-util.h"
 
 int verb_has_tpm2(int argc, char **argv, void *userdata) {
         return verb_has_tpm2_generic(arg_quiet);
 }
+
+int verb_identify_tpm2(int argc, char **argv, void *userdata) {
+#if HAVE_TPM2
+        int r;
+
+        _cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
+        r = tpm2_context_new_or_warn(/* device= */ NULL, &c);
+        if (r < 0)
+                return r;
+
+        Tpm2VendorInfo info;
+        r = tpm2_get_vendor_info(c, &info);
+        if (r < 0)
+                return log_error_errno(r, "Failed to acquire TPM2 vendor information: %m");
+
+        _cleanup_(table_unrefp) Table *table = table_new_vertical();
+        if (!table)
+                return log_oom();
+
+        if (!isempty(info.family_indicator)) {
+                r = table_add_many(
+                                table,
+                                TABLE_FIELD, "Family Indicator",
+                                TABLE_STRING, info.family_indicator);
+                if (r < 0)
+                        return table_log_add_error(r);
+        }
+
+        _cleanup_free_ char *rv = NULL;
+        if (asprintf(&rv, "%" PRIu32 ".%" PRIu32,
+                     info.revision_major,
+                     info.revision_minor) < 0)
+                return log_oom();
+
+        r = table_add_many(
+                        table,
+                        TABLE_FIELD, "Level",
+                        TABLE_UINT32, info.level,
+                        TABLE_FIELD, "Revision",
+                        TABLE_STRING, rv);
+        if (r < 0)
+                return table_log_add_error(r);
+
+        if (info.year >= 1900) {
+                struct tm tm = {
+                        .tm_year = info.year - 1900,
+                        .tm_mon = 0,                   /* january */
+                        .tm_mday = info.day_of_year,   /* timegm() will normalize this */
+                };
+
+                usec_t ts;
+                r = mktime_or_timegm_usec(&tm, /* utc= */ true, &ts);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to convert the specification date, ignoring.");
+                else {
+                        r = table_add_many(
+                                        table,
+                                        TABLE_FIELD, "Specification Date",
+                                        TABLE_TIMESTAMP_DATE, ts);
+                        if (r < 0)
+                                return table_log_add_error(r);
+                }
+        }
+
+        if (!isempty(info.manufacturer)) {
+                r = table_add_many(
+                                table,
+                                TABLE_FIELD, "Manufacturer",
+                                TABLE_STRING, info.manufacturer);
+                if (r < 0)
+                        return table_log_add_error(r);
+        }
+
+        if (!isempty(info.vendor_string)) {
+                r = table_add_many(
+                                table,
+                                TABLE_FIELD, "Vendor String",
+                                TABLE_STRING, info.vendor_string);
+                if (r < 0)
+                        return table_log_add_error(r);
+        }
+
+        if (info.vendor_tpm_type != 0) {
+                r = table_add_many(
+                                table,
+                                TABLE_FIELD, "Vendor TPM Type",
+                                TABLE_UINT32_HEX_0x, info.vendor_tpm_type);
+                if (r < 0)
+                        return table_log_add_error(r);
+        }
+
+        /* Show the first two 16bit words of the firmware version as major/minor */
+        _cleanup_free_ char *fw = NULL;
+        if (asprintf(&fw, "%" PRIu16 ".%" PRIu16,
+                     info.firmware_version_major,
+                     info.firmware_version_minor) < 0)
+                return log_oom();
+
+        /* Show the second 32bit as a single value, if non-zero */
+        if (info.firmware_version2 != 0 && strextendf(&fw, ".%" PRIu32, info.firmware_version2) < 0)
+                return log_oom();
+
+        r = table_add_many(
+                        table,
+                        TABLE_FIELD, "Firmware Version",
+                        TABLE_STRING, fw);
+        if (r < 0)
+                return table_log_add_error(r);
+
+        r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, /* show_header= */ false);
+        if (r < 0)
+                return r;
+
+        return EXIT_SUCCESS;
+#else
+        return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support not enabled at build time.");
+#endif
+}
index c7c639228d87c4ae1cae513af257be49e30a379d..b7d750090b57b21dae0442ffeed986989495121c 100644 (file)
@@ -2,3 +2,4 @@
 #pragma once
 
 int verb_has_tpm2(int argc, char *argv[], void *userdata);
+int verb_identify_tpm2(int argc, char *argv[], void *userdata);
index c69f03ec155cc841cb518ccb9a623bb8e273ebc4..af456314db4465f9ff8aae25e831707df37dadfe 100644 (file)
@@ -258,6 +258,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "  dlopen-metadata FILE       Parse and print ELF dlopen metadata\n"
                "\n%3$sTPM Operations:%4$s\n"
                "  has-tpm2                   Report whether TPM2 support is available\n"
+               "  identify-tpm2              Show TPM2 vendor information\n"
                "  pcrs [PCR...]              Show TPM2 PCRs and their names\n"
                "  nvpcrs [NVPCR...]          Show additional TPM2 PCRs stored in NV indexes\n"
                "  srk [>FILE]                Write TPM2 SRK (to FILE)\n"
@@ -810,6 +811,7 @@ static int run(int argc, char *argv[]) {
                 { "fdstore",            2,        VERB_ANY, 0,  verb_fdstore            },
                 { "image-policy",       2,        2,        0,  verb_image_policy       },
                 { "has-tpm2",           VERB_ANY, 1,        0,  verb_has_tpm2           },
+                { "identify-tpm2",      VERB_ANY, 1,        0,  verb_identify_tpm2      },
                 { "pcrs",               VERB_ANY, VERB_ANY, 0,  verb_pcrs               },
                 { "nvpcrs",             VERB_ANY, VERB_ANY, 0,  verb_nvpcrs             },
                 { "srk",                VERB_ANY, 1,        0,  verb_srk                },