pcrlock: convert to the new option and verb parsers

The VERB definitions are done in order to retain the logical
presentation of verbs in lock+unlock pairs.

Previously --help output was too wide, it now fits in 80 columns.
Cosmetic changes in --help output only.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2026-04-23 17:41:01 +02:00
parent ac2a0355fb
commit 3306104468
+159 -184
View File
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <getopt.h>
#include <openssl/evp.h>
#include <sys/file.h>
#include <unistd.h>
@@ -38,6 +37,7 @@
#include "list.h"
#include "main-func.h"
#include "mkdir-label.h"
#include "options.h"
#include "ordered-set.h"
#include "parse-argument.h"
#include "parse-util.h"
@@ -2500,6 +2500,8 @@ static int event_log_load_and_process(EventLog **ret) {
return 0;
}
VERB(verb_show_log, "log", NULL, VERB_ANY, 1, VERB_DEFAULT,
"Show measurement log");
static int verb_show_log(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *log_table = NULL, *pcr_table = NULL;
_cleanup_(event_log_freep) EventLog *el = NULL;
@@ -2613,6 +2615,8 @@ static int event_log_record_to_cel(EventLogRecord *record, uint64_t *recnum, sd_
return 0;
}
VERB_NOARG(verb_show_cel, "cel",
"Show measurement log in TCG CEL-JSON format");
static int verb_show_cel(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
_cleanup_(event_log_freep) EventLog *el = NULL;
@@ -2648,6 +2652,8 @@ static int verb_show_cel(int argc, char *argv[], uintptr_t _data, void *userdata
return 0;
}
VERB_NOARG(verb_list_components, "list-components",
"List defined .pcrlock components");
static int verb_list_components(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(event_log_freep) EventLog *el = NULL;
_cleanup_(table_unrefp) Table *table = NULL;
@@ -3348,6 +3354,8 @@ static int tpm2_pcr_prediction_run(
return 0;
}
VERB_NOARG(verb_predict, "predict",
"Predict PCR values");
static int verb_predict(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(tpm2_pcr_prediction_done) Tpm2PCRPrediction context = {
arg_pcr_mask != 0 ? arg_pcr_mask : DEFAULT_PCR_MASK,
@@ -3927,6 +3935,8 @@ static int make_policy(bool force, RecoveryPinMode recovery_pin_mode) {
return 1; /* installed new policy */
}
VERB_NOARG(verb_make_policy, "make-policy",
"Predict PCR values and generate TPM2 policy from it");
static int verb_make_policy(int argc, char *argv[], uintptr_t _data, void *userdata) {
int r;
@@ -4027,6 +4037,8 @@ static int remove_policy(void) {
return ret;
}
VERB_NOARG(verb_remove_policy, "remove-policy",
"Remove TPM2 policy");
static int verb_remove_policy(int argc, char *argv[], uintptr_t _data, void *userdata) {
return remove_policy();
}
@@ -4061,6 +4073,8 @@ static int test_tpm2_support_pcrlock(Tpm2Support *ret) {
return 0;
}
VERB_NOARG(verb_is_supported, "is-supported",
"Tests if TPM2 supports necessary features");
static int verb_is_supported(int argc, char *argv[], uintptr_t _data, void *userdata) {
int r;
@@ -4140,6 +4154,10 @@ static bool event_log_record_is_separator(const EventLogRecord *rec) {
return rec->event_payload_valid == EVENT_PAYLOAD_VALID_YES; /* Insist the record is consistent */
}
VERB_GROUP("Protections");
VERB(verb_lock_firmware, "lock-firmware-code", NULL, VERB_ANY, 2, 0,
"Generate a .pcrlock file from current firmware code");
static int verb_lock_firmware(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *array_early = NULL, *array_late = NULL;
_cleanup_(event_log_freep) EventLog *el = NULL;
@@ -4259,6 +4277,8 @@ static int verb_lock_firmware(int argc, char *argv[], uintptr_t _data, void *use
return write_pcrlock(array_late, default_pcrlock_late_path);
}
VERB_NOARG(verb_unlock_firmware, "unlock-firmware-code",
"Remove .pcrlock file for firmware code");
static int verb_unlock_firmware(int argc, char *argv[], uintptr_t _data, void *userdata) {
const char *default_pcrlock_early_path, *default_pcrlock_late_path;
int r;
@@ -4285,6 +4305,14 @@ static int verb_unlock_firmware(int argc, char *argv[], uintptr_t _data, void *u
return 0;
}
VERB(verb_lock_firmware, "lock-firmware-config", NULL, VERB_ANY, 2, 0,
"Generate a .pcrlock file from current firmware configuration");
VERB_NOARG(verb_unlock_firmware, "unlock-firmware-config",
"Remove .pcrlock file for firmware configuration");
VERB_NOARG(verb_lock_secureboot_policy, "lock-secureboot-policy",
"Generate a .pcrlock file from current SecureBoot policy");
static int verb_lock_secureboot_policy(int argc, char *argv[], uintptr_t _data, void *userdata) {
static const struct {
sd_id128_t id;
@@ -4358,6 +4386,8 @@ static int verb_lock_secureboot_policy(int argc, char *argv[], uintptr_t _data,
return write_pcrlock(array, PCRLOCK_SECUREBOOT_POLICY_PATH);
}
VERB_NOARG(verb_unlock_secureboot_policy, "unlock-secureboot-policy",
"Remove .pcrlock file for SecureBoot policy");
static int verb_unlock_secureboot_policy(int argc, char *argv[], uintptr_t _data, void *userdata) {
return unlink_pcrlock(PCRLOCK_SECUREBOOT_POLICY_PATH);
}
@@ -4479,6 +4509,8 @@ static int event_log_ensure_secureboot_consistency(EventLog *el) {
return 0;
}
VERB_NOARG(verb_lock_secureboot_authority, "lock-secureboot-authority",
"Generate a .pcrlock file from current SecureBoot authority");
static int verb_lock_secureboot_authority(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
_cleanup_(event_log_freep) EventLog *el = NULL;
@@ -4558,10 +4590,14 @@ static int verb_lock_secureboot_authority(int argc, char *argv[], uintptr_t _dat
return write_pcrlock(array, PCRLOCK_SECUREBOOT_AUTHORITY_PATH);
}
VERB_NOARG(verb_unlock_secureboot_authority, "unlock-secureboot-authority",
"Remove .pcrlock file for SecureBoot authority");
static int verb_unlock_secureboot_authority(int argc, char *argv[], uintptr_t _data, void *userdata) {
return unlink_pcrlock(PCRLOCK_SECUREBOOT_AUTHORITY_PATH);
}
VERB(verb_lock_gpt, "lock-gpt", "[DISK]", VERB_ANY, 2, 0,
"Generate a .pcrlock file from GPT header");
static int verb_lock_gpt(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL, *record = NULL;
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
@@ -4675,10 +4711,14 @@ static int verb_lock_gpt(int argc, char *argv[], uintptr_t _data, void *userdata
return write_pcrlock(array, PCRLOCK_GPT_PATH);
}
VERB_NOARG(verb_unlock_gpt, "unlock-gpt",
"Remove .pcrlock file for GPT header");
static int verb_unlock_gpt(int argc, char *argv[], uintptr_t _data, void *userdata) {
return unlink_pcrlock(PCRLOCK_GPT_PATH);
}
VERB(verb_lock_pe, "lock-pe", "[BINARY]", VERB_ANY, 2, 0,
"Generate a .pcrlock file from PE binary");
static int verb_lock_pe(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
_cleanup_close_ int fd = -EBADF;
@@ -4734,6 +4774,8 @@ static int verb_lock_pe(int argc, char *argv[], uintptr_t _data, void *userdata)
return write_pcrlock(array, NULL);
}
VERB_NOARG(verb_unlock_simple, "unlock-pe",
"Remove .pcrlock file for PE binary");
static int verb_unlock_simple(int argc, char *argv[], uintptr_t _data, void *userdata) {
return unlink_pcrlock(NULL);
}
@@ -4747,6 +4789,8 @@ static void section_hashes_array_done(SectionHashArray *array) {
free((*array)[i]);
}
VERB(verb_lock_uki, "lock-uki", "[UKI]", VERB_ANY, 2, 0,
"Generate a .pcrlock file from UKI PE binary");
static int verb_lock_uki(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL, *pe_digests = NULL;
_cleanup_(section_hashes_array_done) SectionHashArray section_hashes = {};
@@ -4842,6 +4886,11 @@ static int verb_lock_uki(int argc, char *argv[], uintptr_t _data, void *userdata
return write_pcrlock(array, NULL);
}
VERB_NOARG(verb_unlock_simple, "unlock-uki",
"Remove .pcrlock file for UKI PE binary");
VERB_NOARG(verb_lock_machine_id, "lock-machine-id",
"Generate a .pcrlock file from current machine ID");
static int verb_lock_machine_id(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *record = NULL, *array = NULL;
_cleanup_free_ char *word = NULL;
@@ -4862,6 +4911,8 @@ static int verb_lock_machine_id(int argc, char *argv[], uintptr_t _data, void *u
return write_pcrlock(array, PCRLOCK_MACHINE_ID_PATH);
}
VERB_NOARG(verb_unlock_machine_id, "unlock-machine-id",
"Remove .pcrlock file for machine ID");
static int verb_unlock_machine_id(int argc, char *argv[], uintptr_t _data, void *userdata) {
return unlink_pcrlock(PCRLOCK_MACHINE_ID_PATH);
}
@@ -4894,6 +4945,8 @@ static int pcrlock_file_system_path(const char *normalized_path, char **ret) {
return 0;
}
VERB(verb_lock_file_system, "lock-file-system", "[PATH]", VERB_ANY, 2, 0,
"Generate a .pcrlock file from current root fs + /var/");
static int verb_lock_file_system(int argc, char *argv[], uintptr_t _data, void *userdata) {
const char* paths[3] = {};
int r;
@@ -4947,6 +5000,8 @@ static int verb_lock_file_system(int argc, char *argv[], uintptr_t _data, void *
return 0;
}
VERB(verb_unlock_file_system, "unlock-file-system", "[PATH]", VERB_ANY, 2, 0,
"Remove .pcrlock file for root fs + /var/");
static int verb_unlock_file_system(int argc, char *argv[], uintptr_t _data, void *userdata) {
const char* paths[3] = {};
int r;
@@ -4977,6 +5032,8 @@ static int verb_unlock_file_system(int argc, char *argv[], uintptr_t _data, void
return 0;
}
VERB(verb_lock_kernel_cmdline, "lock-kernel-cmdline", "[FILE]", VERB_ANY, 2, 0,
"Generate a .pcrlock file from kernel command line");
static int verb_lock_kernel_cmdline(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *record = NULL, *array = NULL;
_cleanup_free_ char *cmdline = NULL;
@@ -5014,10 +5071,14 @@ static int verb_lock_kernel_cmdline(int argc, char *argv[], uintptr_t _data, voi
return 0;
}
VERB_NOARG(verb_unlock_kernel_cmdline, "unlock-kernel-cmdline",
"Remove .pcrlock file for kernel command line");
static int verb_unlock_kernel_cmdline(int argc, char *argv[], uintptr_t _data, void *userdata) {
return unlink_pcrlock(PCRLOCK_KERNEL_CMDLINE_PATH);
}
VERB(verb_lock_kernel_initrd, "lock-kernel-initrd", "FILE", VERB_ANY, 2, 0,
"Generate a .pcrlock file from an initrd file");
static int verb_lock_kernel_initrd(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *records = NULL;
_cleanup_fclose_ FILE *f = NULL;
@@ -5041,10 +5102,14 @@ static int verb_lock_kernel_initrd(int argc, char *argv[], uintptr_t _data, void
return 0;
}
VERB_NOARG(verb_unlock_kernel_initrd, "unlock-kernel-initrd",
"Remove .pcrlock file for an initrd file");
static int verb_unlock_kernel_initrd(int argc, char *argv[], uintptr_t _data, void *userdata) {
return unlink_pcrlock(PCRLOCK_KERNEL_INITRD_PATH);
}
VERB(verb_lock_raw, "lock-raw", "[FILE]", VERB_ANY, 2, 0,
"Generate a .pcrlock file from raw data");
static int verb_lock_raw(int argc, char *argv[], uintptr_t _data, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *records = NULL;
_cleanup_fclose_ FILE *f = NULL;
@@ -5068,162 +5133,108 @@ static int verb_lock_raw(int argc, char *argv[], uintptr_t _data, void *userdata
static int help(void) {
_cleanup_free_ char *link = NULL;
_cleanup_(table_unrefp) Table *commands = NULL, *protections = NULL, *options = NULL;
int r;
r = terminal_urlify_man("systemd-pcrlock", "8", &link);
if (r < 0)
return log_oom();
printf("%1$s [OPTIONS...] COMMAND ...\n"
"\n%5$sManage a TPM2 PCR lock.%6$s\n"
"\n%3$sCommands:%4$s\n"
" log Show measurement log\n"
" cel Show measurement log in TCG CEL-JSON format\n"
" list-components List defined .pcrlock components\n"
" predict Predict PCR values\n"
" make-policy Predict PCR values and generate TPM2 policy from it\n"
" remove-policy Remove TPM2 policy\n"
" is-supported Tests if TPM2 supports necessary features\n"
"\n%3$sProtections:%4$s\n"
" lock-firmware-code Generate a .pcrlock file from current firmware code\n"
" unlock-firmware-code Remove .pcrlock file for firmware code\n"
" lock-firmware-config Generate a .pcrlock file from current firmware configuration\n"
" unlock-firmware-config Remove .pcrlock file for firmware configuration\n"
" lock-secureboot-policy Generate a .pcrlock file from current SecureBoot policy\n"
" unlock-secureboot-policy Remove .pcrlock file for SecureBoot policy\n"
" lock-secureboot-authority Generate a .pcrlock file from current SecureBoot authority\n"
" unlock-secureboot-authority Remove .pcrlock file for SecureBoot authority\n"
" lock-gpt [DISK] Generate a .pcrlock file from GPT header\n"
" unlock-gpt Remove .pcrlock file for GPT header\n"
" lock-pe [BINARY] Generate a .pcrlock file from PE binary\n"
" unlock-pe Remove .pcrlock file for PE binary\n"
" lock-uki [UKI] Generate a .pcrlock file from UKI PE binary\n"
" unlock-uki Remove .pcrlock file for UKI PE binary\n"
" lock-machine-id Generate a .pcrlock file from current machine ID\n"
" unlock-machine-id Remove .pcrlock file for machine ID\n"
" lock-file-system [PATH] Generate a .pcrlock file from current root fs + /var/\n"
" unlock-file-system [PATH] Remove .pcrlock file for root fs + /var/\n"
" lock-kernel-cmdline [FILE] Generate a .pcrlock file from kernel command line\n"
" unlock-kernel-cmdline Remove .pcrlock file for kernel command line\n"
" lock-kernel-initrd FILE Generate a .pcrlock file from an initrd file\n"
" unlock-kernel-initrd Remove .pcrlock file for an initrd file\n"
" lock-raw [FILE] Generate a .pcrlock file from raw data\n"
" unlock-raw Remove .pcrlock file for raw data\n"
"\n%3$sOptions:%4$s\n"
" -h --help Show this help\n"
" --version Print version\n"
" --no-pager Do not pipe output into a pager\n"
" --json=pretty|short|off Generate JSON output\n"
" --raw-description Show raw firmware record data as description in table\n"
" --pcr=NR Generate .pcrlock for specified PCR\n"
" --nv-index=NUMBER Use the specified NV index, instead of a random one\n"
" --components=PATH Directory to read .pcrlock files from\n"
" --location=STRING[:STRING]\n"
" Do not process components beyond this component name\n"
" --recovery-pin=MODE Controls whether to show, hide, or ask for a recovery PIN\n"
" --pcrlock=PATH .pcrlock file to write expected PCR measurement to\n"
" --policy=PATH JSON file to write policy output to\n"
" --force Write policy even if it matches existing policy\n"
" --entry-token=machine-id|os-id|os-image-id|auto|literal:…\n"
" Boot entry token to use for this installation\n"
" -q --quiet Suppress unnecessary output\n"
"\nSee the %2$s for details.\n",
r = verbs_get_help_table(&commands);
if (r < 0)
return r;
r = verbs_get_help_table_group("Protections", &protections);
if (r < 0)
return r;
r = option_parser_get_help_table(&options);
if (r < 0)
return r;
(void) table_sync_column_widths(0, commands, protections, options);
printf("%s [OPTIONS...] COMMAND ...\n"
"\n%sManage a TPM2 PCR lock.%s\n",
program_invocation_short_name,
link,
ansi_underline(),
ansi_normal(),
ansi_highlight(),
ansi_normal());
printf("\n%sCommands:%s\n", ansi_underline(), ansi_normal());
r = table_print_or_warn(commands);
if (r < 0)
return r;
printf("\n%sProtections:%s\n", ansi_underline(), ansi_normal());
r = table_print_or_warn(protections);
if (r < 0)
return r;
printf("\n%sOptions:%s\n", ansi_underline(), ansi_normal());
r = table_print_or_warn(options);
if (r < 0)
return r;
printf("\nSee the %s for details.\n", link);
return 0;
}
static int verb_help(int argc, char *argv[], uintptr_t _data, void *userdata) {
return help();
}
VERB_NOARG(verb_unlock_simple, "unlock-raw",
"Remove .pcrlock file for raw data");
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_NO_PAGER,
ARG_JSON,
ARG_RAW_DESCRIPTION,
ARG_PCR,
ARG_NV_INDEX,
ARG_COMPONENTS,
ARG_LOCATION,
ARG_RECOVERY_PIN,
ARG_PCRLOCK,
ARG_POLICY,
ARG_FORCE,
ARG_ENTRY_TOKEN,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "json", required_argument, NULL, ARG_JSON },
{ "raw-description", no_argument, NULL, ARG_RAW_DESCRIPTION },
{ "pcr", required_argument, NULL, ARG_PCR },
{ "nv-index", required_argument, NULL, ARG_NV_INDEX },
{ "components", required_argument, NULL, ARG_COMPONENTS },
{ "location", required_argument, NULL, ARG_LOCATION },
{ "recovery-pin", required_argument, NULL, ARG_RECOVERY_PIN },
{ "pcrlock", required_argument, NULL, ARG_PCRLOCK },
{ "policy", required_argument, NULL, ARG_POLICY },
{ "force", no_argument, NULL, ARG_FORCE },
{ "entry-token", required_argument, NULL, ARG_ENTRY_TOKEN },
{ "quiet", no_argument, NULL, 'q' },
{}
};
bool auto_location = true;
int c, r;
VERB_COMMON_HELP_HIDDEN(help);
static int parse_argv(int argc, char *argv[], char ***ret_args) {
assert(argc >= 0);
assert(argv);
assert(ret_args);
while ((c = getopt_long(argc, argv, "hq", options, NULL)) >= 0)
OptionParser state = { argc, argv };
const char *arg;
bool auto_location = true;
int r;
FOREACH_OPTION(&state, c, &arg, /* on_error= */ return c)
switch (c) {
case 'h':
OPTION_COMMON_HELP:
return help();
case ARG_VERSION:
OPTION_COMMON_VERSION:
return version();
case ARG_NO_PAGER:
OPTION_COMMON_NO_PAGER:
arg_pager_flags |= PAGER_DISABLE;
break;
case ARG_JSON:
r = parse_json_argument(optarg, &arg_json_format_flags);
OPTION_COMMON_JSON:
r = parse_json_argument(arg, &arg_json_format_flags);
if (r <= 0)
return r;
break;
case ARG_RAW_DESCRIPTION:
OPTION_LONG("raw-description", NULL,
"Show raw firmware record data as description in table"):
arg_raw_description = true;
break;
case ARG_PCR: {
r = tpm2_parse_pcr_argument_to_mask(optarg, &arg_pcr_mask);
OPTION_LONG("pcr", "NR",
"Generate .pcrlock for specified PCR"):
r = tpm2_parse_pcr_argument_to_mask(arg, &arg_pcr_mask);
if (r < 0)
return log_error_errno(r, "Failed to parse PCR specification: %s", optarg);
return log_error_errno(r, "Failed to parse PCR specification: %s", arg);
break;
}
case ARG_NV_INDEX:
if (isempty(optarg))
OPTION_LONG("nv-index", "NUMBER",
"Use the specified NV index, instead of a random one"):
if (isempty(arg))
arg_nv_index = 0;
else {
uint32_t u;
r = safe_atou32_full(optarg, 16, &u);
r = safe_atou32_full(arg, 16, &u);
if (r < 0)
return log_error_errno(r, "Failed to parse --nv-index= argument: %s", optarg);
return log_error_errno(r, "Failed to parse --nv-index= argument: %s", arg);
if (u < TPM2_NV_INDEX_FIRST || u > TPM2_NV_INDEX_LAST)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Argument for --nv-index= outside of valid range 0x%" PRIx32 "…0x%" PRIx32 ": 0x%" PRIx32,
@@ -5233,10 +5244,11 @@ static int parse_argv(int argc, char *argv[]) {
}
break;
case ARG_COMPONENTS: {
OPTION_LONG("components", "PATH",
"Directory to read .pcrlock files from"): {
_cleanup_free_ char *p = NULL;
r = parse_path_argument(optarg, /* suppress_root= */ false, &p);
r = parse_path_argument(arg, /* suppress_root= */ false, &p);
if (r < 0)
return r;
@@ -5247,21 +5259,22 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
case ARG_LOCATION: {
OPTION_LONG("location", "START[:END]",
"Do not process components beyond this component name"): {
_cleanup_free_ char *start = NULL, *end = NULL;
const char *e;
auto_location = false;
if (isempty(optarg)) {
if (isempty(arg)) {
arg_location_start = mfree(arg_location_start);
arg_location_end = mfree(arg_location_end);
break;
}
e = strchr(optarg, ':');
e = strchr(arg, ':');
if (e) {
start = strndup(optarg, e - optarg);
start = strndup(arg, e - arg);
if (!start)
return log_oom();
@@ -5269,11 +5282,11 @@ static int parse_argv(int argc, char *argv[]) {
if (!end)
return log_oom();
} else {
start = strdup(optarg);
start = strdup(arg);
if (!start)
return log_oom();
end = strdup(optarg);
end = strdup(arg);
if (!end)
return log_oom();
}
@@ -5288,17 +5301,19 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
case ARG_RECOVERY_PIN:
arg_recovery_pin = recovery_pin_mode_from_string(optarg);
OPTION_LONG("recovery-pin", "MODE",
"Controls whether to show, hide, or ask for a recovery PIN"):
arg_recovery_pin = recovery_pin_mode_from_string(arg);
if (arg_recovery_pin < 0)
return log_error_errno(arg_recovery_pin, "Failed to parse --recovery-pin= mode: %s", optarg);
return log_error_errno(arg_recovery_pin, "Failed to parse --recovery-pin= mode: %s", arg);
break;
case ARG_PCRLOCK:
if (empty_or_dash(optarg))
OPTION_LONG("pcrlock", "PATH",
".pcrlock file to write expected PCR measurement to"):
if (empty_or_dash(arg))
arg_pcrlock_path = mfree(arg_pcrlock_path);
else {
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_pcrlock_path);
r = parse_path_argument(arg, /* suppress_root= */ false, &arg_pcrlock_path);
if (r < 0)
return r;
}
@@ -5306,36 +5321,34 @@ static int parse_argv(int argc, char *argv[]) {
arg_pcrlock_auto = false;
break;
case ARG_POLICY:
if (empty_or_dash(optarg))
OPTION_LONG("policy", "PATH",
"JSON file to write policy output to"):
if (empty_or_dash(arg))
arg_policy_path = mfree(arg_policy_path);
else {
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_policy_path);
r = parse_path_argument(arg, /* suppress_root= */ false, &arg_policy_path);
if (r < 0)
return r;
}
break;
case ARG_FORCE:
OPTION_LONG("force", NULL,
"Write policy even if it matches existing policy"):
arg_force = true;
break;
case ARG_ENTRY_TOKEN:
r = parse_boot_entry_token_type(optarg, &arg_entry_token_type, &arg_entry_token);
OPTION_LONG("entry-token", "TOKEN",
"Boot entry token to use for this installation "
"(machine-id, os-id, os-image-id, auto, literal:…)"):
r = parse_boot_entry_token_type(arg, &arg_entry_token_type, &arg_entry_token);
if (r < 0)
return r;
break;
case 'q':
OPTION('q', "quiet", NULL, "Suppress unnecessary output"):
arg_quiet = true;
break;
case '?':
return -EINVAL;
default:
assert_not_reached();
}
if (auto_location) {
@@ -5359,49 +5372,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_pager_flags |= PAGER_DISABLE;
}
*ret_args = option_parser_get_args(&state);
return 1;
}
static int pcrlock_main(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "help", VERB_ANY, VERB_ANY, 0, verb_help },
{ "log", VERB_ANY, 1, VERB_DEFAULT, verb_show_log },
{ "cel", VERB_ANY, 1, 0, verb_show_cel },
{ "list-components", VERB_ANY, 1, 0, verb_list_components },
{ "predict", VERB_ANY, 1, 0, verb_predict },
{ "lock-firmware-code", VERB_ANY, 2, 0, verb_lock_firmware },
{ "unlock-firmware-code", VERB_ANY, 1, 0, verb_unlock_firmware },
{ "lock-firmware-config", VERB_ANY, 2, 0, verb_lock_firmware },
{ "unlock-firmware-config", VERB_ANY, 1, 0, verb_unlock_firmware },
{ "lock-secureboot-policy", VERB_ANY, 1, 0, verb_lock_secureboot_policy },
{ "unlock-secureboot-policy", VERB_ANY, 1, 0, verb_unlock_secureboot_policy },
{ "lock-secureboot-authority", VERB_ANY, 1, 0, verb_lock_secureboot_authority },
{ "unlock-secureboot-authority", VERB_ANY, 1, 0, verb_unlock_secureboot_authority },
{ "lock-gpt", VERB_ANY, 2, 0, verb_lock_gpt },
{ "unlock-gpt", VERB_ANY, 1, 0, verb_unlock_gpt },
{ "lock-pe", VERB_ANY, 2, 0, verb_lock_pe },
{ "unlock-pe", VERB_ANY, 1, 0, verb_unlock_simple },
{ "lock-uki", VERB_ANY, 2, 0, verb_lock_uki },
{ "unlock-uki", VERB_ANY, 1, 0, verb_unlock_simple },
{ "lock-machine-id", VERB_ANY, 1, 0, verb_lock_machine_id },
{ "unlock-machine-id", VERB_ANY, 1, 0, verb_unlock_machine_id },
{ "lock-file-system", VERB_ANY, 2, 0, verb_lock_file_system },
{ "unlock-file-system", VERB_ANY, 2, 0, verb_unlock_file_system },
{ "lock-kernel-cmdline", VERB_ANY, 2, 0, verb_lock_kernel_cmdline },
{ "unlock-kernel-cmdline", VERB_ANY, 1, 0, verb_unlock_kernel_cmdline },
{ "lock-kernel-initrd", VERB_ANY, 2, 0, verb_lock_kernel_initrd },
{ "unlock-kernel-initrd", VERB_ANY, 1, 0, verb_unlock_kernel_initrd },
{ "lock-raw", VERB_ANY, 2, 0, verb_lock_raw },
{ "unlock-raw", VERB_ANY, 1, 0, verb_unlock_simple },
{ "make-policy", VERB_ANY, 1, 0, verb_make_policy },
{ "remove-policy", VERB_ANY, 1, 0, verb_remove_policy },
{ "is-supported", VERB_ANY, 1, 0, verb_is_supported },
{}
};
return dispatch_verb(argc, argv, verbs, NULL);
}
static int vl_method_read_event_log(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
_cleanup_(event_log_freep) EventLog *el = NULL;
uint64_t recnum = 0;
@@ -5493,7 +5467,8 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return r;
r = parse_argv(argc, argv);
char **args = NULL;
r = parse_argv(argc, argv, &args);
if (r <= 0)
return r;
@@ -5525,7 +5500,7 @@ static int run(int argc, char *argv[]) {
return EXIT_SUCCESS;
}
return pcrlock_main(argc, argv);
return dispatch_verb_with_args(args, NULL);
}
DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);