Compare commits

..

106 Commits

Author SHA1 Message Date
Jan Höppner
77083b1cbb New release s390-tools-2.42.1
Signed-off by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-22 16:34:32 +02:00
Thomas Richter
21c2a04347 cpumf/pai: Remove unnecessary const parameter definition
With glibc 2.43 const-ness is preserved for standard library functions
and a compiler warning will be issued if this is violated.

pai parse_cpulist() receives user input via the parm function
parameter. The parameter is defined as 'const char *' and used as input
value for strchr(). The target pointer (cp) is defined as mutable
'char *' leading to violation of const correctness and this compiler
warning:

pai.c: In function ‘parse_cpulist’:
pai.c:907:20: warning: assignment discards ‘const’ qualifier from
			pointer target type [-Wdiscarded-qualifiers]
  907 |                 cp = strchr(parm, ':');

Since the user input is coming from optarg 'non-const char *', it is
unnecessary to have the function parameters carrying this data defined
as const.

Remove the unnecessary const definition in the function call chain to
fix the described issue.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Suggested-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Suggested-by: Juergen Christ <jchrist@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-22 15:59:36 +02:00
Thomas Richter
8f2d77c9d3 cpumf/pai: Improve -m XXX argument verification
Speed up the check of the option -m argument and improve
the error message. The argument number must be a power of 2 number
and this check is improved.
Furthermore split the error message and provide one message for
invalid characters and one error message for the argument
not being a power of 2 number.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Suggested-by: Eduard Stefes <eddy@linux.ibm.com>
Suggested-by: Juergen Christ <jchrist@linux.ibm.com>
Tested-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Juergen Christ <jchrist@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-22 15:59:36 +02:00
Steffen Eiden
b6a4d7a6c1 pvsecret: Update man files
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-22 15:50:15 +02:00
Steffen Eiden
f223069f0b pvsecret: Fix argument parsing
The latest commit 'promote' a few optional arguments to required.
Fix this breaking behaviour by making them optional again.

Fixes: 080a6678fb ("pvsecret: Add -i -o option variants")
Reported-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Tested-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-22 15:50:15 +02:00
Steffen Eiden
19a5af8da9 rust/utils: Add functions to combine I/O arguments
Add functions to properly parse required and optional input/output
parameters that have to be combined into one.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-22 15:49:45 +02:00
Steffen Eiden
03b73ab3f9 pvsecret: Update man and Readme
man and README got out of sync with --help over time.
Resync them.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-21 13:20:06 +02:00
Steffen Eiden
080a6678fb pvsecret: Add -i -o option variants
All pvattest subcommands use the command line option -i <input> and -o
<output> to specify file input and output respectively. pvsecret however
uses mostly positional arguments for <input> and <output> exclusively,
e.g. pvattest check input.bin output.yaml

$ pvsecret add secret.bin

This provides an inconsistent user interface within the Secure
Execution tools and may confuse users.

Add the -i and -o option to the subcommands if applicable.
Input/output can then be specified like so:

$ pvsecret add -i secret.bin
$ pvsecret list -o list.yaml
$ pvsecret verify -i FILE -o out.yaml
$ pvsecret retrieve -i ID -o id.yaml

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-21 13:20:06 +02:00
Steffen Eiden
1d6f7d0bec pvattest: Update man and Readme
man and README got out of sync with --help over time.
Resync them.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-21 13:20:06 +02:00
Steffen Eiden
a50d0485c9 pvattest: Add -i -o option variant for check
Most pvattest subcommands use the command line option -i <input> and -o
<output> to specify file input and output respectively. pvattest check
however only uses positional arguments for <input> and <output>, e.g.

$ pvattest check input.bin output.yaml

This provides an inconsistent user interface within the tool and may
confuse users.

Add the command -i and -o option to the check subcommand to bring it in
line with the rest of the tool.

$ pvattest check -i input.bin -o output.yaml

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-21 13:20:06 +02:00
Steffen Eiden
d2a6a771a5 pvattest: Show perform -i & -o option in help
Show -i & -o option and display them in the help output. Showing the
additional options to the user may provide a better experience. Users
may expect -i /-o options as other subcommands have them as well.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-21 13:20:06 +02:00
Steffen Eiden
7568a0790f pv: Fix error description
The error texts printed a hardcoded .0 instead of the actual value.
Fix this by using the proper string format arguments.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Fixes: 61c5d7d431 ("rust/pv: Attestation generation and verification support")
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-21 13:20:06 +02:00
Finn Callies
ca0ee966b8 pvics: Add image prereqs in manpage
Specify the requirements for the base image in the pvics manpage.

Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-21 13:20:06 +02:00
Finn Callies
36a7b2e6eb pvebc: Minor bash improvements
Add minor improvements to the scripts the dracut module calls.

Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-21 13:20:06 +02:00
Finn Callies
851f63eb03 pvebc: Fix dependency for non EBC guests
For guests that do not make use of the EBC feature the boot should not
be impacted by this module. This requires removing the boot.mount unit
because it will unconditionally create a dependency on a unit that
conflicts with that idea. The downside is that mounting of the boot
partition has to be done manually.

Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/202
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-21 13:20:06 +02:00
Finn Callies
3d679f61fc pvebc: Disable unit logging to /boot
The boot partition is not designed for log files. Disable logging of the
EBC units to /boot/sics/log.

Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-21 13:20:06 +02:00
Finn Callies
9237c5b675 pvebc: Fix kernel module dependencies
Include the required kernel modules unconditionally when this module is
installed into an initramfs.
The new .conf file contains a list of kernel modules that are loaded by
the systemd-modules-load.service systemd unit.

Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-21 13:20:06 +02:00
Eduard Shishkin
d1ab6be082 zipl/src: Don't modify job->data.dump and job->data.mvdump sequentially
Set job->data.dump.no_compress (job->data.mvdump.force) only after
making sure that the job is 'dump' ('mvdump') respectively. Othrewise,
the second assignment can potentially corrupt the value that was set by
the first assignment.

Reviewed-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-05-21 13:20:06 +02:00
Jan Höppner
d6c2bac99f Prepare for next release
Signed-off by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 17:07:01 +02:00
Jan Höppner
997343f841 New release s390-tools-2.42.0
Signed-off by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 17:06:55 +02:00
Finn Callies
6a767408b3 ebc: Add new tool pvics
pvics (PV Image Customization Support) is a comprehensive tool for
converting existing qcow2 KVM guest images to IBM Secure Execution for
Linux (SEL) images with Early Boot Customization (EBC) support and
encrypted root filesystems.

The tool provides four main actions:
- list: Retrieve information about boot loader entries in a base image
- convert: Convert a base image to an EBC-ready SEL image
- encrypt: Encrypt the root filesystem and prepare EBC resources
- full: Perform both conversion and encryption in one operation

Assisted-by: IBM Bob:1.0.1
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 13:47:26 +02:00
Finn Callies
3aa5c38714 ebc: Add ibm-sel-ebc dracut module
Add 95ibm-sel-ebc dracut module for secure boot-time customization of
SEL guests.

Introduce the IBM SEL EBC dracut module (95ibm-sel-ebc) that enables
Early Boot Customization for SEL guests during the initramfs phase.

The module implements a critical security architecture to prevent
injection attacks: all EBC resources (.asr and .pol files) are copied from
/boot/sics (which resides in the qcow2 image on the host filesystem) to
/run/ibm-sel-ebc (a tmpfs/RAM-backed directory). Since guest RAM is
protected by the Ultravisor, this prevents malicious hosts from modifying
EBC resources during boot.

Systemd units and their purposes:
 - ibm-sel-ebc.target: Groups all EBC-related units
 - boot.mount: Mounts /dev/disk/by-label/boot to /boot
 - ibm-sel-ebc-ensure-sics.service: Fallback to create /boot/sics/ if boot
   partition mount fails (supports Kata VM scenarios)
 - ibm-sel-ebc-pvebc.service: Main unit that copies EBC resources to RAM,
   invokes pvebc tool to verify integrity and add ASRs to UV, retrieves
   LUKS passphrase from UV secret store
 - ibm-sel-ebc-override-crypttab.service: Replaces /etc/crypttab with
   prepared IBM SEL EBC crypttab, reloads systemd daemon, starts cryptsetup
   service
 - ibm-sel-ebc-paes-enforce.service: Verifies root filesystem uses PAES
   encryption to prevent root filesystem substitution attacks

All units write logs to /boot/sics/log for debugging, accessible even if
root filesystem fails to mount. Units are triggered by rd.ibm-sel-ebc
kernel parameter and only execute in initramfs
(ConditionPathExists=/etc/initrd-release).

Assisted-by: IBM Bob:1.0.1
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 13:46:31 +02:00
Finn Callies
c04a0919f6 rust: Add new tool pvebc
Add pvebc tool for parsing and verifying EBC Add-Secret-Request structures

Introduce pvebc, a CLI tool that parses and verifies the integrity of
Add-Secret-Request (ASR) structures used in Early Boot Customization for
SEL guests.

The tool processes an integrity-protected ASR structure consisting of:
 - toc.asr: Meta secret that links to toc.pol via relative filepath and
   SHA512 hash, integrity-protected by its AES GCM authentication tag
 - toc.pol: Policy file containing AES GCM authentication tags (last 16
   bytes) of all user-provided ASRs
 - User ASRs: Individual Add-Secret-Requests containing encrypted secrets

This structure guarantees:
 - Prevents ASR removal: toc.pol lists all expected ASR authentication tags
 - Prevents ASR insertion: Unlisted ASRs are rejected
 - Prevents ASR modification: AES GCM authentication tags provide
   cryptographic integrity
 - Prevents toc.pol tampering: toc.asr's integrity protection secures the
   link

The tool verifies completeness by checking that all ASRs listed in toc.pol
are present and their AES GCM authentication tags match. This prevents
attackers from removing, inserting, or modifying ASRs during transport over
unsecured channels.

After verification, pvebc adds all ASRs to the Ultravisor (UV), which
decrypts them using the guest's secret key and makes them available to
the guest during early boot.

Assisted-by: IBM Bob:1.0.1
Acked-by: Holger Dengler <dengler@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 13:46:31 +02:00
Finn Callies
c803cb925e rust: Add toc support for ebc to pvsecret
Add two new command-line options to pvsecret create for Early Boot
Customization (EBC) Table of Contents (TOC) support:

 1. --policy FILE
    Links an Add-Secret-Request (ASR) to a policy file by embedding a
    PolicyReference in the ASR's user data field. The PolicyReference
    contains the relative file path and SHA512 hash of the policy file,
    enabling integrity verification of the policy. This option conflicts
    with --user-data as both use the same user data field in the ASR
    structure.

 2. --toc-policy FILE
    Appends the AES-GCM authentication tag (MAC tag - last 16 bytes of
    the encrypted ASR) to the specified TOC policy file. This enables
    the TOC policy to maintain a list of all ASR MAC tags for
    completeness verification during boot. The TOC can verify that all
    expected ASRs are present and unmodified by checking their MAC tags
    against this list. This option also conflicts with --user-data.

Both options support the EBC multi-party workflow where an ISV/CSP builds
a generic SEL image and customers customize it with their own secrets. The
TOC mechanism ensures the integrity and completeness of all EBC resources
during the boot process.

Assisted-by: IBM Bob:1.0.1
Acked-by: Holger Dengler <dengler@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 13:46:31 +02:00
Finn Callies
1741ecff96 rust: Add EBC support to pv_core library
Add EBC (Early Boot Customization) utility functions to pv_core library
for parsing and verifying Add-Secret-Request structures.

Introduce the core library functionality needed for EBC:
- Add ebc_utils module to pv_core with ASR parsing and verification
- Export ebc_utils in pv_core lib.rs
- Re-export ebc_utils in pv lib.rs for downstream consumers
- Update pvsecret Cargo.toml dependencies

The library provides the foundation for tools that work with
integrity-protected ASR structures used in SEL guest customization.

Assisted-by: IBM Bob:1.0.1
Acked-by: Holger Dengler <dengler@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 13:46:31 +02:00
Finn Callies
20de1fce2a rust: Fix typo in pv
Change "Extracrted" to "Extracted".

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 13:46:31 +02:00
Szabina Korbai
a5af5bcf70 zcrypt: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts
to chzcrypt, lszcrypt and zcryptstats.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:51:04 +02:00
Szabina Korbai
7730f2489f zipl-editenv: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:51:04 +02:00
Szabina Korbai
6dbc5646f9 lsscm: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:51:04 +02:00
Szabina Korbai
f70991ab1e lsqeth: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:51:04 +02:00
Szabina Korbai
e9ee658492 lscss: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.
Modify --devtype flag description to make it
compatible with zsh autocompletion.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:51:04 +02:00
Szabina Korbai
35d5f41232 chpstat: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:51:03 +02:00
Szabina Korbai
260a0a2428 chp: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts
to chchp and lschp.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:50:38 +02:00
Szabina Korbai
b444e71ee3 zmemtopo: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Tested-by: Mete Durlu <meted@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:50:10 +02:00
Szabina Korbai
31d576a595 zpwr: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:49:28 +02:00
Szabina Korbai
68309ccb7f zpcictl: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:49:26 +02:00
Szabina Korbai
755ea88d5d vmcp: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:49:03 +02:00
Szabina Korbai
af99efaab2 tunedasd: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:48:33 +02:00
Szabina Korbai
3b55ca085e opticsmon: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.
Modify --module-info flag description to make it
compatible with zsh autocompletion.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:48:33 +02:00
Szabina Korbai
9fdfd1a6dc lsstp: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:48:33 +02:00
Szabina Korbai
c459ec08c6 hsavmcore: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:48:33 +02:00
Szabina Korbai
eb63434f44 fdasd: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:48:30 +02:00
Szabina Korbai
0eae712cc2 dump2tar: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:47:35 +02:00
Szabina Korbai
e7e9f137c1 dasdview: Implement zsh and bash autocompletion
Add generation of shell autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:47:33 +02:00
Szabina Korbai
364cb9d869 dasdinfo: Implement zsh and bash autocompletion
Add generation of shell	autocompletion scripts.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:47:05 +02:00
Szabina Korbai
a64e9cab67 dasdfmt: Remove license boilerplate
Remove outdated license boilerplate from autocompletion
generator and cli header file. Fix SPDX-tag style.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Szabina Korbai
74cb6ee40e cpumf: Remove license boilerplate
Remove outdated license boilerplate from autocompletion
generator and cli header files. Fix SPDX-tag style.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Szabina Korbai
8c99c3878e libutil/util_autocomp_host: Remove license boilerplate
Remove outdated license boilerplate and fix
SPDX-tag style.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Jan Höppner
f302f5734b zpwr: Adapt to new JSON Lines text format
util_fmt now provides support for JSON Lines text format. Adapt certain
checks in the code and document the newly supported format in the man
page accordingly.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Jan Höppner
3485192791 zmemtopo: Adapt to new JSON Lines text format
util_fmt now provides support for JSON Lines text format.
Document the newly supported format in the man page accordingly.

Reviewed-by: Mete Durlu <meted@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Jan Höppner
715da84030 lschp: Adapt to new JSON Lines text format
util_fmt now provides support for JSON Lines text format.
Document the newly supported format in the man page accordingly.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Jan Höppner
6e53be736e chpstat: Adapt to new JSON Lines text format
util_fmt now provides support for JSON Lines text format. Adapt certain
checks in the code and document the newly supported format in the man
page accordingly.

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Jan Höppner
88bf638487 cpumf: Adapt to new JSON Lines text format
util_fmt now provides support for JSON Lines text format. Adapt certain
checks in the code and document the newly supported format in the man
pages for lshwc and lspai accordingly.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Jan Höppner
182892da12 hyptop: Adapt to new JSON Lines text format
util_fmt now provides support for JSON Lines text format. Adapt certain
checks in the code and document the newly supported format in the man
page accordingly.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Jan Höppner
f9e07c3916 libutil/util_fmt: Introduce JSON Lines text format
JSON Lines text format (JSONL) [1] is a line-delimited JSON format where
objects are separated by the new line character (\n, LF) as opposed to
the JSON Sequence text format (json-seq) where JSON text is encapsulated
in an ASCII Record Separator (0x1E, RS) and ASCII Line Feed character
(0x0A, LF).

Whilst JSONL is also used for data streaming, this simpler format is
better suited for logging and works also well with traditional
line-oriented Unix tooling (e.g. grep or sed).

Add this format to util_fmt so that users have more choice and control
over formats that are required for their usecases.

Add helper functions that let the user determine whether a given format
type is JSON in general or a JSON streaming format (such as json-seq or
jsonl).

For better readability and more clarity use the helper function
util_fmt_is_json_stream() where the same decision is made for both
JSON streaming formats FMT_JSONSEQ and FMT_JSONL.

[1] https://jsonlines.org/

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Thomas Richter
3aaf3c067e cpumf/pai.c: Install SIGINT/SIGTERM handler for graceful termination
Sending signal SIGINT/SIGTERM to a running pai process causes immediate
termination of that running process. This usually interrupts a
select() system call waiting for more input to read from the installed
events and its mapped memory buffers. As there is no signal handler
installed, a SIGINT or SIGTERM signal simply terminates the process,
sometimes leaving incomplete recorded output file paicryto.XXX
(where XXX is the CPU number).
Install a signal handler to intercept signal SIGINT or SIGTERM and run
one more data collection loop to read out pending data and close all
recording output files properly.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Steffen Eiden
801e404160 pvimg: Fix hidden inferred bound
The associated type bound  for Iterator::Item was unsatisfied for Self.
Fix this by requiring Sized for IntoEnumIterator.

Fixes: 1d2a89b387 ("pvimg: Improve the readability of Display output for control flags")
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Steffen Eiden
280b8509d1 pvimg: Remove unnecessary references
Referencing here is superfluous and makes clippy sad.

Fixes: 87966251c4 ("pvimg: info: Improve JSON output")
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Steffen Eiden
0f56416d82 pvsecret: Improve UX on non-s390 systems
If pvsecret {add, list, retrieve} is executed with options on a non-s390
system the user gets misleading error messages as the options are not
defined.

> pvsecret add -i secret.bin
error: unexpected argument '-i' found

This may lead the user to think wrong arguments where chosen, which is
not entirely true as they are valid on s390. The more helpful error
message would be
error: Command only available on s390x

Which is already the case if no arguments are given.
Solve this by allowing non-s390 systems to parse the options:

> pvsecret add -i secret.bin
  error: Command only available on s390x

Reported-by: Carlo Della Giusta <carlo.dellagiusta@suse.com>
Fixes: dd82c26f87 ("rust: Add tool to manage UV-secrets")
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Steffen Eiden
c88e0276c1 pvattest: Improve UX on non-s390 systems
If pvattest perform is executed with options on a non-s390 system the
user gets misleading error messages as the options are not defined.

> pvattest perform -i attestation_request.bin  -o attresp.bin
  error: unexpected argument '-i' found

This may lead the user to think wrong arguments where chosen, which is
not entirely true as they are valid on s390. The more helpful error
message would be
error: Command only available on s390x

Which is already the case if no arguments are given.
Solve this by allowing non-s390 systems to parse the options:

> pvattest perform -i attestation_request.bin  -o attresp.bin
  error: Command only available on s390x

While at it ignore some unused code warnings in the exchange format code
that appear on non-s390 systems as not all code is used.

Reported-by: Carlo Della Giusta <carlo.dellagiusta@suse.com>
Fixes: 16610a211f ("rust: pvattest-Rust")
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Szabina Korbai
5b7f08624b libutil/util_autocomp_host: Fix script updating
Force the autocompletion script generator to always write to a new
empty file, thus preventing the potential corruption of script contents.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>

Signed-off-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Jörn Siglen
b94d5e8f87 dbginfo.sh: Add command zmemtopo
Display CEC memory topology of allocated memory increments

Suggested-by: Mario Held <mario.held@de.ibm.com>
Suggested-by: Eberhard Pasch <epasch@de.ibm.com>
Reviewed-by: Michael Storzer <MSTORZER@de.ibm.com>
Signed-off-by: Jörn Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Jörn Siglen
a4f171d4ba dbginfo.sh: Update comments and copyright year
first change for 2026 and some clarification in comments

Reviewed-by: Michael Storzer <MSTORZER@de.ibm.com>
Signed-off-by: Jörn Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Ingo Franzki
93f8d093ce libkmipclient: Adjustments for OpenSSL v4.0.0 API changes and deprecations
With OpenSSL 4.0.0 function SSL_set1_host() is deprecated and should be
replaced by SSL_set1_ipaddr() and SSL_set1_dnsname().

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Ingo Franzki
7e68d7f61a libseckey: Adjustments for OpenSSL v4.0.0 API changes and deprecations
With OpenSSL 4.0.0 function X509_NAME_get_entry() returns a const pointer.
Make the local variable also const to avoid compile warnings like:

  warning: assignment discards ‘const’ qualifier from pointer target type
  [-Wdiscarded-qualifiers]

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Ingo Franzki
7755d35995 libekmfweb: Adjustments for OpenSSL v4.0.0 API changes and deprecations
With OpenSSL 4.0.0 function X509_NAME_get_entry() returns a const pointer.
Make the local variable also const to avoid compile warnings like:

  warning: assignment discards ‘const’ qualifier from pointer target type
  [-Wdiscarded-qualifiers]

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Ingo Franzki
211431abc2 zkey: Adjustments for OpenSSL v4.0.0 API changes and deprecations
With OpenSSL 4.0.0 function X509_cmp_current_time() is deprecated and
should be replaced by X509_check_certificate_times().

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:02 +02:00
Jan Höppner
0ae29148f0 gitignore: Update gitignore
zdev usage files were converted from .c to .h files. Adapt the file
names in gitignore.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:01 +02:00
Jan Polensky
43cf7873be zdev: generate usage text headers instead of C files
Generating and then including C source files from another C file can
lead to unexpected compilation errors in certain environments.

Switch the usage text generation from %_usage.c to %_usage.h. The
generated header provides the usage_text definition directly, and
chzdev.c and lszdev.c include the corresponding *_usage.h instead.

