From: Zbigniew Jędrzejewski-Szmek Date: Thu, 16 Apr 2026 21:07:11 +0000 (+0200) Subject: pcrlock: convert to the new option and verb parsers X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=33061044685a449dd98c747a371c530d29afbf98;p=thirdparty%2Fsystemd.git 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 --- diff --git a/src/pcrlock/pcrlock.c b/src/pcrlock/pcrlock.c index 7820774fe08..62a84a26cb6 100644 --- a/src/pcrlock/pcrlock.c +++ b/src/pcrlock/pcrlock.c @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include #include #include #include @@ -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()); - return 0; -} + printf("\n%sCommands:%s\n", ansi_underline(), ansi_normal()); + r = table_print_or_warn(commands); + if (r < 0) + return r; -static int verb_help(int argc, char *argv[], uintptr_t _data, void *userdata) { - return help(); -} + printf("\n%sProtections:%s\n", ansi_underline(), ansi_normal()); + r = table_print_or_warn(protections); + if (r < 0) + return r; -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, - }; + printf("\n%sOptions:%s\n", ansi_underline(), ansi_normal()); + r = table_print_or_warn(options); + if (r < 0) + return r; - 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' }, - {} - }; + printf("\nSee the %s for details.\n", link); + return 0; +} - bool auto_location = true; - int c, r; +VERB_NOARG(verb_unlock_simple, "unlock-raw", + "Remove .pcrlock file for raw data"); + +VERB_COMMON_HELP_HIDDEN(help); +static int parse_argv(int argc, char *argv[], char ***ret_args) { assert(argc >= 0); assert(argv); + assert(ret_args); + + OptionParser state = { argc, argv }; + const char *arg; + bool auto_location = true; + int r; - while ((c = getopt_long(argc, argv, "hq", options, NULL)) >= 0) + 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);