From 0054c9c63bd9d090a4b3df0899f67067e2f2e98f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Hor=C3=A1k?= Date: Wed, 3 Jun 2026 12:25:57 +0200 Subject: [PATCH] - rebased to 2.42.1 (RHEL-174898) - hyptop: Backward compatibility options causes other issues (RHEL-166157) - zipl/boot: Fix stage3 secure boot trailer placement (RHEL-170707) - SEL-EBC: instrumentation of an SEL initramfs to support early boot customization (RHEL-136433) - SEL-EBC: tool to build basic SEL-qcow2 image supporting early boot customization (RHEL-136435) - KVM: Enhance pvimg info command to display additional SE image information (RHEL-73136) - Resolves: RHEL-174898 RHEL-166157 RHEL-170707 RHEL-136433 RHEL-136435 RHEL-73136 --- s390utils-tape-revert.patch | 1733 +++++++++++++++++++++++++++++++++++ s390utils.spec | 23 +- sources | 4 +- 3 files changed, 1756 insertions(+), 4 deletions(-) create mode 100644 s390utils-tape-revert.patch diff --git a/s390utils-tape-revert.patch b/s390utils-tape-revert.patch new file mode 100644 index 0000000..764c822 --- /dev/null +++ b/s390utils-tape-revert.patch @@ -0,0 +1,1733 @@ +From 89134a8f40d328a2c7cfc70f0470ae1c1354b036 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Hor=C3=A1k?= +Date: Tue, 2 Jun 2026 13:25:08 +0200 +Subject: [PATCH 1/7] Revert "zipl/man: Only mention 3490 tape devices" + +This reverts commit 075f7f71868be2b21fa6f6c49355db3df53c3926. +--- + zipl/man/zipl.8.in | 2 +- + zipl/man/zipl.conf.5.in | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/zipl/man/zipl.8.in b/zipl/man/zipl.8.in +index e7256ea5..1226d481 100644 +--- a/zipl/man/zipl.8.in ++++ b/zipl/man/zipl.8.in +@@ -258,7 +258,7 @@ or configuration section on the command line at the same time. + Install a system dump record on the device identified by DEVNODE. + Supported devices are DASD ECKD or FBA disk partitions, + device mapper multipath partitions of FCP attached SCSI disks, +-partitions of NVMe disks and IBM 3490 tape devices. ++partitions of NVMe disks and IBM 3480/3490/3590/3592 tape devices. + + For CCW-type DASD dump, zlib compression is used to compress the + dump data before writing it to the DASD ECKD partition. Zlib compression +diff --git a/zipl/man/zipl.conf.5.in b/zipl/man/zipl.conf.5.in +index 2c25fac8..8d8a0461 100644 +--- a/zipl/man/zipl.conf.5.in ++++ b/zipl/man/zipl.conf.5.in +@@ -372,7 +372,7 @@ indicates the menu name. + .B Configuration section: + .br + Specify a DASD partition, device mapper multipath partition device node of a +-SCSI disk, a NVMe partition or an IBM 3490 tape device on which to ++SCSI disk, a NVMe partition or an IBM 3480/3490/3590 tape device on which to + install a system dump record. Once a device prepared in such a way + is booted, the current system status is written in a raw format to that device + and can later be retrieved using the +@@ -596,7 +596,7 @@ file. + .IP + .B Configuration section: + .br +-Specify a IBM 3490 tape device on which to install a boot record. ++Specify a IBM 3480/3490/3590 tape device on which to install a boot record. + + This option cannot be used together with + .BR 'target' ", " +-- +2.54.0 + + +From e48f23e21c46b4577c1c23063fbe5ba2cf369144 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Hor=C3=A1k?= +Date: Tue, 2 Jun 2026 13:25:38 +0200 +Subject: [PATCH 2/7] Revert "zipl/tape2dump: Remove check for data compaction + support" + +This reverts commit 5af1e8cc693ef9be4a8e7efb23b9fa9a4b2e0d6d. +--- + zipl/boot/tape2dump.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/zipl/boot/tape2dump.c b/zipl/boot/tape2dump.c +index 3cb69f45..41136160 100644 +--- a/zipl/boot/tape2dump.c ++++ b/zipl/boot/tape2dump.c +@@ -25,6 +25,7 @@ + #define WRITE_CMD 0x01 /* Write block */ + #define SENSE_OVERRUN 0x04 /* Sense */ + #define WRITETAPEMARK 0x1f /* Write Tape Mark */ ++#define READ_DEV_CHAR 0x64 /* Read device characteristics */ + #define MODE_SET_DB 0xdb /* Mode set */ + + /* +@@ -104,12 +105,27 @@ static void start_ccw(uint8_t code, uint8_t flags, uint16_t count, void *cda) + } + + /* +- * Enable data compaction ++ * Read tape device characteristics to find out if IDRC compression can be used + */ + static void setup_idrc_compression(void) + { +- ccw_init(&ccw_program.compress, MODE_SET_DB, CCW_FLAG_CC, 0x1, &mode_set_byte); +- orb.cpa = __pa32(&ccw_program.compress); ++ uint16_t type; ++ ++ start_ccw(READ_DEV_CHAR, 0x0, 0x40, ccw_data); ++ ++ memcpy(&type, &ccw_data[3], sizeof(type)); ++ switch (type) { ++ case 0x3490: ++ case 0x3590: // XXX 3592 ++ ccw_init(&ccw_program.compress, MODE_SET_DB, CCW_FLAG_CC, 0x1, ++ &mode_set_byte); ++ orb.cpa = __pa32(&ccw_program.compress); ++ break; ++ default: ++ case 0x3480: ++ orb.cpa = __pa32(&ccw_program.write); ++ break; ++ } + } + + /* +-- +2.54.0 + + +From 78202d1ec90774c252c04c4d4247edc020eb3c18 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Hor=C3=A1k?= +Date: Tue, 2 Jun 2026 13:26:09 +0200 +Subject: [PATCH 3/7] Revert "zipl/tape2dump: Remove load display command" + +This reverts commit 145c21a9ca01b65aac527c8c91f455dccca27581. +--- + zipl/boot/tape2dump.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/zipl/boot/tape2dump.c b/zipl/boot/tape2dump.c +index 41136160..6ad795a4 100644 +--- a/zipl/boot/tape2dump.c ++++ b/zipl/boot/tape2dump.c +@@ -26,6 +26,7 @@ + #define SENSE_OVERRUN 0x04 /* Sense */ + #define WRITETAPEMARK 0x1f /* Write Tape Mark */ + #define READ_DEV_CHAR 0x64 /* Read device characteristics */ ++#define LOAD_DISPLAY 0x9f /* Load tape display */ + #define MODE_SET_DB 0xdb /* Mode set */ + + /* +@@ -128,6 +129,17 @@ static void setup_idrc_compression(void) + } + } + ++/* ++ * Print message on tape display ++ */ ++static void ccw_load_display(const char *msg) ++{ ++ char _msg[24] = {0x20}; ++ ++ strcpy(&_msg[1], msg); ++ start_ccw(LOAD_DISPLAY, CCW_FLAG_SLI, 0x11, (void *) _msg); ++} ++ + /* + * Write sense data to buffer + */ +@@ -170,6 +182,19 @@ static void ccw_write_block(unsigned long addr, unsigned long size, + panic(EMEM, "Device too small"); + } + ++/* ++ * Every 16 MB we update the tape display ++ */ ++static void progress_print_disp(unsigned long addr) ++{ ++ char msg[24]; ++ ++ if (addr % (1024 * 1024 * 16) != 0) ++ return; ++ snprintf(msg, sizeof(msg), "%08u", addr >> 20); ++ ccw_load_display(msg); ++} ++ + /* + * Dump all memory to tape + */ +@@ -187,9 +212,11 @@ void dt_dump_mem(void) + ccw_write_block(addr, BLK_SIZE, page); + total_dump_size += BLK_SIZE; + progress_print(addr + BLK_SIZE); ++ progress_print_disp(addr + BLK_SIZE); + } + df_s390_em_page_init(page); + ccw_write_block(page, sizeof(struct df_s390_em), 0); + free_page(page); + ccw_write_tapemark(); ++ ccw_load_display("DUMP*END"); + } +-- +2.54.0 + + +From 724581ae5ccc9623174dd998a00a0797f2d7f993 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Hor=C3=A1k?= +Date: Tue, 2 Jun 2026 13:26:23 +0200 +Subject: [PATCH 4/7] Revert "lstape: Remove type filter support" + +This reverts commit 1bd8ee4b79885bdf2afd389c914c030490319317. +--- + zconf/lstape | 19 +++++++++++++++++++ + zconf/lstape.8 | 10 ++++++++-- + 2 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/zconf/lstape b/zconf/lstape +index 943f3256..b37bd9cd 100755 +--- a/zconf/lstape ++++ b/zconf/lstape +@@ -28,6 +28,10 @@ function PrintUsage() { + : Print this help text. + : --ccw-only|--scsi-only + : Limit output to CCW or SCSI devices only. ++ : -t|--type ++ : Limit output of CCW tape devices to the given ++ : devices. The list consists of device types ++ : separated by ','. + : --online|--offline + : Show only devices that are either online or + : offline (only one option is allowed). This +@@ -59,6 +63,7 @@ function PrintVersion() + } + + FLSEP="" ++DEVLIST="3490" + SHORTID=false + SHOWCCW=true + VERBOSE=false +@@ -72,6 +77,14 @@ while [ $# -ne 0 ]; do + PrintUsage + exit 0 + ;; ++ -t|--type) ++ if [ $# -lt 2 ]; then ++ RequireArgument $1 1 ++ exit 1 ++ fi ++ shift ++ DEVLIST="$1" ++ ;; + --online) + if $FILTEROFFLINE; then + echo -n "Option --online and --offline " >&2 +@@ -135,6 +148,10 @@ function SysfsCreateListCCW() { + medium_state_str[1] = "LOADED " + medium_state_str[2] = "UNLOADED" + ++ split("'$DEVLIST'", A, ",") ++ for(i = 1; i in A; i++) { ++ devlist[A[i]] = 1 ++ } + shortid = "'$SHORTID'"=="true" ? 1 : 0 + filteronline = "'$FILTERONLINE'"=="true" ? 1 : 0 + filteroffline = "'$FILTEROFFLINE'"=="true" ? 1 : 0 +@@ -151,6 +168,8 @@ function SysfsCreateListCCW() { + + devtype = Read(devdir "/devtype") + split(devtype, A, "/") ++ if (!(A[1] in devlist)) ++ next + + online = Read(devdir "/online") + if (filteronline && !online) +diff --git a/zconf/lstape.8 b/zconf/lstape.8 +index 6262c64d..019b6e58 100644 +--- a/zconf/lstape.8 ++++ b/zconf/lstape.8 +@@ -64,6 +64,12 @@ of SCSI tape devices. + Limit output to either online or offline devices. This filter has no effect + on the output of SCSI devices. + ++.TP ++.BR -t | --type " \fI\fR" ++Limit output to given device types, for example 3490 ++(currently only applies to channel-attached ++tape devices). ++ + .TP + .I + Limits the output to information about the specified tape device or +@@ -125,9 +131,9 @@ The serial number. + List all tape devices that are available + .RE + +-\fBlstape --ccw-only --online\fR ++\fBlstape --ccw-only -t 3490 --online\fR + .RS +-Show all channel-attached tape devices that are online. ++Show all 3490 CCW devices that are online. + .RE + + \fBlstape --scsi-only --verbose\fR +-- +2.54.0 + + +From 064e46bf7d7a827086c522d427b3988317f616cc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Hor=C3=A1k?= +Date: Tue, 2 Jun 2026 13:26:41 +0200 +Subject: [PATCH 5/7] Revert "lstape: Remove 3480 and 3590 tape support" + +This reverts commit 4f0dfae97ea61b0518cb3d61977712f31f1d8206. +--- + zconf/lstape | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/zconf/lstape b/zconf/lstape +index b37bd9cd..9496686b 100755 +--- a/zconf/lstape ++++ b/zconf/lstape +@@ -31,7 +31,7 @@ function PrintUsage() { + : -t|--type + : Limit output of CCW tape devices to the given + : devices. The list consists of device types +- : separated by ','. ++ : separated by ','. (e.g. -t 3480,3490) + : --online|--offline + : Show only devices that are either online or + : offline (only one option is allowed). This +@@ -63,7 +63,7 @@ function PrintVersion() + } + + FLSEP="" +-DEVLIST="3490" ++DEVLIST="3480,3490,3590" + SHORTID=false + SHOWCCW=true + VERBOSE=false +@@ -142,6 +142,8 @@ function SysfsCreateListCCW() { + ( + find $1/bus/ccw/drivers/tape_34xx -type l \ + -printf '%f\n' 2>/dev/null ++ find $1/bus/ccw/drivers/tape_3590 -type l \ ++ -printf '%f\n' 2>/dev/null + ) | awk -v format="$CCWFORMAT" ' + BEGIN{ + medium_state_str[0] = "UNKNOWN " +-- +2.54.0 + + +From 85b6f905206603c20496b91a8035494d6610ca7c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Hor=C3=A1k?= +Date: Tue, 2 Jun 2026 13:26:59 +0200 +Subject: [PATCH 6/7] Revert "lstape: Remove trailing whitespace" + +This reverts commit 3d6bb988c24d1723ca4b631e5ff9489d3e419ed7. +--- + zconf/lstape | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/zconf/lstape b/zconf/lstape +index 9496686b..e2410e1b 100755 +--- a/zconf/lstape ++++ b/zconf/lstape +@@ -220,7 +220,7 @@ function SysfsCreateListCCW() { + (online==0) ? "N/A" : \ + medium_state_str[medium_state]) + } +- ' | sort ++ ' | sort + } + + # handle SCSI device not necessarily zfcp-attached, e.g. virtio-scsi-ccw +-- +2.54.0 + + +From b0e9602ade53403fd6e941e4b1d9ff5f76e9fcaa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Hor=C3=A1k?= +Date: Tue, 2 Jun 2026 13:27:23 +0200 +Subject: [PATCH 7/7] Revert "tape390: Remove tape390_display and + tape390_crypt" + +This reverts commit 8f83002e379eb84b91f09a303c97d8338adc40e0. +--- + .gitignore | 2 + + Makefile | 2 +- + README.md | 7 + + tape390/Makefile | 25 ++ + tape390/tape390_common.c | 86 ++++++ + tape390/tape390_common.h | 22 ++ + tape390/tape390_crypt.8 | 108 +++++++ + tape390/tape390_crypt.c | 581 ++++++++++++++++++++++++++++++++++++++ + tape390/tape390_display.8 | 150 ++++++++++ + tape390/tape390_display.c | 287 +++++++++++++++++++ + 10 files changed, 1269 insertions(+), 1 deletion(-) + create mode 100644 tape390/Makefile + create mode 100644 tape390/tape390_common.c + create mode 100644 tape390/tape390_common.h + create mode 100644 tape390/tape390_crypt.8 + create mode 100644 tape390/tape390_crypt.c + create mode 100644 tape390/tape390_display.8 + create mode 100644 tape390/tape390_display.c + +diff --git a/.gitignore b/.gitignore +index 36a2c851..e76abc9a 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -111,6 +111,8 @@ 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 +diff --git a/Makefile b/Makefile +index 4dbce8cc..329aebfa 100644 +--- a/Makefile ++++ b/Makefile +@@ -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 \ +- osasnmpd qetharp ip_watcher qethconf scripts zconf \ ++ tape390 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 \ +diff --git a/README.md b/README.md +index 91d61c5a..8298e38c 100644 +--- a/README.md ++++ b/README.md +@@ -85,6 +85,13 @@ 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. +diff --git a/tape390/Makefile b/tape390/Makefile +new file mode 100644 +index 00000000..63b5937f +--- /dev/null ++++ b/tape390/Makefile +@@ -0,0 +1,25 @@ ++include ../common.mak ++ ++ALL_CPPFLAGS += -D_FILE_OFFSET_BITS=64 ++ ++all: tape390_display tape390_crypt ++ ++tape390_display: tape390_display.o tape390_common.o ++ ++tape390_crypt: tape390_crypt.o tape390_common.o ++ ++install: all ++ $(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man8 ++ $(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 tape390_display \ ++ $(DESTDIR)$(BINDIR) ++ $(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 tape390_display.8 \ ++ $(DESTDIR)$(MANDIR)/man8 ++ $(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 tape390_crypt \ ++ $(DESTDIR)$(BINDIR) ++ $(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 tape390_crypt.8 \ ++ $(DESTDIR)$(MANDIR)/man8 ++ ++clean: ++ rm -f *.o *~ tape390_display tape390_crypt core ++ ++.PHONY: all install clean +diff --git a/tape390/tape390_common.c b/tape390/tape390_common.c +new file mode 100644 +index 00000000..821e8485 +--- /dev/null ++++ b/tape390/tape390_common.c +@@ -0,0 +1,86 @@ ++/* ++ * tape_390 - Common functions ++ * ++ * Copyright IBM Corp. 2006, 2017 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "tape390_common.h" ++ ++#define PROC_DEVICES_FILE "/proc/devices" ++#define PROC_DEVICES_FILE_WIDTH 100 ++ ++char *prog_name; /* Name of tool */ ++ ++/* ++ * Set name of tool ++ */ ++void set_prog_name(char *name) ++{ ++ prog_name = name; ++} ++ ++/* ++ * Check whether specified device node is tape device ++ */ ++int is_not_tape(char *device) ++{ ++ FILE* fh; ++ char line[PROC_DEVICES_FILE_WIDTH]; ++ char last_line[PROC_DEVICES_FILE_WIDTH]; ++ int found = 0; ++ struct stat stat_struct; ++ ++ if (stat(device, &stat_struct)) { ++ ERRMSG("%s: Unable to get device status for " ++ "'%s'. \n", prog_name, device); ++ perror(""); ++ return 1; ++ } ++ fh = fopen(PROC_DEVICES_FILE,"r"); ++ if (!fh) { ++ ERRMSG("%s: WARNING: Cannot check for tape in file " ++ PROC_DEVICES_FILE ".\n", prog_name); ++ perror(""); ++ return(0); /* check not possible, just continue */ ++ } ++ while (!found && (fscanf(fh, "%s", line) != EOF)) { ++ if (strcmp(line, "tape") == 0) ++ found = 1; ++ else ++ strcpy(last_line, line); ++ } ++ fclose(fh); ++ if (found && (major(stat_struct.st_rdev) == ++ (unsigned int) atoi(last_line))) ++ return (0); ++ else { ++ ERRMSG("%s: '%s' is not a tape device. \n", prog_name, device); ++ return 1; ++ } ++} ++ ++/* ++ * Open the tape device ++ */ ++int open_tape(char *device) ++{ ++ int fd; ++ fd = open(device,O_RDONLY); ++ if (fd < 0) { ++ ERRMSG("%s: Cannot open device %s.\n", ++ prog_name,device); ++ perror(""); ++ exit(EXIT_MISUSE); ++ } ++ return fd; ++} +diff --git a/tape390/tape390_common.h b/tape390/tape390_common.h +new file mode 100644 +index 00000000..d18b88cc +--- /dev/null ++++ b/tape390/tape390_common.h +@@ -0,0 +1,22 @@ ++/* ++ * tape_390 - Common functions ++ * ++ * Copyright IBM Corp. 2006, 2017 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#ifndef _TAPE390_COMMON_H ++#define _TAPE390_COMMON_H ++ ++#define ERRMSG(x...) {fflush(stdout);fprintf(stderr,x);} ++#define ERRMSG_EXIT(ec,x...) do {fflush(stdout);fprintf(stderr,x);exit(ec);} while(0) ++#define EXIT_MISUSE 1 ++ ++extern int is_not_tape(char *); ++extern int open_tape(char *); ++extern void set_prog_name(char *); ++extern char *prog_name; ++ ++#endif +diff --git a/tape390/tape390_crypt.8 b/tape390/tape390_crypt.8 +new file mode 100644 +index 00000000..b3f0c455 +--- /dev/null ++++ b/tape390/tape390_crypt.8 +@@ -0,0 +1,108 @@ ++.\" Copyright 2017 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 TAPE390_CRYPT 8 "Apr 2006" "s390-tools" ++ ++.SH NAME ++tape390_crypt \- encryption support for zSeries tape devices. ++ ++.SH SYNOPSIS ++.B tape390_crypt ++[OPTION] [DEVICE] ++ ++.SH DESCRIPTION ++.B tape390_crypt ++exploits encryption features available in zSeries tape devices. ++It can be used to enable or disable tape encryption and to set ++KEK (Key Encrypting Key) labels. ++ ++.SH OPTIONS ++.TP ++.BR "\-h" " or " "\-\-help" ++Print help information, then exit. ++ ++.TP ++.BR "\-v" " or " "\-\-version" ++Print version information, then exit. ++ ++.TP ++.BR "\-q" " or " "\-\-query" ++Print current encryption status of the specified tape device and of the ++loaded medium. ++If encryption is on and the medium is encrypted , ++additional information on the encryption keys is displayed. ++ ++.TP ++.BR "\-e " { "on" | "off" } " " or " \-\-encryption=" { "on" | "off" } ++sets tape encryption on or off. ++ ++.TP ++.BR "\-k " [ "label" | "hash" ] " " or " \-\-key=" [ "label" | "hash" ] ++sets tape encryption keys. ++.br ++ specifies the KEK ++(Key Encrypting Key), which can be maximal 64 characters long. ++.br ++The store type (either label or hash) specifies how the KEK in is to be stored on the tape medium. Since labels are ++human readable strings and hence more user friendly than hashes, ++the default store type is label. ++.br ++The \-k option can only be specified, if the tape medium is at load point. ++.br ++While processing the \-k option, the tape medium is initialized and all ++data eventually contained on the tape medium is lost. ++To avoid inadvertent data loss a prompt message is issued asking the user ++whether he or she really wants to proceed. ++.br ++The \-k option can be specified maximal twice, because on the tape medium ++maximal two EEDKs (External Encrypted Data Keys) can be stored. ++If specified once, two identical EEDKs are stored. ++.br ++ is a character separating the KEK in from the store type ++(either label or hash). This ++delimiter can be specified with the \-d option as explained below. ++ ++.TP ++.BR "\-d " " or " "\-\-delimiter= ++specifies the character which separates the KEK ++in from the store type (either label or hash). ++The default delimiter is : (colon). ++The \-d option can only be specified together with the \-k option. ++ ++.TP ++.BR "\-f " " or " "\-\-force ++specifies that no prompt message is to be issued before writing the KEK ++information and initializing the tape medium. ++The \-f option can only be specified together with the \-k option. ++ ++.TP ++.BR device ++specifies the device node of the tape device. ++ ++.SH EXAMPLES ++1. Scenario: ++.br ++mount non-encrypted tape and write data with the ++.B "default" ++KEKs: ++.br ++tape390_crypt \-e on /dev/ntibm0 ++.br ++tar cfz /dev/ntibm0 /data ++ ++2. Scenario: ++.br ++mount non-encrypted tape and write data with ++.B "specific" ++KEKs: ++.br ++tape390_crypt \-k my_first_key \-k my_second_key:hash /dev/ntibm0 ++.br ++tar cfz /dev/ntibm0 /data ++ ++3. Scenario: ++.br ++mount tape and display current encryption status: ++.br ++tape390_crypt \-q /dev/ntibm0 +diff --git a/tape390/tape390_crypt.c b/tape390/tape390_crypt.c +new file mode 100644 +index 00000000..03bd4522 +--- /dev/null ++++ b/tape390/tape390_crypt.c +@@ -0,0 +1,581 @@ ++/* ++ * tape390_crypt: Provide encryption for tape devices ++ * ++ * Copyright 2006, 2017 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "lib/zt_common.h" ++#include "tape390_common.h" ++ ++#define KEKL_LENGTH 65 /* 64 bytes plus trailing \0 */ ++#define TOT_KEKL_LENGTH KEKL_LENGTH+1+5 /* kekl plus colon plus LABEL or HASH */ ++#define ENCRYPTION_ON 1 ++#define ENCRYPTION_OFF 0 ++#define CRYPT_SET_FAILED_MSG "%s: Tape drive does not support encryption.\n" ++#define CRYPT_QUERY_FAILED_MSG CRYPT_SET_FAILED_MSG ++#define KEKL_QUERY_FAILED_MSG "%s: Query of encryption keys failed.\n" ++#define KEKL_SET_FAILED_MSG "%s: Unable to set or modify encryption keys.\n" ++#define PROC_DEVICES_FILE "/proc/devices" ++#define PROC_DEVICES_FILE_WIDTH 100 ++#define MAX_BLOCKSIZE 65535 /* max blocksize supported by escon/ficon tapes */ ++ ++#ifndef ENOKEY ++#define ENOKEY 126 ++#endif ++#ifndef EKEYREJECTED ++#define EKEYREJECTED 129 ++#endif ++ ++#define CHECK_SPEC_MAX(i,j,numstr,str) \ ++ {if (i>j) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \ ++ "can only be specified " numstr ".\n",prog_name);} ++ ++#define PRINT_TYPE(byte) \ ++ {if (byte==TAPE390_KEKL_TYPE_LABEL) printf("label\n");\ ++ else if (byte == TAPE390_KEKL_TYPE_HASH) printf("hash\n");\ ++ else printf("Unsupported type\n");} ++ ++/* ++ * Structure tape390_crypt is used to store the command line parameters ++ */ ++struct tape390_crypt { ++ int e_switch; ++ char delimiter; ++ char devname[PATH_MAX]; ++ char kekl_input[2][TOT_KEKL_LENGTH]; ++ int encryption_specified; ++ int query_specified; ++ int key_specified; ++ int delimiter_specified; ++ int force_specified; ++} __attribute__ ((packed)); ++ ++/* ++ * The following ioctl's belong to linux-2.5/include/asm-s390/tape390.h ++ * ++ * The TAPE390_CRYPT_SET ioctl is used to switch on/off encryption. ++ * The "encryption_capable" field is ignored for this ioctl! ++ */ ++#define TAPE390_CRYPT_SET _IOW('d', 2, struct tape390_crypt_info) ++ ++/* ++ * The TAPE390_CRYPT_QUERY ioctl is used to query the encryption state. ++ */ ++#define TAPE390_CRYPT_QUERY _IOR('d', 3, struct tape390_crypt_info) ++ ++struct tape390_crypt_info { ++ char capability; ++ char status; ++ char medium_status; ++} __attribute__ ((packed)); ++ ++/* Macros for "capable" field */ ++#define TAPE390_CRYPT_SUPPORTED_MASK 0x01 ++#define TAPE390_CRYPT_SUPPORTED(x) \ ++ ((x.capability & TAPE390_CRYPT_SUPPORTED_MASK)) ++ ++/* Macros for "status" field */ ++#define TAPE390_CRYPT_ON_MASK 0x01 ++#define TAPE390_CRYPT_ON(x) (((x.status) & TAPE390_CRYPT_ON_MASK)) ++ ++/* Macros for "medium status" field */ ++#define TAPE390_MEDIUM_LOADED_MASK 0x01 ++#define TAPE390_MEDIUM_ENCRYPTED_MASK 0x02 ++#define TAPE390_MEDIUM_ENCRYPTED(x) \ ++ (((x.medium_status) & TAPE390_MEDIUM_ENCRYPTED_MASK)) ++#define TAPE390_MEDIUM_LOADED(x) \ ++ (((x.medium_status) & TAPE390_MEDIUM_LOADED_MASK)) ++ ++/* ++ * The TAPE390_KEKL_SET ioctl is used to set Key Encrypting Key labels. ++ */ ++#define TAPE390_KEKL_SET _IOW('d', 4, struct tape390_kekl_pair) ++ ++/* ++ * The TAPE390_KEKL_QUERY ioctl is used to query Key Encrypting Key labels. ++ */ ++#define TAPE390_KEKL_QUERY _IOR('d', 5, struct tape390_kekl_pair) ++ ++struct tape390_kekl { ++ unsigned char type; ++ unsigned char type_on_tape; ++ char label[65]; ++} __attribute__ ((packed)); ++ ++struct tape390_kekl_pair { ++ struct tape390_kekl kekl[2]; ++} __attribute__ ((packed)); ++ ++/* Values for "kekl1/2_type" and "kekl1/2_type_on_tape" fields */ ++#define TAPE390_KEKL_TYPE_NONE 0 ++#define TAPE390_KEKL_TYPE_LABEL 1 ++#define TAPE390_KEKL_TYPE_HASH 2 ++ ++/* Full tool name */ ++static const char tool_name[] = "tape390_crpyt: zSeries tape encryption program"; ++ ++/* Copyright notice */ ++static const char copyright_notice[] = "Copyright IBM Corp. 2006, 2017"; ++ ++/* ++ * Print version information. ++ */ ++static void print_version (void) ++{ ++ printf ("%s version %s\n", tool_name, RELEASE_STRING); ++ printf ("%s\n", copyright_notice); ++} ++ ++/* ++ * prints out the usage text ++ */ ++static void tape390_crypt_usage (void) ++{ ++ printf ("Usage: tape390_crypt [OPTIONS] [DEVICE]\n" ++ "\n" ++ "Provide encryption for " ++ "tape devices.\n" ++ "DEVICE is the node of the tape device (e.g. '/dev/ntibm0')\n" ++ "\n" ++ "-h, --help Print this help, then exit\n" ++ "-v, --version Print version information, " ++ "then exit\n" ++ "-q, --query Query information on encryption " ++ "status and keys\n" ++ "-k, --key value:type Set encryption key(s)\n" ++ "-d, --delimiter char Specify character separating " ++ "key value from key type\n" ++ "-f, --force Do not prompt user\n" ++ "-e, --encryption on|off Switch encryption on or off\n"); ++} ++ ++/* ++ * initialize the tape390_crypt info structure ++ */ ++static void init_info(struct tape390_crypt *info) ++{ ++ info->delimiter = ':'; ++ info->encryption_specified = 0; ++ info->query_specified = 0; ++ info->key_specified = 0; ++ info->delimiter_specified = 0; ++ info->force_specified = 0; ++} ++ ++/* ++ * parse the commandline options ++ */ ++static void tape390_crypt_parse_opts(struct tape390_crypt *info, int argc, ++ char* argv[]) ++{ ++ int opt, index, kekl_too_long=0, deli_too_long=0, e_switch_invalid=0; ++ int i; ++ static struct option crypt_long_options[] = { ++ { "version", no_argument, NULL, 'v'}, ++ { "encryption", required_argument, NULL, 'e'}, ++ { "query", no_argument, NULL, 'q'}, ++ { "key", required_argument, NULL, 'k'}, ++ { "help", no_argument, NULL, 'h'}, ++ { "delimiter", required_argument, NULL, 'd'}, ++ { "force", no_argument, NULL, 'f'}, ++ { NULL, 0, NULL, 0 } ++ }; ++ /* Command line option abbreviations */ ++ static const char crypt_option_string[] = "ve:qk:hd:f"; ++ ++ while (1) { ++ opt = getopt_long(argc, argv, crypt_option_string, ++ crypt_long_options, &index); ++ if (opt == -1) ++ break; ++ switch (opt) { ++ case 'v': ++ print_version(); ++ exit(0); ++ case 'h': ++ tape390_crypt_usage(); ++ exit(0); ++ case 'q': ++ ++info->query_specified; ++ break; ++ case 'k': ++ ++info->key_specified; ++ if(strlen(optarg) >= TOT_KEKL_LENGTH) ++ kekl_too_long = 1; ++ else if (info->key_specified == 1) ++ for (i = 0; i < 2; i++) ++ strcpy(info->kekl_input[i], optarg); ++ else ++ strcpy(info->kekl_input[1], optarg); ++ break; ++ case 'e': ++ ++info->encryption_specified; ++ if (strcmp(optarg,"off") == 0) ++ info->e_switch = ENCRYPTION_OFF; ++ else if (strcmp(optarg,"on") == 0) ++ info->e_switch = ENCRYPTION_ON; ++ else ++ e_switch_invalid = 1; ++ break; ++ case 'd': ++ ++info->delimiter_specified; ++ if(strlen(optarg) > 1) ++ deli_too_long = 1; ++ else ++ info->delimiter = optarg[0]; ++ break; ++ case 'f': ++ ++info->force_specified; ++ break; ++ default: ++ fprintf(stderr, "Try '%s --help' for more" ++ " information.\n",prog_name); ++ exit(1); ++ } ++ } ++ CHECK_SPEC_MAX(info->query_specified, 1, "once", "query"); ++ CHECK_SPEC_MAX(info->encryption_specified, 1, "once", "encryption"); ++ CHECK_SPEC_MAX(info->delimiter_specified, 1, "once", "delimiter"); ++ CHECK_SPEC_MAX(info->force_specified, 1, "once", "force"); ++ CHECK_SPEC_MAX(info->key_specified,2, "twice", "key"); ++ if (kekl_too_long) ++ ERRMSG_EXIT(EXIT_MISUSE, ++ "%s: Specified key too long.\n",prog_name); ++ if (deli_too_long) ++ ERRMSG_EXIT(EXIT_MISUSE, ++ "%s: Delimiter must be one character.\n",prog_name); ++ if (e_switch_invalid) ++ ERRMSG_EXIT(EXIT_MISUSE, ++ "%s: ERROR: encryption can be set 'on' or 'off'.\n", ++ prog_name); ++ if (((info->query_specified) && ++ (info->key_specified + info->encryption_specified > 0)) || ++ ((info->encryption_specified) && ++ (info->key_specified + info->query_specified > 0)) || ++ ((info->force_specified) && ++ (info->encryption_specified)) || ++ ((info->delimiter_specified) && ++ (info->encryption_specified + info->query_specified > 0))) ++ ERRMSG_EXIT(EXIT_MISUSE, ++ "%s: Conflicting options specified.\n",prog_name); ++ if (info->query_specified + info->encryption_specified + ++ info->key_specified == 0) ++ ERRMSG_EXIT(EXIT_MISUSE, ++ "%s: ERROR: Missing options.\n",prog_name); ++ /* save device */ ++ if (optind >= argc) ++ ERRMSG_EXIT(EXIT_MISUSE, ++ "%s: No device specified.\n",prog_name); ++ if (optind + 1 < argc) ++ ERRMSG_EXIT(EXIT_MISUSE, ++ "%s: More than one device specified.\n",prog_name); ++ strcpy(info->devname, argv[optind]); ++} ++ ++/* ++ * check and parse key operand, must be value:type ++ * where value is an arbitrary string, maximal 64 char long ++ * : is a 1-char delimiter specified with the -d option (default :) ++ * type is the type identifier, which can be either 'hash' or 'label' ++ * default is 'label' ++ */ ++static void fill_kekl(char *s, char delimiter, ++ struct tape390_kekl *mykekl) ++{ ++ int i; ++ char typestring[TOT_KEKL_LENGTH] = {0}; ++ for (i = strlen(s); i >= 0; i--) ++ if (*(s+i) == delimiter) ++ break; ++ if (i == -1) /* delimiter not found, no type specified */ ++ mykekl->type_on_tape = TAPE390_KEKL_TYPE_LABEL; /* default type*/ ++ else if (i == 0) ++ ERRMSG_EXIT(EXIT_MISUSE, ++ "%s: ERROR: delimiter '%c' found as first " ++ "character.\n",prog_name,delimiter); ++ else if (i == (int) strlen(s) - 1) ++ ERRMSG_EXIT(EXIT_MISUSE, ++ "%s: ERROR: Delimiter '%c' found as last " ++ "character.\n",prog_name,delimiter); ++ else { ++ strcpy(typestring,s+i+1); ++ *(s+i) = '\0'; ++ if (strcmp(typestring,"hash") == 0) ++ mykekl->type_on_tape = TAPE390_KEKL_TYPE_HASH; ++ else if (strcmp(typestring,"label") == 0) ++ mykekl->type_on_tape = TAPE390_KEKL_TYPE_LABEL; ++ else ++ ERRMSG_EXIT(EXIT_MISUSE, ++ "%s: Invalid key type '%s'," ++ " must be either 'label' or 'hash'.\n", ++ prog_name,typestring); ++ } ++ if (strlen(s) >= KEKL_LENGTH) ++ ERRMSG_EXIT(EXIT_MISUSE, ++ "%s: Specified key value too long, has %d chars.\n", ++ prog_name,(int)strlen(s)); ++ else { ++ strcpy(mykekl->label, s); ++ mykekl->type = TAPE390_KEKL_TYPE_LABEL; ++ } ++} ++ ++/* ++ * Write two tapemarks on tape to initialize tape after kekl set ++ */ ++ ++static int init_tape(int fd) ++{ ++ struct mtop mtop; ++ int rc; ++ ++ mtop.mt_op = MTWEOF; ++ mtop.mt_count = 2; ++ rc = ioctl(fd, MTIOCTOP, &mtop); ++ if (rc) ++ return rc; ++ mtop.mt_op = MTREW; ++ return ioctl(fd, MTIOCTOP, &mtop); ++} ++ ++/* ++ * Tell the current block on tape ++ */ ++ ++static int tell_tape(int fd) ++{ ++ struct mtop mtop; ++ ++ mtop.mt_op = MTTELL; ++ mtop.mt_count = 1; ++ return ioctl(fd, MTIOCTOP, &mtop); ++} ++ ++ ++/* ++ * Do read IO to tape in order to enforce update of KEKL information. ++ * Leave tape position unchanged. ++ */ ++ ++static int read_tape(int fd) ++{ ++ struct mtop mtop; ++ int block_number, n_read; ++ char buffer[MAX_BLOCKSIZE]; ++ ++ /* remember current block on tape */ ++ block_number = tell_tape(fd); ++ n_read = read(fd, buffer, sizeof(buffer)); ++ if (n_read == -1) { ++ /* tape read failed, ignore if caused by end-of-volume */ ++ if (errno == ENOSPC) ++ return 0; ++ else ++ return 1; ++ } ++ if (block_number != tell_tape(fd)) { ++ /* re-position tape */ ++ mtop.mt_op = MTSEEK; ++ mtop.mt_count = block_number; ++ if (ioctl(fd, MTIOCTOP, &mtop) != 0) ++ return 1; ++ } ++ return 0; ++} ++ ++/* ++ * set Key Encrypting Key labels ++ */ ++static int set_encryption_keys(int fd, struct tape390_crypt *info) ++{ ++ struct tape390_kekl_pair kekls; ++ char delim; ++ char *s, inp_buffer[5]; ++ int i, rc; ++ ++ delim = info->delimiter; ++ for (i = 0; i < 2; i++) { ++ s = info->kekl_input[i]; ++ fill_kekl(s, delim, &kekls.kekl[i]); ++ } ++ if (info->force_specified == 0) { ++ printf("--->> ATTENTION! <<---\n"); ++ printf("All data on tape %s will be lost.\nType " ++ "\"yes\" to continue: ", info->devname); ++ if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL) { ++ fprintf(stderr, "Reading from terminal failed.\n"); ++ exit(1); ++ } ++ if (strcasecmp(inp_buffer,"yes\n")) { ++ printf("Tape and its encryption keys " ++ "remain unchanged.\n"); ++ exit(0); ++ } ++ } ++ rc = ioctl(fd, TAPE390_KEKL_SET, &kekls); ++ if (rc) ++ return rc; ++ return init_tape(fd); ++} ++ ++/* ++ * Switch on/off encryption ++ */ ++static int switch_encryption_on_or_off(int fd,struct tape390_crypt *info) ++{ ++ struct tape390_crypt_info myinfo; ++ ++ memset(&myinfo, 0, sizeof(myinfo)); ++ if (info->e_switch == ENCRYPTION_ON) ++ myinfo.status |= TAPE390_CRYPT_ON_MASK; ++ return ioctl(fd, TAPE390_CRYPT_SET, &myinfo); ++} ++ ++/* ++ * Query information on encryption and keys ++ */ ++static int query_encryption(int fd,struct tape390_crypt *info) ++{ ++ struct tape390_crypt_info myinfo; ++ struct tape390_kekl_pair kekls; ++ int i, ret; ++ ++ ret = ioctl(fd, TAPE390_CRYPT_QUERY, &myinfo); ++ if (ret) ++ return -1; ++ if (!TAPE390_MEDIUM_LOADED(myinfo)) { ++ printf("Medium not loaded\n"); ++ return 0; ++ } ++ printf("ENCRYPTION: "); ++ if (TAPE390_CRYPT_ON(myinfo)) ++ printf("ON\n"); ++ else ++ printf("OFF\n"); ++ printf("MEDIUM: "); ++ if (TAPE390_MEDIUM_ENCRYPTED(myinfo)) ++ printf("ENCRYPTED\n"); ++ else { ++ printf("NOT ENCRYPTED\n"); ++ return 0; ++ } ++ /* ++ * do a dummy read in order to force the control unit to get ++ * the key information from the EKM ++ */ ++ ret = read_tape(fd); ++ if (ret && (info->force_specified == 0)) ++ return -2; ++ ret = ioctl(fd, TAPE390_KEKL_QUERY, &kekls); ++ if (ret) ++ return -2; ++ printf("KEKLs on TAPE:\n"); ++ if (kekls.kekl[0].type == TAPE390_KEKL_TYPE_NONE) { ++ ERRMSG("Unable to retrieve key information.\n"); ++ return 0; ++ } ++ for (i = 0; i < 2; i++) { ++ printf(" KEY%i:\n",i+1); ++ if (kekls.kekl[i].type == TAPE390_KEKL_TYPE_NONE) ++ printf("None\n"); ++ else { ++ printf(" value: %s\n",kekls.kekl[i].label); ++ printf(" type: "); ++ PRINT_TYPE(kekls.kekl[i].type); ++ printf(" ontape: "); ++ PRINT_TYPE(kekls.kekl[i].type_on_tape); ++ } ++ } ++ return 0; ++} ++ ++int main(int argc, char *argv[]) ++{ ++ struct tape390_crypt info; ++ char error_msg[80]; ++ int rc=0, fd=-1; ++ ++ /* set name of program */ ++ set_prog_name(basename(argv[0])); ++ ++ /* set default values */ ++ init_info(&info); ++ ++ /* parse command line options and check syntax */ ++ tape390_crypt_parse_opts(&info, argc, argv); ++ ++ /* check whether specified device node is tape */ ++ if (is_not_tape(info.devname)) ++ exit(EXIT_MISUSE); ++ ++ /* open device */ ++ fd = open_tape(info.devname); ++ ++ /* process -k or -e or -q operand */ ++ if (info.key_specified >= 1) { ++ rc = set_encryption_keys(fd, &info); ++ if (rc == 0) ++ printf("SUCCESS: key information set.\n"); ++ strcpy(error_msg, KEKL_SET_FAILED_MSG); ++ } else if (info.encryption_specified) { ++ rc = switch_encryption_on_or_off(fd, &info); ++ strcpy(error_msg, CRYPT_SET_FAILED_MSG); ++ } else if (info.query_specified) { ++ rc = query_encryption(fd, &info); ++ if (rc == -1) ++ strcpy(error_msg, CRYPT_QUERY_FAILED_MSG); ++ else if (rc == -2) ++ strcpy(error_msg, KEKL_QUERY_FAILED_MSG); ++ } ++ if (rc) { ++ ERRMSG(error_msg, prog_name); ++ switch (errno) { ++ case ENOKEY: ++ ERRMSG("EKM error.\n"); ++ break; ++ case ENOTCONN: ++ ERRMSG("Could not connect to EKM.\n"); ++ break; ++ case EKEYREJECTED: ++ ERRMSG("Key not available on EKM.\n"); ++ break; ++ case EUNATCH: ++ ERRMSG("Encryption must be set ON prior to " ++ "setting or querying encryption " ++ "keys.\n"); ++ break; ++ case EBADSLT: ++ ERRMSG("Tape must be at load point in order " ++ "to set encryption keys.\n"); ++ break; ++ case ENOSYS: ++ ERRMSG("Tape device does not support " ++ "encryption.\n"); ++ break; ++ case EINVAL: ++ ERRMSG("Kernel does not support tape " ++ "encryption.\n"); ++ break; ++ default: ++ perror(""); ++ } ++ } ++ if (fd != -1) ++ close(fd); ++ return(rc); ++} +diff --git a/tape390/tape390_display.8 b/tape390/tape390_display.8 +new file mode 100644 +index 00000000..0c51c5a0 +--- /dev/null ++++ b/tape390/tape390_display.8 +@@ -0,0 +1,150 @@ ++.\" Copyright 2017 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 TAPE390_DISPLAY 8 "Apr 2006" "s390-tools" ++ ++.SH NAME ++tape390_display \- display messages on the display unit of a zSeries tape ++device. ++ ++.SH SYNOPSIS ++.TP 16 ++.B tape390_display ++.RB [ \-b | \-\-blink ] ++.br ++.RB [ \-h | \-\-help ] ++.br ++.RB [ \-l | \-\-load ] ++.br ++.RB [ \-t | \-\-type ] ++.br ++.RB [ \-q | \-\-quiet ] ++.br ++.RB [ \-v | \-\-version ] ++.br ++.IR message1 ++.RB [ ++.I message2 ++.RB ] ++.I device ++ ++.SH DESCRIPTION ++\fBtape390_display\fR displays one or two 8-byte messages on the display ++unit of a zSeries tape device. Characters to be displayed include capital ++letters A-Z, numerics 0-9 and special characters. ++However some special characters may not display on all device types. The ++characters that should display on model 3490 are: ++.br ++ '@$#,./()*&+-=%|:_<>?;' and the character. ++.br ++Spaces and shell-sensitive characters have to be quoted. ++ ++.SH OPTIONS ++.TP 8 ++\fB\-h\fR or \fB\-\-help\fR ++Print help text. ++ ++.TP ++\fB\-b\fR or \fB\-\-blink\fR ++Display \fImessage1\fR repeatedly for 2 seconds at half-second intervals. ++This option is ignored if two messages are specified on command line. ++ ++.TP ++\fB\-l\fR or \fB\-\-load\fR ++If this option is given the display request will cause a load request to be ++sent to the automatic tape loader (if installed). The next indexed tape will ++then be loaded if the loader is in 'system' mode. Otherwise the request is ++ignored. ++ ++.TP ++\fB\-q\fR or \fB\-\-quiet\fR ++This option causes the command to run in quiet mode which will suppress ++all warning messages. ++ ++.TP ++\fB\-t\fR \fItype\fR or \fB\-\-type\fR \fItype\fR ++Set the type of the message to be displayed. This influences how long ++the message(s) stay on the display. Available types are: ++ ++.RS ++.TP 16 ++.B standard ++The message(s) stay displayed until the drive executes the next tape ++movement command. This is the default. ++.TP ++.B load ++Displays the message(s) until a tape is loaded. If there already is ++a tape loaded to the device, nothing is displayed at all. ++.TP ++.B unload ++This will display the message(s) until currently loaded tape is unloaded. ++Again, if the drive \fIis\fR currently unloaded there is no output at all. ++.TP ++.B noop ++For testing purposes only, this will access the drive but won't do anything ++at all (no operation). This doesn't seem to work with 3590 tape devices. ++.TP ++.B reload ++This display type \fBrequires\fR two messages. The first message is ++displayed as long as there is a tape loaded up to the time the unload ++operation is completed (or, if there isn't a tape loaded, it will be ++ignored). The second message is displayed as soon as a tape gets loaded ++into the drive. ++.RE ++ ++.TP ++\fB\-v\fR or \fB\-\-version\fR ++Print the S/390 tools package version, the utility version and exit. ++ ++.TP 8 ++\fBmessage1\fR [ \fBmessage2\fR ] ++The message(s) to be displayed. They stay displayed until either the ++ending condition for the message type takes place or the display is ++updated with another message. ++.br ++If two messages are specified, they are alternated on the display. ++Each message is then displayed repeatedly for 2 seconds ++at half-second intervals. ++ ++.TP ++\fBdevice\fR ++The tape device on which the message(s) will be displayed, e.g.: ++.sp ++ \fB/dev/ntibm\fR\fI0\fR ++.br ++ ++.SH EXAMPLES ++\fBtape390_display \-\-blink \-\-type unload "TESTING" /dev/ntibm\fR\fI0\fR ++.RS ++Let the message TESTING blink on the display of the tape unit until the ++tape is removed (or another message is given). If there is no tape in the ++drive, nothing happens. ++.RE ++\fBtape390_display "BACKUP" "COMPLETE" /dev/ntibm\fR\fI0\fR ++.RS ++This will display the messages BACKUP and COMPLETE each for 2 seconds ++until the tape is moved, ejected or (if there isn't a tape in the ++device) inserted. ++.RE ++\fBtape390_display \-\-type reload "UNLOAD" "LOAD" /dev/ntibm\fR\fI0\fR ++.RS ++The UNLOAD message will be displayed if there is a tape inserted and as ++long as the tape isn't removed. After that the LOAD message is displayed ++until a tape is inserted. If there is no tape inserted when the command ++.RE ++\fBtape390_display \-\-load \-\-type load "LOADING" /dev/ntibm\fR\fI0\fR ++.RS ++Causes the device to display the message LOADING until a tape is inserted ++and to instruct the automatic stacker to load the next tape (if the mode ++of operation is \fIsystem\fR). If there already is a tape loaded, nothing ++will happen at all. ++.RE ++ ++.SH AUTHOR ++.nf ++This man-page was written by Despina Papadopoulou ++.nf ++Updates by Stefan Bader ++.fi ++ +diff --git a/tape390/tape390_display.c b/tape390/tape390_display.c +new file mode 100644 +index 00000000..a77b6dba +--- /dev/null ++++ b/tape390/tape390_display.c +@@ -0,0 +1,287 @@ ++/* ++ * tape390_display - Display messages on the display unit of a tape drive ++ * ++ * Copyright IBM Corp. 2002, 2017 ++ * ++ * s390-tools is free software; you can redistribute it and/or modify ++ * it under the terms of the MIT license. See LICENSE for details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "lib/zt_common.h" ++#include "tape390_common.h" ++ ++#define TAPE390_DISPLAY _IOW('d', 1, struct display_struct) ++ ++/* ++ * The TAPE390_DISPLAY belongs to linux-2.5/include/asm-s390/tape390.h ++ * ++ * The TAPE390_DISPLAY ioctl calls the Load Display command ++ * which transfers 17 bytes of data from the channel to the subsystem: ++ * - 1 format control byte, and ++ * - two 8-byte messages ++ * ++ * Format control byte: ++ * 0-2: New Message Overlay ++ * 3: Alternate Messages ++ * 4: Blink Message ++ * 5: Display Low/High Message ++ * 6: Reserved ++ * 7: Automatic Load Request ++ * ++ */ ++#define TAPE_MSGTYPE_STANDARD 0 ++#define TAPE_MSGTYPE_UNLOAD 1 ++#define TAPE_MSGTYPE_LOAD 2 ++#define TAPE_MSGTYPE_NOOP 3 ++#define TAPE_MSGTYPE_UNLOAD_LOAD 7 ++ ++typedef struct display_struct { ++ struct { ++ unsigned char type :3; ++ unsigned char alternate :1; ++ unsigned char blink :1; ++ unsigned char use_second :1; ++ unsigned char reserved :1; ++ unsigned char load_request :1; ++ } cntrl; ++ char message1[8]; ++ char message2[8]; ++} __attribute__ ((packed)) display_struct; ++ ++/* definitions */ ++static char *help_text = ++ "tape390_display: display one or two 8-byte messages on the display" ++ "unit of a tape drive\n" ++ "\n" ++ "Usage: tape390_display \"\" [\"\"] " ++ "" ++ "\n\n" ++ "where are:\n" ++ "\t-b | --blink\n" ++ "\t\twill cause a single message to blink every 2 seconds\n" ++ "\t\t(this option has only effect with a single message)\n" ++ "\t-h | --help\n" ++ "\t\tprint this text\n" ++ "\t-v | --version\n" ++ "\t\toutput version information and exit\n" ++ "\t-l | --load\n" ++ "\t\twill try to load the next tape if the loader is in system mode\n" ++ "\t-q | --quiet\n" ++ "\t\twill suppress all warning messages\n" ++ "\t-t | --type \"standard|load|unload|noop|reload\"\n" ++ "\t\tcontrols how the message is displayed:\n" ++ "\t\t\tstandard = until the next tape movement (default)\n" ++ "\t\t\tload = until a tape is loaded\n" ++ "\t\t\tunload = until a tape is unloaded\n" ++ "\t\t\tnoop = not at all (test purposes)\n" ++ "\t\t\treload = message1 until tape is unloaded and message2\n" ++ "\t\t\t when the next tape is loaded\n" ++ "\n" ++ "Note: Characters to be displayed include capital letters (A-Z), " ++ "numerics (0-9)\n" ++ "and special characters within single quotes. However not all " ++ "characters\n" ++ "might be displayed on all tape devices. Special characters that " ++ "are supported\n" ++ "for 3490 are '@$#,./()*&+-=%|:_<>?;'.\n"; ++ ++static int quiet; ++ ++/* end of definitions */ ++ ++static int typename2int(char *name) ++{ ++ char *typenames[] = { ++ "standard", ++ "unload", ++ "load", ++ "noop", ++ NULL, ++ NULL, ++ NULL, ++ "reload" ++ }; ++ int i; ++ ++ for(i = 0; i < 8; i++) { ++ if(typenames[i] == NULL) ++ continue; ++ if(strcmp(typenames[i], name) == 0) { ++ return i; ++ } ++ } ++ ++ fprintf(stderr, "Invalid message type <%s>\n", name); ++ return -1; ++} ++ ++static void strchkcpy(char *tgt, const char *src) ++{ ++ static char *nowarn = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ++ "@$#,./'()*&+-=%:_<>?; "; ++ char c; ++ char warned; ++ ++ warned = 0; ++ for(c=0; c<8 && *(src+c); c++) { ++ *(tgt+c) = toupper(*(src+c)); ++ if (index(nowarn, *(tgt+c)) == NULL && !quiet && !warned) { ++ fprintf( ++ stderr, ++ "WARNING: Some special characters may not " ++ "display on all device types.\n" ++ ); ++ warned = 1; ++ } ++ } ++} ++ ++int main(int argc, char *argv[]) { ++ ++ char *options = "hblqt:v"; ++ struct option long_options[] = { ++ { "help", no_argument, NULL, 'h' }, ++ { "blink", no_argument, NULL, 'b' }, ++ { "load", no_argument, NULL, 'l' }, ++ { "quiet", no_argument, NULL, 'q' }, ++ { "type", required_argument, NULL, 't' }, ++ { "version", no_argument, NULL, 'v' }, ++ { NULL, 0, NULL, 0 } ++ }; ++ char *pathname; ++ int c; ++ int fd, ret = 0; ++ struct display_struct ds; ++ ++ /* set name of program */ ++ set_prog_name(basename(argv[0])); ++ ++ memset(&ds, 0, sizeof(ds)); ++ ds.cntrl.type = TAPE_MSGTYPE_STANDARD; ++ ++ while( ++ (c = getopt_long(argc, argv, options, long_options, NULL)) ++ != EOF ++ ) { ++ switch(c) { ++ case 'h': ++ fprintf(stdout, "%s", help_text); ++ exit(0); ++ case 'b': ++ ds.cntrl.blink = 1; ++ break; ++ case 'l': ++ ds.cntrl.load_request = 1; ++ break; ++ case 'q': ++ quiet = 1; ++ break; ++ case 't': { ++ int type = typename2int(optarg); ++ ++ if(type < 0) ++ exit(1); ++ ++ ds.cntrl.type = type; ++ break; ++ } ++ case 'v': { ++ printf("tape390_display: zSeries tape " ++ "display control program version %s\n", ++ RELEASE_STRING); ++ printf("Copyright IBM Corp. 2002, 2017\n"); ++ exit(0); ++ } ++ default: ++ fprintf(stderr, "Try '%s --help' for more" ++ " information.\n",prog_name); ++ exit(1); ++ } ++ } ++ ++ if(optind + 2 < argc ) { ++ if( ++ ds.cntrl.type == TAPE_MSGTYPE_LOAD && ++ ds.cntrl.load_request ++ ) { ++ if(!quiet) { ++ fprintf( ++ stderr, ++ "WARNING: " ++ "A message with the " ++ "--load option will only " ++ "display the first" ++ "\nmessage.\n" ++ ); ++ } ++ } else if( ++ ds.cntrl.type == TAPE_MSGTYPE_UNLOAD_LOAD && ++ ds.cntrl.load_request ++ ) { ++ if(!quiet) { ++ fprintf( ++ stderr, ++ "WARNING: " ++ "A message with the " ++ "--load option will only " ++ "display the second" ++ "\nmessage.\n" ++ ); ++ } ++ } else { ++ ds.cntrl.alternate = 1; ++ ++ if(ds.cntrl.blink) { ++ ds.cntrl.blink = 0; ++ if(!quiet) { ++ fprintf( ++ stderr, ++ "Alternate messages " ++ "override blinking\n" ++ ); ++ } ++ } ++ } ++ strchkcpy(ds.message1, argv[optind]); ++ strchkcpy(ds.message2, argv[optind+1]); ++ pathname = argv[optind+2]; ++ } else if(optind + 1 < argc) { ++ if(ds.cntrl.type == TAPE_MSGTYPE_UNLOAD_LOAD) { ++ fprintf(stderr, "Reload message type requires " ++ "two messages.\n"); ++ exit(1); ++ } else if(ds.cntrl.type == TAPE_MSGTYPE_LOAD) { ++ strchkcpy(ds.message2, argv[optind]); ++ } ++ strchkcpy(ds.message1, argv[optind]); ++ pathname = argv[optind+1]; ++ } else { ++ fprintf(stderr, "%s", help_text); ++ exit(1); ++ } ++ ++ /* check whether specified device node is tape */ ++ if (is_not_tape(pathname)) ++ exit(EXIT_MISUSE); ++ ++ /* open device */ ++ fd = open_tape(pathname); ++ ++ ret = ioctl(fd, TAPE390_DISPLAY, &ds); ++ if (ret != 0) ++ fprintf(stderr, "TAPE390_DISPLAY failed\n"); ++ ++ close(fd); ++ ++ return ret; ++} ++ +-- +2.54.0 + diff --git a/s390utils.spec b/s390utils.spec index edaa910..4868530 100644 --- a/s390utils.spec +++ b/s390utils.spec @@ -13,7 +13,7 @@ Name: s390utils Summary: Utilities and daemons for IBM z Systems -Version: 2.41.0 +Version: 2.42.1 Release: 1%{?dist} Epoch: 2 # MIT covers nearly all the files, except init files @@ -46,6 +46,9 @@ Source25: 91-zipl.install Patch0: s390-tools-zipl-invert-script-options.patch Patch1: s390-tools-zipl-blscfg-rpm-nvr-sort.patch +# reverts to keep stability within major RHEL release +Patch10: s390utils-tape-revert.patch + # upstream fixes/updates #Patch100: s390utils-%%{version}-rhel.patch @@ -250,12 +253,14 @@ touch %{buildroot}%{_sysconfdir}/zipl.conf %endif %{_bindir}/genprotimg %{_bindir}/pvattest +%{_bindir}/pvebc %{_bindir}/pvextract-hdr %{_bindir}/pvimg %{_bindir}/pvsecret %{_bindir}/pvverify %{_mandir}/man1/genprotimg.1* %{_mandir}/man1/pvattest.1* +%{_mandir}/man1/pvebc.1* %{_mandir}/man1/pvattest-check.1* %{_mandir}/man1/pvattest-create.1* %{_mandir}/man1/pvattest-perform.1* @@ -593,6 +598,7 @@ getent group zkeyadm > /dev/null || groupadd -r zkeyadm %{_sbindir}/lszfcp %{_sbindir}/opticsmon %{_sbindir}/pai +%{_sbindir}/pvics %{_sbindir}/qetharp %{_sbindir}/qethconf %{_sbindir}/qethqoat @@ -617,6 +623,7 @@ getent group zkeyadm > /dev/null || groupadd -r zkeyadm %{_bindir}/genprotimg %{_bindir}/mk-s390image %{_bindir}/pvapconfig +%{_bindir}/pvebc %{_bindir}/pvimg %{_bindir}/pvinfo %{_bindir}/pvattest @@ -631,6 +638,7 @@ getent group zkeyadm > /dev/null || groupadd -r zkeyadm %ghost %config(noreplace) %{_sysconfdir}/zipl.conf %config(noreplace) %{_sysconfdir}/sysconfig/dumpconf %{_sysconfdir}/mdevctl.d/* +/usr/lib/dracut/modules.d/95sel-ebc/ /usr/lib/dracut/modules.d/99ngdump/ /usr/lib/dracut/dracut.conf.d/99-pkey.conf # own the mdevctl dirs until new release is available @@ -642,7 +650,6 @@ getent group zkeyadm > /dev/null || groupadd -r zkeyadm /lib/s390-tools/lsznet.raw %dir /lib/s390-tools/zfcpdump /lib/s390-tools/zfcpdump/zfcpdump-initrd -/lib/s390-tools/znetcontrolunits %{_libdir}/libekmfweb.so.* %{_libdir}/libkmipclient.so.* %dir %{_libdir}/zkey @@ -658,6 +665,7 @@ getent group zkeyadm > /dev/null || groupadd -r zkeyadm %{_mandir}/man1/pvattest-create.1* %{_mandir}/man1/pvattest-perform.1* %{_mandir}/man1/pvattest-verify.1* +%{_mandir}/man1/pvebc.1* %{_mandir}/man1/pvimg.1* %{_mandir}/man1/pvimg-create.1* %{_mandir}/man1/pvimg-info.1* @@ -681,6 +689,7 @@ getent group zkeyadm > /dev/null || groupadd -r zkeyadm %{_mandir}/man1/zpwr.1* %{_mandir}/man4/prandom.4* %{_mandir}/man5/hsavmcore.conf.5* +%{_mandir}/man5/pvics.yaml.5* %{_mandir}/man8/chccwdev.8* %{_mandir}/man8/chchp.8* %{_mandir}/man8/chcpumf.8* @@ -711,6 +720,7 @@ getent group zkeyadm > /dev/null || groupadd -r zkeyadm %{_mandir}/man8/lszfcp.8* %{_mandir}/man8/opticsmon.8* %{_mandir}/man8/pai.8* +%{_mandir}/man8/pvics.8* %{_mandir}/man8/qetharp.8* %{_mandir}/man8/qethconf.8* %{_mandir}/man8/qethqoat.8* @@ -1108,6 +1118,15 @@ User-space development files for the s390/s390x architecture. %changelog +* Tue Jun 02 2026 Dan Horák - 2:2.42.1-1 +- rebased to 2.42.1 (RHEL-174898) +- hyptop: Backward compatibility options causes other issues (RHEL-166157) +- zipl/boot: Fix stage3 secure boot trailer placement (RHEL-170707) +- SEL-EBC: instrumentation of an SEL initramfs to support early boot customization (RHEL-136433) +- SEL-EBC: tool to build basic SEL-qcow2 image supporting early boot customization (RHEL-136435) +- KVM: Enhance pvimg info command to display additional SE image information (RHEL-73136) +- Resolves: RHEL-174898 RHEL-166157 RHEL-170707 RHEL-136433 RHEL-136435 RHEL-73136 + * Tue Mar 24 2026 Dan Horák - 2:2.41.0-1 - rebased to 2.41.0 (RHEL-136097) - hsci: Automatically set appropriate MTU for HSCI (RHEL-153550) diff --git a/sources b/sources index ef64f7b..dd5160a 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (s390-tools-2.41.0.tar.gz) = 91f5be56c290b933b8a9723d4eead20c17943427343ad70bf05dcebe971e917157696e4296724bf3df498df14944fb264460b704a0874c5f5446dd951a39fae0 -SHA512 (s390-tools-2.41.0-rust-vendor.tar.xz) = 2dff7187cef849df236babd7dbb687853ba8c30386b29b97ebd5a5a12cc607b2d77e68759da8f797d3f3efea3ddd6ed677db21649d2c88c7cdaf1b28c83b6f90 +SHA512 (s390-tools-2.42.1.tar.gz) = 719b000ffc507837f579db8c395cd929151c77e36c598e872cef7cd76b6612f7cd5f8eba87de1df69a446a05ba3a6daa385a4bca2dfdb5b2b52e70cb5a7a197b +SHA512 (s390-tools-2.42.1-rust-vendor.tar.xz) = 7fbae9b43d956e2a9b71b6a0a0928fca9506a191424d63f6df109ddc0ce4efa9df2d0e245ee231602a139642fe7fc25f13680eec27a4aa914be151a39876b945