Update depfile prerequisites and the clean target to match the new
generated artifacts.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:01 +02:00
Jan Polensky
d8cea21e1e zdev: Makefile: deduplicate *_usage.c generation
Consolidate the duplicated sed command sequences used to generate
*_usage.c files into a shared CSTR_SED definition and a single pattern
rule:

	%_usage.c: %_usage.txt

This removes the copy/pasted rules for chzdev_usage.c and lszdev_usage.c
and keeps the Makefile easier to maintain.

Also drop the explicit chzdev.o/lszdev.o prerequisites on the generated
sources as dependencies are already tracked via the .*.o.d depfiles.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:01 +02:00
Jan Polensky
7093a70b51 dasdinfo: Drop obsolete kernel check and use errx() for arg errors
Remove the uname()/sscanf()-based kernel version gate (Linux < 2.6),
which is long obsolete and does not belong in user-space argument
validation.

While touching the code, replace the repeated warnx() + exit(1) pattern
with errx(EXIT_FAILURE, ...) in the option sanity checks to reduce
boilerplate and keep error paths consistent.

Behaviour is unchanged for supported environments; the version gate is
dropped because it is obsolete.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:01 +02:00
Jan Polensky
06984cd9ee dasdinfo: Modernize NULL pointer checks
Replace explicit NULL comparisons with idiomatic C style:
- 'if (ptr == NULL)' -> 'if (!ptr)'
- 'if (ptr != NULL)' -> 'if (ptr)'

No functional changes.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:01 +02:00
Jan Polensky
3a05ab769d dasdinfo: Apply code style improvements
- Use __packed instead of __attribute__ ((packed))
- Rename EBCtoASC to ebc_to_asc following naming conventions
- Consolidate multi-line error message into single line

No functional changes.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:01 +02:00
Jan Polensky
bcbc69c77f zkey/kmip: Normalize encoding; remove non-UTF-8 artifact
Normalize the man page source to UTF-8/US-ASCII and remove a mojibake
artifact that could not be represented cleanly.

Documentation only, no functional changes.

Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:01 +02:00
Niklas Schnelle
b385b8cc38 opticsmon: Fix wrong reference to --daemon flag in man page
Even before release the flag was renamed to --monitor but the mention in
the man page was missed.

Reported-by: Halil Pasic <pasic@linux.ibm.com>
Fixes: c34adb9cab ("opticsmon: Introduce opticsmon tool")
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:01 +02:00
Jan Höppner
2b282bdacd libutil/util_autocomp: Remove comments describing resulting scripts
Future updates might change the outcome of the resulting scripts and the
comments describing the script output would need to be updated every
time as well. It's not worth the effort.

Remove the comments that list script examples from the functions
generate_bash_autocomp() and generate_zsh_autocomp().

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:01 +02:00
Jan Höppner
bd2610d275 libutil/util_autocomp: Fix default file completion
For Bash, when compspecs are found the generated script is returned as
the full set of possible completions and default completions are
disabled [1]. This leads to the behaviour that command line arguments
are not completed, only options defined by the script.

Zsh has the same issue.

Fix the issue by always adding the bash defaults to the generated
script. For zsh the corresponding file completion is always added to the
end of the argument list and the -A "*" option is added to allow
completion after positional arguments.

[1] https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html#Programmable-Completion-1

Fixes: 638cbbe332 ("libutil: Implement zsh and bash autocompletion")
Reported-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:01 +02:00
Jan Höppner
5cf2cefa94 libutil/util_autocomp: Fix ShellCheck findings and apply coding style
Apply coding style changes by reducing line breaks for a more compactly
generated script and add double quotes to fix ShellCheck findings.
Furthermore, remove the unused variable previous_word and use mapfile to
read the output of compgen into the COMPREPLY array to avoid unwanted
splitting and glob expansion.

