1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include "proc-cmdline.h"
7 #include "parse-util.h"
9 /* A small generator that enqueues tpm2.target as synchronization point if the TPM2 device hasn't shown up
10 * yet, but the firmware reports it to exist. This is supposed to deal with systems where the TPM2 driver
11 * support is built as kmod and must be loaded before it's ready to be used. The tpm2.target is only enqueued
12 * if firmware says there is a TPM2 device, our userspace support for TPM2 is fully available but the TPM2
13 * device hasn't shown up in /dev/ yet. */
15 static const char *arg_dest
= NULL
;
16 static int arg_tpm2_wait
= -1; /* tri-state: negative → don't know */
18 static int parse_proc_cmdline_item(const char *key
, const char *value
, void *data
) {
23 if (proc_cmdline_key_streq(key
, "systemd.tpm2-wait")) {
24 r
= value
? parse_boolean(value
) : 1;
26 log_warning_errno(r
, "Failed to parse 'systemd.tpm2-wait' kernel command line argument, ignoring: %s", value
);
34 static int generate_tpm_target_symlink(void) {
37 if (arg_tpm2_wait
== 0) {
38 log_debug("Not generating tpm2.target synchronization point, as this was explicitly turned off via kernel command line.");
42 if (arg_tpm2_wait
< 0) {
43 Tpm2Support support
= tpm2_support();
45 if (FLAGS_SET(support
, TPM2_SUPPORT_DRIVER
)) {
46 log_debug("Not generating tpm2.target synchronization point, as TPM2 device is already present.");
50 if (!FLAGS_SET(support
, TPM2_SUPPORT_FIRMWARE
)) {
51 log_debug("Not generating tpm2.target synchronization point, as firmware reports no TPM2 present.");
55 if (!FLAGS_SET(support
, TPM2_SUPPORT_SYSTEM
|TPM2_SUPPORT_SUBSYSTEM
|TPM2_SUPPORT_LIBRARIES
)) {
56 log_debug("Not generating tpm2.target synchronization point, as userspace support for TPM2 is not complete.");
61 r
= generator_add_symlink(arg_dest
, SPECIAL_SYSINIT_TARGET
, "wants", SYSTEM_DATA_UNIT_DIR
"/" SPECIAL_TPM2_TARGET
);
63 return log_error_errno(r
, "Failed to hook in tpm2.target: %m");
68 static int run(const char *dest
, const char *dest_early
, const char *dest_late
) {
71 assert_se(arg_dest
= dest
);
73 r
= proc_cmdline_parse(parse_proc_cmdline_item
, NULL
, PROC_CMDLINE_STRIP_RD_PREFIX
);
75 log_warning_errno(r
, "Failed to parse kernel command line, ignoring: %m");
77 return generate_tpm_target_symlink();
80 DEFINE_MAIN_GENERATOR_FUNCTION(run
);