Reviewed-by: Szabina Korbai <szkorbai@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-30 08:44:01 +02:00
Eduard Shishkin
984e008127 zipl/src: Indicate in a verbose output if a component is signed
Regardless of secure boot support, indicate in the verbose zipl(8)
output if a component is signed.

Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-10 11:22:10 +02:00
Eduard Shishkin
fcfee1aa84 zipl/src: Fix a bug in building replicated program tables
When installing IPL on mirrored targets, zipl builds multiple program
tables (one such table per each mirror). If the option "--add-files"
was specified, then zipl uses the in-bootmap files, that was written
at the prevoius iteration (for the mirror ID #0) to build program
tables for mirrors with ID #1 (and larger). The in-bootmap files
already don't contain trailers. Despite this, the building process
cuts off the tail of trailer size, which results in corrupted boot
data.

This bug may result in crashing the kernel when booting from mirrors
with ID #1 (and larger) and manifests only if the boot components are
signed and the option "--add-files" is specified for the installation
session.

Don't count the trailer, when building program tables using in-bootmap
files written at the previous iteration.

Fixes: 431e4542ca ("zipl/src: Reuse data of file components in bootmap")
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-10 11:22:10 +02:00
Chinmaya Kajagar
b401ad0da0 zfcpdbf: Print sysfs unit add store events
New trace tags "sysuas*" added in kernel to trace zfcp sysfs unit add
store events.

Print the trace events under HBA with new record ID 6. The fields under
this tag are WWPN, FCP LUN and return value of the device having issues.

Example zfcpdbf output for unit add store events:

Timestamp      : 2026-02-02-10:50:02:474983
Area           : HBA
Subarea        : 00
Level          : 4
Exception      : -
CPU ID         : 0003
Caller         : 0x000001d89a86bd0e
Record ID      : 6
Tag            : sysuas2
Description    : sysuas2 HBA, Sysfs unit add store failure, unit add failed
Request ID     : 0x00000000ffffffff
Request status : 0xffffffff
FSF cmnd       : 0xffffffff
FSF sequence no: 0xffffffff
WWPN           : 0x500507680b26c449
LUN            : 0x01d0000000000000
Return Value   : 0xfffffff4

Timestamp      : 2026-02-02-10:50:02:475037
Area           : HBA
Subarea        : 00
Level          : 4
Exception      : -
CPU ID         : 0003
Caller         : 0x000001d89a86bd0e
Record ID      : 6
Tag            : sysuas2
Description    : sysuas2 HBA, Sysfs unit add store failure, unit add failed
Request ID     : 0x00000000ffffffff
Request status : 0xffffffff
FSF cmnd       : 0xffffffff
FSF sequence no: 0xffffffff
WWPN           : 0x500507680b26c449
LUN            : 0x01d1000000000000
Return Value   : 0xfffffff4

Signed-off-by: Chinmaya Kajagar <chinmayk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-10 11:21:23 +02:00
Vasily Gorbik
50f909db8f zipl/boot: Fix stage3 secure boot trailer placement
The stage3 linker script places .sb.trailer so that it must end at
COMMAND_LINE_EXTRA. The current script derives the start address from
SIZEOF(.sb.trailer) before the section is emitted:

  . = COMMAND_LINE_EXTRA - SIZEOF(.sb.trailer);

With binutils older than 2.39 before commit 648f6099d4dc ("-z relro
relaxation and ld script SIZEOF") this can result in .sb.trailer being
placed at COMMAND_LINE_EXTRA instead, moving the trailer into the
following area and breaking the expected layout.

The trailer has a fixed size, so use an explicit constant for the
placement calculation and keep the ASSERT to verify the final section
size. This makes the placement deterministic again.

Fixes: a1126352ec ("zipl/boot: Improve linker scripts")
Reviewed-by: Marc Hartmayer <marc@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-04-10 11:21:23 +02:00
Harald Freudenberger
d0046257b6 lszcrypt/chzcrypt: Warn if default domain is unavailable
Improvements for lszcrypt and chzcrypt:
* lszcrypt -b and lszcrypt -d now check for default domain
  available and gives a warning if the current default domain
  is not in the usage_domain_mask of the AP bus.
* lszcrypt without any further device also checks for the
  default domain and emits a warning string if the default
  domain is not available.
* chzcrypt --default-domain emits a warning if the newly
  set default domain is not enabled in the usage_domain_mask
  of the AP bus.

Suggested-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:25:25 +01:00
Ajaykumar Rajappa
daad3bf0e7 ziomon: Send MQ poll status messages to stdout
Move MQ poll status messages from stderr to stdout since they are
normal progress indications rather than warnings/errors.

Signed-off-by: Ajaykumar Rajappa <ajaykr@linux.ibm.com>
Reviewed-by: M Nikhil <nikh1092@linux.ibm.com>
Reviewed-by: Nihar Panda <niharp@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:25:18 +01:00
Ajaykumar Rajappa
6537f711a6 ziomon: Ignore benign blkiomon early-read warnings
The blkiomon warnings "bad trace magic 0" and "blkiomon: bad trace" are
benign startup artifacts caused by early pipeline reads before blktrace
produces a complete record. These messages do not affect processing and
valid reports are still generated. Filter them out so only real errors
trigger failures.

Signed-off-by: Ajaykumar Rajappa <ajaykr@linux.ibm.com>
Reviewed-by: Nihar Panda <niharp@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:25:13 +01:00
Mete Durlu
7c75df9e96 hyptop/opts: Fix long command line option abbreviations
Hyptop should be able to accept abbreviations of the long command line
options as getopt() is able to match them. Ex;

$ hyptop --batch-mode

$ hyptop --batch

$ hyptop --bat

From getopt(3) man page:
"""
  Long option names may be abbreviated if the abbreviation is unique
  or is an exact match for some defined option.
"""

After the introduction of commit c5695e43c4 ("hyptop/opts: Replace long
option formats for consistency") long command line options for hyptop
received additional definitions to support dash separated option formats.
Unfortunately these definitions were defined as new and unique options
and caused an ambiguity for getopt() when abbreviations matched both
definitions. Ex;

$ hyptop --batch
hyptop: option '--batch' is ambiguous;
possibilities: '--batch-mode' '--batch_mode'

Map both long option formats to the same short option to fix the
issue and restore the functionality.

Fixes: c5695e43c4 ("hyptop/opts: Replace long option formats for consistency")
Reported-by: Gorkem Kilinc <kilinc@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Mete Durlu <meted@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:25:03 +01:00
Mete Durlu
376ddfbd22 hyptop/opts: Replace sort_field option with sort
Hyptop's "--sort_field" command line option has always been documented
as "--sort", while the code _only_ explicitly has "--sort_field".
Specifying the shorter "--sort" happened to work due to an unnoticed
getopt() behavior.

From getopt(3) man page:
"""
  Long option names may be abbreviated if the abbreviation is unique
  or is an exact match for some defined option.
"""

With the addition of "--sort-field" as another unique identifier via
commit c5695e43c4 ("hyptop/opts: Replace long option formats for
consistency") "--sort" is no longer unique. getopt() won't be able to
use that as an abbreviation, since there is ambiguity between
"--sort_field" and new "--sort-field" as they are defined as separate
options.

Replace "--sort-field" and "--sort_field" with plain "--sort" to adhere
to the documented hyptop command line argument specification and resolve
the broken behavior.

Fixes: c5695e43c4 ("hyptop/opts: Replace long option formats for consistency")
Reported-by: Gorkem Kilinc <kilinc@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Mete Durlu <meted@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:46 +01:00
Holger Dengler
1afa6efb26 lszcrypt: Change exit code to 0 for empty device list
An empty device list is not an error case, if `lszcrypt` is called
without a specific device list or device filter. Return with rc == 0 in
such cases.

Remove the message about the empty device list on stderr.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:42 +01:00
Jan Höppner
69c89416b0 lsznet: Remove support for lcs device type
Kernel support for LCS devices was removed with commit 6cccb3bb0561
("s390/net: Remove LCS driver") in kernel v6.15. Remove the associated
lsznet support for the lcs device type.

Reviewed-by: Aswin Karuvally <aswin@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:38 +01:00
Jan Höppner
81e0d02d90 znetcontrolunits: Remove znetcontrolunits library
znetcontrolunits provided two arrays and a search function that were
only used by lsznet. Since lsznet has it's own implementation of this
function now and the CU array was a duplicate of CU_TCPIP anyway, remove
znetcontrolunits as it serves no purpose.

Reviewed-by: Aswin Karuvally <aswin@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:36 +01:00
Jan Höppner
d41d968792 znet: Move functionality from znetcontrolunits to lsznet
lsznet sources znetcontrolunits to use search_cu() and set the variable
cu_idx. lsznet's own function search_cu_tcpip() is doing the same thing
as search_cu() without setting cu_idx.

Declare and move cu_idx to the global variable CU_IDX and consolidate
the functions by letting search_cu_tcpip() set CU_IDX. Call
search_cu_tcpip() instead of search_cu() and replace cu_idx with CU_IDX
accordingly. search_cu() is removed and the CU_DEVDRV array is moved to
lsznet.

Reviewed-by: Aswin Karuvally <aswin@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:35 +01:00
Jan Höppner
c81ca8f01b lsznet: Convert space indentation to tabs
Reviewed-by: Aswin Karuvally <aswin@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:33 +01:00
Mikhail Zaslonko
73ab25f419 zipl/boot: Add secure boot option to the dump programm
With SECURE_BOOT_DISABLED always set in add_dump_program() no signature
entries for a dump kernel are written. This might lead to security
violation error from the IPL Loader on the systems with secure boot support
on the attempt to boot the dump kernel:
  MLOLOA6269321F A security violation error was encountered when loading from device <device>
  MLOLOA62693212 Audit: No signed components found for program 0 loaded from device <device>

Propagate '--secure' zipl option to add_dump_program() in order to sign
relevant components upon dump program installation and thus support
secure boot execution for List-directed dump kernels.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Acked-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Tested-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:23 +01:00
Chinmaya Kajagar
6fc1ed1a67 zfcpdbf: Print plogi and prli within open port response as payload
Print plogi and prli of each incoming open port response. Additional
payload ‘fsf_els’ HBA area to trace and print the new open port response
details.

Relevant kernel dbf structure changes are done in a separate patch. New
fields plogi_len and prli_len (u32 i.e. 4 hex digits at new appended
offsets 112 and 120) and payload record(s) are available.
The kernel structure with added members,
struct zfcp_dbf_hba_res {
	u64                        req_issued;           /*     0     8 */
	u32                        prot_status;          /*     8     4 */
	u8                         prot_status_qual[16]; /*    12    16 */
	u32                        fsf_status;           /*    28     4 */
	u8                         fsf_status_qual[16];  /*    32    16 */
	u32                        port_handle;          /*    48     4 */
	u32                        lun_handle;           /*    52     4 */
	u32                        plogi_len;            /*    56     4 */
	u32                        prli_len;             /*    60     4 */
};

zfcpdbf partial output for HBA area with relevant kernel code changes
displaying PLOGI/ PRLI info log with length for each:

PLOGI length   : 116
PRLI length    : 20
Payload time   : 2026-01-29-06:19:15:626629
PLOGI/PRLIinfo : 02000000 00000000 80000800 000a0002
                 00000000 2002000e 1115c62f 2001000e
                 1115c62f 00000000 00000000 00000000
                 00000000 80000000 00000000 00000000
                 00000000 80000000 00000000 000a0000
                 00010000 00000000 00000000 00000000
                 00000000 00000000 00000000 00000000
                 00000000 02100014 08002100 00000000
                 00000000 00000112

Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com>
Signed-off-by: Chinmaya Kajagar <chinmayk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:16 +01:00
Chinmaya Kajagar
1c3547d205 zfcpdbf: Trace all fsf status read buffer fields under HBA
This patch is to enhance fsf status read buffer tracing. Add remaining
status read buffer (SRB) fields including S_ID and reserved fields under
HBA trace area.

Relevant kernel dbf structure changes are done in a seperate patch.

zfcpdbf output for HBA area with relevant kernel code changes:

Timestamp      : 2025-08-22-05:52:04:171750
Area           : HBA
Subarea        : 00
Level          : 2
Exception      : -
CPU ID         : 0003
Caller         : 0x0000021e278c07c8
Record ID      : 2
Tag            : fssrh_4
Description    : fssrh_4 HBA, FSF unsolicited status
Request ID     : 0x0000000000004bfc
Request status : 0x00000000
FSF cmnd       : 0x00006305
FSF sequence no: 0x00000000
SRB stat type  : 0x00000002
SRB stat sub   : 0x00000000
SRB D_ID       : 0x00fffffd
SRB LUN        : 0x0000000000000000
SRB q-design.  : 0x0000000000000000
SRB length     : 0x0000004c
SRB res1       : 0x00000000
SRB res2       : 0x00
SRB class      : 0x00000000
SRB res3       : 0x00
SRB S_ID       : 0x0033c048
SRB res4       : 00000000 00000000 00000000 00000000
                 00000000
SRB pay length : 12
Payload time   : 2025-08-22-05:52:04:171743
SRB info       : 6104000c 0033c024 0033c02e

Signed-off-by: Chinmaya Kajagar <chinmayk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:11 +01:00
Vineeth Vijayan
b6bb87f377 zdev: Remove support for lcs device type
Kernel support for LCS devices was removed with commit 6cccb3bb0561
("s390/net: Remove LCS driver") in kernel v6.15. Remove the associated
zdev support for the lcs device type.

Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:07 +01:00
Jan Höppner
bd0bb9dd5c zipl/man: Remove trailing whitespace
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:05 +01:00
Jan Höppner
075f7f7186 zipl/man: Only mention 3490 tape devices
The Virtual Tape Server (VTS) only supports 3490 tape devices. Remove
all other older device types from the man pages.

Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:04 +01:00
Jan Höppner
5af1e8cc69 zipl/tape2dump: Remove check for data compaction support
Data compaction is only supported by 3490 tape devices. For Virtual Tape
Server (VTS) this is the only supported device. Reading device
characteristics and checking the type is unnecessary.

Remove the corresponding code and simply enable data compaction.

Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:02 +01:00
Jan Höppner
145c21a9ca zipl/tape2dump: Remove load display command
Load Display (LDD) X'9F' is still accepted by the Virtual Tape Server
(VTS) but does not perform any action. Remove code that still uses this
command in tape2dump.c.

Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:01 +01:00
Jan Höppner
1bd8ee4b79 lstape: Remove type filter support
There is only one supported tape device type left. A filter command line
option doesn't make any sense anymore.

Remove the functionality and documentation of the --type option.

Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:24:00 +01:00
Jan Höppner
4f0dfae97e lstape: Remove 3480 and 3590 tape support
The device models 3480 and 3590 are no longer supported by the tape
device driver. Remove them from the device list

Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:23:58 +01:00
Jan Höppner
3d6bb988c2 lstape: Remove trailing whitespace
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:23:57 +01:00
Jan Höppner
8f83002e37 tape390: Remove tape390_display and tape390_crypt
The tape390_display tool was used to send text to the display of tape
storage server. The corresponding command is still accepted by the
Virtual Tape Server (VTS) but no action is performed. The tool is
useless, remove it.

The tape390_crypt tool was used to manage encryption for tape devices.
However, only 3590/3592 models did support encryption. Support for these
models is removed from the Kernel as there is no support for these tape
models in general anymore. The tool is not required anymore, remove it.

Note: VTS uses encryption transparantly for its virtualized 3490 models.

Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:23:55 +01:00
Mikhail Zaslonko
d92f419836 zdump/dfi: Fix dump header check for dfi_s390tape
The magic number used in the dump header for all stage2 dumps (including
tape dump) is DF_S390_MAGIC_EXT since commit ff475d9c7d0a ("zipl: Extend
DASD stand-alone dumpers to drop zero pages").
Adjust dfi_s390tape code accordingly.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-03-11 11:23:52 +01:00
Jan Höppner
8ff8b40182 Prepare for next release
Signed-off by: Jan Höppner <hoeppner@linux.ibm.com>
2026-02-16 15:34:05 +01:00
220 changed files with 6928 additions and 4183 deletions

52
.gitignore vendored
View File

@@ -25,7 +25,7 @@ compile_commands.json
#
**/.detect-openssl.dep.c
*.debug
*/autocompletion_generator_host
**/autocompletion_generator_host
ap_tools/ap-check
cmsfs-fuse/cmsfs-fuse
cpacfstats/cpacfstats
@@ -50,12 +50,22 @@ dasdfmt/dasdfmt
dasdfmt/_dasdfmt
dasdfmt/dasdfmt.bash
dasdinfo/dasdinfo
dasdinfo/_dasdinfo
dasdinfo/dasdinfo.bash
dasdview/dasdview
dasdview/_dasdview
dasdview/dasdview.bash
dump2tar/src/dump2tar
dump2tar/src/_dump2tar
dump2tar/src/dump2tar.bash
fdasd/fdasd
fdasd/_fdasd
fdasd/fdasd.bash
hmcdrvfs/hmcdrvfs
hsavmcore/check-dep-fuse
hsavmcore/hsavmcore
hsavmcore/_hsavmcore
hsavmcore/hsavmcore.bash
hyptop/hyptop
ip_watcher/xcec-bridge
ipl_tools/chreipl
@@ -88,34 +98,58 @@ libutil/*_example
libvmcp/vmcp_example
libzds/libzds.a
lsstp/lsstp
lsstp/_lsstp
lsstp/lsstp.bash
mon_tools/mon_fsstatd
mon_tools/mon_procd
opticsmon/opticsmon
opticsmon/_opticsmon
opticsmon/opticsmon.bash
osasnmpd/osasnmpd
qetharp/qetharp
qethqoat/qethqoat
systemd/cpacfstatsd.service
systemd/iucvtty-login@.service
systemd/ttyrun-getty@.service
tape390/tape390_crypt
tape390/tape390_display
tunedasd/src/tunedasd
tunedasd/src/_tunedasd
tunedasd/src/tunedasd.bash
vmcp/vmcp
vmcp/_vmcp
vmcp/vmcp.bash
vmur/vmur
zconf/chp/chchp
zconf/chp/_chchp
zconf/chp/chchp.bash
zconf/chp/lschp
zconf/chp/_lschp
zconf/chp/lschp.bash
zconf/chp/chpstat/chpstat
zconf/chp/chpstat/_chpstat
zconf/chp/chpstat/chpstat.bash
zconf/css/lscss
zconf/css/_lscss
zconf/css/lscss.bash
zconf/qeth/lsqeth
zconf/qeth/_lsqeth
zconf/qeth/lsqeth.bash
zconf/scm/lsscm
zconf/scm/_lsscm
zconf/scm/lsscm.bash
zconf/zcrypt/chzcrypt
zconf/zcrypt/_chzcrypt
zconf/zcrypt/chzcrypt.bash
zconf/zcrypt/lszcrypt
zconf/zcrypt/_lszcrypt
zconf/zcrypt/lszcrypt.bash
zconf/zcrypt/zcryptctl
zconf/zcrypt/zcryptstats
zconf/zcrypt/_zcryptstats
zconf/zcrypt/zcryptstats.bash
zdev/src/chzdev
zdev/src/chzdev_usage.c
zdev/src/chzdev_usage.h
zdev/src/lszdev
zdev/src/lszdev_usage.c
zdev/src/lszdev_usage.h
zdev/src/zdev_id
zdsfs/zdsfs
zdump/.check_dep_fuse
@@ -139,6 +173,8 @@ zipl/src/chreipl_helper.device-mapper
zipl/src/chreipl_helper.md
zipl/src/zipl
zipl/src/zipl-editenv
zipl/src/_zipl-editenv
zipl/src/zipl-editenv.bash
zipl/src/zipl_helper.device-mapper
zipl/src/zipl_helper.md
zkey/check-dep-zkey
@@ -151,5 +187,11 @@ zkey/kmip/zkey-kmip.so
zkey/zkey
zkey/zkey-cryptsetup
zmemtopo/zmemtopo
zmemtopo/_zmemtopo
zmemtopo/zmemtopo.bash
zpcictl/zpcictl
zpcictl/_zpcictl
zpcictl/zpcictl.bash
zpwr/zpwr
zpwr/_zpwr
zpwr/zpwr.bash

View File

@@ -17,6 +17,7 @@ List of all individuals having contributed content to s390-tools
- Bjoern Walk
- Brian C. Lane
- Carsten Otte
- Chinmaya Kajagar
- Christian Borntraeger
- Christian Ehrhardt
- Christof Schmitt

View File

@@ -1,6 +1,55 @@
Release history for s390-tools (MIT version)
--------------------------------------------
* __v2.42.1 (2026-05-22)__
For Linux kernel version: 7.0
Changes of existing tools:
- cpumf/pai: Improve -m XXX argument verification
- pvattest: Add -i -o option variant for check
- pvattest: Show perform -i & -o option in help
- pvebc: Disable unit logging to /boot
- pvsecret: Add -i -o option variants
Bug Fixes:
- cpumf/pai: Remove unnecessary const parameter definition
- pv: Fix error description
- pvebc: Fix dependency for non EBC guests
- pvebc: Fix kernel module dependencies
- zipl: Don't modify job->data.dump and job->data.mvdump sequentially
* __v2.42.0 (2026-04-30)__
For Linux kernel version: 7.0
Add new tools / libraries:
- Enable zsh and bash autocompletion for various tools
- pvebc: Resolve ASR integrity structure for EBC
- pvics: Generate SEL guests from base images
Remove:
- tape390_display and tape390_crypt removed due to long gone hardware support
- znetcontrolunits: Remove znetcontrolunits library
Changes of existing tools:
- cpumf/pai: Install SIGINT/SIGTERM handler for graceful termination
- dbginfo.sh: Add command zmemtopo
- libutil/util_fmt: Add support for JSON Lines text format
- lstape: Remove 3480 and 3590 tape support
- lsznet: Remove support for lcs device type
- pvsecret: Add support for ASR integrity structure for EBC
- zfcpdbf: Print plogi and prli within open port response as payload
- zfcpdbf: Trace all fsf status read buffer fields under HBA
- zipl/boot: Add secure boot option to the dump programm
- zkey, libekmfweb, libseckey, libkmipclient: Adjust for OpenSSL v4.0.0 API
changes and deprecations
Bug Fixes:
- hyptop/opts: Fix long command line option abbreviations
- libutil/util_autocomp: Fix default file completion
- zipl/boot: Fix stage3 secure boot trailer placement
* __v2.41.0 (2026-02-16)__
For Linux kernel version: 6.19

View File

@@ -11,7 +11,7 @@ BASELIB_DIRS = libutil libseckey
LIB_DIRS = libvtoc libzds libdasd libccw libvmcp libekmfweb \
libkmipclient libcpumf libap libpv libzpci
TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \
osasnmpd qetharp ip_watcher qethconf scripts zconf \
vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl \

View File

@@ -30,6 +30,8 @@ Package contents
Manage secrets for IBM Secure Execution guests
- pvimg:
Create and inspect IBM Secure Execution images
- pvebc:
Verify a secret structure for IBM Secure Execution for Linux.
* dasdfmt:
Low-level format ECKD DASDs with the classical Linux disk layout or the new
@@ -50,6 +52,10 @@ Package contents
Create an IBM Secure Execution (protected virtualization) image. The
genprotimg command is a symbolic link to the `pvimg create` command.
* pvics:
Convert a qcow2 image to a qcow2 image ready to boot as IBM Secure Execution
for Linux guest.
* udev rules:
- 59-dasd.rules: rules for unique DASD device nodes created in /dev/disk/.
- 57-osasnmpd.rules: udev rules for osasnmpd.
@@ -79,13 +85,6 @@ Package contents
* qetharp:
Read and flush the ARP cache on OSA Express network cards.
* tape390_display:
Display information on the message display facility of a s390 tape
device.
* tape390_crypt:
Control and query crypto settings for 3592 tape devices.
* osasnmpd:
NET-SNMP subagent implementing MIBs provided by OSA-Express
features Fast Ethernet, Gigabit Ethernet, 10 Gigabit Ethernet.

View File

@@ -32,8 +32,8 @@ endif
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
VERSION := 2
RELEASE := 41
PATCHLEVEL := 0
RELEASE := 42
PATCHLEVEL := 1
DISTRELEASE := build-$(shell date +%Y%m%d)
S390_TOOLS_RELEASE := $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
export S390_TOOLS_RELEASE

View File

@@ -1,11 +1,7 @@
// SPDX-License-Identifier: MIT
/*
* Autocompletion generation - for cpumf family of tools
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp. 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
* Copyright IBM Corp.
*/
#include "lib/util_autocomp.h"

View File

@@ -1,11 +1,7 @@
/* SPDX-License-Identifier: MIT */
/*
* Command line utilities - for chcpumf
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp. 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
* Copyright IBM Corp.
*/
#ifndef CHCPUMF_CLI_H

View File

@@ -1,11 +1,7 @@
/* SPDX-License-Identifier: MIT */
/*
* Command line utilities - for lscpumf
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp. 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
* Copyright IBM Corp.
*/
#ifndef LSCPUMF_CLI_H

View File

@@ -700,7 +700,7 @@ static int do_it(char *s)
if (output_format == FMT_CSV)
flags |= FMT_NOMETA;
if (output_format == FMT_JSON || output_format == FMT_JSONSEQ)
if (util_fmt_is_json(output_format))
flags |= FMT_HANDLEINT;
if (quote_all)
flags |= FMT_QUOTEALL;
@@ -708,7 +708,7 @@ static int do_it(char *s)
mk_labels();
util_fmt_init(stdout, output_format, flags, 1);
util_fmt_obj_start(FMT_DEFAULT, "lshwc");
if (output_format == FMT_JSON || output_format == FMT_JSONSEQ) {
if (util_fmt_is_json(output_format)) {
util_fmt_obj_start(FMT_ROW, "cpumcf info");
util_fmt_pair(FMT_PERSIST, "counter first", "%d", cfvn);
util_fmt_pair(FMT_PERSIST, "counter second", "%d", csvn);

View File

@@ -1,11 +1,7 @@
/* SPDX-License-Identifier: MIT */
/*
* Command line utilities - for lshwc
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp. 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
* Copyright IBM Corp.
*/
#ifndef LSHWC_CLI_H

View File

@@ -1,11 +1,7 @@
/* SPDX-License-Identifier: MIT */
/*
* Command line utilities - for lspai
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp. 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
* Copyright IBM Corp.
*/
#ifndef LSPAI_CLI_H

View File

@@ -138,7 +138,7 @@ Apply quoting to every output element, regardless of content or format.
.TP
.BR \-f ", " \-\-format \fI\ FORMAT\fP
Retrieve output in one of the following formats:
JSON, CSV, JSON-SEQ or PAIRS.
JSON, CSV, JSON-SEQ, JSONL or PAIRS.
If no format is specified, the output defaults to CSV.
.
.SS JSON Output Structure

View File

@@ -136,7 +136,7 @@ Default sort order is PAI counter name.
.TP
.BI \-\-format "\ FORMAT"
Retrieve output in one of the following formats:
JSON, csv, json-seq or pairs.
JSON, csv, json-seq, jsonl or pairs.
If no format is specified,
the output defaults to a human-readable format.
.

View File

@@ -14,6 +14,7 @@
#include <fcntl.h>
#include <limits.h>
#include <sched.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
@@ -47,6 +48,8 @@
#define S390_EVT_PAI_CRYPTO 0x1000
#define S390_EVT_PAI_NNPA 0x1800
/* SIGINT or SIGTERM signal received */
static volatile unsigned int sigterm;
/* Default values for select() timeout: 1 second */
static unsigned long read_interval = 1000;
/* Size of mapped perf event ring buffer in 4KB pages.
@@ -350,6 +353,10 @@ static int collect(unsigned long cnt)
if (FD_ISSET(i, &r_fds))
readmap(i);
}
} else if (errno == EINTR && sigterm) {
/* Interrupt by signal SIGINT/SIGTERM, one more iteration */
cnt = 2;
rc = 0;
}
} while (rc != -1 && --cnt > 0);
return rc;
@@ -887,7 +894,7 @@ static int parse_event_attr(char *cp)
}
/* Parse CPU list and event specifications */
static void parse_cpulist(int enr, const char *parm)
static void parse_cpulist(int enr, char *parm)
{
unsigned int evt_attr = 0;
cpu_set_t cmdlist, result;
@@ -941,33 +948,27 @@ static const struct util_prg prg = {
}
};
static void record_cpus_crypto(const char *cp)
static void record_cpus_crypto(char *cp)
{
if (!libcpumf_have_pai_crypto())
errx(EXIT_FAILURE, "No support for PAI crypto counters");
parse_cpulist(S390_EVT_PAI_CRYPTO, cp);
}
static void record_cpus_nnpa(const char *cp)
static void record_cpus_nnpa(char *cp)
{
if (!libcpumf_have_pai_nnpa())
errx(EXIT_FAILURE, "No support for PAI nnpa counters");
parse_cpulist(S390_EVT_PAI_NNPA, cp);
}
/* Mapsize must be power of 2 and larger than 4. Count bits in n and
* return 0 if input is invalid and has a bit count larger than one.
/* Mapsize must be power of 2 and larger than 4. Return true in this case.
*/
static unsigned long check_mapsize(unsigned long n)
static bool check_mapsize(unsigned long n)
{
int bit, cnt = 0;
if (n < 4)
return 0;
for (bit = 0; bit < __BITS_PER_LONG; ++bit)
if (n & (1 << bit))
++cnt;
return cnt == 1 ? n : 0;
return (n & (n - 1)) == 0;
}
static void setprio(const char *prio)
@@ -983,6 +984,12 @@ static void setprio(const char *prio)
err(EXIT_FAILURE, "Could not set realtime priority");
}
static void sig_handler(int no)
{
if (no == SIGINT || no == SIGTERM)
sigterm = 1;
}
int main(int argc, char **argv)
{
bool crypto_record = false, report = false;
@@ -1027,11 +1034,11 @@ int main(int argc, char **argv)
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
break;
case 'm':
errno = 0;
mapsize = strtoul(optarg, &slash, 0);
mapsize = check_mapsize(mapsize);
if (errno || !mapsize || *slash)
if (!mapsize || *slash)
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
if (!check_mapsize(mapsize))
errx(EXIT_FAILURE, "No power of 2 number for -%c", ch);
break;
case 'n':
record_cpus_nnpa(optarg);
@@ -1070,6 +1077,10 @@ int main(int argc, char **argv)
errx(EXIT_FAILURE, "Invalid argument for runtime");
}
if (signal(SIGTERM, sig_handler) == SIG_ERR ||
signal(SIGINT, sig_handler) == SIG_ERR)
errx(EXIT_FAILURE, "Failed to set signal handler");
ev_install(group);
ev_enable();

View File

@@ -1,11 +1,7 @@
/* SPDX-License-Identifier: MIT */
/*
* Command line utilities - for pai
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp. 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
* Copyright IBM Corp.
*/
#ifndef PAI_CLI_H

View File

@@ -1,11 +1,7 @@
// SPDX-License-Identifier: MIT
/*
* Autocompletion generation - for dasdfmt tool
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp. 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
* Copyright IBM Corp.
*/
#include "lib/util_autocomp.h"

View File

@@ -1,11 +1,7 @@
/* SPDX-License-Identifier: MIT */
/*
* Command line utilities - for dasdfmt
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp. 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
* Copyright IBM Corp.
*/
#ifndef DASDFMT_CLI_H

View File

@@ -1,5 +1,10 @@
include ../common.mak
zsh-completions = _dasdinfo
bash-completions = dasdinfo.bash
include ../common_autocomp.mak
libs = $(rootdir)/libutil/libutil.a \
$(rootdir)/libdasd/libdasd.a

View File

@@ -0,0 +1,16 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#include "lib/util_autocomp.h"
#include "dasdinfo_cli.h"
int main(void)
{
generate_autocomp(opt_vec, "dasdinfo");
return 0;
}

View File

@@ -30,6 +30,8 @@
#include "lib/util_path.h"
#include "lib/zt_common.h"
#include "dasdinfo_cli.h"
#define RD_BUFFER_SIZE 80
#define TEMP_DEV_MAX_RETRIES 1000
@@ -50,49 +52,6 @@ static const struct util_prg prg = {
}
};
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("DEVICE"),
{
.option = { "block", required_argument, NULL, 'b' },
.argument = "BLOCKDEV",
.desc = "Block device name, e.g. dasdb",
},
{
.option = { "devnode", required_argument, NULL, 'd' },
.argument = "DEVNODE",
.desc = "Device node, e.g. /dev/dasda",
},
{
.option = { "busid", required_argument, NULL, 'i' },
.argument = "BUSID",
.desc = "Bus ID, e.g. 0.0.e910",
},
UTIL_OPT_SECTION("OPTIONS"),
{
.option = { "label", no_argument, NULL, 'l' },
.desc = "Print DASD volume label (volser)",
},
{
.option = { "uid", no_argument, NULL, 'u' },
.desc = "Print DASD uid (without z/VM minidisk token)",
},
{
.option = { "extended-uid", no_argument, NULL, 'x' },
.desc = "Print DASD uid (including z/VM minidisk token)",
},
{
.option = { "all", no_argument, NULL, 'a' },
.desc = "Same as -u -x -l",
},
{
.option = { "export", no_argument, NULL, 'e' },
.desc = "Export ID_BUS, ID_TYPE, ID_SERIAL for use in udev",
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
/* needed because ftw can not pass arbitrary arguments */
static char *searchbusid;
static char *busiddir;
@@ -101,9 +60,9 @@ struct volume_label {
char volkey[4];
char vollbl[4];
char volid[6];
} __attribute__ ((packed));
} __packed;
static char EBCtoASC[256] = {
static char ebc_to_asc[256] = {
/* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */
0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
/* 0x08 -GE -SPS -RPT VT FF CR SO SI */
@@ -175,7 +134,7 @@ static char *dinfo_ebcdic_dec(char *source, char *target, int l)
int i;
for (i = 0; i < l; i++)
target[i] = EBCtoASC[(unsigned char)(source[i])];
target[i] = ebc_to_asc[(unsigned char)(source[i])];
return target;
}
@@ -261,7 +220,7 @@ static void *dinfo_malloc(size_t size)
void *result;
result = malloc(size);
if (result == NULL)
if (!result)
warnx("Could not allocate %lu bytes of memory", size);
return result;
@@ -274,7 +233,7 @@ static char *dinfo_make_path(char *dirname, char *filename)
len = strlen(dirname) + strlen(filename) + 2;
result = (char *)dinfo_malloc(len);
if (result == NULL)
if (!result)
return NULL;
sprintf(result, "%s/%s", dirname, filename);
return result;
@@ -296,12 +255,12 @@ static int dinfo_create_devnode(dev_t dev, char **devno)
/* Try several locations for the temporary device node. */
for (path = 0; path < ARRAY_SIZE(pathname); path++) {
if (pathname[path] == NULL)
if (!pathname[path])
continue;
for (retry = 0; retry < TEMP_DEV_MAX_RETRIES; retry++) {
snprintf(filename, sizeof(filename), "dasdinfo%04d", retry);
result = dinfo_make_path(pathname[path], filename);
if (result == NULL)
if (!result)
return -1;
rc = mknod(result, mode, dev);
if (rc == 0) {
@@ -342,7 +301,7 @@ static int dinfo_extract_dev(dev_t *dev, char *str)
memset(tmp, 0, RD_BUFFER_SIZE);
util_strlcpy(tmp, str, RD_BUFFER_SIZE);
p = strchr(tmp, ':');
if (p == NULL) {
if (!p) {
warnx("Error: unable to extract major/minor");
return -1;
}
@@ -401,14 +360,14 @@ dinfo_is_busiddir(const char *fpath, const struct stat *UNUSED(sb),
return -1;
linkdir = util_readlink(tempdir);
free(tempdir);
if (strstr(linkdir, "dasd") == NULL) {
if (!strstr(linkdir, "dasd")) {
free(linkdir);
return FTW_CONTINUE;
}
free(linkdir);
free(busiddir);
busiddir = strdup(fpath);
if (busiddir == NULL)
if (!busiddir)
return -1;
return FTW_STOP;
}
@@ -421,7 +380,7 @@ dinfo_find_entry(const char *dir, const char *searchstring,
struct dirent *dir_entry = NULL;
directory = opendir(dir);
if (directory == NULL)
if (!directory)
return -1;
while ((dir_entry = readdir(directory)) != NULL) {
/* compare if the found entry has exactly the same name and type
@@ -431,7 +390,7 @@ dinfo_find_entry(const char *dir, const char *searchstring,
strlen(searchstring)) == 0) &&
(dir_entry->d_type & type)) {
*result = strdup(dir_entry->d_name);
if (*result == NULL)
if (!*result)
goto out;
closedir(directory);
return 0; /* found */
@@ -477,7 +436,7 @@ dinfo_get_blockdev_from_busid(char *busid, char **blkdev)
if (rc != 0)
goto out2;
*blkdev = strdup(strchr(result, ':') + 1);
if (*blkdev == NULL)
if (!*blkdev)
rc = -1;
}
@@ -510,7 +469,7 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
path = util_path_sysfs("block/");
directory = opendir(path);
if (directory == NULL) {
if (!directory) {
warnx("Error: could not open directory %s", path);
free(path);
return -1;
@@ -550,8 +509,6 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
int main(int argc, char *argv[])
{
struct utsname uname_buf;
int version, release;
char *uidfile = NULL;
char *device = NULL;
char *readbuf = NULL;
@@ -611,35 +568,19 @@ int main(int argc, char *argv[])
util_prg_print_version();
exit(EXIT_SUCCESS);
default:
fprintf(stderr, "Try 'dasdinfo --help' for more "
"information.\n");
fprintf(stderr, "Try 'dasdinfo --help' for more information.\n");
exit(1);
}
}
uname(&uname_buf);
sscanf(uname_buf.release, "%d.%d", &version, &release);
if (strcmp(uname_buf.sysname, "Linux") ||
version < 2 || (version == 2 && release < 6)) {
warnx("%s %d.%d is not supported", uname_buf.sysname,
version, release);
exit(1);
}
if (!busid && !blockdev && !devnode)
errx(EXIT_FAILURE, "Error: please specify a device using either -b, -i or -d");
if (!busid && !blockdev && !devnode) {
warnx("Error: please specify a device using either -b, -i or -d");
exit(1);
}
if ((busid && blockdev) || (busid && devnode) || (blockdev && devnode))
errx(EXIT_FAILURE, "Error: please specify device only once, either -b, -i or -d");
if ((busid && blockdev) || (busid && devnode) || (blockdev && devnode)) {
warnx("Error: please specify device only once, either -b, -i or -d");
exit(1);
}
if (!print_uid && !print_extended_uid && !print_vlabel) {
warnx("Error: no action specified (e.g. -u)");
exit(1);
}
if (!print_uid && !print_extended_uid && !print_vlabel)
errx(EXIT_FAILURE, "Error: no action specified (e.g. -u)");
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
if (!readbuf)

55
dasdinfo/dasdinfo_cli.h Normal file
View File

@@ -0,0 +1,55 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#ifndef DASDINFO_CLI_H
#define DASDINFO_CLI_H
#include "lib/util_opt.h"
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("DEVICE"),
{
.option = { "block", required_argument, NULL, 'b' },
.argument = "BLOCKDEV",
.desc = "Block device name, e.g. dasdb",
},
{
.option = { "devnode", required_argument, NULL, 'd' },
.argument = "DEVNODE",
.desc = "Device node, e.g. /dev/dasda",
},
{
.option = { "busid", required_argument, NULL, 'i' },
.argument = "BUSID",
.desc = "Bus ID, e.g. 0.0.e910",
},
UTIL_OPT_SECTION("OPTIONS"),
{
.option = { "label", no_argument, NULL, 'l' },
.desc = "Print DASD volume label (volser)",
},
{
.option = { "uid", no_argument, NULL, 'u' },
.desc = "Print DASD uid (without z/VM minidisk token)",
},
{
.option = { "extended-uid", no_argument, NULL, 'x' },
.desc = "Print DASD uid (including z/VM minidisk token)",
},
{
.option = { "all", no_argument, NULL, 'a' },
.desc = "Same as -u -x -l",
},
{
.option = { "export", no_argument, NULL, 'e' },
.desc = "Export ID_BUS, ID_TYPE, ID_SERIAL for use in udev",
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
#endif

View File

@@ -1,5 +1,10 @@
include ../common.mak
zsh-completions = _dasdview
bash-completions = dasdview.bash
include ../common_autocomp.mak
libs = $(rootdir)/libdasd/libdasd.a \
$(rootdir)/libzds/libzds.a \
$(rootdir)/libvtoc/libvtoc.a \

View File

@@ -0,0 +1,16 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#include "lib/util_autocomp.h"
#include "dasdview_cli.h"
int main(void)
{
generate_autocomp(opt_vec, "dasdview");
return 0;
}

View File

@@ -37,6 +37,7 @@
#include "lib/zt_common.h"
#include "dasdview.h"
#include "dasdview_cli.h"
/* Characters per line */
#define DASDVIEW_CPL 16
@@ -56,61 +57,6 @@ static const struct util_prg prg = {
}
};
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("DUMP OPTIONS"),
{
.option = { NULL, no_argument, NULL, '1' },
.desc = "Show DASD content in short Hex/EBCDIC/ASCII format",
.flags = UTIL_OPT_FLAG_NOLONG,
},
{
.option = { NULL, no_argument, NULL, '2' },
.desc = "Show DASD content in detailed Hex/EBCDIC/ASCII format",
.flags = UTIL_OPT_FLAG_NOLONG,
},
{
.option = { "begin", required_argument, NULL, 'b' },
.argument = "BEGIN",
.desc = "Specify start of dump in kilobytes (suffix k), "
"megabytes (m), blocks (b), tracks (t), or cylinders (c)",
},
{
.option = { "size", required_argument, NULL, 's' },
.argument = "SIZE",
.desc = "Specify size of dump in kilobytes (suffix k), "
"megabytes (m), blocks (b), tracks (t), or cylinders (c)",
},
UTIL_OPT_SECTION("MISC"),
{
.option = { "characteristic", no_argument, NULL, 'c' },
.desc = "Print the characteristics of a device",
},
{
.option = { "info", no_argument, NULL, 'i' },
.desc = "Print general DASD information and geometry",
},
{
.option = { "volser", no_argument, NULL, 'j' },
.desc = "Print the volume serial number",
},
{
.option = { "label", no_argument, NULL, 'l' },
.desc = "Print information about the volume label",
},
{
.option = { "vtoc", required_argument, NULL, 't' },
.argument = "SPEC",
.desc = "Print the table of content (VTOC)",
},
{
.option = { "extended", no_argument, NULL, 'x' },
.desc = "Print extended DASD information",
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
/*
* Generate and print an error message based on the formatted
* text string FMT and a variable amount of extra arguments.

67
dasdview/dasdview_cli.h Normal file
View File

@@ -0,0 +1,67 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#ifndef DASDVIEW_CLI_H
#define DASDVIEW_CLI_H
#include "lib/util_opt.h"
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("DUMP OPTIONS"),
{
.option = { NULL, no_argument, NULL, '1' },
.desc = "Show DASD content in short Hex/EBCDIC/ASCII format",
.flags = UTIL_OPT_FLAG_NOLONG,
},
{
.option = { NULL, no_argument, NULL, '2' },
.desc = "Show DASD content in detailed Hex/EBCDIC/ASCII format",
.flags = UTIL_OPT_FLAG_NOLONG,
},
{
.option = { "begin", required_argument, NULL, 'b' },
.argument = "BEGIN",
.desc = "Specify start of dump in kilobytes (suffix k), "
"megabytes (m), blocks (b), tracks (t), or cylinders (c)",
},
{
.option = { "size", required_argument, NULL, 's' },
.argument = "SIZE",
.desc = "Specify size of dump in kilobytes (suffix k), "
"megabytes (m), blocks (b), tracks (t), or cylinders (c)",
},
UTIL_OPT_SECTION("MISC"),
{
.option = { "characteristic", no_argument, NULL, 'c' },
.desc = "Print the characteristics of a device",
},
{
.option = { "info", no_argument, NULL, 'i' },
.desc = "Print general DASD information and geometry",
},
{
.option = { "volser", no_argument, NULL, 'j' },
.desc = "Print the volume serial number",
},
{
.option = { "label", no_argument, NULL, 'l' },
.desc = "Print information about the volume label",
},
{
.option = { "vtoc", required_argument, NULL, 't' },
.argument = "SPEC",
.desc = "Print the table of content (VTOC)",
},
{
.option = { "extended", no_argument, NULL, 'x' },
.desc = "Print extended DASD information",
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
#endif

View File

@@ -0,0 +1,136 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#ifndef DUMP2TAR_CLI_H
#define DUMP2TAR_CLI_H
#include "lib/util_opt.h"
#define OPT_NOSHORT_BASE 256
#define OPT_DEREFERENCE (OPT_NOSHORT_BASE + 0)
#define OPT_NORECURSION (OPT_NOSHORT_BASE + 1)
#define OPT_EXCLUDETYPE (OPT_NOSHORT_BASE + 2)
/* Definition of command line options */
static struct util_opt dump2tar_opts[] = {
UTIL_OPT_SECTION("OUTPUT OPTIONS"),
{
.option = { "output-file", required_argument, NULL, 'o' },
.argument = "FILE",
.desc = "Write archive to FILE (default: standard output)",
},
#ifdef HAVE_ZLIB
{
.option = { "gzip", no_argument, NULL, 'z' },
.desc = "Write a gzip compressed archive",
},
#endif /* HAVE_ZLIB */
{
.option = { "max-size", required_argument, NULL, 'm' },
.argument = "N",
.desc = "Stop adding files when archive size exceeds N bytes",
},
{
.option = { "timeout", required_argument, NULL, 't' },
.argument = "SEC",
.desc = "Stop adding files after SEC seconds",
},
{
.option = { "no-eof", no_argument, NULL, 131 },
.desc = "Do not write an end-of-file marker",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = { "add-cmd-status", no_argument, NULL, 132 },
.desc = "Add status of commands as separate file",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = { "append", no_argument, NULL, 133 },
.desc = "Append output to end of file",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
UTIL_OPT_SECTION("INPUT OPTIONS"),
{
.option = { "files-from", required_argument, NULL, 'F' },
.argument = "FILE",
.desc = "Read filenames from FILE (- for standard input)",
},
{
.option = { "ignore-failed-read", no_argument, NULL, 'i' },
.desc = "Continue after read errors",
},
{
.option = { "buffer-size", required_argument, NULL, 'b' },
.argument = "N",
.desc = "Read data in chunks of N byte (default: 16384)",
},
{
.option = { "file-timeout", required_argument, NULL, 'T' },
.desc = "Stop reading file after SEC seconds",
.argument = "SEC",
},
{
.option = { "file-max-size", required_argument, NULL, 'M' },
.argument = "N",
.desc = "Stop reading file after N bytes",
},
{
.option = { "jobs", required_argument, NULL, 'j' },
.argument = "N",
.desc = "Read N files in parallel (default: 1)",
},
{
.option = { "jobs-per-cpu", required_argument, NULL, 'J' },
.argument = "N",
.desc = "Read N files per CPU in parallel",
},
{
.option = { "exclude", required_argument, NULL, 'x' },
.argument = "PATTERN",
.desc = "Don't add files matching PATTERN",
},
{
.option = { "exclude-from", required_argument, NULL, 'X' },
.argument = "FILE",
.desc = "Don't add files matching patterns in FILE",
},
{
.option = { "exclude-type", required_argument, NULL,
OPT_EXCLUDETYPE },
.argument = "TYPE",
.desc = "Don't add files of specified TYPE (one of: fdcbpls)",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = { "dereference", no_argument, NULL, OPT_DEREFERENCE },
.desc = "Add link targets instead of links",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = { "no-recursion", no_argument, NULL,
OPT_NORECURSION },
.desc = "Don't add files from sub-directories",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
UTIL_OPT_SECTION("MISC OPTIONS"),
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
{
.option = { "verbose", no_argument, NULL, 'V' },
.desc = "Print additional informational output",
},
{
.option = { "quiet", no_argument, NULL, 'q' },
.desc = "Suppress printing of informational output",
},
UTIL_OPT_END,
};
#endif

View File

@@ -1,6 +1,11 @@
# Common definitions
include ../../common.mak
zsh-completions = _dump2tar
bash-completions = dump2tar.bash
include ../../common_autocomp.mak
ALL_CPPFLAGS += -I../include -Wno-unused-parameter
LDLIBS += -lpthread -lrt
ifneq ($(HAVE_ZLIB),0)

View File

@@ -0,0 +1,16 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#include "lib/util_autocomp.h"
#include "../include/dump2tar_cli.h"
int main(void)
{
generate_autocomp(dump2tar_opts, "dump2tar");
return 0;
}

View File

@@ -21,6 +21,7 @@
#include "lib/util_prg.h"
#include "dump.h"
#include "dump2tar_cli.h"
#include "global.h"
#include "idcache.h"
#include "misc.h"
@@ -28,12 +29,6 @@
#define MIN_BUFFER_SIZE 4096
#define OPT_NOSHORT_BASE 256
#define OPT_DEREFERENCE (OPT_NOSHORT_BASE + 0)
#define OPT_NORECURSION (OPT_NOSHORT_BASE + 1)
#define OPT_EXCLUDETYPE (OPT_NOSHORT_BASE + 2)
/* Program description */
static const struct util_prg dump2tar_prg = {
.desc = "Use dump2tar to create a tar archive from the contents "
@@ -52,124 +47,6 @@ static const struct util_prg dump2tar_prg = {
},
};
/* Definition of command line options */
static struct util_opt dump2tar_opts[] = {
UTIL_OPT_SECTION("OUTPUT OPTIONS"),
{
.option = { "output-file", required_argument, NULL, 'o' },
.argument = "FILE",
.desc = "Write archive to FILE (default: standard output)",
},
#ifdef HAVE_ZLIB
{
.option = { "gzip", no_argument, NULL, 'z' },
.desc = "Write a gzip compressed archive",
},
#endif /* HAVE_ZLIB */
{
.option = { "max-size", required_argument, NULL, 'm' },
.argument = "N",
.desc = "Stop adding files when archive size exceeds N bytes",
},
{
.option = { "timeout", required_argument, NULL, 't' },
.argument = "SEC",
.desc = "Stop adding files after SEC seconds",
},
{
.option = { "no-eof", no_argument, NULL, 131 },
.desc = "Do not write an end-of-file marker",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = { "add-cmd-status", no_argument, NULL, 132 },
.desc = "Add status of commands as separate file",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = { "append", no_argument, NULL, 133 },
.desc = "Append output to end of file",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
UTIL_OPT_SECTION("INPUT OPTIONS"),
{
.option = { "files-from", required_argument, NULL, 'F' },
.argument = "FILE",
.desc = "Read filenames from FILE (- for standard input)",
},
{
.option = { "ignore-failed-read", no_argument, NULL, 'i' },
.desc = "Continue after read errors",
},
{
.option = { "buffer-size", required_argument, NULL, 'b' },
.argument = "N",
.desc = "Read data in chunks of N byte (default: 16384)",
},
{
.option = { "file-timeout", required_argument, NULL, 'T' },
.desc = "Stop reading file after SEC seconds",
.argument = "SEC",
},
{
.option = { "file-max-size", required_argument, NULL, 'M' },
.argument = "N",
.desc = "Stop reading file after N bytes",
},
{
.option = { "jobs", required_argument, NULL, 'j' },
.argument = "N",
.desc = "Read N files in parallel (default: 1)",
},
{
.option = { "jobs-per-cpu", required_argument, NULL, 'J' },
.argument = "N",
.desc = "Read N files per CPU in parallel",
},
{
.option = { "exclude", required_argument, NULL, 'x' },
.argument = "PATTERN",
.desc = "Don't add files matching PATTERN",
},
{
.option = { "exclude-from", required_argument, NULL, 'X' },
.argument = "FILE",
.desc = "Don't add files matching patterns in FILE",
},
{
.option = { "exclude-type", required_argument, NULL,
OPT_EXCLUDETYPE },
.argument = "TYPE",
.desc = "Don't add files of specified TYPE (one of: fdcbpls)",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = { "dereference", no_argument, NULL, OPT_DEREFERENCE },
.desc = "Add link targets instead of links",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = { "no-recursion", no_argument, NULL,
OPT_NORECURSION },
.desc = "Don't add files from sub-directories",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
UTIL_OPT_SECTION("MISC OPTIONS"),
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
{
.option = { "verbose", no_argument, NULL, 'V' },
.desc = "Print additional informational output",
},
{
.option = { "quiet", no_argument, NULL, 'q' },
.desc = "Suppress printing of informational output",
},
UTIL_OPT_END,
};
/* Split buffer size specification in @arg into two numbers to be stored in
* @from_ptr and @to_ptr. Return %EXIT_OK on success. */
static int parse_buffer_size(char *arg, size_t *from_ptr, size_t *to_ptr)

View File

@@ -1,5 +1,10 @@
include ../common.mak
zsh-completions = _fdasd
bash-completions = fdasd.bash
include ../common_autocomp.mak
libs = $(rootdir)/libvtoc/libvtoc.a \
$(rootdir)/libzds/libzds.a \
$(rootdir)/libdasd/libdasd.a \

View File

@@ -0,0 +1,16 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#include "lib/util_autocomp.h"
#include "fdasd_cli.h"
int main(void)
{
generate_autocomp(opt_vec, "fdasd");
return 0;
}

View File

@@ -21,6 +21,7 @@
#include "lib/zt_common.h"
#include "fdasd.h"
#include "fdasd_cli.h"
/* global variables */
static struct hd_geometry geo;
@@ -138,58 +139,6 @@ static const struct util_prg prg = {
}
};
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("NON-INTERACTIVE MODE"),
{
.option = { "auto", no_argument, NULL, 'a' },
.desc = "Create a single partition spanning the entire disk",
},
{
.option = { "config", required_argument, NULL, 'c' },
.argument = "FILE",
.desc = "Create partitions(s) based on content of FILE",
},
{
.option = { "keep_volser", no_argument, NULL, 'k' },
.desc = "Do not change the current volume serial",
},
{
.option = { "label", required_argument, NULL, 'l' },
.argument = "VOLSER",
.desc = "Set the volume serial to VOLSER",
},
UTIL_OPT_SECTION("MISC"),
{
.option = { "check_host_count", no_argument, NULL, 'C' },
.desc = "Check if device is in use by other hosts",
},
{
.option = { "force", optional_argument, NULL, 'f' },
.argument = "TYPE,SIZE",
.desc = "Force fdasd to work on non DASD devices with assumed "
"TYPE (3390, 3380, or 9345) and blocksize SIZE",
},
{
.option = { "volser", no_argument, NULL, 'i' },
.desc = "Print volume serial",
},
{
.option = { "table", no_argument, NULL, 'p' },
.desc = "Print partition table",
},
{
.option = { "verbose", no_argument, NULL, 'r' },
.desc = "Provide more verbose output",
},
{
.option = { "silent", no_argument, NULL, 's' },
.desc = "Suppress messages",
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
static int getpos(fdasd_anchor_t *anc, int dsn)
{
return anc->partno[dsn];

64
fdasd/fdasd_cli.h Normal file
View File

@@ -0,0 +1,64 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#ifndef FDASD_CLI_H
#define FDASD_CLI_H
#include "lib/util_opt.h"
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("NON-INTERACTIVE MODE"),
{
.option = { "auto", no_argument, NULL, 'a' },
.desc = "Create a single partition spanning the entire disk",
},
{
.option = { "config", required_argument, NULL, 'c' },
.argument = "FILE",
.desc = "Create partitions(s) based on content of FILE",
},
{
.option = { "keep_volser", no_argument, NULL, 'k' },
.desc = "Do not change the current volume serial",
},
{
.option = { "label", required_argument, NULL, 'l' },
.argument = "VOLSER",
.desc = "Set the volume serial to VOLSER",
},
UTIL_OPT_SECTION("MISC"),
{
.option = { "check_host_count", no_argument, NULL, 'C' },
.desc = "Check if device is in use by other hosts",
},
{
.option = { "force", optional_argument, NULL, 'f' },
.argument = "TYPE,SIZE",
.desc = "Force fdasd to work on non DASD devices with assumed "
"TYPE (3390, 3380, or 9345) and blocksize SIZE",
},
{
.option = { "volser", no_argument, NULL, 'i' },
.desc = "Print volume serial",
},
{
.option = { "table", no_argument, NULL, 'p' },
.desc = "Print partition table",
},
{
.option = { "verbose", no_argument, NULL, 'r' },
.desc = "Provide more verbose output",
},
{
.option = { "silent", no_argument, NULL, 's' },
.desc = "Suppress messages",
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
#endif

View File

@@ -7,6 +7,11 @@
include ../common.mak
zsh-completions = _hsavmcore
bash-completions = hsavmcore.bash
include ../common_autocomp.mak
ALL_CPPFLAGS += -D_FILE_OFFSET_BITS=64
ifeq (${HAVE_FUSE},0)
@@ -41,7 +46,7 @@ endif
ALL_CFLAGS += $(FUSE_CFLAGS) $(SYSTEMD_CFLAGS)
LDLIBS += $(FUSE_LDLIBS) $(SYSTEMD_LDLIBS) -lpthread
sources := $(wildcard *.c)
sources := $(filter-out %_host.c, $(wildcard *.c))
objects := $(patsubst %.c,%.o,$(sources))
libs = $(rootdir)/libutil/libutil.a

View File

@@ -0,0 +1,16 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#include "lib/util_autocomp.h"
#include "hsavmcore_cli.h"
int main(void)
{
generate_autocomp(opt_vec, "hsavmcore");
return 0;
}

View File

@@ -16,6 +16,7 @@
#include "lib/util_log.h"
#include "cmdline_options.h"
#include "hsavmcore_cli.h"
static const struct util_prg prg = {
.desc = "hsavmcore is designed to make the dump process with kdump more "
@@ -32,91 +33,6 @@ static const struct util_prg prg = {
}
};
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("CONFIGURATION"),
{
.option = { "config", required_argument, NULL, 'c' },
.argument = "CONFIGFILE",
.desc = "Path to the configuration file.\n"
"Default: no configuration file is used",
},
{
.option = { "vmcore", required_argument, NULL, 'C' },
.argument = "VMCOREFILE",
.desc = "Path to the vmcore file.\n"
"Default: " PROC_VMCORE,
},
{
.option = { "hsa", required_argument, NULL, 'H' },
.argument = "ZCOREHSAFILE",
.desc = "Path to the zcore HSA file.\n"
"Default: " ZCORE_HSA,
},
{
.option = { "workdir", required_argument, NULL, 'W' },
.argument = "WORKDIR",
.desc = "Path to the work directory where temporary files can be "
"stored.\nDefault: " WORKDIR,
},
{
.option = { "bmvmcore", required_argument, NULL, 'B' },
.argument = "VMCOREFILE",
.desc = "Path to the target of the bind mount for the vmcore "
"replacement.\nDefault: " PROC_VMCORE,
},
{
.option = { "swap", required_argument, NULL, 'S' },
.argument = "PATH",
.desc = "Path to a swap device or file. The specified swap "
"device or file must exist and have the proper swap "
"format.\nDefault: no swap device or file is activated",
},
{
.option = { "hsasize", required_argument, NULL, 'T' },
.argument = "HSASIZE",
.desc = "HSA size in bytes.\n"
"Default: -1 (read from the zcore HSA file)",
},
{
.option = { "dbgfsmnt", no_argument, NULL, 'D' },
.desc = "Mount the debug file system.\n"
"Default: the debug file system is not mounted",
},
{
.option = { "hsamem", no_argument, NULL, 'F' },
.desc = "Cache the HSA memory in regular memory.\n"
"Default: the HSA memory is cached as a file within "
"WORKDIR",
},
{
.option = { "norelhsa", no_argument, NULL, 'R' },
.desc = "Do NOT release the HSA memory after caching.\n"
"Default: the HSA memory is released",
},
{
.option = { "nobindmnt", no_argument, NULL, 'N' },
.desc = "Do NOT replace the system's vmcore.\n"
"Default: the system's vmcore is replaced",
},
UTIL_OPT_SECTION("LOGGING"),
{
.option = { "verbose", no_argument, NULL, 'V' },
.desc = "Print verbose messages to stdout. Repeat this option "
"for increased verbosity from just error messages to "
"also include warning, information, debug, and trace "
"messages. This option is intended for debugging",
},
{
.option = { "fusedbg", no_argument, NULL, 'G' },
.desc = "Enable FUSE debugging.\n"
"Default: FUSE debugging is disabled",
},
UTIL_OPT_SECTION("GENERAL OPTIONS"),
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
void parse_cmdline_options(int argc, char *argv[], struct config *config)
{
int opt, ret;

99
hsavmcore/hsavmcore_cli.h Normal file
View File

@@ -0,0 +1,99 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#ifndef HSAVMCORE_CLI_H
#define HSAVMCORE_CLI_H
#include "lib/util_opt.h"
#include "common.h"
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("CONFIGURATION"),
{
.option = { "config", required_argument, NULL, 'c' },
.argument = "CONFIGFILE",
.desc = "Path to the configuration file.\n"
"Default: no configuration file is used",
},
{
.option = { "vmcore", required_argument, NULL, 'C' },
.argument = "VMCOREFILE",
.desc = "Path to the vmcore file.\n"
"Default: " PROC_VMCORE,
},
{
.option = { "hsa", required_argument, NULL, 'H' },
.argument = "ZCOREHSAFILE",
.desc = "Path to the zcore HSA file.\n"
"Default: " ZCORE_HSA,
},
{
.option = { "workdir", required_argument, NULL, 'W' },
.argument = "WORKDIR",
.desc = "Path to the work directory where temporary files can be "
"stored.\nDefault: " WORKDIR,
},
{
.option = { "bmvmcore", required_argument, NULL, 'B' },
.argument = "VMCOREFILE",
.desc = "Path to the target of the bind mount for the vmcore "
"replacement.\nDefault: " PROC_VMCORE,
},
{
.option = { "swap", required_argument, NULL, 'S' },
.argument = "PATH",
.desc = "Path to a swap device or file. The specified swap "
"device or file must exist and have the proper swap "
"format.\nDefault: no swap device or file is activated",
},
{
.option = { "hsasize", required_argument, NULL, 'T' },
.argument = "HSASIZE",
.desc = "HSA size in bytes.\n"
"Default: -1 (read from the zcore HSA file)",
},
{
.option = { "dbgfsmnt", no_argument, NULL, 'D' },
.desc = "Mount the debug file system.\n"
"Default: the debug file system is not mounted",
},
{
.option = { "hsamem", no_argument, NULL, 'F' },
.desc = "Cache the HSA memory in regular memory.\n"
"Default: the HSA memory is cached as a file within "
"WORKDIR",
},
{
.option = { "norelhsa", no_argument, NULL, 'R' },
.desc = "Do NOT release the HSA memory after caching.\n"
"Default: the HSA memory is released",
},
{
.option = { "nobindmnt", no_argument, NULL, 'N' },
.desc = "Do NOT replace the system's vmcore.\n"
"Default: the system's vmcore is replaced",
},
UTIL_OPT_SECTION("LOGGING"),
{
.option = { "verbose", no_argument, NULL, 'V' },
.desc = "Print verbose messages to stdout. Repeat this option "
"for increased verbosity from just error messages to "
"also include warning, information, debug, and trace "
"messages. This option is intended for debugging",
},
{
.option = { "fusedbg", no_argument, NULL, 'G' },
.desc = "Enable FUSE debugging.\n"
"Default: FUSE debugging is disabled",
},
UTIL_OPT_SECTION("GENERAL OPTIONS"),
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
#endif

View File

@@ -96,6 +96,17 @@ with an ASCII Record Separator character (0x1e) and suffixed with an ASCII Line
Feed character (0x0a) in accordance with RFC7464.
.BR
See section "OUTPUT FORMAT" for more details.
.BR
.PP
.IP \(bu 3
.B jsonl:
Line-delimited JSON data structures
Data for each iteration is formatted as a separate JSON data structure
separated by ASCII Line Feed character (0x0a, LF).
.BR
See section "OUTPUT FORMAT" for more details.
.BR
.PP
@@ -458,6 +469,14 @@ Subsequent objects each represent performance data for one iteration
.br
.PP
.SS jsonl
The jsonl output format is a data streaming variation of the JSON output format
described above with the same properties as the json\-seq output with the
difference that JSON data is separated only by an ASCII Line Feed character
(0x0a, LF).
.SH EXAMPLES
To start hyptop with the "sys_list" window in interactive mode, enter:
.br

View File

@@ -233,7 +233,7 @@ static void l_fmt_init(void)
flags |= FMT_QUOTEALL;
if (g.o.format == FMT_CSV || g.o.format_all)
flags |= FMT_KEEPINVAL;
if (g.o.format == FMT_JSON || g.o.format == FMT_JSONSEQ)
if (util_fmt_is_json(g.o.format))
flags |= FMT_HANDLEINT;
util_fmt_init(stdout, g.o.format, flags, 1);
}

View File

@@ -54,14 +54,6 @@ static char HELP_TEXT[] =
#define OPT_FORMAT 256 /* --format */
#define OPT_FORMAT_ALL 261 /* --all*/
/*
* Options with underscore to keep compatibility
*/
#define OPT_BATCH_MODE 257 /* --batch_mode */
#define OPT_SORT_FIELD 258 /* --sort | --sort_field */
#define OPT_CPU_TYPES 259 /* --cpu_types */
#define OPT_SMT_FACTOR 260 /* --smt_factor */
/*
* Initialize default settings
*/
@@ -224,7 +216,7 @@ static void l_fields_set(char *str)
}
/*
* Set the "--sort_field" option
* Set the "--sort" option
*/
static void l_sort_field_set(char *str)
{
@@ -362,19 +354,18 @@ void opts_parse(int argc, char *argv[])
{ "version", no_argument, NULL, 'v'},
{ "help", no_argument, NULL, 'h'},
{ "batch-mode", no_argument, NULL, 'b'},
{ "batch_mode", no_argument, NULL, OPT_BATCH_MODE},
{ "batch_mode", no_argument, NULL, 'b'},
{ "all", no_argument, NULL, OPT_FORMAT_ALL },
{ "delay", required_argument, NULL, 'd'},
{ "smt-factor", required_argument, NULL, 'm'},
{ "smt_factor", required_argument, NULL, OPT_SMT_FACTOR},
{ "smt_factor", required_argument, NULL, 'm'},
{ "window", required_argument, NULL, 'w'},
{ "sys", required_argument, NULL, 's'},
{ "iterations", required_argument, NULL, 'n'},
{ "fields", required_argument, NULL, 'f'},
{ "sort-field", required_argument, NULL, 'S'},
{ "sort_field", required_argument, NULL, OPT_SORT_FIELD},
{ "sort", required_argument, NULL, 'S'},
{ "cpu-types", required_argument, NULL, 't'},
{ "cpu_types", required_argument, NULL, OPT_CPU_TYPES},
{ "cpu_types", required_argument, NULL, 't'},
{ "format", required_argument, NULL, OPT_FORMAT },
{ NULL, 0, NULL, 0 }
};
@@ -393,14 +384,12 @@ void opts_parse(int argc, char *argv[])
case 'h':
l_usage();
hyptop_exit(0);
case OPT_BATCH_MODE:
case 'b':
l_batch_mode_set();
break;
case 'd':
l_delay_set(optarg);
break;
case OPT_SMT_FACTOR:
case 'm':
l_factor_set(optarg);
break;
@@ -413,14 +402,12 @@ void opts_parse(int argc, char *argv[])
case 'n':
l_iterations_set(optarg);
break;
case OPT_CPU_TYPES:
case 't':
l_cpu_types_set(optarg);
break;
case 'f':
l_fields_set(optarg);
break;
case OPT_SORT_FIELD:
case 'S':
l_sort_field_set(optarg);
break;

View File

@@ -1037,7 +1037,7 @@ void table_fmt_start(void)
{
if (!g.o.format_specified)
return;
if (g.o.format != FMT_JSONSEQ)
if (!util_fmt_is_json_stream(g.o.format))
util_fmt_obj_start(FMT_LIST, "hyptop");
}
@@ -1045,7 +1045,7 @@ void table_fmt_end(void)
{
if (!g.o.format_specified)
return;
if (g.o.format != FMT_JSONSEQ)
if (!util_fmt_is_json_stream(g.o.format))
util_fmt_obj_end(); /* hyptop[] */
}

View File

@@ -1,15 +1,7 @@
/* SPDX-License-Identifier: MIT */
/*
* autocomp - command line autocompletion
*
* Generating autocompletion scripts for bash and zsh
* based on util_opt struct
*
* Copyright IBM Corp. 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#ifndef LIB_UTIL_AUTOCOMP_H

View File

@@ -45,12 +45,13 @@
#define FMT_DEFAULT 0
/* Names of supported output format types. */
#define FMT_TYPE_NAMES "json json-seq pairs csv"
#define FMT_TYPE_NAMES "json json-seq jsonl pairs csv"
/**
* enum util_fmt_t - Output format types.
* @FMT_JSON: JavaScript Object Notation output data structure
* @FMT_JSONSEQ: Sequence of JSON data structures according to RFC7464
* @FMT_JSONL: Line-delimited JSON
* @FMT_PAIRS: Textual key=value pairs
* @FMT_CSV: Comma-separated-values output
*
@@ -59,6 +60,7 @@
enum util_fmt_t {
FMT_JSON,
FMT_JSONSEQ,
FMT_JSONL,
FMT_PAIRS,
FMT_CSV,
};
@@ -232,4 +234,23 @@ void util_fmt_obj_end(void);
*/
void util_fmt_pair(unsigned int mflags, const char *key, const char *fmt, ...);
/**
* util_fmt_is_json() - Determine whether format is JSON.
* @type: Format type identifier.
*
* Return: %true if type is JSON, %false otherwise.
*/
bool util_fmt_is_json(enum util_fmt_t type);
/**
* util_fmt_is_json_stream() - Determine whether format is JSON stream.
* @type: Format type identifier.
*
* Determine whether a given format @type represents a JSON streaming format
* such as json-seq (@FMT_JSONSEQ) or jsonl (@FMT_JSONL).
*
* Return: %true if type is either @FMT_JSONSEQ or @FMT_JSONL, %false otherwise.
*/
bool util_fmt_is_json_stream(enum util_fmt_t type);
#endif /* LIB_UTIL_FMT_H */

View File

@@ -2172,7 +2172,7 @@ int write_public_key(const char *pem_filename, EVP_PKEY *pkey)
*/
static bool is_duplicate_name_entry(X509_NAME *name, X509_NAME_ENTRY *entry)
{
X509_NAME_ENTRY *ne;
const X509_NAME_ENTRY *ne;
int count, i;
count = X509_NAME_entry_count(name);

View File

@@ -378,8 +378,14 @@ int kmip_connection_tls_init(struct kmip_connection *conn, bool debug)
if (conn->config.tls_verify_host) {
SSL_set_hostflags(conn->plain_tls.ssl,
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
#if OPENSSL_VERSION_PREREQ(4, 0)
if (SSL_set1_ipaddr(conn->plain_tls.ssl, hostname) != 1 &&
SSL_set1_dnsname(conn->plain_tls.ssl, hostname) != 1) {
kmip_debug(debug, "SSL_set1_ipaddr/dnsname failed");
#else
if (SSL_set1_host(conn->plain_tls.ssl, hostname) != 1) {
kmip_debug(debug, "SSL_set1_host failed");
#endif
if (debug)
ERR_print_errors_fp(stderr);
rc = -EIO;

View File

@@ -395,7 +395,7 @@ const struct sk_digest_info *SK_UTIL_get_digest_info(int digest_nid)
static bool SK_UTILS_is_duplicate_name_entry(const X509_NAME *name,
const X509_NAME_ENTRY *entry)
{
X509_NAME_ENTRY *ne;
const X509_NAME_ENTRY *ne;
int count, i;
count = X509_NAME_entry_count(name);

View File

@@ -1,15 +1,7 @@
// SPDX-License-Identifier: MIT
/*
* autocomp - command line autocompletion
*
* Generating autocompletion scripts for bash and zsh
* based on util_opt struct
*
* Copyright IBM Corp. 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#include <errno.h>
@@ -22,18 +14,19 @@
#include "lib/util_autocomp.h"
#include "lib/util_opt.h"
static const char *bash_script_part1 = "() {\n\n\
\tlocal current_word previous_word options_array\n\n\
static const char *bash_script_part1 = "() {\n\
\tlocal current_word options_array\n\
\tCOMPREPLY=()\n\n\
\tcurrent_word=\"${COMP_WORDS[COMP_CWORD]}\"\n\n\
\tprevious_word=\"${COMP_WORDS[COMP_CWORD-1]}\"\n\n\
\tcurrent_word=\"${COMP_WORDS[COMP_CWORD]}\"\n\
\toptions_array=\"";
static const char *bash_script_part2 = "\tif [[ ${current_word} == -* || ${COMP_CWORD} -eq 1 ]] ; then\n\n\
\t\tCOMPREPLY=( $(compgen -W \"${options_array}\" -- ${current_word} ) )\n\n\
\t\treturn 0\n\n\
\tfi\n\n\
}\n\n\
static const char *bash_script_part2 = "\tif [[ ${current_word} == -* ]] ; then\n\
\t\tmapfile -t \"COMPREPLY\" < <(compgen -W \"${options_array}\" -- \"$current_word\")\n\
\telse\n\
\t\tcompopt -o bashdefault -o default\n\
\tfi\n\
\treturn 0\n\
}\n\
complete -F ";
static char *format_name(const char *fmt, char *tool_name)
@@ -63,7 +56,7 @@ static int init_scriptfile(char *file_path)
{
int fd;
fd = open(file_path, O_CREAT | O_WRONLY, 0644);
fd = open(file_path, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd < 0)
return -EIO;
return fd;
@@ -86,7 +79,7 @@ static int start_bash_scriptfile(int fd, char *func_name)
static int start_zsh_scriptfile(int fd, char *func_name, char *tool_name)
{
const char *part3 = " {\n\n\t_arguments -C \\\n";
const char *part3 = " {\n\n\t_arguments -C -A \"*\" \\\n";
const char *part2 = "\n\nfunction ";
const char *part1 = "#compdef ";
int len, ret = 0;
@@ -127,6 +120,7 @@ static int write_bash_command_options(struct util_opt *opt_vec, int fd)
static int write_zsh_command_options(struct util_opt *opt_vec, int fd)
{
const char *end = "\t\t\"*:files:_files\"\n}\n";
const char *name, *desc;
char *str;
int len;
@@ -145,8 +139,14 @@ static int write_zsh_command_options(struct util_opt *opt_vec, int fd)
free(str);
}
}
if (write(fd, "\n}\n", 3) != 3)
len = asprintf(&str, "%s", end);
if (len == -1)
return -EIO;
if (write(fd, str, len) != len) {
free(str);
return -EIO;
}
free(str);
return 0;
}
@@ -169,35 +169,6 @@ static int finish_bash_scriptfile(char *tool_name, int fd, char *func_name)
* Adds tab completion in bash for a command.
* Works by generating an autocompletion
* script file at '/usr/share/bash-completion/completions'.
*
* The full script will be as follows, supposing the tool name is
* 'example' and it only has the options '--help' and
* '--version':
*
* _example() {
*
* local current_word previous_word options_array
*
* COMPREPLY=()
*
* current_word="${COMP_WORDS[COMP_CWORD]}"
*
* previous_word="${COMP_WORDS[COMP_CWORD-1]}"
*
* options_array="--version --help"
*
* if [[ ${current_word} == -* || ${COMP_CWORD} -eq 1 ]] ; then
*
* COMPREPLY=( $(compgen -W "${options_array}" -- ${current_word} ) )
*
* return 0
*
* fi
*
* }
*
* complete -F _example example
*
*/
static void generate_bash_autocomp(struct util_opt *opt_vec, char *tool_name)
{
@@ -244,22 +215,6 @@ end:
* Adds tab completion in zsh for a command.
* Works by generating an autocompletion
* script file at '/usr/share/zsh/site-functions'.
*
* The full script will be as follows, supposing the tool name is
* 'example' and it only has the options '--help', -h and
* '--version' (the descriptions, as well as the flags are
* taken from a util_opt struct):
*
* #compdef example_completion
*
* function _example_completion {
*
* _arguments -C \
* "-h[Show help information]" \
* "--help[Show help but long format]" \
* "--version[Show version]"
* }
*
*/
static void generate_zsh_autocomp(struct util_opt *opt_vec, char *tool_name)
{

View File

@@ -91,6 +91,7 @@ static const struct {
} formats[] = {
{ "json", FMT_JSON },
{ "json-seq", FMT_JSONSEQ },
{ "jsonl", FMT_JSONL },
{ "pairs", FMT_PAIRS },
{ "csv", FMT_CSV },
};
@@ -111,6 +112,29 @@ bool util_fmt_name_to_type(const char *name, enum util_fmt_t *type)
return false;
}
bool util_fmt_is_json(enum util_fmt_t type)
{
switch (type) {
case FMT_JSON:
case FMT_JSONSEQ:
case FMT_JSONL:
return true;
default:
return false;
}
}
bool util_fmt_is_json_stream(enum util_fmt_t type)
{
switch (type) {
case FMT_JSONSEQ:
case FMT_JSONL:
return true;
default:
return false;
}
}
static void safe_write(const char *str)
{
size_t done, todo;
@@ -129,7 +153,7 @@ static void _indent(unsigned int off, bool safe)
{
unsigned int num, i;
if (f.type == FMT_JSONSEQ)
if (util_fmt_is_json_stream(f.type))
return;
num = f.ind_base + off;
if (f.type == FMT_JSON && f.lvl > 0)
@@ -408,8 +432,8 @@ static void emit_meta_object(void)
util_fmt_pair(quoted, "time", "%s", date);
_util_fmt_obj_end();
if (f.type == FMT_JSONSEQ) {
/* Tool meta-data is a separate object for JSONSEQ. */
if (util_fmt_is_json_stream(f.type)) {
/* Tool meta-data is a separate object for JSON streams. */
util_fmt_obj_end();
}
}
@@ -478,7 +502,7 @@ void util_fmt_obj_end(void)
{
_util_fmt_obj_end();
if (f.lvl == 1 && f.meta_done && f.type != FMT_JSONSEQ) {
if (f.lvl == 1 && f.meta_done && !util_fmt_is_json_stream(f.type)) {
/* Emit closure for top-level meta-container object. */
util_fmt_obj_end();
}
@@ -737,7 +761,7 @@ void util_fmt_init(FILE *fd, enum util_fmt_t type, unsigned int flags,
f.do_warn = (flags & FMT_WARN);
f.handle_int = (flags & FMT_HANDLEINT);
f.api_level = api_level;
if (type == FMT_JSONSEQ)
if (util_fmt_is_json_stream(type))
f.nl = "";
else
f.nl = "\n";
@@ -750,6 +774,7 @@ void util_fmt_init(FILE *fd, enum util_fmt_t type, unsigned int flags,
break;
case FMT_JSON:
case FMT_JSONSEQ:
case FMT_JSONL:
f.obj_start = &json_obj_start;
f.obj_end = &json_obj_end;
f.map = &json_map;

View File

@@ -193,6 +193,9 @@ int main(int UNUSED(argc), char *UNUSED(argv[]))
announce("JSON formatted as sequence");
simple_example(FMT_JSONSEQ, FMT_DEFAULT);
announce("JSON Lines format");
simple_example(FMT_JSONL, FMT_DEFAULT);
announce("Pairs output");
simple_example(FMT_PAIRS, FMT_KEEPINVAL);
@@ -232,6 +235,9 @@ int main(int UNUSED(argc), char *UNUSED(argv[]))
announce("JSON sequence output with meta-data");
meta_example(FMT_JSONSEQ);
announce("JSON Lines output with meta-data");
meta_example(FMT_JSONL);
announce("Pairs output with meta-data");
meta_example(FMT_PAIRS);

View File

@@ -1,5 +1,10 @@
include ../common.mak
zsh-completions = _lsstp
bash-completions = lsstp.bash
include ../common_autocomp.mak
libs = $(rootdir)/libutil/libutil.a
all: lsstp

View File

@@ -0,0 +1,16 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#include "lib/util_autocomp.h"
#include "lsstp_cli.h"
int main(void)
{
generate_autocomp(opt_vec, "lsstp");
return 0;
}

View File

@@ -22,6 +22,8 @@
#include "lib/util_prg.h"
#include "lib/util_path.h"
#include "lsstp_cli.h"
static const struct util_prg prg = {
.desc = "Display STP system information",
.args = "",
@@ -34,12 +36,6 @@ static const struct util_prg prg = {
}
};
static struct util_opt opt_vec[] = {
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
struct stp_parms {
uint64_t ctn_id;
unsigned int online;

18
lsstp/lsstp_cli.h Normal file
View File

@@ -0,0 +1,18 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#ifndef LSSTP_CLI_H
#define LSSTP_CLI_H
#include "lib/util_opt.h"
static struct util_opt opt_vec[] = {
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
#endif

View File

@@ -2,6 +2,11 @@ include ../common.mak
TESTS := tests/
zsh-completions = _opticsmon
bash-completions = opticsmon.bash
include ../common_autocomp.mak
libs =$(rootdir)/libzpci/libzpci.a $(rootdir)/libutil/libutil.a
ifneq (${HAVE_OPENSSL},0)

View File

@@ -0,0 +1,16 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#include "lib/util_autocomp.h"
#include "opticsmon_cli.h"
int main(void)
{
generate_autocomp(opt_vec, "opticsmon");
return 0;
}

View File

@@ -45,7 +45,7 @@ opticsmon - Monitor optical modules for directly attached PCI based NICs
Use
.B opticsmon
to monitor the health of the optical modules of directly attached PCI based
NICs. When executed without the \fB--daemon\fR option it will collect optical
NICs. When executed without the \fB--monitor\fR option it will collect optical
module data from all available PCI network interface physical functions and
print a summary in JSON format. Add the \fB--send-report\fR option to report
this data to the support element.
@@ -55,7 +55,7 @@ this data to the support element.
.
.SH OPTIONS
.SS Operation Options
.OD daemon "d"
.OD monitor "m"
Run continuously and report on link state changes and periodically
.PP
.

View File

@@ -27,10 +27,11 @@
#include <openssl/evp.h>
#include "optics_info.h"
#include "optics_sclp.h"
#include "ethtool.h"
#include "link_mon.h"
#include "optics_info.h"
#include "optics_sclp.h"
#include "opticsmon_cli.h"
#define API_LEVEL 1
@@ -61,44 +62,6 @@ static const struct util_prg prg = {
UTIL_PRG_COPYRIGHT_END }
};
#define OPT_DUMP 128
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("OPERATION OPTIONS"),
{
.option = { "monitor", no_argument, NULL, 'm' },
.desc = "Run continuously and report on link state changes "
"collecting optics health data when a change is detected",
},
{
.option = { "send-report", no_argument, NULL, 'r' },
.desc = "Report the optics health data to the Support Element",
},
{
.option = { "quiet", no_argument, NULL, 'q' },
.desc = "Be quiet and don't print optics health summary",
},
{
.option = { "module-info", no_argument, NULL, OPT_DUMP },
.desc = "Include a base64 encoded binary dump of the module's "
"SFF-8636/8472/8024 standard data for each netdev. "
"This matches \"ethtool --module-info <netdev> raw on\"",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
UTIL_OPT_SECTION("OPTIONS WITH ARGUMENTS"),
{
.option = { "interval", required_argument, NULL, 'i' },
.argument = "seconds",
.desc = "Interval in seconds at which to collect monitoring data "
"in the absence of link state changes. A value larger than "
"24 hours (86400 seconds) is clamped down to 24 hours.",
},
UTIL_OPT_SECTION("GENERAL OPTIONS"),
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
static void parse_cmdline(int argc, char *argv[], struct options *opts)
{
uint32_t seconds;

50
opticsmon/opticsmon_cli.h Normal file
View File

@@ -0,0 +1,50 @@
/*
* SPDX-License-Identifier: MIT
*
* Copyright IBM Corp.
*/
#ifndef OPTICSMON_CLI_H
#define OPTICSMON_CLI_H
#include "lib/util_opt.h"
#define OPT_DUMP 128
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("OPERATION OPTIONS"),
{
.option = { "monitor", no_argument, NULL, 'm' },
.desc = "Run continuously and report on link state changes "
"collecting optics health data when a change is detected",
},
{
.option = { "send-report", no_argument, NULL, 'r' },
.desc = "Report the optics health data to the Support Element",
},
{
.option = { "quiet", no_argument, NULL, 'q' },
.desc = "Be quiet and don't print optics health summary",
},
{
.option = { "module-info", no_argument, NULL, OPT_DUMP },
.desc = "Include a base64 encoded binary dump of the module's "
"SFF-8636/8472/8024 standard data for each netdev. "
"This matches 'ethtool --module-info <netdev> raw on'",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
UTIL_OPT_SECTION("OPTIONS WITH ARGUMENTS"),
{
.option = { "interval", required_argument, NULL, 'i' },
.argument = "seconds",
.desc = "Interval in seconds at which to collect monitoring data "
"in the absence of link state changes. A value larger than "
"24 hours (86400 seconds) is clamped down to 24 hours.",
},
UTIL_OPT_SECTION("GENERAL OPTIONS"),
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
#endif

105
rust/Cargo.lock generated
View File

@@ -62,9 +62,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.95"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
[[package]]
name = "autocfg"
@@ -111,6 +111,15 @@ dependencies = [
"wyz",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "byteorder"
version = "1.5.0"
@@ -212,6 +221,25 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "curl"
version = "0.4.49"
@@ -302,6 +330,16 @@ dependencies = [
"syn",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "enum_dispatch"
version = "0.3.13"
@@ -363,6 +401,16 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.16"
@@ -404,6 +452,12 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "ident_case"
version = "1.0.1"
@@ -641,6 +695,20 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "pvebc"
version = "0.12.0"
dependencies = [
"anyhow",
"clap",
"clap_complete",
"hex",
"s390_pv_core",
"sha2",
"utils",
"zerocopy",
]
[[package]]
name = "pvimg"
version = "0.12.0"
@@ -687,6 +755,7 @@ dependencies = [
"s390_pv",
"serde_yaml",
"utils",
"zerocopy",
]
[[package]]
@@ -891,6 +960,7 @@ dependencies = [
"regex",
"serde",
"serde_test",
"sha2",
"thiserror",
"zerocopy",
]
@@ -969,6 +1039,17 @@ dependencies = [
"unsafe-libyaml",
]
[[package]]
name = "sha2"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "shlex"
version = "1.3.0"
@@ -1069,6 +1150,12 @@ dependencies = [
"winnow",
]
[[package]]
name = "typenum"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
name = "unarray"
version = "0.1.4"
@@ -1112,6 +1199,12 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wait-timeout"
version = "0.2.0"
@@ -1238,18 +1331,18 @@ dependencies = [
[[package]]
name = "zerocopy"
version = "0.8.25"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.25"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -5,6 +5,7 @@ members = [
"pv_core",
"pvapconfig",
"pvattest",
"pvebc",
"pvimg",
"pvinfo",
"pvsecret",

View File

@@ -10,8 +10,10 @@ CARGO_TARGETS :=
PV_TARGETS :=
CARGO_TEST_TARGETS :=
SEL_EBC_MODDIR := 95sel-ebc
ifneq (${HAVE_CARGO},0)
CARGO_TARGETS :=
CARGO_TARGETS := pvebc
BUILD_TARGETS = $(CARGO_TARGETS)
INSTALL_TARGETS := install-rust-tools install-man install-shell-completions
@@ -29,6 +31,7 @@ ifneq (${HAVE_LIBCURL},0)
ifeq ($(HOST_ARCH),s390x)
PV_TARGETS += pvapconfig pvinfo
INSTALL_TARGETS += install-ebc-dracut-module
else
BUILD_TARGETS += skip-pvapconfig skip-pvinfo
endif #HOSTARCH
@@ -104,6 +107,25 @@ endif # CARGO
rust-test: $(CARGO_TEST_TARGETS)
install-ebc-dracut-module:
ifneq ($(HAVE_DRACUT),0)
$(INSTALL) -m 755 -d $(DESTDIR)$(DRACUTMODDIR)/
$(INSTALL) -m 755 -d $(DESTDIR)$(DRACUTMODDIR)/$(SEL_EBC_MODDIR)
$(INSTALL) -m 755 pvebc/$(SEL_EBC_MODDIR)/module-setup.sh \
pvebc/$(SEL_EBC_MODDIR)/override-crypttab.sh \
pvebc/$(SEL_EBC_MODDIR)/pvebc-wrapper.sh \
pvebc/$(SEL_EBC_MODDIR)/boot-mount.sh \
pvebc/$(SEL_EBC_MODDIR)/sel-ebc-modules.conf \
$(DESTDIR)$(DRACUTMODDIR)/$(SEL_EBC_MODDIR)
$(INSTALL) -m 644 pvebc/$(SEL_EBC_MODDIR)/sel-ebc-boot-mount.service \
pvebc/$(SEL_EBC_MODDIR)/sel-ebc-override-crypttab.service \
pvebc/$(SEL_EBC_MODDIR)/sel-ebc-paes-enforce.service \
pvebc/$(SEL_EBC_MODDIR)/sel-ebc-pvebc.service \
pvebc/$(SEL_EBC_MODDIR)/sel-ebc.crypttab \
pvebc/$(SEL_EBC_MODDIR)/sel-ebc.target \
$(DESTDIR)$(DRACUTMODDIR)/$(SEL_EBC_MODDIR)
endif
install-rust-tools: $(BUILD_TARGETS)
$(INSTALL) -d -m 755 $(DESTDIR)$(USRBINDIR)
$(foreach target,$(CARGO_TARGETS),\

View File

@@ -90,11 +90,11 @@ pub enum Error {
#[error("Input does not contain an attestation request")]
NoArcb,
#[error("The attestation request has an unknown version (.0)")]
#[error("The attestation request has an unknown version {0}")]
BinArcbInvVersion(u32),
#[error(
"The attestation request encrypted sice is to0 small (.0). Request probably tampered with."
"The attestation request encrypted sice is to0 small {0}. Request probably tampered with."
)]
BinArcbSeaSmall(u32),

View File

@@ -104,7 +104,14 @@ pub mod request {
/// Reexports some useful OpenSSL symbols
pub mod openssl {
pub use openssl::{error::ErrorStack, hash::DigestBytes, nid::Nid, pkey, x509};
pub use openssl::{
error::ErrorStack,
hash::DigestBytes,
nid::Nid,
pkey,
sha::{Sha256, Sha512},
x509,
};
// rust-OpenSSL does not define these NIDs
#[allow(missing_docs)]
pub const NID_ED25519: Nid = Nid::from_raw(openssl_sys::NID_ED25519);
@@ -113,6 +120,8 @@ pub mod request {
}
pub use pv_core::request::*;
pub use pv_core::PolicyReference;
}
/// Functionalities for creating add-secret requests

View File

@@ -248,7 +248,7 @@ fn check_key_format(kind: UserDataType, key: &PKeyRef<Public>) -> Result<()> {
///
/// # Returns
///
/// Extracrted user-data if available
/// Extracted user-data if available
///
/// # Errors
///

View File

@@ -23,6 +23,7 @@ zerocopy = {version = "0.8", features = ["derive"]}
serde = { version = "1.0.217", features = ["derive"]}
byteorder = "1.5"
regex = "1.10"
sha2 = "0.10.9"
[dev-dependencies]
serde_test = "1.0.177"

View File

@@ -6,6 +6,7 @@ mod apdevice;
mod confidential;
mod error;
mod macros;
mod policy;
mod utils;
mod uvattest;
mod uvdevice;
@@ -13,6 +14,13 @@ mod uvsecret;
pub use error::{Error, FileAccessErrorType, FileIoErrorType, Result};
/// Early Boot Customization (EBC) utilities.
///
/// This module provides types and functions for working with Early Boot
/// Customization. The integrity and completeness of ASRs are ensured through
/// cryptographically protected table of contents files.
pub use policy::PolicyReference;
/// Functionalities for reading attestation requests
pub mod attest {
pub use crate::uvattest::{AttestationMagic, AttestationMeasAlg};

112
rust/pv_core/src/policy.rs Normal file
View File

@@ -0,0 +1,112 @@
// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp.
use crate::misc::encode_hex;
use crate::utils::open_file;
use crate::{Error, Result};
use std::{
fmt::{Display, Formatter, Result as Resfmt},
fs::File,
os::unix::ffi::OsStrExt,
path::{Path, PathBuf},
str::from_utf8,
};
use zerocopy::{FromBytes, Immutable, IntoBytes};
const HASH_LEN: usize = 32;
// UserDataType::Unsigned.max() returns 512
const USER_DATA_MAX_SIZE: usize = 512;
/// A reference to a policy file containing its SHA-256 hash and file path.
///
/// This structure is used in Early Boot Customization (EBC) to store
/// a reference to a policy file. It contains the SHA-256 hash of the policy
/// file content and the file path as a fixed-size byte array.
///
/// The total size is constrained by `USER_DATA_MAX_SIZE` (512 bytes), with
/// 32 bytes allocated for the hash and the remaining bytes for the file path.
#[derive(Debug, FromBytes, IntoBytes, Immutable, Copy, Clone)]
#[repr(C)]
pub struct PolicyReference {
/// SHA-256 hash of the policy file content (32 bytes)
pub hash: [u8; HASH_LEN],
/// File path stored as a null-terminated byte array
pub name: [u8; USER_DATA_MAX_SIZE - HASH_LEN],
}
impl PolicyReference {
/// Creates a new `PolicyReference` from a file path.
///
/// Opens the file, reads its content, and computes the SHA-256 hash.
///
/// # Parameters
///
/// * `src` - The path to the policy file
/// * `sha256` - A function that computes the SHA-256 hash of the content
///
/// # Returns
///
/// Returns a `PolicyReference` containing the SHA-256 hash and the file path,
/// or an error if the file cannot be opened or the hash computation fails.
///
/// # Note
///
/// The file path is truncated if it exceeds the available space in the `name` field.
pub fn new<P, H>(src: P, sha256: H) -> Result<Self>
where
P: AsRef<Path>,
H: Fn(File) -> Result<Vec<u8>>,
{
let mut ret = Self {
hash: [0; HASH_LEN],
name: [0; USER_DATA_MAX_SIZE - HASH_LEN],
};
let file = open_file(src.as_ref())?;
ret.hash.copy_from_slice(sha256(file)?.as_bytes());
let strbytes = src.as_ref().as_os_str().as_bytes();
let nbytes = strbytes.len().min(ret.name.len());
ret.name[..nbytes].copy_from_slice(&strbytes[..nbytes]);
Ok(ret)
}
/// Converts the stored file path back to a `PathBuf`.
///
/// # Returns
///
/// Returns the file path as a `PathBuf`, or an error if the stored name
/// is not valid UTF-8.
///
/// # Errors
///
/// * `Error::ParseError` - If the name contains invalid UTF-8
pub fn to_path(&self) -> Result<PathBuf> {
// Extract bytes until the first null byte (null-terminated string)
let name_bytes: Vec<u8> = self
.name
.iter()
.copied()
.take_while(|&byte| byte != 0)
.collect();
let rust_string = String::from_utf8(name_bytes).map_err(|e| Error::ParseError {
subject: "PolicyReference name".to_string(),
content: format!("Invalid UTF-8 in name: {}", e),
})?;
Ok(Path::new(&rust_string).to_owned())
}
}
impl Display for PolicyReference {
fn fmt(&self, f: &mut Formatter) -> Resfmt {
write!(
f,
"{} {}",
encode_hex(self.hash),
from_utf8(&self.name).expect("unable to convert name")
)
}
}

View File

@@ -17,7 +17,7 @@ Create an attestation measurement request
- **perform**
<ul>
Send the attestation request to the Ultravisor
Send the attestation request to the Ultravisor (s390x only.)
</ul>
- **verify**
@@ -150,11 +150,11 @@ Print help (see a summary with '-h').
### Synopsis
`pvattest perform [OPTIONS] [IN] [OUT]`
### Description
Send the attestation request to the Ultravisor. Run a measurement of this system
through /dev/uv. This device must be accessible and the attestation
Ultravisor facility must be present. The input must be an attestation request
created with pvattest create. Output will contain the original request and
the response from the Ultravisor.
Send the attestation request to the Ultravisor (s390x only.) Run a measurement
of this system through /dev/uv. This device must be accessible and the
attestation Ultravisor facility must be present. The input must be an
attestation request created with pvattest create. Output will contain the
original request and the response from the Ultravisor. Only available on s390x.
### Arguments
`<IN>`
@@ -171,6 +171,18 @@ Write the result to FILE.
### Options
`-i`, `--input <FILE>`
<ul>
Specify the request to be sent.
</ul>
`-o`, `--output <FILE>`
<ul>
Write the result to FILE.
</ul>
`-u`, `--user-data <File>`
<ul>
Provide up to 256 bytes of user input User-data is arbitrary user-defined data
@@ -256,7 +268,7 @@ Print help (see a summary with '-h').
## pvattest check
### Synopsis
`pvattest check [OPTIONS] <IN> <OUT>`
`pvattest check [OPTIONS] [IN] [OUT]`
### Description
Check if the attestation result matches defined policies. After the attestation
verification, check whether the attestation result complies with user-defined
@@ -277,6 +289,18 @@ Specify the output file for the check result.
### Options
`-i`, `--input <FILE>`
<ul>
Specify the attestation response to check whether the policies are validated.
</ul>
`-o`, `--output <FILE>`
<ul>
Specify the output file for the check result.
</ul>
`--format <FORMAT>`
<ul>
Define the output format.

View File

@@ -3,7 +3,7 @@
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH "PVATTEST-CHECK" "1" "2025-03-12" "s390-tools" "Attestation Manual"
.TH "PVATTEST-CHECK" "1" "2026-05-19" "s390-tools" "Attestation Manual"
.nh
.ad l
.SH NAME
@@ -11,7 +11,7 @@ pvattest-check \- Check if the attestation result matches defined policies
.SH SYNOPSIS
.nf
.fam C
pvattest check [OPTIONS] <IN> <OUT>
pvattest check [OPTIONS] [IN] [OUT]
.fam C
.fi
.SH DESCRIPTION
@@ -31,6 +31,18 @@ Specify the output file for the check result.
.RE
.RE
.PP
\-i, \-\-input <FILE>
.RS 4
Specify the attestation response to check whether the policies are validated.
.RE
.RE
.PP
\-o, \-\-output <FILE>
.RS 4
Specify the output file for the check result.
.RE
.RE
.PP
\-\-format <FORMAT>
.RS 4

View File

@@ -3,7 +3,7 @@
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH "PVATTEST-CREATE" "1" "2026-02-12" "s390-tools" "Attestation Manual"
.TH "PVATTEST-CREATE" "1" "2026-05-20" "s390-tools" "Attestation Manual"
.nh
.ad l
.SH NAME
@@ -21,6 +21,7 @@ Workstation. To avoid compromising the attestation do not publish the
attestation request protection key and shred it after verification. Every
\fBcreate\fR will generate a new, random protection key.
.SH OPTIONS
.PP
\-k, \-\-host\-key\-document <FILE>
.RS 4

View File

@@ -3,11 +3,11 @@
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH "PVATTEST-PERFORM" "1" "2025-03-12" "s390-tools" "Attestation Manual"
.TH "PVATTEST-PERFORM" "1" "2026-05-19" "s390-tools" "Attestation Manual"
.nh
.ad l
.SH NAME
pvattest-perform \- Send the attestation request to the Ultravisor
pvattest-perform \- Send the attestation request to the Ultravisor (s390x only.)
.SH SYNOPSIS
.nf
.fam C
@@ -18,7 +18,8 @@ pvattest perform [OPTIONS] [IN] [OUT]
Run a measurement of this system through /dev/uv. This device must be
accessible and the attestation Ultravisor facility must be present. The input
must be an attestation request created with pvattest create. Output will
contain the original request and the response from the Ultravisor.
contain the original request and the response from the Ultravisor. Only
available on s390x.
.SH OPTIONS
.PP
<IN>
@@ -33,6 +34,18 @@ Write the result to FILE.
.RE
.RE
.PP
\-i, \-\-input <FILE>
.RS 4
Specify the request to be sent.
.RE
.RE
.PP
\-o, \-\-output <FILE>
.RS 4
Write the result to FILE.
.RE
.RE
.PP
\-u, \-\-user\-data <File>
.RS 4

View File

@@ -3,7 +3,7 @@
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH "PVATTEST-VERIFY" "1" "2026-02-12" "s390-tools" "Attestation Manual"
.TH "PVATTEST-VERIFY" "1" "2026-05-20" "s390-tools" "Attestation Manual"
.nh
.ad l
.SH NAME
@@ -26,6 +26,7 @@ solely verifies that the Attestation measurement is correct. It does not check
for the content of additional data or user data. See `pvattest check` for policy
checks after you verified the Attestation measurement.
.SH OPTIONS
.PP
\-i, \-\-input <FILE>
.RS 4

View File

@@ -3,7 +3,7 @@
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH "PVATTEST" "1" "2026-02-12" "s390-tools" "Attestation Manual"
.TH "PVATTEST" "1" "2026-05-19" "s390-tools" "Attestation Manual"
.nh
.ad l
.SH NAME
@@ -29,7 +29,7 @@ Create an attestation measurement request
\fBpvattest\-perform(1)\fR
.RS 4
Send the attestation request to the Ultravisor
Send the attestation request to the Ultravisor (s390x only.)
.RE
.PP
@@ -47,6 +47,7 @@ Check if the attestation result matches defined policies
.RE
.SH OPTIONS
.PP
\-v, \-\-verbose
.RS 4

View File

@@ -35,12 +35,12 @@ pub enum Command {
/// shred it after verification. Every 'create' will generate a new, random protection key.
Create(Box<CreateAttOpt>),
/// Send the attestation request to the Ultravisor.
/// Send the attestation request to the Ultravisor (s390x only.)
///
/// Run a measurement of this system through /dev/uv. This device must be accessible and the
/// attestation Ultravisor facility must be present. The input must be an attestation request
/// created with pvattest create. Output will contain the original request and the response
/// from the Ultravisor.
/// from the Ultravisor. Only available on s390x.
Perform(PerformAttOpt),
/// Verify an attestation response.
@@ -110,28 +110,23 @@ pub enum AttAddFlags {
FirmwareState,
}
// all members s390x only
#[derive(Args, Debug)]
pub struct PerformAttOpt {
/// Specify the request to be sent.
#[cfg(target_arch = "s390x")]
#[arg(hide=true, short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
pub input: Option<String>,
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
input: Option<String>,
/// Specify the request to be sent.
#[cfg(target_arch = "s390x")]
#[arg(value_name = "IN", value_hint = ValueHint::FilePath, required_unless_present("input"), conflicts_with("input"))]
pub input_pos: Option<String>,
input_pos: Option<String>,
/// Write the result to FILE.
#[cfg(target_arch = "s390x")]
#[arg(hide=true, short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
pub output: Option<String>,
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
output: Option<String>,
/// Write the result to FILE.
#[arg(value_name = "OUT", value_hint = ValueHint::FilePath, required_unless_present("output"), conflicts_with("output"))]
#[cfg(target_arch = "s390x")]
pub output_pos: Option<String>,
output_pos: Option<String>,
/// Provide up to 256 bytes of user input
///
@@ -139,7 +134,7 @@ pub struct PerformAttOpt {
/// It is verified during the Attestation measurement verification.
/// May be any arbitrary data, as long as it is less or equal to 256 bytes
#[arg(short, long, value_name = "File", value_hint = ValueHint::FilePath,)]
pub user_data: Option<String>,
user_data: Option<String>,
}
#[cfg(target_arch = "s390x")]
@@ -222,12 +217,20 @@ pub enum OutputType {
#[derive(Args, Debug)]
pub struct CheckOpt {
/// Specify the attestation response to check whether the policies are validated.
#[arg(value_name = "IN", value_hint = ValueHint::FilePath,)]
pub input: PathBuf,
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
input: Option<PathBuf>,
/// Specify the attestation response to check whether the policies are validated.
#[arg(value_name = "IN", value_hint = ValueHint::FilePath, required_unless_present("input"), conflicts_with("input"))]
input_pos: Option<PathBuf>,
/// Specify the output file for the check result.
#[arg(value_name = "OUT", value_hint = ValueHint::FilePath,)]
pub output: PathBuf,
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
output: Option<PathBuf>,
/// Specify the output file for the check result.
#[arg(value_name = "OUT", value_hint = ValueHint::FilePath, required_unless_present("output"), conflicts_with("output"))]
output_pos: Option<PathBuf>,
/// Define the output format.
#[arg(long, value_enum, default_value_t)]
@@ -305,6 +308,30 @@ pub struct CheckOpt {
pub firmware_verify_url: Option<String>,
}
#[derive(Debug)]
pub struct CheckOptIO<'a> {
pub input: &'a PathBuf,
pub output: &'a PathBuf,
}
impl<'a> From<&'a CheckOpt> for CheckOptIO<'a> {
fn from(value: &'a CheckOpt) -> Self {
let input = match (&value.input, &value.input_pos) {
(None, Some(i)) => i,
(Some(i), None) => i,
(Some(_), Some(_)) => unreachable!(),
(None, None) => unreachable!(),
};
let output = match (&value.output, &value.output_pos) {
(None, Some(o)) => o,
(Some(o), None) => o,
(Some(_), Some(_)) => unreachable!(),
(None, None) => unreachable!(),
};
Self { input, output }
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
pub enum HostKeyCheckPolicy {
/// Check the host-key used for the attestation request.

View File

@@ -12,7 +12,12 @@ use self::{
secret_store::secret_store_check,
secret_store::SecretStoreCheck,
};
use crate::{additional::AttestationResult, cli::CheckOpt, exchange::ExchangeFormatResponse};
use crate::{
additional::AttestationResult,
cli::{CheckOpt, CheckOptIO},
exchange::ExchangeFormatResponse,
};
use anyhow::Result;
use log::{debug, info, warn};
use pv::{
@@ -104,7 +109,8 @@ pub struct CheckResult<'a> {
/// Perform the policy checks
pub fn check(opt: &CheckOpt) -> Result<ExitCode> {
let mut input = open_file(&opt.input)?;
let opt_io = CheckOptIO::from(opt);
let mut input = open_file(opt_io.input)?;
let inp = ExchangeFormatResponse::read(&mut input)?;
let auth = AttestationRequest::auth_bin(inp.arcb())?;
let att_res = AttestationResult::from_exchange(&inp, auth.flags())?;
@@ -139,7 +145,7 @@ pub fn check(opt: &CheckOpt) -> Result<ExitCode> {
};
debug!("res {res:?}");
let output = create_file(&opt.output)?;
let output = create_file(opt_io.output)?;
serde_yaml::to_writer(output, &res)?;
match res.successful {

View File

@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp. 2024
#![allow(unused)]
use anyhow::{anyhow, bail, Error, Result};
use pv::{assert_size, request::MagicValue, uv::AttestationCmd, uv::ConfigUid};
use std::{

View File

@@ -0,0 +1,31 @@
#!/bin/bash
# SPDX-License-Identifier: MIT
#
# Copyright IBM Corp.
set -eu
mntp="/boot"
block_dev="$(blkid -L boot)"
if [[ -z "${block_dev}" ]]; then
echo "Unable to find partition with label boot"
exit 1
elif [[ ! -b "${block_dev}" ]]; then
echo "Unable to find block device ${block_dev}"
exit 1
else
echo "Found block device ${block_dev}"
fi
if [[ ! -d "${mntp}" ]]; then
echo "Mountpoint ${mntp} does not exist, creating..."
mkdir "${mntp}"
else
echo "Mountpoint ${mntp} exists"
fi
echo "Mounting ${block_dev} to ${mntp}"
mount --options ro "${block_dev}" "${mntp}"
exit 0

View File

@@ -0,0 +1,84 @@
#!/bin/bash
# SPDX-License-Identifier: MIT
#
# Copyright IBM Corp.
# Called by dracut
check() {
# always include
return 0
}
# Called by dracut
depends() {
# We need systemd in the initramfs
echo systemd
echo systemd-udevd
echo crypt
echo dm
return 0
}
# Called by dracut
installkernel() {
# kernel modules needed for opening an encrypted rfs
hostonly='' instmods -c uvdevice
hostonly='' instmods -c paes_s390
hostonly='' instmods -c pkey_uv
hostonly='' instmods -c pkey_pckmo
hostonly='' instmods -c pkey
}
# Called by dracut
install() {
# shellcheck disable=SC2154
# moddir, systemdsystemunitdir, and initdir are provided by dracut
# Copy the units into the initramfs' systemd unit dir
inst_simple "$moddir/sel-ebc.target" \
"$systemdsystemunitdir/sel-ebc.target"
inst_simple "$moddir/sel-ebc-pvebc.service" \
"$systemdsystemunitdir/sel-ebc-pvebc.service"
inst_simple "$moddir/sel-ebc-paes-enforce.service" \
"$systemdsystemunitdir/sel-ebc-paes-enforce.service"
inst_simple "$moddir/sel-ebc-override-crypttab.service" \
"$systemdsystemunitdir/sel-ebc-override-crypttab.service"
inst_simple "$moddir/sel-ebc-boot-mount.service" \
"$systemdsystemunitdir/sel-ebc-boot-mount.service"
# already exisitng unit we depend on for kernel modules
inst_simple /usr/lib/systemd/system/systemd-modules-load.service \
"$systemdsystemunitdir/systemd-modules-load.service"
# wrapper for sel-ebc.service
inst_simple "$moddir/pvebc-wrapper.sh" \
"/etc/sel-ebc/pvebc-wrapper.sh"
# override crypttab
inst_simple "$moddir/override-crypttab.sh" \
"/etc/sel-ebc/override-crypttab.sh"
# mount boot partition to /boot
inst_simple "$moddir/boot-mount.sh" \
"/etc/sel-ebc/boot-mount.sh"
# install kernel module dependencies
inst_simple "$moddir/sel-ebc-modules.conf" \
"/usr/lib/modules-load.d/sel-ebc-modules.conf"
# copy main application
inst_binary "/usr/bin/pvebc"
inst_binary "/usr/bin/pvsecret"
inst_simple "$moddir/sel-ebc.crypttab" "/etc/sel-ebc/crypttab"
# Create the enablement symlinks in the image using host systemctl:
# shellcheck disable=SC2154
inst_dir "$initdir/etc/systemd/system"
systemctl --root "$initdir" --no-reload --quiet enable sel-ebc.target
systemctl --root "$initdir" --no-reload --quiet enable sel-ebc-pvebc.service
systemctl --root "$initdir" --no-reload --quiet enable sel-ebc-override-crypttab.service
systemctl --root "$initdir" --no-reload --quiet enable sel-ebc-paes-enforce.service
systemctl --root "$initdir" --no-reload --quiet enable systemd-modules-load.service
systemctl --root "$initdir" --no-reload --quiet enable sel-ebc-boot-mount.service
}

View File

@@ -0,0 +1,38 @@
#!/bin/bash
# SPDX-License-Identifier: MIT
#
# Copyright IBM Corp.
set -eu
IBM_RSRC_DIR="/etc/sel-ebc"
block_dev="$(blkid -L cryptroot)"
if [[ -z "${block_dev}" ]]; then
echo "Unable to find partition with label cryptroot"
exit 1
elif [[ ! -b "${block_dev}" ]]; then
echo "Unable to find block device ${block_dev}"
exit 1
else
echo "Found block device ${block_dev}"
fi
if [[ ! -f "${IBM_RSRC_DIR}/crypttab" ]]; then
echo "Error: source file $IBM_RSRC_DIR/crypttab does not exist"
exit 1
fi
# Unconditionally override /etc/crypttab to ensure correct EBC configuration
cp "${IBM_RSRC_DIR}/crypttab" "/etc/crypttab"
systemctl daemon-reload
udevadm trigger --subsystem-match=block --settle
if ! systemctl restart systemd-cryptsetup@cryptroot_mapper.service; then
systemctl status systemd-cryptsetup@cryptroot_mapper.service
exit 1
fi
exit 0

View File

@@ -0,0 +1,70 @@
#!/bin/bash
# SPDX-License-Identifier: MIT
#
# Copyright IBM Corp.
SYSFS=/sys/firmware/uv/prot_virt_guest
SICS=/boot/sics
EBC_TMPFS=/run/sel-ebc
TOC=toc.asr
ASR_NAME=luks-rfs-passphrase
# Early exit for non SEL guests
if [[ ! -e $SYSFS ]]; then
echo "Not running in a SEL guest."
exit 1
fi
if [[ $(cat $SYSFS) -ne 1 ]]; then
echo "Not running in a SEL guest."
exit 1
fi
echo "Running in SEL guest."
# Copy EBC resources from /boot/sics to tmpfs for security
# This protects against host injection attacks by moving resources to UV-protected RAM
echo "Copying EBC resources from $SICS to $EBC_TMPFS"
if ! mkdir -p "$EBC_TMPFS"; then
echo "Failed to create $EBC_TMPFS"
exit 1
fi
# Copy only .asr and .pol files
for file in "$SICS"/*.asr "$SICS"/*.pol; do
if [[ -f "$file" && ! -L "$file" ]]; then
cp "$file" "$EBC_TMPFS/" || {
echo "Failed to copy $file to $EBC_TMPFS"
exit 1
}
fi
done
# Verify toc.asr was copied
if [[ ! -f "$EBC_TMPFS/$TOC" ]]; then
echo "Error: $EBC_TMPFS/$TOC does not exist after copy"
exit 1
fi
# execute the actual tool with the copied toc.asr
pvebc --toc "$EBC_TMPFS/$TOC"
rc=$?
if [[ $rc -ne 0 ]]; then
echo "pvebc failed with rc=${rc}"
exit $rc
fi
# Retrieve and check for dummy LUKS passphrase
pvsecret retrieve --inform name -o "$EBC_TMPFS/$ASR_NAME" --outform bin "$ASR_NAME"
rc=$?
if [[ $rc -ne 0 ]]; then
echo "pvsecret failed with rc=${rc}"
exit $rc
fi
if [[ ! -f "$EBC_TMPFS/$ASR_NAME" ]]; then
echo "$EBC_TMPFS/$ASR_NAME does not exist"
exit 1
fi
chmod 400 "$EBC_TMPFS/$ASR_NAME"
exit $?

View File

@@ -0,0 +1,21 @@
[Unit]
Description=Mount a partition identified by label boot to /boot
# Ensure this runs before the handoff to the real root, if that's required:
Before=sel-ebc-pvebc.service
# Initramfs requirement
DefaultDependencies=no
# Make absolutely sure this only runs in initramfs
ConditionPathExists=/etc/initrd-release
ConditionKernelCommandLine=rd.sel-ebc
[Service]
Type=oneshot
ExecStart=/bin/bash /etc/sel-ebc/boot-mount.sh
RemainAfterExit=yes
# On failure immediately abort boot
FailureAction=poweroff-immediate
[Install]
RequiredBy=sel-ebc-pvebc.service

View File

@@ -0,0 +1,5 @@
uvdevice
paes_s390
pkey_uv
pkey_pckmo
pkey

View File

@@ -0,0 +1,35 @@
[Unit]
Description=Override crypttab
# boot partition contains SICS
# Loading of kernel modules is required which are needed for protected keys
Requires=systemd-modules-load.service
# Ensure this runs before the handoff to the real root, if that's required:
After=systemd-modules-load.service
Before=cryptsetup-pre.target
Before=cryptsetup.target
Before=systemd-cryptsetup@.service
Before=initrd-root-device.target
After=sel-ebc-pvebc.service
# Initramfs requirement
DefaultDependencies=no
# Make absolutely sure this only runs in initramfs
ConditionPathExists=/etc/initrd-release
ConditionKernelCommandLine=rd.sel-ebc
ConditionKernelCommandLine=root
[Service]
Type=oneshot
ExecStart=/bin/bash /etc/sel-ebc/override-crypttab.sh
RemainAfterExit=yes
# If pvebc fails immediately abort boot
FailureAction=poweroff-immediate
# boot partition is unencrypted and contains SICS so we can get logs out this way
# logs do not leek any sensitive information
StandardOutput=console
StandardError=console
[Install]
RequiredBy=sel-ebc.target

View File

@@ -0,0 +1,27 @@
[Unit]
Description=Enforce PAES encrypted root fs for SEL guests
# Ensure this runs before the handoff to the real root, if that's required:
After=cryptsetup.target
After=initrd-root-device.target
Before=sysroot.mount
# Initramfs requirement
DefaultDependencies=no
# Make absolutely sure this only runs in initramfs
ConditionPathExists=/etc/initrd-release
ConditionKernelCommandLine=rd.sel-ebc
ConditionKernelCommandLine=root
[Service]
Type=oneshot
ExecStart=bash -c 'dmsetup table /dev/disk/by-label/root | grep "paes-xts-plain64"'
FailureAction=poweroff-immediate
RemainAfterExit=yes
# logs do not leek any sensitive information
StandardOutput=console
StandardError=console
[Install]
RequiredBy=sel-ebc.target

View File

@@ -0,0 +1,36 @@
[Unit]
Description=Run pvebc during early boot to process SICS
# boot partition contains SICS
# Loading of kernel modules is required which are needed for protected keys
Requires=systemd-modules-load.service
Requires=sel-ebc-boot-mount.service
# Ensure this runs before the handoff to the real root, if that's required:
Before=initrd-root-device.target
Before=cryptsetup-pre.target
Before=cryptsetup.target
After=systemd-modules-load.service
After=sel-ebc-boot-mount.service
# Initramfs requirement
DefaultDependencies=no
# Make absolutely sure this only runs in initramfs
ConditionPathExists=/etc/initrd-release
AssertPathIsDirectory=/boot/sics
ConditionKernelCommandLine=rd.sel-ebc
[Service]
Type=oneshot
# execute pvebc
ExecStart=/bin/bash /etc/sel-ebc/pvebc-wrapper.sh
RemainAfterExit=yes
# If pvebc fails immediately abort boot
FailureAction=poweroff-immediate
# boot partition is unencrypted and contains SICS so we can get logs out this way
# logs do not leek any sensitive information
StandardOutput=console
StandardError=console
[Install]
RequiredBy=sel-ebc.target

View File

@@ -0,0 +1 @@
cryptroot_mapper /dev/disk/by-label/cryptroot /run/sel-ebc/luks-rfs-passphrase

View File

@@ -0,0 +1,27 @@
[Unit]
Description=Target unit for IBM Secure Execution for Linux early boot customization
# enable for use in initramfs
DefaultDependencies=no
# if not met start the target without starting its dependencies
ConditionPathExists=/etc/initrd-release
ConditionKernelCommandLine=rd.sel-ebc
# if not met the target is considered failed
# AssertVirtualization=kvm
# if target fails abort immediately
FailureAction=poweroff-immediate
Requires=sel-ebc-pvebc.service
Requires=sel-ebc-override-crypttab.service
Requires=sel-ebc-paes-enforce.service
# ordering dependencies
After=systemd-modules-load.service
Before=initrd-root-device.target
[Install]
# most basic hook to start target by default
WantedBy=initrd.target

22
rust/pvebc/Cargo.toml Normal file
View File

@@ -0,0 +1,22 @@
[package]
name = "pvebc"
version = "0.12.0"
edition.workspace = true
license.workspace = true
rust-version.workspace = true
[dependencies]
sha2 = "0.10"
hex = "0.4"
clap = { version = "4.5", features = ["derive"] }
pv_core = { path = "../pv_core" , package = "s390_pv_core" }
utils = { path = "../utils" }
anyhow = { version = "1.0.95", features = ["std"] }
zerocopy = { version = "0.8.27", features = ["derive"] }
[build-dependencies]
clap = { version ="4.5", features = ["derive"]}
clap_complete = "4.5"
[lints]
workspace = true

165
rust/pvebc/man/pvebc.1 Normal file
View File

@@ -0,0 +1,165 @@
.\" Copyright IBM Corp.
.\" s390-tools is free software; you can redistribute it and/or modify
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH "PVEBC" "1" "2026-03-24" "s390-tools" "EBC Management Manual"
.nh
.ad l
.SH NAME
pvebc \- Protected Virtualization Early Boot Customization Tool
.SH SYNOPSIS
.nf
.fam C
pvebc [OPTIONS] \-\-toc <FILE>
.fam C
.fi
.SH DESCRIPTION
Use the \fBpvebc\fR tool to process add-secret request files (\fBtoc.asr\fR)
that define the root of early boot customization (EBC) resources for
IBM Secure Execution for Linux (SEL) guests. The tool validates the
integrity and completeness of add-secret request (ASR) files using
cryptographic verification to prevent tampering during transmission
over unsecured channels.
The tool operates on a structure consisting of three types of files:
.RS 4
\- \fBtoc.asr\fP: The root add\-secret request file that references the table of contents (TOC policy).
\- \fBtoc.pol\fP: The table of contents policy file that contains a list of AES\-GCM authentication tags (MAC tags)
\- \fBASR files\fP: Individual add-secret request files to be added to the guest
.RE
The integrity protection mechanism works as follows:
.RS 4
.IP "1." 3
Each add-secret request file includes an AES\-GCM authentication tag (last 16 bytes), which provides integrity
protection for the file.
.IP "2." 3
The toc.pol file lists the expected message authentication code (MAC) tags of all add-secret request files.
.IP "3." 3
The toc.asr file contains a cryptographically protected reference to toc.pol, consisting
of the relative file path and a SHA\-512 hash of the policy file.
.IP "4." 3
The AES\-GCM authentication tag of toc.asr protects the integrity of this reference.
.RE
This structure prevents attackers from:
.RS 4
\- Removing add-secret request files from the set
\- Inserting unauthorized add-secret request files
\- Modifying existing add-secret request files
\- Altering the policy file
.RE
\fBpvebc\fR validates the entire chain of trust by:
.RS 4
\- Verifying that the SHA\-512 hash of toc.pol matches the reference stored in toc.asr
\- Checking that all MAC tags listed in toc.pol correspond to existing add-secret request files
\- Ensuring that all add-secret request files are present and unmodified
.RE
The tool can run in one of two modes:
.RS 4
\- \fBNormal mode\fP: Validates add\-secret requests and adds the defined secrets to the SEL guest (z/Architecture only)
\- \fBDry\-run mode\fP: Validates the request structure without adding secrets; useful for verification on non\-SEL systems
.RE
.SH OPTIONS
.PP
\-t, \-\-toc <FILE>
.RS 4
Specify the table\-of\-contents add\-secret request file toc.asr, which serves as the root of the EBC
resources. This file must contain a reference to toc.pol in its user data field,
as generated by \fBpvsecret\fR with the \fB\-\-policy\fR option. The toc.asr
file cryptographically links to the policy file by using a relative path and
SHA\-512 hash, ensuring the integrity of the complete EBC structure.
.RE
.RE
.PP
\-\-dry\-run
.RS 4
Validate the EBC structure without adding the add\-secret requests to the
ultravisor. Use this option to verify the integrity of the generated
policy file and the links between add\-secret request files and the policy.
This mode can be run on non\-SEL guests to validate the
structure before deployment. When \fB\-\-dry\-run\fR is specified, the tool
performs all cryptographic verifications but skips the actual addition of
secrets to the ultravisor secret store.
.RE
.RE
.PP
\-\-version
.RS 4
Print version information and exit.
.RE
.RE
.PP
\-h, \-\-help
.RS 4
Print help information.
.RE
.RE
.SH FILES
.PP
The \fBpvebc\fR tool operates on the following file types (actual names may
differ):
.PP
\fBtoc.asr\fR
.RS 4
The root add\-secret request file that contains a reference to the table\-of\-content \fBtoc.pol\fR in its
user data field. This file is generated by using \fBpvsecret create\fR with the
\fB\-\-policy\fR option.
.RE
.PP
\fBtoc.pol\fR
.RS 4
The policy file containing a newline\-separated list of AES\-GCM authentication
tags (MAC tags) in hexadecimal format. Each entry corresponds to one
add\-secret request file.
This file is generated by using \fBpvsecret create\fR with the
\fB\-\-toc\-policy\fR option.
.RE
.PP
\fB*.asr\fR
.RS 4
Individual add\-secret request files that contain the actual secrets to be added to
the SEL guest. Each add\-secret request file includes an AES\-GCM authentication tag (the last 16 bytes), which
provides integrity protection.
.RE
.SH EXIT STATUS
.PP
\fBpvebc\fR returns the following exit codes:
.PP
\fB0\fR
.RS 4
Success. All validations passed and secrets were added (if not in dry\-run mode).
.RE
.PP
\fB1\fR
.RS 4
Failure. An error occurred during validation or secret addition. Error details
are printed to stderr.
.RE
.SH NOTES
.PP
\- All file paths in a policy reference must be relative to the directory
that contains the referencing file.
.PP
\- On z/Architecture systems, the tool requires access to the ultravisor device
(\fB/dev/uv\fR) to add secrets.
.PP
.SH "SEE ALSO"
.sp
\fBpvsecret\fR(1), \fBpvsecret\-create\fR(1), \fBpvsecret\-add\fR(1)

39
rust/pvebc/src/cli.rs Normal file
View File

@@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp.
use std::{path::PathBuf, sync::OnceLock};
use clap::{ArgAction, Parser, ValueHint};
static VERSION: OnceLock<String> = OnceLock::new();
/// The pvebc command processes an AddSecretRequest file (toc.asr) that defines the root of EBC
/// resources. It validates references to the associated toc.pol policy and manages their addition,
/// with options for verification and dry-run execution.
#[derive(Parser)]
#[command(long_version=ver(), disable_version_flag(true))]
pub struct Cli {
/// Print version information and exit.
#[arg(long, action=ArgAction::Version)]
version: (),
/// Specifies the toc.asr which is the root of the EBC resources
///
/// Specify the add-secret request file toc.asr that serves as the root of the EBC resources.
/// Its user data must contain a reference to toc.pol as generated by pvsecret with the --policy
/// option.
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath)]
pub toc: PathBuf,
/// Prevents adding of the AddSecretRequest
///
/// Do not add the AddSecretRequest. Use this option to validate a generated policy. It can be
/// run on a non-SEL guest to verify ASR-to-policy links and the associated policy toc.pol.
#[arg(long)]
pub dry_run: bool,
}
fn ver() -> &'static str {
VERSION.get_or_init(|| utils::tools_version_fmt!(2026))
}

View File

@@ -0,0 +1,54 @@
// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp.
use anyhow::{bail, Context, Result};
use pv_core::misc::open_file;
use std::{io::Read, path::Path};
/// Length of the MAC tag in bytes (last 16 bytes of AddSecretRequest files)
pub const MAC_TAG_LEN: usize = 16;
/// Opens a file and returns a boxed reader
pub fn get_reader_from_filepath<P: AsRef<Path>>(filepath: P) -> Result<Box<dyn Read>> {
Ok(Box::new(open_file(filepath)?))
}
/// Get reader from &Path with additional context on error
pub fn get_reader(filepath: &Path) -> Result<Box<dyn Read>> {
get_reader_from_filepath(filepath)
.with_context(|| format!("unable to get reader from {:?}", filepath))
}
/// Read all data from a reader into a Vec<u8>
pub fn get_data(rd_in: &mut Box<dyn Read>) -> Result<Vec<u8>> {
let mut data_in = Vec::new();
rd_in
.read_to_end(&mut data_in)
.context("Cannot read input file")?;
Ok(data_in)
}
/// Extract the MAC tag (last 16 bytes) from an AddSecretRequest file
///
/// # Errors
///
/// Returns an error if:
/// - The file cannot be read
/// - The file is smaller than MAC_TAG_LEN bytes
pub fn get_mac_tag(filepath: &Path) -> Result<Vec<u8>> {
let mut rd_in = get_reader(filepath)?;
let data_in = get_data(&mut rd_in)?;
if data_in.len() < MAC_TAG_LEN {
bail!(
"File {:?} too small to contain MAC tag (expected at least {} bytes, got {})",
filepath,
MAC_TAG_LEN,
data_in.len()
);
}
Ok(data_in[data_in.len() - MAC_TAG_LEN..].to_vec())
}

369
rust/pvebc/src/main.rs Normal file
View File

@@ -0,0 +1,369 @@
// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp.
//! # pvebc - Protected Virtualization Early Boot Customization Tool
//!
//! This tool processes AddSecretRequest files (toc.asr) that define the root of EBC
//! (Early Boot Customization) resources. It validates references to associated
//! toc.pol policies and manages their addition to the system.
//!
//! ## Features
//!
//! - Validates AddSecretRequest files and their associated policies
//! - Verifies cryptographic hashes of policy files using SHA-256
//! - Supports dry-run mode for validation without system changes
//! - MAC tag validation for AddSecretRequest files
#![allow(missing_docs)]
mod cli;
mod ebc_utils;
#[cfg(target_arch = "s390x")]
use pv_core::uv::{AddCmd, UvDevice};
#[cfg(target_arch = "s390x")]
use utils::get_reader_from_cli_file_arg;
use anyhow::{bail, Context, Error, Result};
use clap::Parser;
use pv_core::{
misc::{decode_hex, encode_hex},
PolicyReference,
};
use std::{
fs::{self, File},
io::{BufRead, Read},
path::{Path, PathBuf},
process::ExitCode,
str::from_utf8,
};
// Don't use openssl here because this tool is intended to run in the initramfs
// phase of the boot and there we don't want to dynamically link against a C lib
use sha2::{self, Digest};
use zerocopy::TryFromBytes;
use crate::cli::Cli;
use crate::ebc_utils::{get_data, get_mac_tag, get_reader};
/// Offset in bytes where user data starts in an ASRCB v1 structure
const V1_USER_DATA_OFFS: usize = 536;
/// Size in bytes of the user data field in an ASRCB
const USER_DATA_SIZE: usize = 512;
/// Validates and resolves a policy name relative to a base directory
///
/// # Errors
/// Returns an error if path traversal is detected or the resolved path
/// is outside the base directory
fn validate_and_resolve_policy_path(base: &Path, name: &str) -> Result<PathBuf> {
// Validate path to prevent directory traversal
if name.contains("..") || name.starts_with('/') {
bail!("Invalid policy name: path traversal detected in '{}'", name);
}
let resolved = base.join(name);
// Ensure the resulting path is within the expected directory
if !resolved.starts_with(base) {
bail!(
"Policy path '{}' is outside the expected directory",
resolved.display()
);
}
Ok(resolved)
}
/// Extracts and validates the policy name from a PolicyReference
///
/// # Errors
/// Returns an error if the policy name contains invalid UTF-8 or is empty
fn extract_policy_name(policy_ref: &PolicyReference) -> Result<String> {
let name = from_utf8(&policy_ref.name)
.context("Policy name contains invalid UTF-8")?
.trim_matches('\0')
.to_string();
if name.is_empty() {
bail!("Policy name is empty");
}
Ok(name)
}
/// Computes the SHA-256 hash of data from a reader.
///
/// Reads data from the provided reader in 4096-byte chunks and computes
/// the SHA-256 hash of the entire content.
///
/// # Parameters
///
/// * `r` - A reader providing the data to hash
///
/// # Returns
///
/// Returns a `Vec<u8>` containing the 32-byte SHA-256 hash, or an error
/// if reading fails.
///
/// # Errors
///
/// Returns an error if reading from the reader fails.
pub fn sha256_hash<R: Read>(mut r: R) -> Result<Vec<u8>, Error> {
let mut hasher = sha2::Sha256::new();
let mut buf: [u8; 4096] = [0; 4096];
loop {
let read = r.read(&mut buf)?;
if read == 0 {
break;
}
hasher.update(&buf[..read]);
}
Ok(hasher.finalize().to_vec())
}
/// Extract the user data from an ASRCB
///
/// # Errors
///
/// Returns an error if the ASRCB is too small to contain user data
fn get_user_data(asrcb: &[u8]) -> Result<Option<Vec<u8>>> {
if asrcb.len() < V1_USER_DATA_OFFS + USER_DATA_SIZE {
bail!(
"ASRCB too small (expected at least {} bytes, got {})",
V1_USER_DATA_OFFS + USER_DATA_SIZE,
asrcb.len()
);
}
let user_data = &asrcb[V1_USER_DATA_OFFS..V1_USER_DATA_OFFS + USER_DATA_SIZE];
Ok(Some(user_data.to_vec()))
}
/// Get user data from AddSecretRequest
fn verify_user_data(filepath: &Path) -> Result<Option<Vec<u8>>> {
let mut rd_in = get_reader(filepath)?;
let data_in = get_data(&mut rd_in)?;
get_user_data(&data_in).context("Could not verify the Add-secret request")
}
/// Adds the given AddSecretRequest (if dryrun == false) and parses the contained user data
///
/// # Returns
///
/// On Success returns the PolicyReference parsed from the given AddSecretRequest
///
/// # Errors
///
/// returns an error if
/// - unable to open UvDevice
/// - reader from path fails
/// - adding of ASR fails
/// - verify_user_data fails
/// - unable to convert user data to PolicyReference
fn asr_to_pol_ref(filepath: &Path, dryrun: bool) -> Result<Option<PolicyReference>> {
print!("Add-Secret-Request: \"{}\"", filepath.display());
if !dryrun {
#[cfg(target_arch = "s390x")]
{
let uv = UvDevice::open()?;
let mut rd_in = get_reader_from_cli_file_arg(filepath)?;
let mut cmd = AddCmd::new(&mut rd_in)
.context(format!("Processing input file {:?}", filepath.to_str()))?;
uv.send_cmd(&mut cmd)?;
println!();
}
#[cfg(not(target_arch = "s390x"))]
{
println!(" (skip adding: not running on s390x architecture)");
}
} else {
println!(" (skip adding: dry-run mode)");
}
Ok(match verify_user_data(filepath)? {
Some(ud) => {
let ret = PolicyReference::try_read_from_bytes(&ud).map_err(|e| {
anyhow::anyhow!("Failed to parse PolicyReference from user data: {:?}", e)
})?;
println!(" Reference: {}", ret);
Some(ret)
}
None => None,
})
}
/// Read the mac tag list of the toc policy, parse and verify every tag
fn execute_toc_pol(path: &Path, toc_pol_ref: PolicyReference) -> Result<Vec<PathBuf>> {
let name = extract_policy_name(&toc_pol_ref)?;
let toc_path = validate_and_resolve_policy_path(path, &name)?;
let mut ret: Vec<PathBuf> = Vec::new();
let mut rd_in = get_reader(&toc_path)?;
let data_in = get_data(&mut rd_in)?;
let macs = data_in.lines();
let base = get_base_dir(&toc_path);
println!("Mac tags in {:?}:", toc_path);
for mac in macs {
let mut mac_tag = Vec::new();
let mac_tag_ref = match mac {
Ok(s) => s,
_ => continue,
};
print!(" {}", mac_tag_ref);
let entries = fs::read_dir(base)?;
for entry in entries {
let path = entry?;
let filepath = path.path();
let ext = match filepath.extension() {
Some(e) => e,
None => continue,
};
if ext == "asr" {
mac_tag = get_mac_tag(filepath.as_path())?;
if mac_tag == decode_hex(&mac_tag_ref)? {
println!(" -> {}", filepath.display());
ret.push(filepath.clone());
break;
}
}
}
if mac_tag != decode_hex(&mac_tag_ref)? {
bail!(
"No ASR with mac tag \"{}\" found in {:?}",
mac_tag_ref,
base
);
}
}
println!();
Ok(ret)
}
/// Checks whether the given hash in polref matches the actual hash of the referenced file
fn verify_policy(basename: &Path, polref: PolicyReference) -> Result<()> {
let name = extract_policy_name(&polref)?;
let filepath = validate_and_resolve_policy_path(basename, &name)?;
println!("Verify \"{}\"", filepath.display());
println!(" Referenced: {}", encode_hex(polref.hash));
let f = File::open(filepath.as_path())?;
let check_hash = sha256_hash(f)?;
println!(" Calculated: {}", encode_hex(&check_hash));
if check_hash != polref.hash {
bail!(
"{:?} ({}) does not match expected hash ({})",
filepath,
encode_hex(&check_hash),
encode_hex(polref.hash)
);
}
Ok(())
}
/// For every AddSecretRequest find the corresponding policy
fn execute_asrs(asrs: Vec<PathBuf>, dryrun: bool) -> Result<()> {
// loop over ASRs
for asr in asrs {
// get the referenced policy
let pol_ref = match asr_to_pol_ref(asr.as_path(), dryrun)? {
Some(pr) => pr,
None => continue,
};
if pol_ref.hash.iter().all(|&b| b == 0) {
continue;
}
let base = get_base_dir(asr.as_path());
let name = extract_policy_name(&pol_ref)?;
let _pol_path = validate_and_resolve_policy_path(base, &name)?;
// verify the integrity of the referenced policy
verify_policy(base, pol_ref)?;
}
Ok(())
}
/// Get the parent directory of the given file
fn get_base_dir(filepath: &Path) -> &Path {
match filepath.parent() {
Some(p) => p,
None => Path::new(""),
}
}
/// Print a given error and return the failure exit code
fn error_to_exit_code(err: Error) -> ExitCode {
eprintln!("Error: {}", err);
ExitCode::FAILURE
}
/// main function
pub fn main() -> ExitCode {
let opt: Cli = Cli::parse();
let dryrun = opt.dry_run;
if dryrun {
println!("Dry-run mode detected, skipping secret addition");
println!();
}
// get toc asr filepath - wrapper script has already copied files to tmpfs
let toc_asr = &opt.toc;
let basename = match toc_asr.parent() {
Some(p) => p,
None => {
return error_to_exit_code(Error::msg("Unable to get directory from specified path"))
}
};
// get the PolicyReference from toc.asr to toc.pol
let toc_pol = match asr_to_pol_ref(toc_asr, dryrun) {
Ok(o) => match o {
Some(r) => r,
None => {
return error_to_exit_code(Error::msg(
"There is no linked policy in the supplied ASR",
))
}
},
Err(e) => return error_to_exit_code(e),
};
// verify the integrity on the referenced toc.pol
if let Err(e) = verify_policy(basename, toc_pol) {
return error_to_exit_code(e);
}
println!();
// get and verify ASRs from mac list of toc policy
let asr_list = match execute_toc_pol(basename, toc_pol) {
Ok(v) => v,
Err(e) => return error_to_exit_code(e),
};
// execute ASRs
if let Err(e) = execute_asrs(asr_list, dryrun) {
return error_to_exit_code(e);
}
ExitCode::SUCCESS
}

View File

@@ -28,7 +28,7 @@ use std::{fmt::Display, fmt::LowerHex, marker::PhantomData, mem::size_of};
use pv::misc::{Flags, Msb0Flags64};
pub trait IntoEnumIterator {
pub trait IntoEnumIterator: Sized {
/// Returns an iterator over all variants of this enum.
fn iter() -> impl Iterator<Item = Self>;
}

View File

@@ -98,7 +98,7 @@ pub mod serde_base64 {
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
BASE64_STANDARD.decode(&s).map_err(serde::de::Error::custom)
BASE64_STANDARD.decode(s).map_err(serde::de::Error::custom)
}
}
@@ -124,7 +124,7 @@ pub mod serde_base64_array {
{
let s = String::deserialize(deserializer)?;
let decoded = BASE64_STANDARD
.decode(&s)
.decode(s)
.map_err(serde::de::Error::custom)?;
try_copy_slice_to_array(&decoded).map_err(serde::de::Error::custom)
}

View File

@@ -13,6 +13,7 @@ anyhow = { version = "1.0.95", features = ["std"] }
clap = { version ="4.5", features = ["derive", "wrap_help"]}
log = { version = "0.4.25", features = ["std", "release_max_level_debug"] }
serde_yaml = "0.9"
zerocopy = "0.8"
pv = { path = "../pv" , package = "s390_pv" }
utils = { path = "../utils"}

View File

@@ -253,6 +253,28 @@ Optional. No user-data by default.
</ul>
`--policy <FILE>`
<ul>
Links an AddSecret-Request (ASR) to a policy file. This option embeds a
PolicyReference in the ASR user data field. The PolicyReference includes the
relative file path and the SHA512 hash of the policy file, allowing the
policys integrity to be verified.
This option conflicts with --user-data, because both options use the same user
data field in the ASR structure.
</ul>
`--toc-policy <FILE>`
<ul>
Adds the AESGCM authentication tag to a TOC policy file. This option appends
the AESGCM authentication tag to the specified TOC policy file. This allows
the TOC policy to maintain a list of all ASR MAC tags for completeness
verification during boot. During verification, the TOC checks the MAC tags
against this list to ensure that all expected ASRs are present and unmodified.
</ul>
`--user-sign-key <FILE>`
<ul>
Use the content of FILE as user signing key. Adds a signature calculated from
@@ -407,14 +429,14 @@ Print help (see a summary with '-h').
## pvsecret add
### Synopsis
`pvsecret add [OPTIONS] <FILE>`
`pvsecret add [OPTIONS] [INPUT]`
### Description
Submit an add-secret request to the Ultravisor (s390x only). Perform an
add-secret request using a previously generated add-secret request. Only
available on s390x.
### Arguments
`<FILE>`
`<INPUT>`
<ul>
Specify the request to be sent.
</ul>
@@ -422,6 +444,12 @@ Specify the request to be sent.
### Options
`-i`, `--input <FILE>`
<ul>
Specify the request to be sent.
</ul>
`-f`, `--force`
<ul>
Force the addition of add-secret requests. Add an add-secret request even if
@@ -445,22 +473,27 @@ fail. Only available on s390x.
## pvsecret list
### Synopsis
`pvsecret list [OPTIONS] [FILE]`
`pvsecret list [OPTIONS] [OUTPUT]`
### Description
List all ultravisor secrets (s390x only). Lists the IDs of all non-null secrets
currently stored in the ultravisor for the currently running IBM Secure
Execution guest. Only available on s390x.
### Arguments
`<FILE>`
`<OUTPUT>`
<ul>
Store the result in FILE.
Default value: '-'
</ul>
### Options
`-o`, `--output <FILE>`
<ul>
Store the result in FILE.
</ul>
`--format <FORMAT>`
<ul>
Define the output format of the list.
@@ -480,7 +513,7 @@ Print help (see a summary with '-h').
## pvsecret verify
### Synopsis
`pvsecret verify [OPTIONS] <FILE>`
`pvsecret verify [OPTIONS] [INPUT] [OUTPUT]`
### Description
Verifies that the given request is an Add-Secret request by testing for some
values to be present. If the request contains signed user-data, the signature
@@ -520,14 +553,27 @@ The verification process works as follows:
### Arguments
`<FILE>`
`<INPUT>`
<ul>
Specify the request to be checked.
</ul>
`<OUTPUT>`
<ul>
Store the result in FILE If the request contained abirtary user-data the output
contains this user-data with padded zeros if available.
</ul>
### Options
`-i`, `--input <FILE>`
<ul>
Specify the request to be checked.
</ul>
`--user-cert <FILE>`
<ul>
Certificate containing a public key used to verify the user data signature.
@@ -540,11 +586,10 @@ curve over a 521 bit prime field (secp521r1).
</ul>
`-o`, `--output <FILE>`
`-o`, `--output <OUTPUT>`
<ul>
Store the result in FILE If the request contained abirtary user-data the output
contains this user-data with padded zeros if available.
Default value: '-'
</ul>
@@ -556,13 +601,13 @@ Print help (see a summary with '-h').
## pvsecret retrieve
### Synopsis
`pvsecret retrieve [OPTIONS] <ID>`
`pvsecret retr [OPTIONS] <ID>`
`pvsecret retrieve [OPTIONS] [INPUT] [OUTPUT]`
`pvsecret retr [OPTIONS] [INPUT] [OUTPUT]`
### Description
Retrieve a secret from the UV secret store (s390x only)
### Arguments
`<ID>`
`<INPUT>`
<ul>
Specify the secret ID to be retrieved. Input type depends on '--inform'. If
`yaml` (default) is specified, it must be a yaml created by the create
@@ -574,12 +619,29 @@ retrieved.
</ul>
`<OUTPUT>`
<ul>
Specify the output path to place the secret value.
</ul>
### Options
`-i`, `--input <ID>`
<ul>
Specify the secret ID to be retrieved. Input type depends on '--inform'. If
`yaml` (default) is specified, it must be a yaml created by the create
subcommand of this tool. If `hex` is specified, it must be a 32 byte handle
encodes in hexadecimal. Leading zeros are required. If there are multiple
secrets in the store with the same Id there are no guarantees on which specific
secret is retrieved. Use --inform=idx to make sure a specific secret is
retrieved.
</ul>
`-o`, `--output <FILE>`
<ul>
Specify the output path to place the secret value.
Default value: '-'
</ul>

View File

@@ -3,7 +3,7 @@
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH "PVSECRET-ADD" "1" "2026-02-12" "s390-tools" "UV\-Secret Manual"
.TH "PVSECRET-ADD" "1" "2026-05-21" "s390-tools" "UV\-Secret Manual"
.nh
.ad l
.SH NAME
@@ -11,7 +11,7 @@ pvsecret-add \- Submit an add-secret request to the Ultravisor (s390x only)
.SH SYNOPSIS
.nf
.fam C
pvsecret add [OPTIONS] <FILE>
pvsecret add [OPTIONS] [INPUT]
.fam C
.fi
.SH DESCRIPTION
@@ -19,12 +19,18 @@ Perform an add\-secret request using a previously generated add\-secret request.
Only available on s390x.
.SH OPTIONS
.PP
<FILE>
<INPUT>
.RS 4
Specify the request to be sent.
.RE
.RE
.PP
\-i, \-\-input <FILE>
.RS 4
Specify the request to be sent.
.RE
.RE
.PP
\-f, \-\-force
.RS 4

View File

@@ -3,7 +3,7 @@
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH "PVSECRET-CREATE-RETRIEVABLE" "1" "2026-02-12" "s390-tools" "UV\-Secret Manual"
.TH "PVSECRET-CREATE-RETRIEVABLE" "1" "2026-05-20" "s390-tools" "UV\-Secret Manual"
.nh
.ad l
.SH NAME
@@ -29,30 +29,30 @@ the following curves: secp256r1, secp384r1, secp521r1, ed25519, or ed448.
\fBHMAC\-SHA preprocessing\fP
.RS 2
The \fBHMAC\-SHA\fP key supplied in the plain bytes file is the key \fBK_0\fP
as of \fBFIPS\-198\-1\fP, i.e. the key \fBK\fP after any necessary
pre\-processing. The pre\-processing must be performed by the user prior to
creating the retrievable secret.
.PP Pre\-processing means that if the key \fBK\fP is shorter than the block
size of the to\-be\-used HMAC digest, then the key must be padded with binary
zeros to the right up to the block size. The block size of SHA\-224 and
SHA\-256 is 512 bits (64 bytes) and the bock size of SHA\-384 and SHA\-512 is
1024 bits (128 bytes). Such padding can for example be achieved by using the
\fBtruncate\fP command with the desired size in bytes, e.g. \fB'truncate
\-\-size 64 <key\-file>'\fP for creating a \fBK_0\fP key for HMAC\-SHA\-224
and HMAC\-SHA\-256.
The \fBHMAC\-SHA\fP key supplied in the plain bytes file is the key \fBK_0\fP as
of \fBFIPS\-198\-1\fP, i.e. the key \fBK\fP after any necessary pre\-processing.
The pre\-processing must be performed by the user prior to creating the
retrievable secret.
.PP Pre\-processing means that if the key \fBK\fP is shorter than the block size
of the to\-be\-used HMAC digest, then the key must be padded with binary zeros
to the right up to the block size. The block size of SHA\-224 and SHA\-256 is
512 bits (64 bytes) and the bock size of SHA\-384 and SHA\-512 is 1024 bits (128
bytes). Such padding can for example be achieved by using the \fBtruncate\fP
command with the desired size in bytes, e.g. \fB'truncate \-\-size 64
<key\-file>'\fP for creating a \fBK_0\fP key for HMAC\-SHA\-224 and
HMAC\-SHA\-256.
.PP
In case key \fBK\fP is longer than the block size of the to\-be\-used HMAC
digest, then key \fBK\fP must first be hashed with the to\-be\-used HMAC
digest, and the result must then be padded with binary zeros to the right up to
the block size of the digest. This can be achieved by using the following
OpenSSL command followed by the \fBtruncate\fP command: \fB'openssl sha256
\-binary \-out <key2\-file> <key\-file>'\fP and then \fB'truncate \-\-size
64 <key2\-file>'\fP for creating a \fBK_0\fP key for HMAC\-SHA\-256.
digest, then key \fBK\fP must first be hashed with the to\-be\-used HMAC digest,
and the result must then be padded with binary zeros to the right up to the
block size of the digest. This can be achieved by using the following OpenSSL
command followed by the \fBtruncate\fP command: \fB'openssl sha256 \-binary
\-out <key2\-file> <key\-file>'\fP and then \fB'truncate \-\-size 64
<key2\-file>'\fP for creating a \fBK_0\fP key for HMAC\-SHA\-256.
.PP
\fBATTENTION:\fP The digest used for hashing the key \fBK\fP must be the exact
same as the later to\-be\-used HMAC digest! If the pre\-processing and the
HMAC calculation use different digests, then a wrong MAC is calculated!
same as the later to\-be\-used HMAC digest! If the pre\-processing and the HMAC
calculation use different digests, then a wrong MAC is calculated!
.RE
.SH OPTIONS

View File

@@ -3,7 +3,7 @@
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH "PVSECRET-CREATE-UPDATE-CCK" "1" "2026-02-12" "s390-tools" "UV\-Secret Manual"
.TH "PVSECRET-CREATE-UPDATE-CCK" "1" "2026-05-20" "s390-tools" "UV\-Secret Manual"
.nh
.ad l
.SH NAME
@@ -18,6 +18,7 @@ pvsecret create cck \-\-secret <CCK\-FILE>
.SH DESCRIPTION
Insert a customer communication key into a guest.
.SH OPTIONS
.PP
\-\-secret <CCK\-FILE>
.RS 4

Some files were not shown because too many files have changed in this diff Show More