Compare commits

...

119 Commits

Author SHA1 Message Date
Jan Höppner d8b8114e6f New release s390-tools-2.21.0
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-04-20 13:29:04 +02:00
Mikhail Zaslonko c4e4b926b4 zdump/dfi: Fix segfault due to double free
The problem can happen when dfi_s390mv_init_gen() returns with an error
code to dfi_init() in dfi.c.
Double free condition occurs on zg_close() call at the end of the
while loop in dfi_init() if zg_close() has already been called for the
same file handle at the end of open_dump() function in scope of
dfi_s390mv_init_gen() processing.
This global file handle is not closed during init() call for any
other dump formats. Since it is not reopened/reused after open_dump() call
during multi-volume dump initialization, we should not close it at all.

The problem can be reproduced in the following steps:

1) Install multi-volume dump tool

   # zipl -M mvdump.conf
   Dump target: 2 partitions with a total size of 4732 MB.
   Warning: All information on the following partitions will be lost!
      /dev/dasdb2
      /dev/dasdb3
   Do you want to continue creating multi-volume dump partitions (y/n)?y
   Done.

2) Run zgetdump -i using device (not partition) as a parameter without
   taking actual dump.

   # zgetdump -i /dev/dasdb
   free(): double free detected in tcache 2
   Aborted (core dumped)

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>
2022-04-19 18:37:17 +02:00
Niklas Schnelle 6324f62da7 zpcictl: Add option to trigger firmware reset
With "zpcictl --reset DDDD:BB:FF.F" now causing a fully Linux driven
reset where the Linux kernel does an explicit device driver unbind,
disable and re-enable, let's also expose a way to instead have firmware
perform a device reset by issuing an SCLP with SCLP_ERRNOTIFY_RESET.

When firmware is done resetting the device it will then issue an error
notification with PCI Error Code 0x3a indicating successful reset, which
will subsequently cause the new kernel based automatic recovery
mechanism to perform recovery in coordination with the device driver.
This allows resetting devices without unbinding them from their device
driver and thus without losing related block devices or network
interfaces. This may also be used to test the automatic recovery
mechanism.

Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-04-12 17:18:26 +02:00
Niklas Schnelle 3ade063ea2 zpcictl: Fix race of SCLP reset and Linux recovery
Currently "zpcictl --reset DDDD:BB:FF.F" issues an SCLP call with
SCLP_ERRNOTIFY_AQ_RESET followed by a Linux driven device reset via the
recover sysfs attribute. The latter was introduced with commit
bc0d40c580 ("zpcictl: Initiate recover after reset") because the
firmware driven reset leaves the device in the error state. Now with the
addition of transparent PCI recovery however the situation has changed
as Linux will not leave the device in the error state after the reset
but will instead initiate its automatic recovery flow. With that however
the two mechanisms, automatic PCI recovery and the zpcictl triggered
recovery attribute handler will race against each other.

In practice this is harmless as the automatic recovery is serialized
with the recover attribute and whichever wins the race will do the reset.
The losing side will detect that the original device was removed and
will refrain from causing a double reset.

Letting both mechanisms race against each other is not predictable
behavior though so instead of SCLP_ERRNOTIFY_AQ_RESET issue
a SCLP_ERRNOTIFY_AQ_REPORT_ERROR that will report a device error to the
Support Element but not cause a reset and then predictably reset via the
recover sysfs attribute. If instead a firmware driven reset followed by
the automatic recovery flow is desired the new "--reset-fw" option may
be used.

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>
2022-04-12 17:18:26 +02:00
Viktor Mihajlovski 92a3b30323 genprotimg/check_hostkeydoc: allow to disable default issuer check
The default issuer check may fail if the to-be-verified host key
document was issued and signed by an entity not known at the point
in time check_hostkeydoc was released.

In order to allow verification of the chain of trust for an unknown
but otherwise valid issuer, check_hostkeydoc can be called with
the -d command line option.

This commit also enhances the help text by briefly describing the
command line options and fixes a typo.

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-04-06 16:11:19 +02:00
Viktor Mihajlovski 673ff375d9 genprotimg/check_hostkeydoc: relax default issuer check
While the original default issuer's organizationalUnitName (OU)
was defined as "IBM Z Host Key Signing Service", any OU ending
with "Key Signing Service" is considered legal.

Let's relax the default issuer check by stripping off characters
preceding "Key Signing Service".

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-04-06 16:11:19 +02:00
Ingo Franzki 4e2ebe0370 libseckey: Fix re-enciphering of EP11 secure key
The re-enciphering of EP11 asymmetric secure keys does not work.
First, the result of the re-encipher operation of the private key
part must be copied back into the user supplied key token buffer.
Second, the public key part, i.e. the MACed SubjectPublicKeyInfo
(SPKI) structure must also be re-enciphered (i.e. re-MACed), since
the MAC is calculated with the EP11 master key.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-04-06 16:11:19 +02:00
Marc Hartmayer 78b053326c genprotimg: remove DigiCert root CA pinning
Remove the DigiCert root CA pinning. The root CA used for the chain of trust can
change in the future therefore let's remove this check. If someone wants to
enforce the usage of a specific root CA it can be selected by the genprotimg
command line option `--root-ca $CA`. Make it transparent to the user which root
CA is actually being used by printing the subject name of the root CA to stdout
in verbose mode.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Acked-by: Viktor Mihajlovski <mihajlov@linux.ibm.com>
Reviewed-and-tested-by: Nico Boehr <nrb@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-04-06 16:11:19 +02:00
Peter Oberparleiter ab06a5d88a cpictl: Handle excessive kernel version numbers
Some development kernel versions provide an 8-digit date number like
"20220325" in place of the second kernel sublevel, while the data
format used to send this information to the HMC only supports 16 Bit
numbers. As a result, the HMC displays a seemingly random sublevel
number.

Fix this by replacing excessive sublevel numbers with 0 to ensure that
these numbers are handled consistently.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-04-06 16:11:19 +02:00
Viktor Mihajlovski a0a71efde0 fdasd: Fix endless menu loop on EOF
Hitting CTRL-D anywhere will cause fdasd to go into an endless loop
displaying the main menu over and over again. Killing fdasd (e.g.
via CTR-C) is the only way out.
The issue is that read_line() is just ignoring the resulting EOF
condition on stdin. Subsequent invocations of read_line() will return
immediately and thus cause the loop. A simple fix is to reset stdin
after EOF. A caller of read_line() will see the same behavior as for
EOL with no input.

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-04-06 16:11:19 +02:00
Steffen Maier b4b2202ff5 dbginfo.sh: collect all places where modprobe.d config files could exist
This can now include /lib/modprobe.d/10-unsupported-modules.conf

Strictly speaking, modprobe would only consider *.conf files inside
those directories, but for consistency with the already existing
collection of /etc/modprobe.d instead of /etc/modprobe.d/*.conf,
do the same for the added missing locations.

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-04-06 16:11:19 +02:00
Steffen Maier a26f61c4fe dbginfo.sh: collect config files of systemd-modules-load.service
Recent multipath-tools can depend on this.
https://github.com/opensvc/multipath-tools/commit/a1eabea75e8e0f6072f2b655cae25ec473b006c5
("multipathd.service: drop ExecStartPre for loading dm-multipath")
https://github.com/opensvc/multipath-tools/commit/92f0893ac1f0c9daf7eef8753e6bd9730bcce4c6
("multipath-tools: install modules-load.d/multipath.conf")

This can now also include /usr/lib/modules-load.d/s390-pkey.conf
Complements v2.8.0 commit
dffd41943e ("pkey: Support autoloading kernel pkey module").

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-04-06 16:11:19 +02:00
Javier Martinez Canillas a28b396d9e zipl: make IPL sections defined with BLS to inherit a target field
The target field is required for IPL sections, but the ones populated from
BLS snippets did not have this field. This was only working when using BLS
snippets because IPL sections inherit the target field with "defaultauto".

But that's not the case when using a menu, for example the following zipl
configuration will fail if it's used along with BLS defined IPL sections:
fail when running the zipl tool:

  [defaultboot]
  defaultmenu = menu1

  :menu1
  target = /boot
  1 = linux
  2 = test
  default = 1
  prompt = 1
  timeout = 0

Because "linux" and "test" will be defined using BLS snippets and these
don't have an option to define target fields. Let's make these to always
inherit a target field, either from the [defaultboot] section or a menu
section if there's a defaultmenu defined.

Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/111
Closes: https://github.com/ibm-s390-linux/s390-tools/pull/113
[hoeppner@linux.ibm.com: Fixed a couple of style issues]
Reported-by: Renaud Métrich <rmetrich@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Tested-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-18 14:41:43 +01:00
Juergen Christ 0012eaf68e zcryptctl: Fix some typos
Fix typos in usage and error messages.

Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-18 14:41:21 +01:00
Juergen Christ c22d282e67 zcryptctl: Add control domain handling
Support control domain handling for custom zcrypt device nodes.

Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-18 14:41:21 +01:00
Marc Hartmayer 071522f7d2 editorconfig: py/yaml: use spaces for indentation
Use spaces for the indentation of Python and YAML files.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-18 14:41:21 +01:00
Marc Hartmayer ae7217806b common.mak: remove LINK and LINKXX
Now that we've concluded that the compiler is used for calling the actual
linker, it doesn't make much sense to select a different compiler for linking.
Even worse, it's prone to error. A naive user might try to compile s390-tools
using clang as follows:

  $ make -C genprotimg CC=clang
  ...
  CC      genprotimg/src/utils/curl.o
  LINK    genprotimg/src/genprotimg
  /usr/bin/ld: genprotimg.o: `stderr@@GLIBC_2.2' non-PLT reloc for symbol defined in shared library and accessed from executable (rebuild file with -fPIC ?)
  /usr/bin/ld: final link failed: bad value
  collect2: error: ld returned 1 exit status

Therefore it makes sense to use the same compiler for linking as well.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:49 +01:00
Marc Hartmayer 9f6150db34 common.mak: D=1: use -g3 and -ggdb3 compiler options
Level 3 includes extra information, such as macro definitions.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:49 +01:00
Marc Hartmayer b39bdfbf6e common.mak: W=1: add multiple compiler warning options
Add multiple compiler warning options if `W=1` is set.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:49 +01:00
Jan Höppner 71fe58111c s390-tools: Clean up NO_PIE_* flags
Remove NO_PIE_LINKFLAGS and follow the naming convention by using
LDFLAGS for linker flags. Replace all occurrences accordingly.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:49 +01:00
Jan Höppner 5e46632767 zipl: Use the compiler for linking instead of ld
Instead of directly calling ld, it is recommended to call the compiler
to do the linking. Do that and adapt the linker flags accordingly.

This also fixes build issues with newer binutils as -no-pie has never
been a valid option for ld itself.

See:
https://sourceware.org/bugzilla/show_bug.cgi?id=27050
https://bugs.launchpad.net/ubuntu/+source/s390-tools/+bug/1907789

LD has no user anymore and is removed.

Closes: https://github.com/ibm-s390-tools/s390-tools/pull/106
Reported-by: Lukas Märdian <lukas.maerdian@canonical.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:49 +01:00
Steffen Maier 1bd64f5b0f dbginfo.sh: sort list of environment variables for readability
The "detour" with NUL terminated records ensures that sorting
works as expected for environment variables with values containing
one or more lines and thus '\n' as regular record separator.

Reviewed-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:49 +01:00
Steffen Maier d311506dc4 dbginfo.sh: add hex FCP LUN to multipath FC addressing
Make use of multipath-tools 0.8.9 commit
("libmultipath: add %L path wildcard for 64-bit hex LUN")
https://github.com/opensvc/multipath-tools/commit/260d7cb411fedf49167646ccc8834fd4b88f8005 .
Multipath-tools versions that do not know the format wildcard simply
ignore it and expand to an empty string, so it's backwards compatible.

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:49 +01:00
Steffen Maier 08e4520a4f dbginfo.sh: add multipath info to map paths to FC addressing and prio group
Eases mapping of multipath paths and FCP by-path information
without having to use different tool output and correlate,
such as "multipathd -k'show topo'" and "lszfcp -D".

Possibly the HBA is reported as "[undef]" for zfcp
[without multipath-tools 0.8.9 commit
 ("libmultipath: support host adapter name lookup for s390x ccw bus")
 https://github.com/opensvc/multipath-tools/commit/852a1dfd9488395e9a907ff882a630f11d10935c ]
and the FCP LUN needs to be manually converted from the SCSI LUN in h:c:i:l.

While at it, append correlation information for block device name and
major:minor, as well as all information from a standard 'show paths',
which is the path state 3-tuple and next_check,
plus the number of path failures.

Example output:

$ multipathd -k'show paths format "%w|%a|%r|%p|%i|%d|%D|%t|%T|%o|%0|%C"'
uuid                             |host adapter|target WWPN       |pri|hcil     |dev|dev_t|dm_st |chk_st|dev_st |failures|next_check
3600507640081818ab00000000000025e|[undef]     |0x500507680b2581fa|10 |0:0:0:606|sdb|8:16 |active|ready |running|0       |XXXXXX.... 13/20
3600507640081818ab00000000000025e|[undef]     |0x500507680b2581fb|50 |0:0:1:606|sdc|8:32 |active|ready |running|0       |XX........ 4/20
3600507640081818ab00000000000025e|[undef]     |0x500507680b2681fa|10 |1:0:0:606|sdd|8:48 |active|ready |running|0       |XXXX...... 8/20
3600507640081818ab00000000000025e|[undef]     |0x500507680b2681fb|50 |1:0:1:606|sde|8:64 |active|ready |running|0       |XXXXXXX... 15/20

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:49 +01:00
Harald Freudenberger 46fd42af0c lszcrypt: new option to show the serial numbers of CCA and EP11 cards
The new option -s, long --serial shows the serial numbers of
CCA and EP11 cards.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:49 +01:00
Harald Freudenberger a8b0d7ace8 lszcrypt: new options to filter cards/queues only
New options:
  --cardonly
  --queueonly
which filter the output to show only card or queue information.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:49 +01:00
Harald Freudenberger a29b3c8997 lszcrypt: new options to show only accel, cca or ep11 cards/queues
New options:
  --accelonly
  --ccaonly
  --ep11only
which restrict the output to only cards/queues with the given mode.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:49 +01:00
Harald Freudenberger 27dce3317a lszcrypt: add support for checkstop state
Newer kernel show a sysfs attribute chkstop which displays
the checkstop state of a crypto card. This patch enables
support for lszcrypt to display the checkstop state.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:49 +01:00
Harald Freudenberger 4382901daa lszcrypt: show AP bus msg size limit capability
If there is a max_msg_size attribute for the card
the lszcrypt -c option will show this limit as
  AP bus max message size limit xx Kb

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:45 +01:00
Harald Freudenberger bcbb6fcae6 zcryptstats: add CEX8 support
Add the CEX8 crypto card to the list of known crypto cards.

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>
2022-03-09 12:11:45 +01:00
Harald Freudenberger b16a6d4fe1 lszcrypt: add CEX8S support
Recognize AP type 14 as CEX8S crypto express card.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:11:42 +01:00
Benjamin Block 0d15a07c0a chreipl-fcp-mpath: bundle a pre-cooked version of the man page
On several distributions `pandoc` is not available via the default
repositories, and thus not available in the build environments for the
distribution packages. That means, the man page can't be bundled along
with the packages generated for those distributions.

But since this is a valuable asset for some users, instead of requiring
`pandoc` in order to have a man page be generated during the build, so it
can be installed, bundle a pre-cooked version that corresponds to the
current version of the `README.md` file. This way, the man page can always
be packaged, and is now always installed, even if `ENABLE_DOC` is set to
`0` (the default).

This also means, whenever the `README.md` file is changed, the bundled
man page needs to be regenerated, so it stays in sync. As a safeguard
we also add a checksum of the `README.md` file that is regenerated along
with the man page. This checksum is tested even when `pandoc` is not
available, and the user is notified whenever it runs out of sync (with a
hint as to how to remedy it).

Nothing changes for the compile/installation workflow, if `ENABLE_DOC` is
set to `1`.

Suggested-by: Jens Remus <jremus@linux.ibm.com>
Reviewed-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-03-09 12:08:24 +01:00
Marc Hartmayer 5394cd363c genprotimg: add PV guest dump support
Sometimes dumping a virtual machine from the outside is the only way to
get the data that is needed. This can be the case if a dumping mechanism
like kdump hasn't been configured or data needs to be fetched at a
specific point. Dumping a protected guest from the outside without help
from FW/HW doesn't yield sufficient data to be useful. Hence we now
introduce Protected Virtualization (PV) dump support.

The PV dump support works by integrating the firmware into the dump
process. New Ultravisor calls are used to initiate the dump process,
dump cpu data, dump memory state and lastly complete the dump process.
The guest's data is fully encrypted and can only be decrypted by the
entity that owns the customer communication key for the dumped guest.
Also dumping needs to be allowed via a flag in the SE header.

This patch adds support for PV guest dumps to genprotimg. To prepare a
PV image in order that the PV guest can later be dumped from the
outside, the user has to provide a customer communication key used for
the dump process and he has to set the corresponding control flag. For
specifying the customer communication key a new command line option
`--comm-key` is added and for enabling/disabling the control flag the
command line options `--enable-dump` and `--disable-dump` are added.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Acked-by: Viktor Mihajlovski <mihajlov@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 17:06:33 +01:00
Marc Hartmayer 0906293cd8 genprotimg: --enable-pckmo and --disable-pckmo are mutually exclusive
Declare `--enable-pckmo` and `--disable-pckmo` as mutually exclusive.
Let's define a helper macro for this which allows an easier definition
of mutually exclusive command line flags.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 17:06:33 +01:00
Marc Hartmayer a9e13a2d69 genprotimg: introduce macro for the control flags and sort them
Introduce a private macro for the calculation of the control flags and
sort the flags by bit value.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 17:06:33 +01:00
Philipp Kern ee2c6d4160 zipl: Allow optional entries that are left out when files are missing.
Debian carried a patch forever that allowed zipl to run even if not all
menu items had files attached. If a required file is missing for an
entry (e.g. vmlinuz.old or initrd.img.old) and it is marked as
"optional" in the config, the section will be skipped. This allows
zipl to install after bootstrapping, as booting on s390 still relies
on the kernel/initrd symlinks in the root directory.

Closes: https://github.com/ibm-s390-linux/s390-tools/pull/2
Signed-off-by: Philipp Kern <pkern@debian.org>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
[sth@linux.ibm.com: adapted patches to latest changes, merged patches]
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Alexander Egorenkov 455ad953a9 zdump: Fix /dev/mem reading
This commit makes zgetdump work with /dev/mem again.
zg_seek() should not attempt to verify the given offset for devices before
issuing lseek() because special devices like /dev/mem report 0 in
stat.sb_size.

$ zgetdump -i /dev/mem
zgetdump: Trying to seek past file end "/dev/mem"

Fixes: 11e78cada5 ("zdump: catch attempts to seek past end of file in zg_seek()")
Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen 02a0d12988 dbginfo.sh: (re)group commands by block/scsi
This change will group the commands executed for block and scsi devices
into a section with a comment.
By grouping, we intend to enhance the handling in our runtime.out file
and help to understand the purpose of command groups.

In addition we did get feedback for promoting some commands to the top.

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Sa Liu <saliu@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Reviewed-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen be47b51890 dbginfo.sh: (re)group commands by z device
This change will group the commands executed for Z device subsystem
into a section with a comment.
By grouping, we try to enhance the handling in our runtime.out file and
help to understand the purpose of command groups.

In addition we did get feedback for promoting some commands to the top.
lspci -t was added on request of SMEs during the discussions

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Sa Liu <saliu@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Acked-by: Nicklas Schnelle <Niklas.Schnelle@ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen 2677a4182d dbginfo.sh: (re)group commands by system state
This change will group the commands executed for overall state into a
first section with a comment.
By grouping, we intend to enhance the handling in our runtime.out file
and help to understand the purpose of command groups.

In addition we did get feedback for promoting some commands to the top.

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Sa Liu <saliu@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen 812df795c3 dbginfo.sh: (re)group commands by topic
This change will group the commands executed for crypto, special SW or
specific for a distro into sections with a comment.
By grouping, we intend to enhance the handling in our runtime.out file
and help to understand the purpose of command groups.

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Sa Liu <saliu@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen a0d6edf03c dbginfo.sh: (re)group commands by long output
This change will group the commands with long output into two
sections with a comment.
By grouping, we intend to enhance the handling in our runtime.out file
and help to understand the purpose of command groups.

We did get feedback for moveing some independent long output files to
the end for speed up the scrolling in the upper parts.
Files which already have a separate output file are bundled in a
separate group at the end.

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Sa Liu <saliu@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen 81920f7cfd dbginfo.sh: (re)group commands for network
This change will regroup & reorder the commands executed for network.
By grouping, we intend to enhance the handling in our runtime.out file
and help to understand the purpose of command groups.

In addition we did get feedback for promoting some commands to the top.
"ip -br a" was added on request of SMEs during the discussions

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Sa Liu <saliu@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Acked-by: Sandy Winter <WINTERA@de.ibm.com>
Acked-by: Stefan Raspl <stefan.raspl@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Thomas Richter 40dd63e2ac cpumf/lshwc: Fix missing CPU list invocation
When lshwc is invoked with
 # ./lshwc -a :P
 lshwc: ioctl S390_HWCTR_START: Invalid argument
 #
it returns an error instead of listing all problem state counters
of all online CPUs. The reason is an empty CPU list when it is
omitted and only a counter set is specified. Fix this.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen a8579a0727 dbginfo.sh: replace indents with 8char tab
cleanup of indents according to the guidlines
this patch has no logic changes

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Sa Liu <saliu@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen 2ab27bdaf2 dbginfo.sh: update copyright date
adjust second year field on recent updates

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Thomas Richter 03fef264bd cpumf: Remove unneeded defines.h
With the introduction of libcpumf/libcpumf.a library there is no need
for this file anymore. Its defines have been moved to
include/lib/libcpumf.h are obsolete.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Thomas Richter 927a48e607 cpumf/lshwc: Use libcpumf.a library functions
Use new library functions defined in libcpumf/libcpumf.a

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Thomas Richter fbcb3f384a cpumf/chcpumf-lscpumf: Use libcpumf.a library functions
Use new library functions defined in libcpumf/libcpumf.a

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Thomas Richter c7fe21b019 libcpumf: Create library libcpumf for CPU Measurement functions
Add a function to detect the existence of the CPU Measurement Sampling
Facility on a system.
Add a function which extracts the CPU Measurement Sampling Facility
characteristics on a system, such as
 - minimum sample speed
 - maximum sample speed
 - current CPU speed
 - basic sample size in bytes
 - diagnostic sample size in bytes

Add a function to detect the existence of the CPU Measurement Sampling
Facility on a system and return the current sampling buffer management
characteristics, such as:
 - minimum supported sampling buffer size
 - maximum supported sampling buffer size

Add a function to detect the existence of the CPU Measurement Counting
Facility on a system.
Add a function which extracts the CPU Measurement Counting Facility
characteristics on a system, such as
 - counter first version number
 - counter second version number
 - counter set authorization level

Add a function the returm the PMU type number of a CPU Measurement
Facility device driver. These numbers may vary between boots.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen 50a4740443 dbginfo.sh: replace "which" by builtin command "type" for cmd checks
'which' tool is packaged separately from other core tools and there will
likely be scenarios where this check will fail because 'which' is
unavailable.
The "type" is builtin itself and should solve this problem.
For a built in command, we will not suppress error out -> removing 2>&1.
On this replace - in call_run_command - get cmd_type as variable only once

Reported by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen 164d4817ec dbginfo.sh: check existence of dump2tar before executing
a missing dump2tar command did show misleading error messages
now check it and give clear messages

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen abec41f514 dbginfo.sh: alphabetic order of log- and config files
as order itself does not matter for collection of log and config files,
we decided to use alphabetic order for better maintenance

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Reviewed-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen fcb503ea3c dbginfo.sh: sync excludes in sysfs data collection
critical paths in dump2tar data collection have been already excluded -
this update will sync the excludes in the fall back, running in case
dump2tar is missing or failing on a system
By this we also sync the filtering to match exact the same pattern.

Reported by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Sa Liu <saliu@de.ibm.com>

Fixes: 12c84469fd ("dbginfo.sh: exclude reading page_idle/bitmap sysfs
attribute")
Fixes: b627b8d8e1 ("Initial s390-tools-2.0.0 import")

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen 2eea614bbf dbginfo.sh: unify indents - prettify code
adopt all indents to have the same setting overall - NO logic changes !
tooling: vim used with setting "shiftwidth=8",expandtab,autoindent
  commands "gg=G",":retab"
  some additional line brakes to stay below 100 chars
  and one line added manual before "collect_procfs"

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Joern Siglen 3a13cb43f2 dbginfo.sh: unify console output
use same look over all output

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Peter Oberparleiter e8fca95592 zdev: Fix off-by one errors in cio_ignore handling
chzdev fails to generate correct cio_ignore udev-rules for a CCW device
with device number 0xffff. Also chzdev aborts due to a segmentation
fault when a CCW device with CSSID 0xff is configured. Both issues are
caused by off-by-one errors while interpreting CCW device ID limits
CSSID_MAX, SSID_MAX and DEVNO_MAX.

Fix these errors by correctly interpreting CCW device ID limits.

Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-21 12:54:34 +01:00
Jan Höppner b5604850ab Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-04 12:34:47 +01:00
Jan Höppner 18efac6306 New release s390-tools-2.20.0
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-04 12:34:47 +01:00
Jan Höppner 18f8db2225 bin/mk-authors: Run only on master branch history
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-04 12:34:47 +01:00
Marc Hartmayer f1a13749df genprotimg: pv_comp: remove useless function
The endianness handling is already done before, so there is no need for
this function. Let's remove the useless `uint64_to_uint8_buf` function.

Suggested-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-04 09:50:29 +01:00
Matthew Rosato b5da337d1e zdev: check for errors when removing a devtype setting
Currently, a device type setting being --removed from both the active and
persistent configuration via 'chzdev -t' can result in a scenario where
the setting is not removed from the active configuration (and an error
message is presented) but chzdev still proceeds to remove the setting from
the persistent configuration.
Update this logic so that devtype_remove_settings behaves the same way as
device_remove_settings and only perform the removal when no errors are
encountered.

Reported-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Reviewed-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-04 09:50:29 +01:00
Peter Oberparleiter a67888f36a cpictl: Report extended version information
Extend cpictl to report Linux distribution type and version information,
and another sublevel of Linux kernel version data via the system level
field of the SCLP CPI firmware interface. This data is intended to be
decoded by the IBM Z HMC web-UI to provide users a more detailed view of
Linux software levels installed in LPARs.

For this purpose, the format of the 64-bit system level word is extended
in a compatible way, that is, the meaning of existing fields remains
unchanged while additional data is added to previously unused fields.

The new format is defined as 0xabccddeeeeffgghh, where:
 - a=statistics flags
 - b=distro id
 - c=distro major version
 - d=distro minor version(s)
 - e=kernel sublevel 2
 - f=kernel version
 - g=kernel patchlevel
 - h=kernel sublevel 1

This format will be automatically reported for supported distributions
based on data from /etc/os-release. As before, users can override the
data by specifying a custom system level word in /etc/sysconfig/cpi.

To support manual specification of new data fields, the format of
cpictl's -L command line option and the CPI_SYSTEM_LEVEL environment
variable are extended as follows:

 - 0x<level>

   Specifies the system level as 64 bit hex value

 - [[[flags:]distro_id:distro_version:]kernel_version]

   Specifies the system level as list of optional fields. Any field that
   is omitted is initialized with automatically determined values.

Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Acked-by: Viktor Mihajlovski <mihajlov@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-02 11:54:30 +01:00
Marc Hartmayer e1f174ae22 zipl/libc.h: declare start as __noreturn function
Declare `start` as __noreturn function since the function doesn't
return. Use the gcc/clang built-in function `__builtin_unreachable` to
make clear that `lpsw` and `diag308(DIAG390_IPL, NULL)` doesn't
return (see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html and
https://clang.llvm.org/docs/LanguageExtensions.html#builtin-unreachable).

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-02 11:54:30 +01:00
Marc Hartmayer 7503d88b3b genprotimg/boot: add extended kernel command line support
In the past s390 used a fixed command line length of 896 bytes. This has
changed with newer Linux kernels. There is now a parm area indicating
the maximum command line size. This parm area has always been
initialized to zero, so with old kernels this field would read zero and
we must then assume that only 896 bytes are available.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-02 11:54:30 +01:00
Marc Hartmayer 43039943cd genprotimg/boot: remove useless volatile keyword
There is no reason to declare the variable @psw on the stack as
volatile.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-02 11:54:30 +01:00
Marc Hartmayer b2e02d202a Add EditorConfig configuration
EditorConfig (https://editorconfig.org/) defines a file format for
defining coding styles. The most common editor do either provide native
support or via plugin support for EditorConfig.

This patch adds an EditorConfig configuration for s390-tools.

Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-02 11:54:30 +01:00
Peter Oberparleiter 1faa5d2957 zdev: Fix path resolution for multi-mount point file systems
zdev provides path resolution logic to determine which z-specific
devices contribute to the file system mounted at a specific mount point.
This logic is used by command-line option --by-path, but also to
determine the list of devices needed to enable the root file system.

Path resolution fails when a device provides multiple mount points such
as, for example, when using btrfs subvolumes, or when mounting the same
file system at multiple mount points. The failure is caused by zdev
relying on the MOUNTPOINT attribute of lsblk's output which only
contains a single mount point.

Fix this by making use of lsblk's MOUNTPOINTS attribute that contains
the full list of mount points. Note that MOUNTPOINTS was only introduced
with util-linux v2.37, therefore a fall-back to the old format is
needed.

Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/129
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Reviewed-by: Eduard Shishkin <edward6@linux.ibm.com>
Reported-by: Dan Horák <dan@danny.cz>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-02 11:54:30 +01:00
Thomas Richter d62e075450 cpumf/lshwc.c: Fix CPU list parameter setup for device driver
lshwc allows to specify a list of CPUs, for example

   # ./lshwc -a 2-3,66-68:b
   Date,Time,CPU,CPU_CYCLES(0),INSTRUCTIONS(1),L1I_DIR_WRITES(2),....
   2022-01-21,12:51:54,CPU2,68762,20999,283,14157,601,87255
   2022-01-21,12:51:54,CPU3,70514,21179,288,10654,586,90188
   2022-01-21,12:51:54,CPU4,48504,21018,141,7831,438,78494
   2022-01-21,12:51:54,Total,187780,63196,712,32642,1625,255937
   #

However, as seen on the output, the CPU list is incorrect. It shows
CPUs 2, 3 and 4 even when only CPU 2 and 3 was requested. CPUs 66, 67
and 68 have not been online and can not be displayed.

What happens is a wrong parameter conversion for the device driver.
CPUs 66, 67 and 68 are passed to the device driver as CPUs 2 3 and 4
and that data is returned.

Fix this and submit a CPU list with correct bit ordering:

   # ./lshwc -a 2-3,66-68:b
   Date,Time,CPU,CPU_CYCLES(0),INSTRUCTIONS(1),L1I_DIR_WRITES(2),...
   2022-01-21,12:59:18,CPU2,50753,18042,246,10972,494,60345
   2022-01-21,12:59:18,CPU3,54002,20390,232,9219,511,66033
   2022-01-21,12:59:18,Total,104755,38432,478,20191,1005,126378
   #

Reported-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-02 11:54:30 +01:00
Marc Hartmayer 983233730c zipl: add missing static declarations
Fix Sparse findings like:

 warning: symbol 'hash_table_find' was not declared. Should it be static?

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-02-02 11:54:30 +01:00
Vineeth Vijayan ad024c06e1 zdev: modify the lsblk output parser in lszdev
Since version 2.37.x, with the commit 58b510e58 ("libsmartcols: sanitize
variable names on export output"), util-linux changes the output
characters of lsblk, where the ":" is replaced with an "_". Align the
lsblk output parser function in lszdev as per this change.

Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Suggested-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reported-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Tested-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Eduard Shishkin e2843232d5 zipl/src: make gcc 11.2 happy
Add a prophylactic check that @filename is not NULL before its
dereference.

This addresses the following warning (which is a false positive,
since stat(2) is never called with NULL file name):

job.c:514:13: warning: argument 1 null where non-null expected
[-Wnonnull]
514 | if (stat(filename, &stats)) {
| ^~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/features.h:488,
from /usr/include/errno.h:25,
from job.c:13:
job.c: In function 'check_job_ipl_data':
/usr/include/sys/stat.h:227:12: note: in a call to function
'stat' declared 'nonnull'
227 | extern int __REDIRECT_NTH (stat, (const char *__restrict __file,

Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/127
Reported-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Viktor Mihajlovski b79d17d233 cpictl: Suppress messages for unwritable sysfs files
Under certain conditions, e.g. in a KVM guest, a write operation
to /sys/firmware/cpi/set can result in an error message to
stderr while the script returns with a zero exit code, indicating
success.

This can cause confusion if cpictl is called by systemd due to
the existence of a writable /sys/firmware/cpi/. Let's silence
cpictl when writing to the /sys/firmware/cpi/set. This is OK, as
nothing can be inferred from failure or success from the perspective
of the invoking Linux instance.

Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/120

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle 11b401b599 zipl: move and make check for maximum command line length dynamic
The maximum command line length is now dependent on the kernel image
that is loaded. Therefore move the check to check_common_ipl_data().
This function now reads the new kernel image, and check whether the
command line length is in the allowed range.

The command line size limit in zipl is now set to 64k, which is hopefully
enough.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle 69c5ee2e52 zipl: no need to check for NULL when calling free()
free() accepts NULL pointers, so no need for an extra check.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle 3ee625d74f zipl: add check_common_ipl_data()
There are two places where we check whether the initrd and kernel image
is readably. Add one helper function that checks this. This is also a
preparation for the extended command line handling, so that we have to
add that code in only one location.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle 832268ecb0 zipl: add error_text_section()
There are quite a few places that do:

if (section == NULL) {
	error_text("file '%s'", file);
} else {
	error_text("file '%s' in section '%s'", file, section);
}

Add a helper function to deduplicate that.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle 5fb6434548 zipl: add get_common_components() and finalize_common_address_data()
Most of get_*_components() and finalize_*_address_data() is the same
for normal ip, tape and dump types, so we can unify that.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle 5894e3f700 zipl: add free_common_ipl_data()
Add a small helper function to free the common ipl data to avoid
having the same code duplicated multiple times. Also remove the if()
check before the free as it is allowed to pass NULL pointers to free().

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle e384f06014 zipl: add common ipl data
Each ipl type takes at least a kernel image, parameter line and initrd
parameter. This is duplicated all over the place in the current
implementation. To simplify this, add struct job_common_ipl_data which
will hold this data.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle 1627c6a39f zipl: Support command lines longer than 896 bytes in bootloader
This adds support for long command lines. The boot loader stages
will no longer use a fixed limit when copying the command line, but
will use the maximum length from the kernel image that is being loaded.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle bb8f17a7da zipl: fix tape boot
The assembly code in tape0.S loads the kernel from tape to offset 0x4000.
After loading the kernel it loads the parm file and stores it to the
address provided by zipl. zipl doesn't know about the 0x4000 load offset,
so this address is inside of the kernel image and will silently corrupt
the loaded image in memory.

Fix this by copying the kernel to the final destination before loading
the parm files and initrd. We can do this because we can strip the first
0x10000 bytes like the zipl C code does for non-tape IPL.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle 8b3d3dd4bd zipl: rename COMMAND_LINE_SIZE to LEGACY_COMMAND_LINE_SIZE
Preparation to support command lines that are longer than 896 bytes.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle a5c04e5746 zipl/boot: rewrite setup_commandline()
No need to use memcpy() and carry the length around all the time.
Switch to using strlcpy() to simplify the code.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle c5ae1a41da zipl/boot: add strlcpy implementation
add strlcpy from libutil to the zipl boot mini libc.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:02 +01:00
Sven Schnelle 970c697983 zipl: move command line processing into its own function
Makes the code easier to read.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland<sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:01 +01:00
Sven Schnelle cff4b0384f zipl: move secure boot verification into its own function
Makes the code easier to read.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-01-20 09:35:01 +01:00
Dan Horák 724f800dc5 cpictl: fix permissions
The regular 0755 permission should be sufficient for cpictl.

Link: https://bugzilla.redhat.com/show_bug.cgi?id=2024102
Closes: https://github.com/ibm-s390-linux/s390-tools/pull/124
Signed-off-by: Dan Horák <dan@danny.cz>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 21:48:58 +01:00
Graham Inggs 4cdfe91ca9 README.md: refer to fuse3 instead of fuse
Update READMEs to refer to fuse3 instead of fuse.
Also, update minimum versions and FUSE upstream's homepage

Closes: https://github.com/ibm-s390-linux/s390-tools/pull/117
Signed-off-by: Graham Inggs <ginggs@debian.org>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Graham Inggs a44db0f367 zdump, man pages: remove references to 'nonempty' option
In FUSE 3, nonempty is always true, and has been removed.
By default it is false on FUSE 2.

Therefore, remove 'nonempty' option from zdump and references to
the same in man pages.

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/117
Signed-off-by: Graham Inggs <ginggs@debian.org>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Graham Inggs 03ddcd6267 zdsfs: fix compiler warnings
Compiling against fuse3 shows 'incompatible pointer type' warnings due
to the additional function arguments in the new API.

Therefore, adjust the declarations of zdsfs_getattr() and
zdsfs_readdir() to match.

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/117
Signed-off-by: Graham Inggs <ginggs@debian.org>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Graham Inggs 5c468a220e hmcdrvfs: fix compiler warnings
Compiling against fuse3 shows 'incompatible pointer type' warnings due
to the additional function arguments in the new API.

Therefore, adjust the declarations of hmcdrv_fuse_getattr(),
hmcdrv_fuse_readdir() and hmcdrv_fuse_init() to match.

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/117
Signed-off-by: Graham Inggs <ginggs@debian.org>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Graham Inggs 4ba65eaa74 cmsfs-fuse: fix compiler warnings
Compiling against fuse3 shows 'incompatible pointer type' warnings due
to the additional function arguments in the new API.

Therefore, adjust the declarations of cmsfs_getattr(), cmsfs_readdir(),
cmsfs_utimens(), cmsfs_rename() and cmsfs_truncate() to match.

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/117
Signed-off-by: Graham Inggs <ginggs@debian.org>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Graham Inggs 58cae4fecd zdump: fix compiler warnings
Compiling against fuse3 shows 'incompatible pointer type' warnings due
to the additional function arguments in the new API.

Therefore, adjust the declarations of zfuse_getattr() and
zfuse_readdir() to match.

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/117
Signed-off-by: Graham Inggs <ginggs@debian.org>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Graham Inggs 9b84de4b0a hsavmcore: fix compiler warnings
Compiling against fuse3 shows 'incompatible pointer type' warnings due
to the additional function arguments in the new API.

Therefore, adjust the declarations of vmcore_fuse_getattr() and
vmcore_fuse_readdir() to match.

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/117
Signed-off-by: Graham Inggs <ginggs@debian.org>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Graham Inggs e679a88d88 Switch from fuse2 to fuse3
Fuse 3.0.0 was released in December 2016. The last maintenance release
from the 2.9 branch was in January 2019, and users are encouraged to
transition to the actively developed 3.x branch.
https://github.com/libfuse/libfuse/releases/tag/fuse-2.9.9

Therefore, adapt cmsfs-fuse, hmcdrvfs, hsavmcore, zdsfs and zdump to
the new API, and adapt associated Makefiles to link the new library.

Closes: https://github.com/ibm-s390-linux/s390-tools/issues/116
GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/117
Link: https://bugs.launchpad.net/ubuntu/+source/s390-tools/+bug/1935666
[hoeppner@linux.ibm.com: Add links to commit message]
Signed-off-by: Graham Inggs <ginggs@debian.org>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Benjamin Block 6acf6ed76d chreipl-fcp-mpath: fix directory dependencies for parallel make install
When `make install` is called with parallel execution enabled (e.g.:
`-j2`), the dependencies for the necessary directories are not correct.
The `install` target depends on `install_dirs`, which creates the
necessary directories, and needs to run before any of the
`chreipl-fcp-mpath-install*` targets that have prerequisites on these
directories; but the `chreipl-fcp-mpath-install*` targets have
indirectly the same "hierarchy level" as `install_dirs`, and no direct
dependency on it.

Simplified it looks like this:
    install: install_dirs chreipl-fcp-mpath-install
    chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-udev-rules ...

This works fine with only one job, as `install_dirs` will be satisfied
first, before recursing into any other branch of the dependency tree.
But if we have more than one job, there is nothing in the rules that
prevents Make from working on both branches - `install_dirs` and
`chreipl-fcp-mpath-install` - at the same time, and so
`chreipl-fcp-mpath-install-udev-rules` might run before `install_dirs`,
and end up with a unsatisfied dependency:
    make[2]: *** No rule to make target '/usr/lib/udev/rules.d', needed by 'chreipl-fcp-mpath-install-udev-rules'.  Stop.

Fix this by adding direct dependencies on `install_dirs` for all the
directory prerequisites of `chreipl-fcp-mpath-install*` targets. This
way Make will need to satisfy `install_dirs` before it can work on any
of the other targets, and so the necessary directories will be created
in the correct order.

Reported-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Steffen Maier <maier@linux.ibm.com>
Tested-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Marc Hartmayer e7abf256f6 genprotimg: use NULL and not 0 for a NULL pointer
This fixes the sparse warning:

utils/crypto.c:443:68: warning: Using plain integer as NULL pointer

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Alexander Egorenkov 0d407904dd zdump/zg: Convert print macros to functions which can be mocked
This change allows mocking of print macros in unit tests.
Being able to do this in unit tests, enables us to catch output from
zgetdump functions and test it.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Alexander Egorenkov 2238eb820f zdump/zg: Save errno in _zg_err_errno()
_zg_err_errno() should save the current errno value before calling any
libc functions because they could change it. Failing to do so, may result
in _zg_err_errno() displaying an incorrect error message.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Alexander Egorenkov 81013f0c70 zdump/zg: Convert error and abort macros to functions which can be mocked
This change allows mocking of error/abort macros in unit tests.
Being able to do this in unit tests, enables us to test error conditions w/o
terminating the unit test runner.

The new error functions do not have "noreturn" attribute because
this would make mocking of them in unit tests impossible. We must not
compile these functions as noreturn because we need to return from them
in unit tests and returning from a noreturn function is an undefined
behavior in the C++ standard!

For more details:
- ISO/IEC 14882:2017, Chapter 10.6.8 "Noreturn attribute""
- https://en.cppreference.com/w/cpp/language/attributes/noreturn.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Marc Hartmayer 697c5dc405 zdump: write_dump: use FILE *
Use the more common `FILE *` for writing to the output.

Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Marc Hartmayer e9deec4c62 zdump: copy: add support for file output
It is unusual to write the file output from a tool to stdout. Therefore
add a positional argument to the zgetdump convert action where the
output file can be specified. If no positional argument is given the
output is written to stdout as before and therefore there is no change
in the default behavior.

If the file output already exists an error is returned. The reason for
this is to avoid the situation where an existing dump is accidentally
overwritten by the user.

Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Alexander Egorenkov d60b7770fd zdump/zg.h: Remove extern keyword from function declarations
The keyword extern before a function declaration is not required with
modern C compilers.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Alexander Egorenkov 70925f9aff zdump/df_elf: Introduce symbolic names for note names
To reduce code duplication.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Alexander Egorenkov ef88fac874 zdump: Extract common ELF routines from dfo_elf and move to df_elf
The primary goal of this change is to split DFO ELF module into
multiple smaller ones for better unit testability.

The change doesn't introduce any functionality changes, just shuffling code
around.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Alexander Egorenkov 4bd16ba8ea zdump: Extract dfo_mem_chunk interface from DFO
The primary goal is to separate DFO code into multiple smaller modules
and make it unit testable.

This refactoring only moved the code around w/o changing any functionality.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-12-09 16:19:25 +01:00
Steffen Maier f6a7da141c dbginfo.sh: fix missing syslog for step create_package
Without the fix, readers of syslog / systemd-journal can erroneously
think that dbginfo.sh was incomplete because the last logged step is
"17 of 18".
The fix also makes the missing line appear in dbginfo.log inside the
generated DBGINFO....tgz.
s390-tools v2.17.0 commit b7807d0195 ("dbginfo.sh: Add KVM commands
and rework data collection") turned create_package into a numbered
step.

Snippet of terminal output:

...
17 of 18:  Postprocessing
18 of 18:  Finalizing: Creating archive with collected data
Collected data was saved to:
 >>  /tmp/DBGINFO-....tgz  <<
Please review all collected data before sending to your service organization.

Syslog before:

...
dbginfo.sh[...]: 17 of 18:  Postprocessing
dbginfo.sh[...]: Data collection completed

Syslog after:

...
dbginfo.sh[...]: 17 of 18:  Postprocessing
dbginfo.sh[...]: 18 of 18:  Finalizing: Creating archive with collected data
dbginfo.sh[...]: Data collection completed

Fixes: b7807d0195 ("dbginfo.sh: Add KVM commands and rework data collection")
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-17 15:48:22 +01:00
Benjamin Block 1bbd34e500 chreipl-fcp-mpath: don't compress the manpage before installing it
Remove the call to `gzip` before installing the manpage during the
`make install` call. What and if compression is done should be handled by
the distribution tooling.

This also removes a dependency for the build process.

Reviewed-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-17 15:48:22 +01:00
Benjamin Block c2f8988444 chreipl-fcp-mpath: remove shebang from chreipl-fcp-mpath-common.sh.in
`chreipl-fcp-mpath-common.sh.in` is never executed, only used as argument
for `source` in the udev helper scripts, so the shebang is unnecessary, and
might be confusing.

Also, tools like `rpmlint` from the rpm software management will complain
about this; e.g.:
  s390-tools-chreipl-fcp-mpath.s390x: W: non-executable-script /usr/lib/chreipl-fcp-mpath/chreipl-fcp-mpath-common.sh 644 /bin/bash

Reviewed-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-17 15:48:22 +01:00
Alexander Egorenkov d2990db15f zdump/df_elf.h: Remove unused header include
df_elf.h doesn't use anything from dfo.h

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-17 15:48:22 +01:00
Marc Hartmayer fd3d79335a zdump: dfo_elf: get rid of file local static data
Remove the need to have global file local static data.

Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-17 15:48:22 +01:00
Marc Hartmayer 07b3837e68 zdump: dump_chunks_init: replace 0 with off variable
...to make clear why `off` is initialized to 0 and that all calls to
`dfo_chunk_add` occur for the same reason. For consistency reasons adapt
the `off` value calculation as well.

Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-17 15:48:22 +01:00
Marc Hartmayer 13a1227a02 zdump: notes_init: rename some parameters
Rename the parameter `ptr` of `notes_init` to something meaningful. Since
it points to the start of the notes segment rename it to `segment_start`.
In addition, improve the documentation for the function.

Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-17 15:48:22 +01:00
Marc Hartmayer 52118a8d02 zdump: loads_init: refactor the code
Use `mem_chunk->size` instead of recalculate it. In addition, assign
`p_vaddr` to `p_paddr` to make clear that they must be equal and rename the
parameter `load_offset` to `elf_offset` to make clear that the offset in
the ELF vmcore file is meant. Finally rename `loads_init` to
`load_phdrs_init`.

Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-17 15:48:22 +01:00
Marc Hartmayer ee89b850fe zdump: dfo_elf: notes_init: use PTR_DIFF
Use `PTR_DIFF` since this is exactly what is done here.

Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-17 15:48:22 +01:00
Marc Hartmayer 5160f41079 zdump: PTR_(SUB|ADD) cast result to void pointer
This cast makes the macros easier to use without getting compiler warnings.

e.g.

dfo_elf.c: In function 'dfo_elf_init':
dfo_elf.c:343:20: warning: assignment to 'Elf64_Phdr *' from incompatible pointer type 'char *' [-Wincompatible-pointer-types]
  343 |         phdrs_load = PTR_ADD(phdr_notes, sizeof(Elf64_Phdr) * phdrs_notes_count);

Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-17 15:48:22 +01:00
Steffen Eiden 5b0115fdb4 zdump: refractor PTR_DIFF
PTR_SUB already implements subtraction of pointers. Let's reuse it.

Suggested-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-17 15:48:22 +01:00
Jan Höppner ae305b5158 Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-10 17:05:37 +01:00
110 changed files with 4025 additions and 2353 deletions
+21
View File
@@ -0,0 +1,21 @@
# Check https://editorconfig.org for details
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = tab
tab_width = 8
[*.sh]
shell_variant = bash # used by `shfmt`
[*.y{a,}ml]
indent_style = space
indent_size = 2
[*.py]
indent_style = space
indent_size = 4
+6 -2
View File
@@ -5,7 +5,7 @@ List of all individuals having contributed content to s390-tools
- Alexandra Winter - Alexandra Winter
- Alexey Ishchuk - Alexey Ishchuk
- Andreas Herrmann - Andreas Herrmann
- Andre Wild - André Wild
- Antoinette Kaschner - Antoinette Kaschner
- Arnd Bergmann - Arnd Bergmann
- Axel Wirbser - Axel Wirbser
@@ -19,6 +19,7 @@ List of all individuals having contributed content to s390-tools
- Clemens von Mann - Clemens von Mann
- Colin Walters - Colin Walters
- Dan Horak - Dan Horak
- Dan Horák
- Despina Papadopoulou - Despina Papadopoulou
- Dimitri John Ledkov - Dimitri John Ledkov
- Eberhard Pasch - Eberhard Pasch
@@ -38,6 +39,7 @@ List of all individuals having contributed content to s390-tools
- Fritz Elfert - Fritz Elfert
- Gerald Schaefer - Gerald Schaefer
- Gerhard Tonn - Gerhard Tonn
- Graham Inggs
- Guevenc Guelce - Guevenc Guelce
- Hannes Reinecke - Hannes Reinecke
- Hans-Joachim Picht - Hans-Joachim Picht
@@ -52,7 +54,7 @@ List of all individuals having contributed content to s390-tools
- Ingo Franzki - Ingo Franzki
- Ingo Tuchscherer - Ingo Tuchscherer
- Jan Glauber - Jan Glauber
- Jan Hoeppner - Jan Höppner
- Jan Willeke - Jan Willeke
- Jason J. Herne - Jason J. Herne
- Javier Martinez Canillas - Javier Martinez Canillas
@@ -74,6 +76,7 @@ List of all individuals having contributed content to s390-tools
- Martin Peschke - Martin Peschke
- Martin Petermann - Martin Petermann
- Martin Schwidefsky - Martin Schwidefsky
- Matthew Rosato
- Maxim Shchetynin - Maxim Shchetynin
- Melissa Howland - Melissa Howland
- Michael Ernst - Michael Ernst
@@ -103,6 +106,7 @@ List of all individuals having contributed content to s390-tools
- Stefan Raspl - Stefan Raspl
- Stefan Reimbold - Stefan Reimbold
- Stefan Weinhuber - Stefan Weinhuber
- Steffen Eiden
- Steffen Maier - Steffen Maier
- Steffen Thoss - Steffen Thoss
- Susanne Wintenberger - Susanne Wintenberger
+56
View File
@@ -1,5 +1,61 @@
Release history for s390-tools (MIT version) Release history for s390-tools (MIT version)
-------------------------------------------- --------------------------------------------
* __v2.21.0 (2022-04-20)__
For Linux kernel version: 5.17
Add new tools / libraries:
- libcpumf: Create library libcpumf for CPU Measurement functions
Changes of existing tools:
- chreipl-fcp-mpath: bundle a pre-cooked version of the manpage for build
environments without access to `pandoc`
- dbginfo.sh: Add multipath info to map paths to FC addressing and prio group
- dbginfo.sh: Collect config files of systemd-modules-load.service
- dbginfo.sh: Sort list of environment variables for readability
- dbginfo.sh: Replace "which" by builtin command "type"
- dbginfo.sh: Rework script formatting (indents, order)
- dbginfo.sh: Update sysfs collection (excludes, messages)
- genprotimg: Add Protected Virtualization (PV) dump support
- genprotimg: Remove DigiCert root CA pinning
- lszcrypt: Add CEX8S support
- zcryptctl: Add control domain handling
- zcryptstats: Add CEX8 support
- zipl: Allow optional entries that are left out when files are missing
- zipl: make IPL sections defined with BLS to inherit a target field
- zpcictl: Add option to trigger firmware reset
Bug Fixes:
- cpictl: Handle excessive kernel version numbers
- dbginfo.sh: Collect all places where modprobe.d config files could exist
- fdasd: Fix endless menu loop on EOF
- zdump/dfi: Fix segfault due to double free
- zdump: Fix /dev/mem reading
- zpcictl: Fix race of SCLP reset and Linux recovery
* __v2.20.0 (2022-02-04)__
For Linux kernel version: 5.16
Add new tools / libraries:
- Add EditorConfig configuration
Changes of existing tools:
- s390-tools switches to Fuse 3 as Fuse 2 is deprecated.
Affected tools: cmsfs, hmcdrvfs, hsavmcore, zdsfs, zdump
- chreipl-fcp-mpath: don't compress the manpage before installing it
- cpictl: Report extended version information
- genprotimg: Add extended kernel command line support
- zdev: modify the lsblk output parser in lszdev
- zipl: Add support for longer kernel command lines (now supports up to 64k length)
Bug Fixes:
- cpictl: Suppress messages for unwritable sysfs files
- dbginfo.sh: Fix missing syslog for step create_package
- lshwc: Fix CPU list parameter setup for device driver
- zdev: Check for errors when removing a devtype setting
- zdev: Fix path resolution for multi-mount point file systems
* __v2.19.0 (2021-11-10)__ * __v2.19.0 (2021-11-10)__
For Linux kernel version: 5.15 For Linux kernel version: 5.15
+1 -1
View File
@@ -10,7 +10,7 @@ include common.mak
# #
BASELIB_DIRS = libutil libseckey BASELIB_DIRS = libutil libseckey
LIB_DIRS = libvtoc libzds libdasd libvmdump libccw libvmcp libekmfweb \ LIB_DIRS = libvtoc libzds libdasd libvmdump libccw libvmcp libekmfweb \
libkmipclient libkmipclient libcpumf
TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \ TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \ tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \
vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \ vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
+9 -8
View File
@@ -292,7 +292,7 @@ build options:
| __LIBRARY__ | __BUILD OPTION__ | __TOOLS__ | | __LIBRARY__ | __BUILD OPTION__ | __TOOLS__ |
|----------------|:------------------:|:-------------------------------------:| |----------------|:------------------:|:-------------------------------------:|
| fuse | `HAVE_FUSE` | cmsfs-fuse, zdsfs, hmcdrvfs, zgetdump,| | fuse3 | `HAVE_FUSE` | cmsfs-fuse, zdsfs, hmcdrvfs, zgetdump,|
| | | hsavmcore | | | | hsavmcore |
| zlib | `HAVE_ZLIB` | zgetdump, dump2tar | | zlib | `HAVE_ZLIB` | zgetdump, dump2tar |
| ncurses | `HAVE_NCURSES` | hyptop | | ncurses | `HAVE_NCURSES` | hyptop |
@@ -355,12 +355,12 @@ the different tools are provided:
* cmsfs-fuse/zdsfs/hmcdrvfs/zgetdump: * cmsfs-fuse/zdsfs/hmcdrvfs/zgetdump:
The tools cmsfs-fuse, zdsfs, hmcdrvfs, and zgetdump depend on FUSE. The tools cmsfs-fuse, zdsfs, hmcdrvfs, and zgetdump depend on FUSE.
FUSE is provided by installing the fuse and libfuse packages and by a FUSE is provided by installing the fuse3 and libfuse3 packages and by a
kernel compiled with `CONFIG_FUSE_FS`. For compiling the s390-tools package kernel compiled with `CONFIG_FUSE_FS`. For compiling the s390-tools package
the fuse-devel package is required. the fuse3-devel package is required.
The cmsfs-fuse tool requires FUSE version 2.8.1 or newer for full The cmsfs-fuse tool requires FUSE version 3.0 or newer for full
functionality. functionality.
For further information about FUSE see: http://fuse.sourceforge.net For further information about FUSE see: https://github.com/libfuse/libfuse
* hyptop: * hyptop:
The ncurses-devel package is required to build hyptop. The ncurses-devel package is required to build hyptop.
@@ -456,7 +456,7 @@ the different tools are provided:
`HAVE_JSONC=0`, or `HAVE_LIBCURL=0` to the make invocation. `HAVE_JSONC=0`, or `HAVE_LIBCURL=0` to the make invocation.
* hsavmcore: * hsavmcore:
For building the hsavmcore tool you need fuse version 2.6 and optionally For building the hsavmcore tool you need fuse version 3.0 and optionally
systemd which is enabled by default, to disable systemd support, systemd which is enabled by default, to disable systemd support,
add `HAVE_SYSTEMD=0` to the make invocation. add `HAVE_SYSTEMD=0` to the make invocation.
Tip: you may skip the hsavmcore build by adding `HAVE_FUSE=0` Tip: you may skip the hsavmcore build by adding `HAVE_FUSE=0`
@@ -478,5 +478,6 @@ the different tools are provided:
Summarized: chreipl-fcp-mpath requires GNU Bash, GNU Core Utilities, Summarized: chreipl-fcp-mpath requires GNU Bash, GNU Core Utilities,
util-linux, udev, and multipath-tools. When using `HAVE_DRACUT=1` with the util-linux, udev, and multipath-tools. When using `HAVE_DRACUT=1` with the
make invocation, it also requires dracut. When using `ENABLE_DOC=1` with the make invocation, it also requires dracut. When using `ENABLE_DOC=1` with the
make invocation to build a man page and render the README.md as HTML, make make invocation to build a fresh man page (instead of using the pre-cooked
further requires pandoc, GNU awk, and GNU Gzip for the build process. version) and render the README.md as HTML, make further requires pandoc and
GNU awk for the build process.
+2 -2
View File
@@ -32,7 +32,7 @@ Usage: $cmd [-t LAST_GIT_TAG]
Add all new authors since last release to the $authors_file file. Without Add all new authors since last release to the $authors_file file. Without
the -t option the tool uses the last available git tag as last release. the -t option the tool uses the last available git tag as last release.
The tool should be called form the s390-tools master branch. The tool runs on the s390-tools master branch.
OPTIONS OPTIONS
-t, --tag LAST_GIT_TAG Use git tag LAST_GIT_TAG as starting point -t, --tag LAST_GIT_TAG Use git tag LAST_GIT_TAG as starting point
@@ -116,7 +116,7 @@ echo "$cmd: Adding new authors since tag: $release_tag_last"
# Print authors list without header # Print authors list without header
tail -n +4 $authors_file_path tail -n +4 $authors_file_path
# Add the new authors # Add the new authors
git log --format="- %an" $release_tag_last.. git log --format="- %an" $release_tag_last..master
# Then sort everything and remove duplicates # Then sort everything and remove duplicates
} | sort | uniq > $authors_file_tmp } | sort | uniq > $authors_file_tmp
# Create new AUTHORS file with header ... # Create new AUTHORS file with header ...
@@ -0,0 +1 @@
8e604dab39577678bc9f24bfe5e2ee35354b2f4b1759edd16093157b1ecce9d3 README.md
-2
View File
@@ -9,5 +9,3 @@
/README.html /README.html
/README.pdf /README.pdf
/chreipl-fcp-mpath.md /chreipl-fcp-mpath.md
/chreipl-fcp-mpath.7
/chreipl-fcp-mpath.7.gz
+30 -15
View File
@@ -11,9 +11,9 @@
# - chreipl-fcp-mpath.mak # - chreipl-fcp-mpath.mak
# bash: # bash:
# - bash # - bash
# GNU coreutils:
# - sha256sum
# If $(ENABLE_DOC) is `1`: # If $(ENABLE_DOC) is `1`:
# GNU Gzip:
# - gzip
# GNU awk: # GNU awk:
# - gawk # - gawk
@@ -102,20 +102,41 @@ chreiplzfcpmp-doc-man-meta = \
-V footer="s390-tools $(S390_TOOLS_RELEASE)" -V footer="s390-tools $(S390_TOOLS_RELEASE)"
chreipl-fcp-mpath.7: PANDOCFLAGS += $(chreiplzfcpmp-doc-man-meta) chreipl-fcp-mpath.7: PANDOCFLAGS += $(chreiplzfcpmp-doc-man-meta)
chreipl-fcp-mpath.7: .chreipl-fcp-mpath.7.cksum
.INTERMEDIATE: chreipl-fcp-mpath.md .INTERMEDIATE: chreipl-fcp-mpath.md
chreipl-fcp-mpath.md: README.md chreipl-fcp-mpath.md: README.md
gawk -- '/NOT-IN-MAN \{/,/NOT-IN-MAN \}/ { next } { print }' $(<) > $(@) gawk -- '/NOT-IN-MAN \{/,/NOT-IN-MAN \}/ { next } { print }' $(<) > $(@)
.chreipl-fcp-mpath.7.cksum: README.md
sha256sum $(<) > $(@)
.PHONY: chreipl-fcp-mpath-doc-clean .PHONY: chreipl-fcp-mpath-doc-clean
chreipl-fcp-mpath-doc-clean: chreipl-fcp-mpath-doc-clean:
rm -f README.html README.pdf chreipl-fcp-mpath.md chreipl-fcp-mpath.7 rm -f README.html README.pdf chreipl-fcp-mpath.md
chreipl-fcp-mpath: chreipl-fcp-mpath-doc chreipl-fcp-mpath: chreipl-fcp-mpath-doc
chreipl-fcp-mpath-clean: chreipl-fcp-mpath-doc-clean chreipl-fcp-mpath-clean: chreipl-fcp-mpath-doc-clean
else # $(ENABLE_DOC) != 1
# We bundle a pre-cooked man page with the source-code so that distributions
# don't need `pandoc` in order to be able to ship the man page. As of this
# writing multiple distributions don't have a packaged version of it.
#
# In order to remember to regenerate this pre-cooked version whenever the
# README.md is changed, we also generate a checksum of the README.md, bundle
# that as well, and compare that whenever `make` is called. This way, the
# freshness of the man page can be checked, even if `pandoc` is not available,
# or ENABLE_DOC disabled.
MANPAGE_FRESH := $(shell sha256sum --check .chreipl-fcp-mpath.7.cksum >/dev/null && echo 1 || echo 0)
ifeq ($(MANPAGE_FRESH),0)
$(warning chreipl-fcp-mpath.7 is outdated, please regenerate it by calling `make ENABLE_DOC=1`)
endif endif
endif # $(ENABLE_DOC) == 1
# #
## Install ## Install
# #
@@ -133,6 +154,7 @@ install: chreipl-fcp-mpath-install
# install udev rules # install udev rules
INSTDIRS += $(UDEVRULESDIR) INSTDIRS += $(UDEVRULESDIR)
$(DESTDIR)$(UDEVRULESDIR): install_dirs
.PHONY: chreipl-fcp-mpath-install-udev-rules .PHONY: chreipl-fcp-mpath-install-udev-rules
chreipl-fcp-mpath-install-udev-rules: | $(DESTDIR)$(UDEVRULESDIR) chreipl-fcp-mpath-install-udev-rules: | $(DESTDIR)$(UDEVRULESDIR)
@@ -144,6 +166,7 @@ chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-udev-rules
# install udev helper programs # install udev helper programs
INSTDIRS += $(UDEVDIR) INSTDIRS += $(UDEVDIR)
$(DESTDIR)$(UDEVDIR): install_dirs
.PHONY: chreipl-fcp-mpath-install-udev-helper .PHONY: chreipl-fcp-mpath-install-udev-helper
chreipl-fcp-mpath-install-udev-helper: | $(DESTDIR)$(UDEVDIR) chreipl-fcp-mpath-install-udev-helper: | $(DESTDIR)$(UDEVDIR)
@@ -154,6 +177,7 @@ chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-udev-helper
# install common library files # install common library files
INSTDIRS += $(CHREIPLZFCPMPDIR) INSTDIRS += $(CHREIPLZFCPMPDIR)
$(DESTDIR)$(CHREIPLZFCPMPDIR): install_dirs
.PHONY: chreipl-fcp-mpath-install-libfiles .PHONY: chreipl-fcp-mpath-install-libfiles
chreipl-fcp-mpath-install-libfiles: | $(DESTDIR)$(CHREIPLZFCPMPDIR) chreipl-fcp-mpath-install-libfiles: | $(DESTDIR)$(CHREIPLZFCPMPDIR)
@@ -167,6 +191,7 @@ ifeq ($(HAVE_DRACUT),1)
# install dracut config files # install dracut config files
INSTDIRS += $(DRACUTCONFDIR) INSTDIRS += $(DRACUTCONFDIR)
$(DESTDIR)$(DRACUTCONFDIR): install_dirs
.PHONY: chreipl-fcp-mpath-install-dracut-config .PHONY: chreipl-fcp-mpath-install-dracut-config
chreipl-fcp-mpath-install-dracut-config: | $(DESTDIR)$(DRACUTCONFDIR) chreipl-fcp-mpath-install-dracut-config: | $(DESTDIR)$(DRACUTCONFDIR)
@@ -178,28 +203,18 @@ chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-dracut-config
endif endif
ifeq ($(ENABLE_DOC),1)
# chreipl-fcp-mpath: install man page # chreipl-fcp-mpath: install man page
INSTDIRS += $(MANDIR) INSTDIRS += $(MANDIR)
$(DESTDIR)$(MANDIR)/man7: install_dirs
.PHONY: chreipl-fcp-mpath-install-man-page .PHONY: chreipl-fcp-mpath-install-man-page
chreipl-fcp-mpath-install-man-page: | $(DESTDIR)$(MANDIR)/man7 chreipl-fcp-mpath-install-man-page: | $(DESTDIR)$(MANDIR)/man7
chreipl-fcp-mpath-install-man-page: chreipl-fcp-mpath.7 chreipl-fcp-mpath-install-man-page: chreipl-fcp-mpath.7
$(GZIP) -fk --best chreipl-fcp-mpath.7
$(INSTALL_DATA) -t $(DESTDIR)$(MANDIR)/man7 \ $(INSTALL_DATA) -t $(DESTDIR)$(MANDIR)/man7 \
chreipl-fcp-mpath.7.gz chreipl-fcp-mpath.7
chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-man-page chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-man-page
.PHONY: chreipl-fcp-mpath-install-man-page-clean
chreipl-fcp-mpath-install-man-page-clean:
rm -f chreipl-fcp-mpath.7.gz
chreipl-fcp-mpath-clean: chreipl-fcp-mpath-install-man-page-clean
endif
# #
## Utility ## Utility
# #
+8 -7
View File
@@ -120,19 +120,20 @@ in place, but the toolset has some software dependencies besides the
requirements in section [Requirements](#requirements): requirements in section [Requirements](#requirements):
- GNU Bash; - GNU Bash;
- GNU Core Utilities (mktemp, readlink, sync, truncate); - GNU Core Utilities (mktemp, readlink, sync, truncate, sha256sum);
- util-linux (flock, hexdump, logger); - util-linux (flock, hexdump, logger);
- udev / systemd-udev; - udev / systemd-udev;
- multipath-tools. - multipath-tools.
To make use of the optional dracut configuration you need: dracut. To make use of the optional dracut configuration you need: dracut.
To build and install the documentation (man page) you need: To build a fresh version of the documentation (man page) you need:
- pandoc; - pandoc;
- GNU Core Utilities (date); - GNU Core Utilities (date);
- GNU awk; - GNU awk;
- GNU Gzip.
otherwise the pre-cooked version shipped with the source will be used.
INSTALLATION INSTALLATION
============ ============
@@ -161,7 +162,7 @@ steps and copies the resulting components to their final destination.
| Option | Values | Default | Effect | Option | Values | Default | Effect
| :----- | :----: | :-----: | :----- | :----- | :----: | :-----: | :-----
| HAVE_DRACUT | 0, 1 | 0 | Install a dracut configuration file that includes **chreipl-fcp-mpath** in the initial ramdisks built with **dracut**. | HAVE_DRACUT | 0, 1 | 0 | Install a dracut configuration file that includes **chreipl-fcp-mpath** in the initial ramdisks built with **dracut**.
| ENABLE_DOC | 0, 1 | 0 | Build and install a man page for **chreipl-fcp-mpath**. | ENABLE_DOC | 0, 1 | 0 | Build a fresh version of the man page for **chreipl-fcp-mpath**.
Specify any options as arguments for both the **make** and **make install** Specify any options as arguments for both the **make** and **make install**
command as shown in the following example: command as shown in the following example:
@@ -196,8 +197,8 @@ the boot record to find the new initial ramdisk.
~ # zipl ~ # zipl
With dracut and documentation enabled, **make install** deploys the following With dracut enabled, **make install** deploys the following files to these
files to these default locations: default locations:
/usr/lib/chreipl-fcp-mpath/chreipl-fcp-mpath-common.sh /usr/lib/chreipl-fcp-mpath/chreipl-fcp-mpath-common.sh
/usr/lib/dracut/dracut.conf.d/70-chreipl-fcp-mpath.conf /usr/lib/dracut/dracut.conf.d/70-chreipl-fcp-mpath.conf
@@ -207,7 +208,7 @@ files to these default locations:
/usr/lib/udev/chreipl-fcp-mpath-record-volume-identifier /usr/lib/udev/chreipl-fcp-mpath-record-volume-identifier
/usr/lib/udev/chreipl-fcp-mpath-try-change-ipl-path /usr/lib/udev/chreipl-fcp-mpath-try-change-ipl-path
/usr/lib/udev/rules.d/70-chreipl-fcp-mpath.rules /usr/lib/udev/rules.d/70-chreipl-fcp-mpath.rules
/usr/share/man/man7/chreipl-fcp-mpath.7.gz /usr/share/man/man7/chreipl-fcp-mpath.7
UNINSTALL UNINSTALL
========= =========
@@ -1,4 +1,3 @@
#!/bin/bash
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
# #
# chreipl-fcp-mpath: use multipath information to change FCP IPL target # chreipl-fcp-mpath: use multipath information to change FCP IPL target
+183
View File
@@ -0,0 +1,183 @@
.\" Automatically generated by Pandoc 2.16.1
.\"
.TH "CHREIPL-FCP-MPATH" "7" "2022-02-24" "s390-tools 2.20.0-build-20220224" "Administrator Manual"
.hy
.SH NAME
.PP
chreipl-fcp-mpath - use multipath information for re-IPL path failover
on a running Linux instance
.SH DESCRIPTION
.PP
The IPL process of Linux on Z or LinuxONE from an FCP-attached SCSI
volume uses exactly one path to the volume.
If this path is unavailable, the IPL fails.
.PP
The \f[B]chreipl-fcp-mpath\f[R] toolset monitors \f[B]udev\f[R] events
about paths to the re-IPL volume.
If the currently configured re-IPL path becomes unavailable, the toolset
checks for operational paths to the same volume.
If available, it reconfigures the re-IPL settings to use an operational
path.
.PP
Thus, re-IPL from an FCP-attached SCSI volume can be successful despite
path failures on a running Linux instance if at least one path to the
re-IPL volume remains operational.
.PP
\f[B]Chreipl-fcp-mpath\f[R] requires \f[B]udev\f[R],
\f[B]multipathd\f[R] and \f[B]dm-multipath\f[R].
Once installed, the toolset runs automatically and autonomously.
No user intervention is possible or required.
.PP
Other than installing the toolset, there is no user interface for
\f[B]chreipl-fcp-mpath\f[R].
.SS Requirements
.PP
The \f[B]chreipl-fcp-mpath\f[R] tool has the following requirements on
the Linux instance that is being monitored:
.IP \[bu] 2
The Linux instance must have started successfully, during IPL.
.IP \[bu] 2
The running Linux instance must use \f[B]dm-multipath\f[R] and
\f[B]multipathd\f[R] for the configured re-IPL volume - a volume that
contains a zipl boot record and has one of its paths used in the re-IPL
configuration.
.IP \[bu] 2
\f[B]udev\f[R] must run.
.IP \[bu] 2
The toolset must observe at least one event about the configured re-IPL
path.
Examples for such events are: the SCSI disk comes online, or a path of
the corresponding multipath device goes down or comes back online.
.RS 2
.IP \[bu] 2
The WWID of the re-IPL volume must not change while the Linux instance
is running.
.RE
.IP \[bu] 2
When the configured re-IPL path becomes unavailable while the Linux
instance is running, at least one operational path to the re-IPL volume
must be available, or must become available.
If no such path is available when the Linux instance is rebooted, the
re-IPL path is not changed.
.IP \[bu] 2
The tool assumes that any manually reconfigured re-IPL device is valid
and operational.
.RS 2
.PP
The tool treats a newly configured re-IPL device like the initially
configured re-IPL device.
In particular, if the newly configured re-IPL device fulfills the
requirements of the tool, re-IPL path failover takes place if the
configured re-IPL path becomes unavailable.
.RE
.SS Caution with Manual Changes to the Configured re-IPL Target
.PP
\f[B]chreipl-fcp-mpath\f[R] is designed to accept operator-inititated
changes of the re-IPL device.
However, concurrent changes by the operator and tool driven changes can
result in the operator change being overwritten.
.PP
To avoid this problem, change the re-IPL device only during steady-state
operations, when no path events happen.
Alternatively, make sure that no events are processed while you change
the device.
See EXAMPLES for one way to suspend event processing.
.SH MESSAGES
.PP
During monitoring and event processing, \f[B]chreipl-fcp-mpath\f[R]
writes messages to the syslog.
.PP
When the configured re-IPL path is changed to a different path to the
same volume (priority \f[I]daemon.notice\f[R]):
.RS
.PP
Changed re-IPL path to: <device-bus-id>:<wwpn>:<lun>.
.RE
.PP
When a path event indicates that the last available path has become
non-operational (priority \f[I]daemon.alert\f[R]):
.RS
.PP
The re-IPL device cannot be changed because no operational path to the
re-IPL volume remains.
The next re-IPL might fail unless you re-attach or enable at least one
valid path to the re-IPL volume.
.RE
.PP
When changing the configured re-IPL device failed because of an error
with the used Linux kernel interface (priority \f[I]daemon.crit\f[R]):
.RS
.PP
Changing the re-IPL device failed.
The current re-IPL settings might be inconsistent.
Check and correct the settings (see the README.md of chreipl-fcp-mpath)
to make sure that the current re-IPL device is valid.
.RE
.PP
A failure to change the re-IPL device can indicate an inconsistent
setting that cannot be corrected automatically by
\f[B]chreipl-fcp-mpath\f[R].
As a result, the next re-IPL might fail or might not use the intended
re-IPL device.
.PP
You can use the following tools to check and correct the current
settings:
.IP \[bu] 2
\f[B]lsreipl\f[R] to confirm that the intended re-IPL device is
configured;
.IP \[bu] 2
\f[B]chreipl\f[R] to change the re-IPL device;
.IP \[bu] 2
\f[B]lszfcp\f[R] to inspect the state of available paths to the re-IPL
device.
.SH EXAMPLES
.SS Manual Changes to the Configured re-IPL Device
.PP
As outlined in DESCRIPTION, be cautious when manually changing the
configured re-IPL device.
Assure that your reconfiguration actions do not collide with concurrent
automatic event processing by \f[B]chreipl-fcp-mpath\f[R].
You can avoid such collisions, by stopping event processing, making your
changes, and then re-enabling event processing.
You need \f[I]root\f[R] privileges for running the commands in the
following example:
.IP
.nf
\f[C]
\[ti] # udevadm settle
\[ti] # udevadm control --stop-exec-queue
\[ti] # chreipl ...
\[ti] # udevadm control --start-exec-queue
\f[R]
.fi
.SS Listing messages with journalctl
.PP
If your Linux instance includes \f[B]journalctl\f[R], use the following
command to list all messages that are issued by
\f[B]chreipl-fcp-mpath\f[R]:
.IP
.nf
\f[C]
\[ti] # journalctl -t chreipl-fcp-mpath
\f[R]
.fi
.PP
To list only messages that were issued since the last IPL, use this
command:
.IP
.nf
\f[C]
\[ti] # journalctl -t chreipl-fcp-mpath -b
\f[R]
.fi
.SH REPORTING BUGS
.PP
Use the \f[B]Issues\f[R] functionality on GitHub to report any bugs in
\f[B]chreipl-fcp-mpath\f[R]: s390-tools
Issues (https://github.com/ibm-s390-linux/s390-tools/issues).
.SH SEE ALSO
.PP
\f[B]chreipl\f[R](8), \f[B]dracut\f[R](8), \f[B]journalctl\f[R](1),
\f[B]lsreipl(8)\f[R], \f[B]lszfcp\f[R](8), \f[B]multipath\f[R](8),
\f[B]multipathd\f[R](8), \f[B]udev\f[R](7), \f[B]udevadm\f[R](8),
\f[B]zipl\f[R](8)
+7 -6
View File
@@ -16,17 +16,18 @@ check_dep:
$(call check_dep, \ $(call check_dep, \
"cmsfs-fuse", \ "cmsfs-fuse", \
"fuse.h", \ "fuse.h", \
"fuse-devel or libfuse-dev", \ "fuse3-devel or libfuse3-dev", \
"HAVE_FUSE=0") "HAVE_FUSE=0", \
"-DFUSE_USE_VERSION=30")
all: check_dep cmsfs-fuse all: check_dep cmsfs-fuse
ifneq ($(shell sh -c 'command -v pkg-config'),) ifneq ($(shell sh -c 'command -v pkg-config'),)
FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse) FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse3)
FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse) FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse3)
else else
FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse3
FUSE_LDLIBS = -lfuse FUSE_LDLIBS = -lfuse3
endif endif
ALL_CFLAGS += -DHAVE_SETXATTR $(FUSE_CFLAGS) ALL_CFLAGS += -DHAVE_SETXATTR $(FUSE_CFLAGS)
LDLIBS += $(FUSE_LDLIBS) -lm LDLIBS += $(FUSE_LDLIBS) -lm
-3
View File
@@ -80,9 +80,6 @@ Allow access by other users
\fB\-o\fR allow_root \fB\-o\fR allow_root
Allow access by root Allow access by root
.TP .TP
\fB\-o\fR nonempty
Allow mounts over non\-empty file/dir
.TP
\fB\-o\fR default_permissions \fB\-o\fR default_permissions
Enable permission checking by kernel Enable permission checking by kernel
.TP .TP
+23 -9
View File
@@ -9,7 +9,7 @@
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#define FUSE_USE_VERSION 26 #define FUSE_USE_VERSION 30
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
@@ -1516,7 +1516,7 @@ static void walk_dir_block(struct fst_entry *fst, struct walk_file *walk,
decode_edf_name(file, fst->name, fst->type); decode_edf_name(file, fst->name, fst->type);
if (!file_unlinked(file)) { if (!file_unlinked(file)) {
cache_fst_addr(walk->addr, file); cache_fst_addr(walk->addr, file);
walk->filler(walk->buf, file, NULL, 0); walk->filler(walk->buf, file, NULL, 0, 0);
} }
} }
} }
@@ -1728,8 +1728,11 @@ static off_t get_file_size_logical(struct fst_entry *fst)
return total; return total;
} }
static int cmsfs_getattr(const char *path, struct stat *stbuf) static int cmsfs_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *fi)
{ {
(void) fi;
int mask = (cmsfs.allow_other) ? 0444 : 0440; int mask = (cmsfs.allow_other) ? 0444 : 0440;
struct fst_entry fst; struct fst_entry fst;
@@ -1783,13 +1786,15 @@ static int cmsfs_getattr(const char *path, struct stat *stbuf)
} }
static int cmsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, static int cmsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi) off_t offset, struct fuse_file_info *fi,
enum fuse_readdir_flags flags)
{ {
struct walk_file walk; struct walk_file walk;
struct fst_entry fst; struct fst_entry fst;
(void) offset; (void) offset;
(void) fi; (void) fi;
(void) flags;
/* /*
* Offset is ignored and 0 passed to the filler fn so the whole * Offset is ignored and 0 passed to the filler fn so the whole
@@ -1800,8 +1805,8 @@ static int cmsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
if (strcmp(path, "/") != 0) if (strcmp(path, "/") != 0)
return -ENOENT; return -ENOENT;
filler(buf, ".", NULL, 0); filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0); filler(buf, "..", NULL, 0, 0);
memset(&walk, 0, sizeof(walk)); memset(&walk, 0, sizeof(walk));
/* readdir is possible without open so fi->fh is not set */ /* readdir is possible without open so fi->fh is not set */
@@ -2683,13 +2688,16 @@ static int cmsfs_statfs(const char *path, struct statvfs *buf)
return 0; return 0;
} }
static int cmsfs_utimens(const char *path, const struct timespec ts[2]) static int cmsfs_utimens(const char *path, const struct timespec ts[2],
struct fuse_file_info *fi)
{ {
struct fst_entry fst; struct fst_entry fst;
off_t fst_addr; off_t fst_addr;
struct tm tm; struct tm tm;
int rc; int rc;
(void) fi;
if (cmsfs.readonly) if (cmsfs.readonly)
return -EACCES; return -EACCES;
@@ -2825,7 +2833,8 @@ error:
return rc; return rc;
} }
static int cmsfs_rename(const char *path, const char *new_path) static int cmsfs_rename(const char *path, const char *new_path,
unsigned int flags)
{ {
struct fst_entry fst, fst_new; struct fst_entry fst, fst_new;
off_t fst_addr, fst_addr_new; off_t fst_addr, fst_addr_new;
@@ -2835,6 +2844,8 @@ static int cmsfs_rename(const char *path, const char *new_path)
struct file *f; struct file *f;
int rc; int rc;
(void) flags;
if (cmsfs.readonly) if (cmsfs.readonly)
return -EACCES; return -EACCES;
@@ -3232,13 +3243,16 @@ static void update_fst(struct file *f, off_t addr)
unhide_null_blocks(f); unhide_null_blocks(f);
} }
static int cmsfs_truncate(const char *path, off_t size) static int cmsfs_truncate(const char *path, off_t size,
struct fuse_file_info *fi)
{ {
struct fst_entry fst; struct fst_entry fst;
off_t fst_addr, len; off_t fst_addr, len;
struct file *f; struct file *f;
int rc = 0; int rc = 0;
(void) fi;
if (cmsfs.readonly) if (cmsfs.readonly)
return -EROFS; return -EROFS;
+10 -10
View File
@@ -5,7 +5,7 @@ COMMON_INCLUDED = true
# The variable "DISTRELEASE" should be overwritten in rpm spec files with: # The variable "DISTRELEASE" should be overwritten in rpm spec files with:
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}" # "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
VERSION = 2 VERSION = 2
RELEASE = 19 RELEASE = 21
PATCHLEVEL = 0 PATCHLEVEL = 0
DISTRELEASE = build-$(shell date +%Y%m%d) DISTRELEASE = build-$(shell date +%Y%m%d)
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE) S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
@@ -59,11 +59,8 @@ define cmd_define
endef endef
$(eval $(call cmd_define, AS," AS ",$(CROSS_COMPILE)as)) $(eval $(call cmd_define, AS," AS ",$(CROSS_COMPILE)as))
$(eval $(call cmd_define, LINK," LINK ",$(CROSS_COMPILE)gcc))
$(eval $(call cmd_define, LD," LD ",$(CROSS_COMPILE)ld))
$(eval $(call cmd_define, CC," CC ",$(CROSS_COMPILE)gcc)) $(eval $(call cmd_define, CC," CC ",$(CROSS_COMPILE)gcc))
$(eval $(call cmd_define, HOSTCC," HOSTCC ",gcc)) $(eval $(call cmd_define, HOSTCC," HOSTCC ",gcc))
$(eval $(call cmd_define, LINKXX," LINKXX ",$(CROSS_COMPILE)g++))
$(eval $(call cmd_define, CXX," CXX ",$(CROSS_COMPILE)g++)) $(eval $(call cmd_define, CXX," CXX ",$(CROSS_COMPILE)g++))
$(eval $(call cmd_define, CPP," CPP ",$(CROSS_COMPILE)gcc -E)) $(eval $(call cmd_define, CPP," CPP ",$(CROSS_COMPILE)gcc -E))
$(eval $(call cmd_define, AR," AR ",$(CROSS_COMPILE)ar)) $(eval $(call cmd_define, AR," AR ",$(CROSS_COMPILE)ar))
@@ -84,6 +81,8 @@ CHECKTOOL = $(call echocmd," CHECK ",/$@)$(CHECK_SILENT)
SKIP = echo " SKIP $(call reldir) due to" SKIP = echo " SKIP $(call reldir) due to"
INSTALL = install INSTALL = install
LINK = $(CC)
LINKXX = $(CXX)
CP = cp CP = cp
ifneq ("${V}","1") ifneq ("${V}","1")
MAKEFLAGS += --quiet MAKEFLAGS += --quiet
@@ -92,13 +91,12 @@ ifneq ("${V}","1")
else else
echocmd= echocmd=
endif endif
DEFAULT_CFLAGS = -g -rdynamic -fstack-protector-all -W -Wall -Wformat-security
ifeq ("${W}","1") ifeq ("${W}","1")
DEFAULT_CFLAGS = -g -rdynamic -fstack-protector-all -W -Wall -Wformat-security -Wextra DEFAULT_CFLAGS += -Wextra -Wshadow -Wundef -Wuninitialized -Wdouble-promotion -Wconversion
else
DEFAULT_CFLAGS = -g -rdynamic -fstack-protector-all -W -Wall -Wformat-security
endif endif
ifeq ("${D}","1") ifeq ("${D}","1")
DEFAULT_CFLAGS += -Og DEFAULT_CFLAGS += -Og -g3 -ggdb3
else else
DEFAULT_CFLAGS += -O3 DEFAULT_CFLAGS += -O3
endif endif
@@ -252,11 +250,9 @@ export AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP INSTALL CFLAGS CXXFLAGS \
ifneq ($(shell $(CC_SILENT) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),) ifneq ($(shell $(CC_SILENT) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),)
NO_PIE_CFLAGS := -fno-pie NO_PIE_CFLAGS := -fno-pie
NO_PIE_LINKFLAGS := -no-pie
NO_PIE_LDFLAGS := -no-pie NO_PIE_LDFLAGS := -no-pie
else else
NO_PIE_CFLAGS := NO_PIE_CFLAGS :=
NO_PIE_LINKFLAGS :=
NO_PIE_LDFLAGS := NO_PIE_LDFLAGS :=
endif endif
@@ -371,6 +367,10 @@ $(rootdir)/libvmcp/libvmcp.a: $(rootdir)/libvmcp
$(MAKE) -C $(rootdir)/libvmcp/ libvmcp.a $(MAKE) -C $(rootdir)/libvmcp/ libvmcp.a
.PHONY: $(rootdir)/libvmcp .PHONY: $(rootdir)/libvmcp
$(rootdir)/libcpumf/libcpumf.a: $(rootdir)/libcpumf
$(MAKE) -C $(rootdir)/libcpumf/ libcpumf.a
.PHONY: $(rootdir)/libcpumf
$(rootdir)/libekmfweb/libekmfweb.so: $(rootdir)/libekmfweb $(rootdir)/libekmfweb/libekmfweb.so: $(rootdir)/libekmfweb
$(MAKE) -C $(rootdir)/libekmfweb/ libekmfweb.so $(MAKE) -C $(rootdir)/libekmfweb/ libekmfweb.so
.PHONY: $(rootdir)/libekmfweb .PHONY: $(rootdir)/libekmfweb
+1 -1
View File
@@ -5,7 +5,7 @@ MAN_FILES = lscpumf.1 chcpumf.8 lshwc.1
all: $(BIN_FILES) all: $(BIN_FILES)
libs = $(rootdir)/libutil/libutil.a libs = $(rootdir)/libutil/libutil.a $(rootdir)/libcpumf/libcpumf.a
lscpumf: lscpumf.o $(libs) lscpumf: lscpumf.o $(libs)
chcpumf: chcpumf.o $(libs) chcpumf: chcpumf.o $(libs)
+20 -39
View File
@@ -1,7 +1,7 @@
/* /*
* chcpumf - Change CPU Measurement Facility Characteristics * chcpumf - Change CPU Measurement Facility Characteristics
* *
* Copyright IBM Corp. 2020 * Copyright IBM Corp. 2020, 2022
* *
* s390-tools is free software; you can redistribute it and/or modify * s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
@@ -20,9 +20,9 @@
#include "lib/util_prg.h" #include "lib/util_prg.h"
#include "lib/util_base.h" #include "lib/util_base.h"
#include "defines.h" #include "lib/libcpumf.h"
static int verbose; static unsigned int verbose;
static unsigned long min_sdb, max_sdb; static unsigned long min_sdb, max_sdb;
static struct util_opt opt_vec[] = { static struct util_opt opt_vec[] = {
@@ -85,55 +85,30 @@ static long parse_buffersize(char *string)
return bytes; return bytes;
} }
static void read_sfb(unsigned long *min, unsigned long *max) static int write_sfb(unsigned int min, unsigned int max)
{
unsigned long cur_min_sdb, cur_max_sdb;
FILE *fp;
if (geteuid())
errx(EXIT_FAILURE, "Must run as root");
fp = fopen(PERF_SFB_SIZE, "r");
if (!fp)
err(EXIT_FAILURE, PERF_SFB_SIZE);
if (fscanf(fp, "%ld,%ld", &cur_min_sdb, &cur_max_sdb) != 2) {
fclose(fp);
errx(EXIT_FAILURE, "Can not parse file " PERF_SFB_SIZE);
} else {
if (*min == 0)
*min = cur_min_sdb;
if (*max == 0)
*max = cur_max_sdb;
}
fclose(fp);
if (*min >= *max)
errx(EXIT_FAILURE,
"The specified maximum must be greater than the minimum");
}
static int write_sfb(unsigned long min, unsigned long max)
{ {
int rc = EXIT_SUCCESS; int rc = EXIT_SUCCESS;
char text[64]; char text[64];
size_t len; size_t len;
FILE *fp; FILE *fp;
fp = fopen(PERF_SFB_SIZE, "w"); fp = fopen(S390_CPUMSF_BUFFERSZ, "w");
if (!fp) if (!fp)
err(EXIT_FAILURE, PERF_SFB_SIZE); err(EXIT_FAILURE, S390_CPUMSF_BUFFERSZ);
snprintf(text, sizeof text, "%ld,%ld", min, max); snprintf(text, sizeof(text), "%u,%u", min, max);
len = strlen(text) + 1; len = strlen(text) + 1;
if (fwrite(text, 1, len, fp) != len) { if (fwrite(text, 1, len, fp) != len) {
warn(PERF_SFB_SIZE); warn(S390_CPUMSF_BUFFERSZ);
rc = EXIT_FAILURE; rc = EXIT_FAILURE;
} }
if (fclose(fp)) { if (fclose(fp)) {
warn(PERF_SFB_SIZE); warn(S390_CPUMSF_BUFFERSZ);
rc = EXIT_FAILURE; rc = EXIT_FAILURE;
} }
if (verbose && rc != EXIT_FAILURE) if (verbose && rc != EXIT_FAILURE)
warnx("Sampling buffer sizes:\n" warnx("Sampling buffer sizes:\n"
" Minimum:%7ld sample-data-blocks\n" " Minimum:%7d sample-data-blocks\n"
" Maximum:%7ld sample-data-blocks\n", " Maximum:%7d sample-data-blocks\n",
min, max); min, max);
return rc; return rc;
} }
@@ -183,15 +158,21 @@ static int parse_args(int argc, char **argv)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct stat sbuf; unsigned long my_min, my_max;
util_prg_init(&prg); util_prg_init(&prg);
util_opt_init(opt_vec, NULL); util_opt_init(opt_vec, NULL);
parse_args(argc, argv); parse_args(argc, argv);
if (stat(PERF_PATH PERF_SF, &sbuf)) if (geteuid())
errx(EXIT_FAILURE, "Must run as root");
if (!libcpumf_have_sfb())
errx(EXIT_FAILURE, errx(EXIT_FAILURE,
"No CPU-measurement sampling facility detected"); "No CPU-measurement sampling facility detected");
read_sfb(&min_sdb, &max_sdb); libcpumf_sfb_info(&my_min, &my_max);
if (!min_sdb)
min_sdb = my_min;
if (!max_sdb)
max_sdb = my_max;
return write_sfb(min_sdb, max_sdb); return write_sfb(min_sdb, max_sdb);
} }
-18
View File
@@ -1,18 +0,0 @@
/*
* Defines for CPU Measurement Facility Characteristics
*
* Copyright IBM Corp. 2020
*
* 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 DEFINES_H
#define DEFINES_H
#define PERF_SFB_SIZE "/sys/module/kernel/parameters/cpum_sfb_size"
#define PERF_PATH "/sys/bus/event_source/devices/"
#define PERF_SF "cpum_sf"
#define PERF_CF "cpum_cf"
#endif
+49 -146
View File
@@ -1,7 +1,7 @@
/* /*
* lscpumf - Show CPU Measurement Facility Characteristics * lscpumf - Show CPU Measurement Facility Characteristics
* *
* Copyright IBM Corp. 2020 * Copyright IBM Corp. 2020, 2022
* *
* s390-tools is free software; you can redistribute it and/or modify * s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
@@ -28,7 +28,7 @@
#include "lib/util_opt.h" #include "lib/util_opt.h"
#include "lib/util_prg.h" #include "lib/util_prg.h"
#include "defines.h" #include "lib/libcpumf.h"
#define ACTION_NONE 0 #define ACTION_NONE 0
#define ACTION_INFO 1 #define ACTION_INFO 1
@@ -45,9 +45,6 @@ static bool actions[ACTION_SAMPLE + 1]; /* Specified command line options */
#define PER_SDBT_SIZE 511 #define PER_SDBT_SIZE 511
/* File names to read data from */ /* File names to read data from */
#define SERVICELEVEL "/proc/service_levels"
#define CPUMF_CF_TYPE "/sys/devices/cpum_cf/type"
#define CPUMF_SF_TYPE "/sys/devices/cpum_sf/type"
static struct util_opt opt_vec[] = { static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("OPTIONS"), UTIL_OPT_SECTION("OPTIONS"),
@@ -92,19 +89,18 @@ static char prefix[32]; /* Counter prefix */
static bool show_names; static bool show_names;
static struct cpumf_info { static struct cpumf_info {
unsigned int first_vn; /* Counter facility first version nr */ int first_vn; /* Counter facility first version nr */
unsigned int second_vn; /* Counter facility second version nr */ int second_vn; /* Counter facility second version nr */
unsigned int authorization; /* Counter facility authorization */ int authorization; /* Counter facility authorization */
float version;
unsigned long min_rate; /* Minimum sampling rate */ unsigned long min_rate; /* Minimum sampling rate */
unsigned long max_rate; /* Maximum sampling rate */ unsigned long max_rate; /* Maximum sampling rate */
unsigned long cpu_speed; /* CPU Cycles per micro second */ unsigned long cpu_speed; /* CPU Cycles per micro second */
unsigned int basic_sample_sz; /* # of Bytes per basic sample */ int basic_sample_sz; /* # of Bytes per basic sample */
unsigned int diag_sample_sz; /* # of bytes per diagnostic sample */ int diag_sample_sz; /* # of bytes per diagnostic sample */
unsigned char have_counter; /* CPUM counter facility detected */ bool have_counter; /* CPUM counter facility detected */
unsigned char have_samples; /* CPUM sampling facility detected */ bool have_samples; /* CPUM sampling facility detected */
unsigned int min_sfb; /* Minimum sampling buffer size */ unsigned long min_sfb; /* Minimum sampling buffer size */
unsigned int max_sfb; /* Maximum sampling buffer size */ unsigned long max_sfb; /* Maximum sampling buffer size */
unsigned short machine_type; /* Machine Type */ unsigned short machine_type; /* Machine Type */
} cpumf; } cpumf;
@@ -2565,26 +2561,12 @@ static struct counters cpumcf_z15_counters[] = {
* If perf_pmu_register() kernel function assigned any other (higher) type * If perf_pmu_register() kernel function assigned any other (higher) type
* number, set the prefix to <type-nr>: * number, set the prefix to <type-nr>:
*/ */
static int read_cpumf_type(const char *filename, const char *type) static void set_prefix(int nr)
{ {
int nr, rc = EXIT_FAILURE; if (nr == PERF_TYPE_RAW)
FILE *fp = fopen(filename, "r"); strcat(prefix, "r");
else
if (fp == NULL) { snprintf(prefix, sizeof(prefix), "%d:", nr);
warnx("No CPU-measurement %s facility detected", type);
return rc;
}
if (fscanf(fp, "%d", &nr) != 1) {
warnx("Can not parse file %s", filename);
} else {
rc = EXIT_SUCCESS;
if (nr == PERF_TYPE_RAW)
strcat(prefix, "r");
else
snprintf(prefix, sizeof prefix, "%d:", nr);
}
fclose(fp);
return rc;
} }
/* Parse tool parameters. In case of --help or --version, print /* Parse tool parameters. In case of --help or --version, print
@@ -2661,8 +2643,6 @@ static unsigned long div_ceil(unsigned long a, unsigned long b)
static void show_info(struct cpumf_info *p, int details) static void show_info(struct cpumf_info *p, int details)
{ {
struct stat sbuf;
if (!p->have_counter && !p->have_samples) { if (!p->have_counter && !p->have_samples) {
warnx("No CPU-measurement facilities detected"); warnx("No CPU-measurement facilities detected");
return; return;
@@ -2672,7 +2652,7 @@ static void show_info(struct cpumf_info *p, int details)
if (details) { if (details) {
printf("----------------------------------------------" printf("----------------------------------------------"
"----------------------------\n"); "----------------------------\n");
printf("Version: %3.1f\n\n", p->version); printf("Version: %d.%d\n\n", p->first_vn, p->second_vn);
printf("Authorized counter sets:\n"); printf("Authorized counter sets:\n");
if (!p->authorization) if (!p->authorization)
printf(" None\n"); printf(" None\n");
@@ -2689,8 +2669,7 @@ static void show_info(struct cpumf_info *p, int details)
if (0x8000 & p->authorization) if (0x8000 & p->authorization)
printf(" Coprocessor Group counter Set\n"); printf(" Coprocessor Group counter Set\n");
printf("\nLinux perf event support: %s\n\n", printf("\nLinux perf event support: %s\n\n",
(stat(PERF_PATH PERF_CF, &sbuf)) ? "No" : !p->have_counter ? "No" : "Yes (PMU: cpum_cf)");
"Yes (PMU: " PERF_CF ")");
} }
} else } else
@@ -2718,19 +2697,18 @@ static void show_info(struct cpumf_info *p, int details)
p->diag_sample_sz); p->diag_sample_sz);
printf("\nLinux perf event support: %s\n\n", printf("\nLinux perf event support: %s\n\n",
(stat(PERF_PATH PERF_SF, &sbuf)) ? "No" : !p->have_samples ? "No" : "Yes (PMU: cpum_sf)");
"Yes (PMU: " PERF_SF ")");
printf("Current sampling buffer settings for %s:\n", printf("Current sampling buffer settings for"
PERF_SF); " cpum_sf:\n");
printf(" Basic-sampling mode\n"); printf(" Basic-sampling mode\n");
total = p->min_sfb + div_ceil(p->min_sfb, PER_SDBT_SIZE); total = p->min_sfb + div_ceil(p->min_sfb, PER_SDBT_SIZE);
human(text, sizeof text, PAGE_SIZE * total); human(text, sizeof(text), PAGE_SIZE * total);
printf(" Minimum: %6d" printf(" Minimum: %6ld"
" sample-data-blocks (%6s)\n", p->min_sfb, text); " sample-data-blocks (%6s)\n", p->min_sfb, text);
total = p->max_sfb + div_ceil(p->max_sfb, PER_SDBT_SIZE); total = p->max_sfb + div_ceil(p->max_sfb, PER_SDBT_SIZE);
human(text, sizeof text, PAGE_SIZE * total); human(text, sizeof(text), PAGE_SIZE * total);
printf(" Maximum: %6d" printf(" Maximum: %6ld"
" sample-data-blocks (%6s)\n\n", p->max_sfb, " sample-data-blocks (%6s)\n\n", p->max_sfb,
text); text);
@@ -2739,13 +2717,13 @@ static void show_info(struct cpumf_info *p, int details)
fdiag = div_ceil(p->diag_sample_sz, p->basic_sample_sz); fdiag = div_ceil(p->diag_sample_sz, p->basic_sample_sz);
total = fdiag * p->min_sfb total = fdiag * p->min_sfb
+ div_ceil(p->min_sfb, PER_SDBT_SIZE); + div_ceil(p->min_sfb, PER_SDBT_SIZE);
human(text, sizeof text, PAGE_SIZE * total); human(text, sizeof(text), PAGE_SIZE * total);
printf(" Minimum: %6ld" printf(" Minimum: %6ld"
" sample-data-blocks (%6s)\n", " sample-data-blocks (%6s)\n",
fdiag * p->min_sfb, text); fdiag * p->min_sfb, text);
total = fdiag * p->max_sfb total = fdiag * p->max_sfb
+ div_ceil(p->max_sfb * fdiag, PER_SDBT_SIZE); + div_ceil(p->max_sfb * fdiag, PER_SDBT_SIZE);
human(text, sizeof text, PAGE_SIZE * total); human(text, sizeof(text), PAGE_SIZE * total);
printf(" Maximum: %6ld" printf(" Maximum: %6ld"
" sample-data-blocks (%6s)\n", fdiag * p->max_sfb, " sample-data-blocks (%6s)\n", fdiag * p->max_sfb,
text); text);
@@ -2755,27 +2733,6 @@ static void show_info(struct cpumf_info *p, int details)
warnx("No CPU-measurement sampling facility detected"); warnx("No CPU-measurement sampling facility detected");
} }
/* Read CPU Measurement sampling facility device driver minimum and maximum
* buffer size
*/
static int read_sfb(struct cpumf_info *p)
{
int rc = EXIT_SUCCESS;
FILE *fp;
fp = fopen(PERF_SFB_SIZE, "r");
if (!fp) {
warn(PERF_SFB_SIZE);
return EXIT_FAILURE;
}
if (fscanf(fp, "%d,%d", &p->min_sfb, &p->max_sfb) != 2) {
warnx("Can not parse %s", PERF_SFB_SIZE);
rc = EXIT_FAILURE;
}
fclose(fp);
return rc;
}
/* Set the counter name for z15 counter numbered 265. It is either named /* Set the counter name for z15 counter numbered 265. It is either named
* DFLT_CCERROR or DFLT_CCFINISH, depending on the linux version. The * DFLT_CCERROR or DFLT_CCFINISH, depending on the linux version. The
* counter was renamed from CCERROR to CCFINISH in linux version 5.8. * counter was renamed from CCERROR to CCFINISH in linux version 5.8.
@@ -2803,81 +2760,23 @@ static void read_ccerror(struct counters *cp, size_t cp_cnt)
/* Read allnecessary information from /sysfs file /proc/service_levels */ /* Read allnecessary information from /sysfs file /proc/service_levels */
static int read_info(void) static int read_info(void)
{ {
char *linep = NULL; int rc = EXIT_FAILURE;
size_t line_sz;
ssize_t nbytes;
FILE *slp;
int rc;
memset(&cpumf, 0, sizeof cpumf); cpumf.have_counter = libcpumf_cpumcf_info(&cpumf.first_vn,
slp = fopen(SERVICELEVEL, "r"); &cpumf.second_vn,
if (!slp) { &cpumf.authorization);
warn(SERVICELEVEL); cpumf.have_samples = libcpumf_cpumsf_info(&cpumf.min_rate,
return EXIT_FAILURE; &cpumf.max_rate,
} &cpumf.cpu_speed,
&cpumf.basic_sample_sz,
while ((nbytes = getline(&linep, &line_sz, slp)) != EOF) { &cpumf.diag_sample_sz);
if (!strncmp(linep, "CPU-MF: Counter facility:", 25)) { if (cpumf.have_samples)
rc = sscanf(linep, "CPU-MF: Counter facility:" libcpumf_sfb_info(&cpumf.min_sfb, &cpumf.max_sfb);
" version=%f authorization=%x",
&cpumf.version, &cpumf.authorization);
if (rc != 2) {
warnx("Can not parse line %s", linep);
rc = EXIT_FAILURE;
goto out;
}
cpumf.have_counter = 1;
cpumf.first_vn = (int)cpumf.version;
cpumf.second_vn = ((int)(10 * cpumf.version) % 10);
}
if (!strncmp(linep, "CPU-MF: Sampling facility: min", 30)) {
rc = sscanf(linep, "CPU-MF: Sampling facility:"
" min_rate=%ld max_rate=%ld cpu_speed=%ld",
&cpumf.min_rate, &cpumf.max_rate,
&cpumf.cpu_speed);
if (rc != 3) {
warnx("Can not parse line %s", linep);
rc = EXIT_FAILURE;
goto out;
}
cpumf.have_samples = 1;
}
if (!strncmp(linep, "CPU-MF: Sampling facility: mode=basic", 37)) {
rc = sscanf(linep, "CPU-MF: Sampling facility:"
" mode=basic sample_size=%u",
&cpumf.basic_sample_sz);
if (rc != 1) {
warnx("Can not parse line %s", linep);
rc = EXIT_FAILURE;
goto out;
}
}
if (!strncmp(linep, "CPU-MF: Sampling facility: mode=diag", 36)) {
rc = sscanf(linep, "CPU-MF: Sampling facility:"
" mode=diagnostic sample_size=%u",
&cpumf.diag_sample_sz);
if (rc != 1) {
warnx("Can not parse line %s", linep);
rc = EXIT_FAILURE;
goto out;
}
}
}
if (cpumf.have_samples) {
rc = read_sfb(&cpumf);
if (rc == EXIT_FAILURE)
goto out;
}
cpumf.machine_type = util_arch_machine_type(); cpumf.machine_type = util_arch_machine_type();
if (cpumf.machine_type == UTIL_ARCH_MACHINE_TYPE_UNKNOWN) { if (cpumf.machine_type == UTIL_ARCH_MACHINE_TYPE_UNKNOWN)
rc = EXIT_FAILURE; rc = EXIT_FAILURE;
goto out; else
} rc = EXIT_SUCCESS;
rc = EXIT_SUCCESS;
out:
fclose(slp);
free(linep);
return rc; return rc;
} }
@@ -3051,14 +2950,18 @@ int main(int argc, char **argv)
case ACTION_CNT: case ACTION_CNT:
case ACTION_CNTALL: case ACTION_CNTALL:
all = ret == ACTION_CNTALL; all = ret == ACTION_CNTALL;
ret = read_cpumf_type(CPUMF_CF_TYPE, "counter"); ret = libcpumf_pmutype(S390_CPUMF_CF);
if (ret == EXIT_SUCCESS) if (ret >= EXIT_SUCCESS) {
set_prefix(ret);
show_counter(all); show_counter(all);
}
break; break;
case ACTION_SAMPLE: case ACTION_SAMPLE:
ret = read_cpumf_type(CPUMF_SF_TYPE, "sampling"); ret = libcpumf_pmutype(S390_CPUMF_SF);
if (ret == EXIT_SUCCESS) if (ret >= EXIT_SUCCESS) {
set_prefix(ret);
show_sample(); show_sample();
}
break; break;
case ACTION_NONE: case ACTION_NONE:
case ACTION_INFO: case ACTION_INFO:
+34 -88
View File
@@ -38,17 +38,18 @@
#include "lib/util_path.h" #include "lib/util_path.h"
#include "lib/util_scandir.h" #include "lib/util_scandir.h"
#include "lib/util_libc.h" #include "lib/util_libc.h"
#include "lib/libcpumf.h"
#include "lshwc.h" #include "lshwc.h"
#define SERVICELEVEL "/proc/service_levels"
#define CPUS_ONLINE "/sys/devices/system/cpu/online" #define CPUS_ONLINE "/sys/devices/system/cpu/online"
#define CPUS_POSSIBLE "/sys/devices/system/cpu/possible" #define CPUS_POSSIBLE "/sys/devices/system/cpu/possible"
#define CPUS_KERNELMAX "/sys/devices/system/cpu/kernel_max" #define CPUS_KERNELMAX "/sys/devices/system/cpu/kernel_max"
#define MAXCTRS 512 #define MAXCTRS 512
#define IOCTLSLEEP 60U #define IOCTLSLEEP 60U
static unsigned int read_interval = IOCTLSLEEP, cfvn, csvn, authorization; static unsigned int read_interval = IOCTLSLEEP;
static int cfvn, csvn, authorization;
static unsigned long loop_count = 1; static unsigned long loop_count = 1;
static unsigned char *ioctlbuffer; static unsigned char *ioctlbuffer;
static bool allcpu; static bool allcpu;
@@ -151,20 +152,6 @@ static unsigned long getnumber(char *word, char stopchar)
return no; return no;
} }
/* Remove all whitespace from string. */
static void kill_whitespace(char *s)
{
char *cp = s;
for (; *s != '\0'; ++s) {
if (isspace(*s))
continue;
if (isprint(*s))
*cp++ = *s;
}
*cp = '\0';
}
/* Read file to get all online CPUs */ /* Read file to get all online CPUs */
static bool get_cpus(char *file, char *buf, size_t bufsz) static bool get_cpus(char *file, char *buf, size_t bufsz)
{ {
@@ -242,29 +229,34 @@ static char *show_ctrset(unsigned long set)
static void parse_cpulist(char *parm, struct s390_hwctr_start *start) static void parse_cpulist(char *parm, struct s390_hwctr_start *start)
{ {
uint64_t *words = start->cpumask; uint64_t *words = start->cpumask;
unsigned long i, no_a, no_b; unsigned int i, no_a, no_b;
char *cp, *tokens[16]; /* Used to parse command line params */ cpu_set_t cpulist;
char cpubuf[256]; int rc;
CPU_ZERO(&cpulist);
start->data_bytes = 0; start->data_bytes = 0;
if (parm) start->counter_sets = S390_HWCTR_ALL; /* Default all counter sets */
kill_whitespace(parm);
if (!parm || *parm == ':') { if (parm) { /* CPU list with optional counter set */
/* No CPU list or just counter sets */ char *cp = strchr(parm, ':');
if (!get_cpus(CPUS_ONLINE, cpubuf, sizeof(cpubuf)))
exit(EXIT_FAILURE); if (cp) { /* Handle counter set */
if (parm) *cp = '\0';
strcat(cpubuf, parm); start->counter_sets = parse_ctrset(++cp);
parm = cpubuf; }
if (strlen(parm) > 0) /* Handle CPU list */
rc = libcpumf_cpuset(parm, &cpulist);
else
rc = libcpumf_cpuset_fn(S390_CPUS_ONLINE, &cpulist);
if (rc)
errx(EXIT_FAILURE, "Cannot use CPU list %s", parm);
} else { /* No CPU list and no counter sets */
rc = libcpumf_cpuset_fn(S390_CPUS_ONLINE, &cpulist);
if (rc)
err(EXIT_FAILURE, "Cannot read file " S390_CPUS_ONLINE);
} }
cp = strchr(parm, ':');
if (cp) { /* Handle counter set */
*cp = '\0';
start->counter_sets = parse_ctrset(++cp);
} else {
start->counter_sets = S390_HWCTR_ALL;
}
/* Check with authorized counter sets */ /* Check with authorized counter sets */
if ((start->counter_sets & authorization) != start->counter_sets) { if ((start->counter_sets & authorization) != start->counter_sets) {
unsigned int noton = ~(start->counter_sets & authorization); unsigned int noton = ~(start->counter_sets & authorization);
@@ -276,19 +268,10 @@ static void parse_cpulist(char *parm, struct s390_hwctr_start *start)
show_ctrset(noton)); show_ctrset(noton));
} }
for (i = 0; i < ARRAY_SIZE(tokens) && (tokens[i] = strtok(parm, ",")); for (rc = 0; rc < CPU_SETSIZE; ++rc)
++i, parm = NULL) { if (CPU_ISSET(rc, &cpulist))
cp = strchr(tokens[i], '-'); /* Range character? */ if (!check_set(rc, rc, start->counter_sets))
if (cp) { errx(EXIT_FAILURE, "Invalid CPU %d", rc);
no_a = getnumber(tokens[i], *cp);
no_b = getnumber(++cp, '\0');
} else {
no_b = getnumber(tokens[i], '\0');
no_a = no_b;
}
if (!check_set(no_a, no_b, start->counter_sets))
errx(EXIT_FAILURE, "Invalid CPU list %s", tokens[i]);
}
/* Convert the CPU list to a bitmask for kernel cpumask_t */ /* Convert the CPU list to a bitmask for kernel cpumask_t */
for (i = 0, no_b = 0; i < max_possible_cpus; ++i) { for (i = 0, no_b = 0; i < max_possible_cpus; ++i) {
@@ -298,14 +281,8 @@ static void parse_cpulist(char *parm, struct s390_hwctr_start *start)
words[no_b] |= 1ULL << no_a; words[no_b] |= 1ULL << no_a;
} }
} }
/* no_b is highest used index, swap array */ /* no_b is highest used index */
start->cpumask_len = (no_b + 1) * 8; start->cpumask_len = (no_b + 1) * CHAR_BIT;
for (no_a = 0; no_a < no_b; ++no_a, --no_b) {
uint64_t tmp = words[no_a];
words[no_a] = words[no_b];
words[no_b] = tmp;
}
start->version = S390_HWCTR_START_VERSION; start->version = S390_HWCTR_START_VERSION;
} }
@@ -638,37 +615,6 @@ static int do_it(char *s)
return rc ? EXIT_FAILURE : EXIT_SUCCESS; return rc ? EXIT_FAILURE : EXIT_SUCCESS;
} }
/* Read counter first and second version number */
static bool get_cvn(void)
{
char *linep = NULL;
bool good = false;
size_t line_sz;
ssize_t nbytes;
FILE *slp;
slp = fopen(SERVICELEVEL, "r");
if (!slp) {
warn(SERVICELEVEL);
return false;
}
while ((nbytes = getline(&linep, &line_sz, slp)) != EOF) {
if (!strncmp(linep, "CPU-MF: Counter facility:", 25)) {
int rc;
rc = sscanf(linep, "CPU-MF: Counter facility: version=%d.%d authorization=%x",
&cfvn, &csvn, &authorization);
good = rc == 3;
if (!good)
warnx("Cannot parse line %s", linep);
break;
}
}
fclose(slp);
free(linep);
return good;
}
static struct util_opt opt_vec[] = { static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("OPTIONS"), UTIL_OPT_SECTION("OPTIONS"),
{ {
@@ -752,7 +698,7 @@ int main(int argc, char **argv)
} }
have_support(); have_support();
if (!get_cvn()) if (!libcpumf_cpumcf_info(&cfvn, &csvn, &authorization))
return EXIT_FAILURE; return EXIT_FAILURE;
if (!check_setpossible()) if (!check_setpossible())
return EXIT_FAILURE; return EXIT_FAILURE;
+3 -1
View File
@@ -408,8 +408,10 @@ static int read_line(void)
{ {
bzero(line_buffer, LINE_LENGTH); bzero(line_buffer, LINE_LENGTH);
line_ptr = line_buffer; line_ptr = line_buffer;
if (!fgets(line_buffer, LINE_LENGTH, stdin)) if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
clearerr(stdin);
return 0; return 0;
}
while (*line_ptr && !isgraph(*line_ptr)) while (*line_ptr && !isgraph(*line_ptr))
line_ptr++; line_ptr++;
+3 -3
View File
@@ -74,9 +74,9 @@ stage3b_reloc.elf:
%.elf: %.o %.elf: %.o
case $* in \ case $* in \
stage3a) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3a.lds";; \ stage3a) SFLAGS="$(NO_PIE_LDFLAGS) -nostdlib -Wl,-T,stage3a.lds";; \
stage3b) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3b.lds";; \ stage3b) SFLAGS="$(NO_PIE_LDFLAGS) -nostdlib -Wl,-T,stage3b.lds";; \
stage3b_reloc) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-estage3b_reloc_start,-Ttext,0";; \ stage3b_reloc) SFLAGS="$(NO_PIE_LDFLAGS) -nostdlib -Wl,-estage3b_reloc_start,-Ttext,0";; \
esac; \ esac; \
$(LINK) $$SFLAGS -m64 $(filter %.o, $^) -o $@ $(LINK) $$SFLAGS -m64 $(filter %.o, $^) -o $@
@chmod a-x $@ @chmod a-x $@
+14 -4
View File
@@ -28,13 +28,23 @@ static inline void __noreturn load_psw(struct psw_t psw)
; ;
} }
static unsigned long get_kernel_cmdline_size(void)
{
unsigned long size = *(volatile unsigned long *)MAX_COMMAND_LINE_SIZE;
if (size != 0)
return size;
return LEGACY_COMMAND_LINE_SIZE;
}
void __noreturn start(void) void __noreturn start(void)
{ {
volatile struct stage3b_args *args = &loader_parms; volatile struct stage3b_args *args = &loader_parms;
volatile struct memblob *kernel = &args->kernel; volatile struct memblob *kernel = &args->kernel;
volatile struct memblob *cmdline = &args->cmdline; volatile struct memblob *cmdline = &args->cmdline;
volatile struct memblob *initrd = &args->initrd; volatile struct memblob *initrd = &args->initrd;
volatile struct psw_t psw = args->psw; struct psw_t psw = args->psw;
/* set up ASCII and line-mode */ /* set up ASCII and line-mode */
sclp_setup(SCLP_LINE_ASCII_INIT); sclp_setup(SCLP_LINE_ASCII_INIT);
@@ -42,14 +52,14 @@ void __noreturn start(void)
if (kernel->size < IMAGE_LOAD_ADDRESS) if (kernel->size < IMAGE_LOAD_ADDRESS)
panic(EINTERNAL, "Invalid kernel\n"); panic(EINTERNAL, "Invalid kernel\n");
if (cmdline->size > COMMAND_LINE_SIZE)
panic(EINTERNAL, "Command line is too large\n");
/* move the kernel and cut the kernel header */ /* move the kernel and cut the kernel header */
memmove((void *)IMAGE_LOAD_ADDRESS, memmove((void *)IMAGE_LOAD_ADDRESS,
(void *)(kernel->src + IMAGE_LOAD_ADDRESS), (void *)(kernel->src + IMAGE_LOAD_ADDRESS),
kernel->size - IMAGE_LOAD_ADDRESS); kernel->size - IMAGE_LOAD_ADDRESS);
if (cmdline->size > get_kernel_cmdline_size())
panic(EINTERNAL, "Command line is too large\n");
/* move the kernel cmdline */ /* move the kernel cmdline */
memmove((void *)COMMAND_LINE, memmove((void *)COMMAND_LINE,
(void *)cmdline->src, (void *)cmdline->src,
+28 -14
View File
@@ -87,13 +87,23 @@ CRLs. Optional.
.TP .TP
\fB\-\-root\-ca\fR=\fI\,FILE\/\fR \fB\-\-root\-ca\fR=\fI\,FILE\/\fR
Specifies the root CA certificate for the verification. If omitted, Specifies the root CA certificate for the verification. If omitted,
the DigiCert root CA certificate installed on the system is used. Use the system wide root CAs installed on the system is used. Use
this only if you trust the specified certificate. Optional. this only if you trust the specified certificate. Optional.
.TP .TP
\fB\-\-no-verify\fR \fB\-\-no-verify\fR
Do not require the host-key documents to be valid. For testing Do not require the host-key documents to be valid. For testing
purposes, do not use for a production image. Optional. purposes, do not use for a production image. Optional.
.TP .TP
\fB\-\-comm\-key\fR=\fI\,FILE\/\fR
Specifies the encryption key you want to use for the PV guest dump. Use a
secure, random, plaintext AES-256 GCM key. Optional.
.TP
\fB\-\-enable\-dump\fR
Enable PV guest dumps. Requires the \fB\-\-comm-key\fR option. Optional.
.TP
\fB\-\-disable\-dump\fR
Disable PV guest dumps. This is the default. Optional.
.TP
\fB\-\-enable\-pckmo\fR \fB\-\-enable\-pckmo\fR
Enable the support for the DEA, TDEA, AES, and ECC PCKMO key encryption Enable the support for the DEA, TDEA, AES, and ECC PCKMO key encryption
functions. This is the default. Optional. functions. This is the default. Optional.
@@ -105,21 +115,25 @@ functions. Optional.
\fB\-v\fR, \fB\-\-version\fR \fB\-v\fR, \fB\-\-version\fR
Prints version information, then exits. Prints version information, then exits.
.SH EXAMPLE .SH EXAMPLES
These are examples to generate a protected virtualization image in
\fI\,/boot/vmlinuz.pv\/\fR, using the kernel file \fI\,vmlinuz\/\fR, the
initrd in \fI\,initramfs\/\fR, the kernel parameters contained in
\fI\,parmfile\/\fR, the intermediate CA in \fI\,DigiCertCA.crt\/\fR, the
IBM Z signing key in \fI\,ibm-z-host-key-signing.crt\/\fR, and the
host-key document in \fI\,host_key.crt\/\fR. An AES-256 GCM key is stored in
\fI\,comm-key\/\fR, which is used for the PV guest dump support in the second
example.
Generate a protected virtualization image:
.PP .PP
Generate a protected virtualization image in .B genprotimg \-i \fI\,vmlinuz\/\fR \-r \fI\,initramfs\/\fR \-p \fI\,parmfile\/\fR \-k \fI\,host_key.crt\/\fR \-C \fI\,ibm-z-host-key-signing.crt\/\fR \-C \fI\,DigiCertCA.crt\fR \-o \fI\,/boot/vmlinuz.pv\/\fR
\fI\,/boot/vmlinuz.pv\/\fR, using the kernel file \fI\,vmlinuz\/\fR,
the initrd in \fI\,initramfs\/\fR, the kernel parameters contained in Generate a protected virtualization image with PV guest dump support:
\fI\,parmfile\/\fR, the intermediate CA in \fI\,DigiCertCA.crt\/\fR,
the IBM Z signing key in \fI\,ibm-z-host-key-signing.crt\/\fR, and the
host-key document in \fI\,host_key.crt\/\fR:
.PP
.Vb 1
.EX
\& genprotimg \-i \fI\,vmlinuz\/\fR \-r \fI\,initramfs\/\fR \-p \fI\,parmfile\/\fR \-k \fI\,host_key.crt\/\fR \-C \fI\,ibm-z-host-key-signing.crt\/\fR \-C \fI\,DigiCertCA.crt \-o \fI\,/boot/vmlinuz.pv\/\fR
.EE
.Ve
.PP .PP
.B genprotimg \-i \fI\,vmlinuz\/\fR \-r \fI\,initramfs\/\fR \-p \fI\,parmfile\/\fR \-k \fI\,host_key.crt\/\fR \-C \fI\,ibm-z-host-key-signing.crt\/\fR \-C \fI\,DigiCertCA.crt\fR \-o \fI\,/boot/vmlinuz.pv\/\fR \-\-enable\-dump \-\-comm\-key \fI\,comm-key\fR
.SH NOTES .SH NOTES
.IP "1." 4 .IP "1." 4
+34 -9
View File
@@ -23,6 +23,7 @@ BODY_FILE=$(mktemp)
ISSUER_DN_FILE=$(mktemp) ISSUER_DN_FILE=$(mktemp)
SUBJECT_DN_FILE=$(mktemp) SUBJECT_DN_FILE=$(mktemp)
DEF_ISSUER_DN_FILE=$(mktemp) DEF_ISSUER_DN_FILE=$(mktemp)
CANONICAL_ISSUER_DN_FILE=$(mktemp)
CRL_SERIAL_FILE=$(mktemp) CRL_SERIAL_FILE=$(mktemp)
# Cleanup on exit # Cleanup on exit
@@ -30,7 +31,7 @@ cleanup()
{ {
rm -f $ISSUER_PUBKEY_FILE $SIGNATURE_FILE $BODY_FILE \ rm -f $ISSUER_PUBKEY_FILE $SIGNATURE_FILE $BODY_FILE \
$ISSUER_DN_FILE $SUBJECT_DN_FILE $DEF_ISSUER_DN_FILE \ $ISSUER_DN_FILE $SUBJECT_DN_FILE $DEF_ISSUER_DN_FILE \
$CRL_SERIAL_FILE $CANONICAL_ISSUER_DN_FILE $CRL_SERIAL_FILE
} }
trap cleanup EXIT trap cleanup EXIT
@@ -47,13 +48,21 @@ set -e
usage() usage()
{ {
cat <<-EOF cat <<-EOF
Usage: `basename $1` host-key-doc signing-key-cert [-c CA-cert] [-r CRL] Usage: `basename $1` [-d] [-c CA-cert] [-r CRL] host-key-doc signing-key-cert
Verify an IBM Secure Execution host key document against Verify an IBM Secure Execution host key document against
a signing key. a signing key.
Options:
-d disable default issuer check of host-key-doc
-c CA-cert trusted CA certificate
-r CRL list of revoked host-key-docs
Note that in order to have the full trust chain verified Note that in order to have the full trust chain verified
it is necessary to provide the issueing CA's certificate. it is necessary to provide the issuing CA's certificate.
The default issuer check may be disabled if a non-default
signing key certificate needs to be verified against the
CA certificate.
EOF EOF
} }
@@ -121,20 +130,34 @@ default_issuer()
commonName = International Business Machines Corporation commonName = International Business Machines Corporation
countryName = US countryName = US
localityName = Poughkeepsie localityName = Poughkeepsie
organizationalUnitName = IBM Z Host Key Signing Service organizationalUnitName = Key Signing Service
organizationName = International Business Machines Corporation organizationName = International Business Machines Corporation
stateOrProvinceName = New York stateOrProvinceName = New York
EOF EOF
} }
verify_issuer_files() # As organizationalUnitName can have an arbitrary prefix but must
# end with "Key Signing Service" let's normalize the OU name by
# stripping off the prefix
verify_default_issuer()
{ {
default_issuer > $DEF_ISSUER_DN_FILE default_issuer > $DEF_ISSUER_DN_FILE
if ! diff $ISSUER_DN_FILE $DEF_ISSUER_DN_FILE sed "s/\(^[ ]*organizationalUnitName[ ]*=[ ]*\).*\(Key Signing Service$\)/\1\2/" \
$ISSUER_DN_FILE > $CANONICAL_ISSUER_DN_FILE
if ! diff $CANONICAL_ISSUER_DN_FILE $DEF_ISSUER_DN_FILE
then then
echo Incorrect default issuer >&2 && exit 1 echo Incorrect default issuer >&2 && exit 1
fi fi
}
verify_issuer_files()
{
if [ $1 -eq 1 ]
then
verify_default_issuer
fi
if diff $ISSUER_DN_FILE $SUBJECT_DN_FILE if diff $ISSUER_DN_FILE $SUBJECT_DN_FILE
then then
@@ -196,14 +219,16 @@ check_file()
# check args # check args
CRL_FILE= CRL_FILE=
CA_FILE= CA_FILE=
CHECK_DEFAULT_ISSUER=1
args=$(getopt -qu "r:c:h" $*) args=$(getopt -qu "dr:c:h" $*)
if [ $? = 0 ] if [ $? = 0 ]
then then
set -- $args set -- $args
while [ $1 != "" ] while [ $1 != "" ]
do do
case $1 in case $1 in
-d) CHECK_DEFAULT_ISSUER=0; shift;;
-r) CRL_FILE=$2; shift 2;; -r) CRL_FILE=$2; shift 2;;
-c) CA_FILE=$2; shift 2;; -c) CA_FILE=$2; shift 2;;
-h) usage $0; exit 0;; -h) usage $0; exit 0;;
@@ -244,7 +269,7 @@ exit 1
# Verify the issuer # Verify the issuer
canonical_dn x509 $HKD_FILE issuer $ISSUER_DN_FILE canonical_dn x509 $HKD_FILE issuer $ISSUER_DN_FILE
canonical_dn x509 $HKSK_FILE subject $SUBJECT_DN_FILE canonical_dn x509 $HKSK_FILE subject $SUBJECT_DN_FILE
verify_issuer_files verify_issuer_files $CHECK_DEFAULT_ISSUER
# Verify dates # Verify dates
verify_dates $(cert_time $HKD_FILE startdate) $(cert_time $HKD_FILE enddate) verify_dates $(cert_time $HKD_FILE startdate) $(cert_time $HKD_FILE enddate)
@@ -261,7 +286,7 @@ then
echo -n "CRL " echo -n "CRL "
canonical_dn crl $CRL_FILE issuer $ISSUER_DN_FILE canonical_dn crl $CRL_FILE issuer $ISSUER_DN_FILE
canonical_dn x509 $HKSK_FILE subject $SUBJECT_DN_FILE canonical_dn x509 $HKSK_FILE subject $SUBJECT_DN_FILE
verify_issuer_files verify_issuer_files $CHECK_DEFAULT_ISSUER
verify_dates $(crl_time $CRL_FILE lastupdate) $(crl_time $CRL_FILE nextupdate) 'CRL' verify_dates $(crl_time $CRL_FILE lastupdate) $(crl_time $CRL_FILE nextupdate) 'CRL'
-3
View File
@@ -29,9 +29,6 @@
*/ */
#define PV_CERTS_SECURITY_LEVEL 2 #define PV_CERTS_SECURITY_LEVEL 2
/* SKID for DigiCert Assured ID Root CA */
#define DIGICERT_ASSURED_ID_ROOT_CA_SKID "45EBA2AFF492CB82312D518BA7A7219DF36DC80F"
union ecdh_pub_key { union ecdh_pub_key {
struct { struct {
uint8_t x[80]; uint8_t x[80];
+8 -4
View File
@@ -24,11 +24,15 @@
#define PV_MAGIC_NUMBER 0x49424d5365634578ULL #define PV_MAGIC_NUMBER 0x49424d5365634578ULL
#define PV_VERSION_1 0x00000100U #define PV_VERSION_1 0x00000100U
/* Internal helper macro */
#define __PV_BIT(nr) (1ULL << (63 - (nr)))
/* Plaintext control flags */ /* Plaintext control flags */
#define PV_PCF_PCKM_ECC (1ULL << 5) /* PCKMO encrypt-ECC-key functions allowed */ #define PV_PCF_ALLOW_DUMPING __PV_BIT(34) /* dumping of the configuration is allowed */
#define PV_PCF_PCKMO_AES (1ULL << 6) /* PCKMO encrypt-AES-key functions allowed */ #define PV_PCF_NO_DECRYPTION __PV_BIT(35) /* prevent Ultravisor decryption during unpack operation */
#define PV_PCF_PCKMO_DEA_TDEA (1ULL << 7) /* PCKMO encrypt-DEA/TDEA-key functions allowed */ #define PV_PCF_PCKMO_DEA_TDEA __PV_BIT(56) /* PCKMO encrypt-DEA/TDEA-key functions allowed */
#define PV_PCF_NO_DECRYPTION (1ULL << 28) /* prevent Ultravisor decryption during unpack operation */ #define PV_PCF_PCKMO_AES __PV_BIT(57) /* PCKMO encrypt-AES-key functions allowed */
#define PV_PCF_PCKM_ECC __PV_BIT(58) /* PCKMO encrypt-ECC-key functions allowed */
/* maxima for the PV version 1 */ /* maxima for the PV version 1 */
#define PV_V1_IPIB_MAX_SIZE PAGE_SIZE #define PV_V1_IPIB_MAX_SIZE PAGE_SIZE
+85 -44
View File
@@ -64,13 +64,17 @@ static gint pv_args_validate_options(PvArgs *args, GError **err)
{ {
PvComponentType KERNEL = PV_COMP_TYPE_KERNEL; PvComponentType KERNEL = PV_COMP_TYPE_KERNEL;
if (args->pcf && args->allow_pckmo != PV_NOT_SET) { /* Check for mutually exclusive arguments */
g_set_error(err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX, if (args->pcf && !(args->allow_pckmo == PV_NOT_SET &&
_("The '--x-pcf' and '--(enable|disable)-pckmo' options are mutually" args->allow_dump == PV_NOT_SET)) {
" exclusive.\nUse 'genprotimg --help' for more information")); g_set_error(
err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX,
_("The '--x-pcf' option cannot be used with the '--(enable|disable)-pckmo' or"
" '--(enable|disable)-dump' flags.\nUse 'genprotimg --help' for more information"));
return -1; return -1;
} }
/* Check for unused arguments */
if (args->unused_values->len > 0) { if (args->unused_values->len > 0) {
g_autofree gchar *unused = NULL; g_autofree gchar *unused = NULL;
@@ -88,6 +92,14 @@ static gint pv_args_validate_options(PvArgs *args, GError **err)
return -1; return -1;
} }
/* Check for mandatory arguments */
if (args->allow_dump == PV_TRUE && !args->cust_comm_key_path) {
g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT,
_("Option '--allow-dump' requires the '--comm-key' option.\nUse 'genprotimg "
"--help' for more information"));
return -1;
}
if (!args->output_path) { if (!args->output_path) {
g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT, g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT,
_("Option '--output' is required.\nUse 'genprotimg --help' for more information")); _("Option '--output' is required.\nUse 'genprotimg --help' for more information"));
@@ -111,7 +123,7 @@ static gint pv_args_validate_options(PvArgs *args, GError **err)
g_strv_length(args->untrusted_cert_paths) == 0)) { g_strv_length(args->untrusted_cert_paths) == 0)) {
g_set_error( g_set_error(
err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT, err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT,
_("Either specify the IBM Z signing key and (DigiCert) intermediate CA certificate\n" _("Either specify the IBM Z signing key and intermediate CA certificate\n"
"by using the '--cert' option, or use the '--no-verify' flag to disable the\n" "by using the '--cert' option, or use the '--no-verify' flag to disable the\n"
"host-key document verification completely (at your own risk).")); "host-key document verification completely (at your own risk)."));
return -1; return -1;
@@ -155,14 +167,14 @@ static gboolean cb_set_string_option(const gchar *option, const gchar *value,
{ {
gchar **args_option = NULL; gchar **args_option = NULL;
if (g_str_equal(option, "--comm-key"))
args_option = &args->cust_comm_key_path;
if (g_str_equal(option, "--root-ca")) if (g_str_equal(option, "--root-ca"))
args_option = &args->root_ca_path; args_option = &args->root_ca_path;
if (g_str_equal(option, "-o") || g_str_equal(option, "--output")) if (g_str_equal(option, "-o") || g_str_equal(option, "--output"))
args_option = &args->output_path; args_option = &args->output_path;
if (g_str_equal(option, "--x-comp-key")) if (g_str_equal(option, "--x-comp-key"))
args_option = &args->xts_key_path; args_option = &args->xts_key_path;
if (g_str_equal(option, "--x-comm-key"))
args_option = &args->cust_comm_key_path;
if (g_str_equal(option, "--x-header-key")) if (g_str_equal(option, "--x-header-key"))
args_option = &args->cust_root_key_path; args_option = &args->cust_root_key_path;
if (g_str_equal(option, "--x-pcf")) if (g_str_equal(option, "--x-pcf"))
@@ -188,19 +200,6 @@ static gboolean cb_set_string_option(const gchar *option, const gchar *value,
return TRUE; return TRUE;
} }
static gboolean cb_enable_disable_flag(const gchar *option, const gchar *value G_GNUC_UNUSED,
PvArgs *args, GError **err G_GNUC_UNUSED)
{
if (g_str_equal(option, "--enable-pckmo"))
args->allow_pckmo = PV_TRUE;
else if (g_str_equal(option, "--disable-pckmo"))
args->allow_pckmo = PV_FALSE;
else
g_assert_not_reached();
return TRUE;
}
static gboolean cb_set_log_level(const gchar *option G_GNUC_UNUSED, static gboolean cb_set_log_level(const gchar *option G_GNUC_UNUSED,
const gchar *value G_GNUC_UNUSED, PvArgs *args, const gchar *value G_GNUC_UNUSED, PvArgs *args,
GError **err G_GNUC_UNUSED) GError **err G_GNUC_UNUSED)
@@ -217,8 +216,51 @@ static gboolean cb_remaining_values(const gchar *option G_GNUC_UNUSED,
return TRUE; return TRUE;
} }
#define MUT_EXCL_BOOL_FLAG_CB_NAME(FLAG, VALUE) (cb_##FLAG##_##VALUE)
#define DEFINE_MUT_EXCL_BOOL_FLAG_CB(FLAG, VALUE) \
static gboolean MUT_EXCL_BOOL_FLAG_CB_NAME(FLAG, VALUE)( \
const gchar *option G_GNUC_UNUSED, const gchar *value G_GNUC_UNUSED, \
PvArgs *args, GError **err) \
{ \
if (!(args->allow_##FLAG == PV_NOT_SET || \
args->allow_##FLAG == VALUE)) { \
g_set_error(err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, \
"'--enable-" #FLAG "' and '--disable-" #FLAG \
"' are mutually exclusive"); \
return FALSE; \
} \
args->allow_##FLAG = VALUE; \
return TRUE; \
}
#define DEFINE_MUT_EXCL_BOOL_FLAG_CBS(FLAG) \
DEFINE_MUT_EXCL_BOOL_FLAG_CB(FLAG, PV_TRUE) \
DEFINE_MUT_EXCL_BOOL_FLAG_CB(FLAG, PV_FALSE)
#define MUT_EXCL_BOOL_FLAG(FLAG, ENABLE_DESC, DISABLE_DESC) \
{ \
.long_name = "enable-" #FLAG, \
.short_name = 0, \
.flags = G_OPTION_FLAG_NO_ARG, \
.arg = G_OPTION_ARG_CALLBACK, \
.arg_data = MUT_EXCL_BOOL_FLAG_CB_NAME(FLAG, PV_TRUE), \
.description = ENABLE_DESC, \
}, \
{ \
.long_name = "disable-" #FLAG, \
.short_name = 0, \
.flags = G_OPTION_FLAG_NO_ARG, \
.arg = G_OPTION_ARG_CALLBACK, \
.arg_data = MUT_EXCL_BOOL_FLAG_CB_NAME(FLAG, PV_FALSE), \
.description = DISABLE_DESC, \
}
#define INDENT " " #define INDENT " "
/* Define the callbacks for mutually exclusive command line flags */
DEFINE_MUT_EXCL_BOOL_FLAG_CBS(dump)
DEFINE_MUT_EXCL_BOOL_FLAG_CBS(pckmo)
gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[], gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[],
GError **err) GError **err)
{ {
@@ -282,21 +324,28 @@ gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[],
.description = _("Use the kernel parameters stored in PARMFILE\n" INDENT .description = _("Use the kernel parameters stored in PARMFILE\n" INDENT
"(optional)."), "(optional)."),
.arg_description = _("PARMFILE") }, .arg_description = _("PARMFILE") },
{.long_name = "enable-pckmo", MUT_EXCL_BOOL_FLAG(
.short_name = 0, dump,
.flags = G_OPTION_FLAG_NO_ARG, _("Enable PV guest dumps (optional). This option\n" INDENT
.arg = G_OPTION_ARG_CALLBACK, "requires the '--comm-key' option."),
.arg_data = cb_enable_disable_flag, _("Disable PV guest dumps (default) (optional).")),
.description = _("Enable the support for the DEA, TDEA, AES, and\n" INDENT MUT_EXCL_BOOL_FLAG(
"ECC PCKMO key encryption functions (default)\n" INDENT pckmo,
"(optional).")}, _("Enable the support for the DEA, TDEA, AES, and\n" INDENT
{.long_name = "disable-pckmo", "ECC PCKMO key encryption functions (default)\n" INDENT
.short_name = 0, "(optional)."),
.flags = G_OPTION_FLAG_NO_ARG, _("Disable the support for the DEA, TDEA, AES, and\n" INDENT
.arg = G_OPTION_ARG_CALLBACK, "ECC PCKMO key encryption functions (optional).")),
.arg_data = cb_enable_disable_flag, { .long_name = "comm-key",
.description = _("Disable the support for the DEA, TDEA, AES, and\n" INDENT .short_name = 0,
"ECC PCKMO key encryption functions (optional).")}, .flags = G_OPTION_FLAG_FILENAME,
.arg = G_OPTION_ARG_CALLBACK,
.arg_data = cb_set_string_option,
.description = _(
"FILE contains the key with which you encrypt\n" INDENT
"the PV guest dump (optional). Required by\n" INDENT
"the '--enable-dump' option."),
.arg_description = _("FILE") },
{ .long_name = "crl", { .long_name = "crl",
.short_name = 0, .short_name = 0,
.flags = G_OPTION_FLAG_NONE, .flags = G_OPTION_FLAG_NONE,
@@ -355,15 +404,6 @@ gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[],
}; };
GOptionEntry x_entries[] = { GOptionEntry x_entries[] = {
{ .long_name = "x-comm-key",
.short_name = 0,
.flags = G_OPTION_FLAG_FILENAME,
.arg = G_OPTION_ARG_CALLBACK,
.arg_data = cb_set_string_option,
.description = _(
"Use FILE as the customer communication key.\n" INDENT
"Optional; default: auto-generated."),
.arg_description = _("FILE") },
{ .long_name = "x-comp-key", { .long_name = "x-comp-key",
.short_name = 0, .short_name = 0,
.flags = G_OPTION_FLAG_FILENAME, .flags = G_OPTION_FLAG_FILENAME,
@@ -446,6 +486,7 @@ PvArgs *pv_args_new(void)
g_autoptr(PvArgs) args = g_new0(PvArgs, 1); g_autoptr(PvArgs) args = g_new0(PvArgs, 1);
args->unused_values = g_ptr_array_new_with_free_func(g_free); args->unused_values = g_ptr_array_new_with_free_func(g_free);
args->allow_dump = PV_NOT_SET;
args->allow_pckmo = PV_NOT_SET; args->allow_pckmo = PV_NOT_SET;
return g_steal_pointer(&args); return g_steal_pointer(&args);
} }
+1
View File
@@ -34,6 +34,7 @@ typedef struct {
gboolean offline; gboolean offline;
gchar *pcf; gchar *pcf;
gchar *scf; gchar *scf;
PvTristate allow_dump;
PvTristate allow_pckmo; PvTristate allow_pckmo;
gchar *psw_addr; /* PSW address which will be used for the start of gchar *psw_addr; /* PSW address which will be used for the start of
* the actual component (e.g. Linux kernel) * the actual component (e.g. Linux kernel)
+1 -17
View File
@@ -248,19 +248,6 @@ gint pv_component_align(PvComponent *component, const gchar *tmp_path,
g_assert_not_reached(); g_assert_not_reached();
} }
/* Convert uint64_t address to byte array */
static void uint64_to_uint8_buf(uint8_t dst[8], uint64_t addr)
{
uint8_t *p = (uint8_t *)&addr;
g_assert(dst);
for (gint i = 0; i < 8; i++) {
/* cppcheck-suppress objectIndex */
dst[i] = p[i];
}
}
int64_t pv_component_update_ald(const PvComponent *comp, EVP_MD_CTX *ctx, int64_t pv_component_update_ald(const PvComponent *comp, EVP_MD_CTX *ctx,
GError **err) GError **err)
{ {
@@ -273,11 +260,8 @@ int64_t pv_component_update_ald(const PvComponent *comp, EVP_MD_CTX *ctx,
do { do {
uint64_t cur_be = GUINT64_TO_BE(cur); uint64_t cur_be = GUINT64_TO_BE(cur);
uint8_t addr_buf[8];
uint64_to_uint8_buf(addr_buf, cur_be); if (EVP_DigestUpdate(ctx, &cur_be, sizeof(cur_be)) != 1) {
if (EVP_DigestUpdate(ctx, addr_buf, sizeof(addr_buf)) != 1) {
g_set_error(err, PV_CRYPTO_ERROR, g_set_error(err, PV_CRYPTO_ERROR,
PV_CRYPTO_ERROR_INTERNAL, PV_CRYPTO_ERROR_INTERNAL,
_("EVP_DigestUpdate failed")); _("EVP_DigestUpdate failed"));
+22 -18
View File
@@ -229,7 +229,9 @@ static gint pv_img_set_psw_addr(PvImage *img, const gchar *psw_addr_s,
} }
static gint pv_img_set_control_flags(PvImage *img, const gchar *pcf_s, static gint pv_img_set_control_flags(PvImage *img, const gchar *pcf_s,
const gchar *scf_s, PvTristate allow_pckmo, GError **err) const gchar *scf_s,
PvTristate allow_dump,
PvTristate allow_pckmo, GError **err)
{ {
uint64_t flags; uint64_t flags;
@@ -247,6 +249,11 @@ static gint pv_img_set_control_flags(PvImage *img, const gchar *pcf_s,
img->scf = flags; img->scf = flags;
} }
if (allow_dump == PV_TRUE)
img->pcf |= PV_PCF_ALLOW_DUMPING;
else if (allow_dump == PV_FALSE)
img->pcf &= ~PV_PCF_ALLOW_DUMPING;
if (allow_pckmo == PV_TRUE) if (allow_pckmo == PV_TRUE)
img->pcf |= PV_PCF_PCKM_ECC | PV_PCF_PCKMO_AES | PV_PCF_PCKMO_DEA_TDEA; img->pcf |= PV_PCF_PCKM_ECC | PV_PCF_PCKMO_AES | PV_PCF_PCKMO_DEA_TDEA;
else if (allow_pckmo == PV_FALSE) else if (allow_pckmo == PV_FALSE)
@@ -304,9 +311,10 @@ static gint pv_img_hostkey_verify(GSList *host_key_certs,
} }
/* Load all untrusted certificates (e.g. IBM Z signing key and /* Load all untrusted certificates (e.g. IBM Z signing key and
* DigiCert intermediate CA) that are required to establish a chain of * intermediate CA) that are required to establish a chain of trust
* trust starting from the host-key document up to the root CA (if not * starting from the host-key document up to the root CA (if not
* otherwise specified that's the DigiCert Assured ID Root CA). * otherwise specified that can be one of the system wide installed
* root CAs, e.g. DigiCert).
*/ */
untrusted_certs_with_path = load_certificates(untrusted_cert_paths, err); untrusted_certs_with_path = load_certificates(untrusted_cert_paths, err);
if (!untrusted_certs_with_path) if (!untrusted_certs_with_path)
@@ -341,9 +349,8 @@ static gint pv_img_hostkey_verify(GSList *host_key_certs,
* For this we must check: * For this we must check:
* *
* 1. Can a chain of trust be established ending in a root CA * 1. Can a chain of trust be established ending in a root CA
* 2. Is the correct root CA ued? It has either to be the * 2. Is the correct root CA used? It has either to be a system CA
* 'DigiCert Assured ID Root CA' or the root CA specified via * or the root CA specified via command line.
* command line.
*/ */
for (gint i = 0; i < sk_X509_num(ibm_signing_certs); ++i) { for (gint i = 0; i < sk_X509_num(ibm_signing_certs); ++i) {
X509 *ibm_signing_cert = sk_X509_value(ibm_signing_certs, i); X509 *ibm_signing_cert = sk_X509_value(ibm_signing_certs, i);
@@ -364,17 +371,12 @@ static gint pv_img_hostkey_verify(GSList *host_key_certs,
if (verify_cert(ibm_signing_cert, ctx, err) < 0) if (verify_cert(ibm_signing_cert, ctx, err) < 0)
goto error; goto error;
/* Verify the build chain of trust chain. If the user passes a /* If there is a chain of trust using either the provided root
* trusted root CA on the command line then the check for the * CA on the command line or a system wide trusted root CA.
* Subject Key Identifier (SKID) is skipped, otherwise let's
* check if the SKID meets our expectation.
*/ */
if (!root_ca_path && if (check_chain_parameters(X509_STORE_CTX_get0_chain(ctx),
check_chain_parameters(X509_STORE_CTX_get0_chain(ctx), err) < 0)
get_digicert_assured_id_root_ca_skid(),
err) < 0) {
goto error; goto error;
}
ibm_signing_crls = store_ctx_find_valid_crls(ctx, ibm_signing_cert, err); ibm_signing_crls = store_ctx_find_valid_crls(ctx, ibm_signing_cert, err);
if (!ibm_signing_crls) { if (!ibm_signing_crls) {
@@ -588,7 +590,7 @@ PvImage *pv_img_new(PvArgs *args, const gchar *stage3a_path, GError **err)
g_warning(_("host-key document verification is disabled. Your workload is not secured.")); g_warning(_("host-key document verification is disabled. Your workload is not secured."));
if (args->root_ca_path) if (args->root_ca_path)
g_warning(_("A different root CA than the default DigiCert root CA is selected. Ensure that this root CA is trusted.")); g_warning(_("The root CA is selected through the command line. Ensure that this root CA is trusted."));
ret->comps = pv_img_comps_new(EVP_sha512(), EVP_sha512(), EVP_sha512(), err); ret->comps = pv_img_comps_new(EVP_sha512(), EVP_sha512(), EVP_sha512(), err);
if (!ret->comps) if (!ret->comps)
@@ -608,7 +610,9 @@ PvImage *pv_img_new(PvArgs *args, const gchar *stage3a_path, GError **err)
return NULL; return NULL;
/* set the control flags: PCF and SCF */ /* set the control flags: PCF and SCF */
if (pv_img_set_control_flags(ret, args->pcf, args->scf, args->allow_pckmo, err) < 0) if (pv_img_set_control_flags(ret, args->pcf, args->scf,
args->allow_dump, args->allow_pckmo,
err) < 0)
return NULL; return NULL;
/* read in the keys */ /* read in the keys */
+22 -28
View File
@@ -440,7 +440,7 @@ static int check_signature_algo_match(const EVP_PKEY *pkey, const X509 *subject,
static X509_CRL *load_crl_from_bio(BIO *bio) static X509_CRL *load_crl_from_bio(BIO *bio)
{ {
g_autoptr(X509_CRL) crl = PEM_read_bio_X509_CRL(bio, NULL, 0, NULL); g_autoptr(X509_CRL) crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
gint rc; gint rc;
if (crl) if (crl)
@@ -1079,8 +1079,8 @@ int store_set_verify_param(X509_STORE *store, GError **err)
g_abort(); g_abort();
/* The maximum depth level of the chain of trust for the verification of /* The maximum depth level of the chain of trust for the verification of
* the IBM Z signing key is 2, i.e. IBM Z signing key -> (DigiCert) * the IBM Z signing key is 2, i.e. IBM Z signing key -> intermediate CA
* intermediate CA -> (DigiCert) root CA * -> root CA
*/ */
X509_VERIFY_PARAM_set_depth(param, 2); X509_VERIFY_PARAM_set_depth(param, 2);
@@ -1267,46 +1267,38 @@ static int security_level_to_bits(int level)
return security_bits[level]; return security_bits[level];
} }
static ASN1_OCTET_STRING *digicert_assured_id_root_ca;
const ASN1_OCTET_STRING *get_digicert_assured_id_root_ca_skid(void)
{
pv_crypto_init();
return digicert_assured_id_root_ca;
}
/* Used for the caching of the downloaded CRLs */ /* Used for the caching of the downloaded CRLs */
static GHashTable *cached_crls; static GHashTable *cached_crls;
void pv_crypto_init(void) void pv_crypto_init(void)
{ {
if (digicert_assured_id_root_ca) if (cached_crls)
return; return;
cached_crls = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, cached_crls = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify)X509_CRL_free); (GDestroyNotify)X509_CRL_free);
digicert_assured_id_root_ca = s2i_ASN1_OCTET_STRING(
NULL, NULL, DIGICERT_ASSURED_ID_ROOT_CA_SKID);
} }
void pv_crypto_cleanup(void) void pv_crypto_cleanup(void)
{ {
if (!digicert_assured_id_root_ca) if (!cached_crls)
return; return;
g_clear_pointer(&cached_crls, g_hash_table_destroy); g_clear_pointer(&cached_crls, g_hash_table_destroy);
g_clear_pointer(&digicert_assured_id_root_ca, ASN1_OCTET_STRING_free);
} }
gint check_chain_parameters(const STACK_OF_X509 *chain, gint check_chain_parameters(const STACK_OF_X509 *chain,
const ASN1_OCTET_STRING *skid, GError **err) GError **err)
{ {
const ASN1_OCTET_STRING *ca_skid = NULL; const X509_NAME *ca_x509_subject = NULL;
g_autofree gchar *ca_subject = NULL;
gint len = sk_X509_num(chain); gint len = sk_X509_num(chain);
X509 *ca = NULL; X509 *ca = NULL;
g_assert(skid);
/* at least one root and one leaf certificate must be defined */ /* at least one root and one leaf certificate must be defined */
g_assert(len >= 2); if (len < 2) {
g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL,
_("there must be at least on root and one leaf certificate in the chain of trust"));
return -1;
}
/* get the root certificate of the chain of trust */ /* get the root certificate of the chain of trust */
ca = sk_X509_value(chain, len - 1); ca = sk_X509_value(chain, len - 1);
@@ -1316,19 +1308,21 @@ gint check_chain_parameters(const STACK_OF_X509 *chain,
return -1; return -1;
} }
ca_skid = X509_get0_subject_key_id(ca); ca_x509_subject = X509_get_subject_name(ca);
if (!ca_skid) { if (!ca_x509_subject) {
g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_MALFORMED_ROOT_CA, g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL,
_("malformed root certificate")); _("subject of the root CA cannot be retrieved"));
return -1; return -1;
} }
if (ASN1_STRING_cmp(ca_skid, skid) != 0) { ca_subject = X509_NAME_oneline(ca_x509_subject, NULL, 0);
g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_WRONG_CA_USED, if (!ca_subject) {
_("expecting DigiCert root CA to be used")); g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL,
_("subject name of the root CA cannot be retrieved"));
return -1; return -1;
} }
g_info("Root CA used: '%s'", ca_subject);
return 0; return 0;
} }
+1 -3
View File
@@ -125,7 +125,6 @@ int check_crl_valid_for_cert(X509_CRL *crl, X509 *cert,
gint verify_flags, GError **err); gint verify_flags, GError **err);
void pv_crypto_init(void); void pv_crypto_init(void);
void pv_crypto_cleanup(void); void pv_crypto_cleanup(void);
const ASN1_OCTET_STRING *get_digicert_assured_id_root_ca_skid(void);
gint verify_host_key(X509 *host_key, GSList *issuer_pairs, gint verify_host_key(X509 *host_key, GSList *issuer_pairs,
gint verify_flags, int level, GError **err); gint verify_flags, int level, GError **err);
X509 *load_cert_from_file(const char *path, GError **err); X509 *load_cert_from_file(const char *path, GError **err);
@@ -138,8 +137,7 @@ X509_STORE *store_setup(const gchar *root_ca_path,
int store_set_verify_param(X509_STORE *store, GError **err); int store_set_verify_param(X509_STORE *store, GError **err);
X509_CRL *load_crl_by_cert(X509 *cert, GError **err); X509_CRL *load_crl_by_cert(X509 *cert, GError **err);
STACK_OF_X509_CRL *try_load_crls_by_certs(GSList *certs_with_path); STACK_OF_X509_CRL *try_load_crls_by_certs(GSList *certs_with_path);
gint check_chain_parameters(const STACK_OF_X509 *chain, gint check_chain_parameters(const STACK_OF_X509 *chain, GError **err);
const ASN1_OCTET_STRING *skid, GError **err);
X509_NAME *c2b_name(const X509_NAME *name); X509_NAME *c2b_name(const X509_NAME *name);
STACK_OF_X509 *delete_ibm_signing_certs(STACK_OF_X509 *certs); STACK_OF_X509 *delete_ibm_signing_certs(STACK_OF_X509 *certs);
+6 -6
View File
@@ -16,17 +16,17 @@ check_dep:
$(call check_dep, \ $(call check_dep, \
"hmcdrvfs", \ "hmcdrvfs", \
"fuse.h", \ "fuse.h", \
"fuse-devel or libfuse-dev", \ "fuse3-devel or libfuse3-dev", \
"HAVE_FUSE=0") "HAVE_FUSE=0")
ifneq ($(shell sh -c 'command -v pkg-config'),) ifneq ($(shell sh -c 'command -v pkg-config'),)
FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse) FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse3)
FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse) FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse3)
else else
FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse3
FUSE_LDLIBS = -lfuse FUSE_LDLIBS = -lfuse3
endif endif
ALL_CFLAGS += -DFUSE_USE_VERSION=26 -D_LARGEFILE_SOURCE $(FUSE_CFLAGS) ALL_CFLAGS += -DFUSE_USE_VERSION=30 -D_LARGEFILE_SOURCE $(FUSE_CFLAGS)
LDLIBS += $(FUSE_LDLIBS) -lpthread -lrt -ldl -lm LDLIBS += $(FUSE_LDLIBS) -lpthread -lrt -ldl -lm
OBJECTS = hmcdrvfs.o OBJECTS = hmcdrvfs.o
-3
View File
@@ -111,9 +111,6 @@ allow access by other users
.B -o allow_root .B -o allow_root
allow access by root allow access by root
.TP .TP
.B -o nonempty
allow mounts over non-empty file/dir
.TP
.B -o default_permissions .B -o default_permissions
enable permission checking by kernel enable permission checking by kernel
.TP .TP
+9 -6
View File
@@ -990,7 +990,7 @@ static int hmcdrv_cache_dir(const char *dir, fuse_fill_dir_t filler, void *buf)
hmcdrv_cache_refresh(path, &st, symlink); hmcdrv_cache_refresh(path, &st, symlink);
if ((filler != NULL) && if ((filler != NULL) &&
(filler(buf, fname, &st, 0) != 0)) (filler(buf, fname, &st, 0, 0) != 0))
filler = NULL; /* stop filling */ filler = NULL; /* stop filling */
#ifdef DEBUG #ifdef DEBUG
strftime(symlink, sizeof(symlink), strftime(symlink, sizeof(symlink),
@@ -1109,7 +1109,8 @@ static struct hmcdrv_fuse_file *hmcdrv_file_get(const char *path)
* *
* Note: The most important function which FUSE calls (very often). * Note: The most important function which FUSE calls (very often).
*/ */
static int hmcdrv_fuse_getattr(const char *path, struct stat *stbuf) static int hmcdrv_fuse_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *UNUSED(fi))
{ {
struct hmcdrv_fuse_file *fp; struct hmcdrv_fuse_file *fp;
int rc = 0; int rc = 0;
@@ -1175,12 +1176,13 @@ static int hmcdrv_fuse_opendir(const char *UNUSED(path),
*/ */
static int hmcdrv_fuse_readdir(const char *path, void *buf, static int hmcdrv_fuse_readdir(const char *path, void *buf,
fuse_fill_dir_t filler, off_t UNUSED(offset), fuse_fill_dir_t filler, off_t UNUSED(offset),
struct fuse_file_info *UNUSED(fi)) struct fuse_file_info *UNUSED(fi),
enum fuse_readdir_flags UNUSED(flags))
{ {
int ret; int ret;
filler(buf, ".", NULL, 0); filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0); filler(buf, "..", NULL, 0, 0);
pthread_mutex_lock(&hmcdrv_ctx.mutex); pthread_mutex_lock(&hmcdrv_ctx.mutex);
ret = hmcdrv_cache_dir(path, filler, buf); ret = hmcdrv_cache_dir(path, filler, buf);
@@ -1232,7 +1234,8 @@ static int hmcdrv_fuse_read(const char *path, char *buf, size_t size,
* Return: value to be passed in the private_data field of fuse_context to * Return: value to be passed in the private_data field of fuse_context to
* all file operations and as a parameter to the destroy() method * all file operations and as a parameter to the destroy() method
*/ */
static void *hmcdrv_fuse_init(struct fuse_conn_info *UNUSED(conn)) static void *hmcdrv_fuse_init(struct fuse_conn_info *UNUSED(conn),
struct fuse_config *UNUSED(cfg))
{ {
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
+7 -6
View File
@@ -23,11 +23,11 @@ else # HAVE_FUSE
# FUSE # FUSE
# #
ifneq ($(shell sh -c 'command -v pkg-config'),) ifneq ($(shell sh -c 'command -v pkg-config'),)
FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse) FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse3)
FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse) FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse3)
else else
FUSE_CFLAGS = -I/usr/include/fuse FUSE_CFLAGS = -I/usr/include/fuse3
FUSE_LDLIBS = -lfuse FUSE_LDLIBS = -lfuse3
endif endif
# #
@@ -67,8 +67,9 @@ check-dep-fuse:
$(call check_dep, \ $(call check_dep, \
"hsavmcore", \ "hsavmcore", \
"fuse.h", \ "fuse.h", \
"fuse-devel or libfuse-dev", \ "fuse3-devel or libfuse3-dev", \
"HAVE_FUSE=0") "HAVE_FUSE=0", \
"-DFUSE_USE_VERSION=30")
touch check-dep-fuse touch check-dep-fuse
install: all install: all
+1 -1
View File
@@ -15,7 +15,7 @@ sudo reboot
## Dependencies ## Dependencies
```shell ```shell
sudo dnf install -y fuse fuse-devel systemd-devel sudo dnf install -y fuse3 fuse3-devel systemd-devel
``` ```
## Build hsavmcore ## Build hsavmcore
+1 -1
View File
@@ -18,7 +18,7 @@ sudo reboot
## Dependencies ## Dependencies
```shell ```shell
sudo zypper install -y fuse fuse-devel systemd-devel sudo zypper install -y fuse3 fuse3-devel systemd-devel
``` ```
## Build hsavmcore ## Build hsavmcore
+1 -1
View File
@@ -11,7 +11,7 @@
## Dependencies ## Dependencies
```shell ```shell
sudo apt-get install -y make gcc kdump-tools fuse libfuse-dev libsystemd-dev sudo apt-get install -y make gcc kdump-tools fuse3 libfuse3-dev libsystemd-dev
``` ```
## Build hsavmcore ## Build hsavmcore
+11 -6
View File
@@ -15,7 +15,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#define FUSE_USE_VERSION 26 #define FUSE_USE_VERSION 30
#include <fuse.h> #include <fuse.h>
#include "lib/util_log.h" #include "lib/util_log.h"
@@ -31,8 +31,11 @@ struct vmcore_overlay {
bool fuse_debug; bool fuse_debug;
}; };
static int vmcore_fuse_getattr(const char *path, struct stat *stbuf) static int vmcore_fuse_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *fi)
{ {
(void)fi;
struct vmcore_overlay *overlay = fuse_get_context()->private_data; struct vmcore_overlay *overlay = fuse_get_context()->private_data;
int ret = 0; int ret = 0;
@@ -54,18 +57,20 @@ static int vmcore_fuse_getattr(const char *path, struct stat *stbuf)
static int vmcore_fuse_readdir(const char *path, void *buf, static int vmcore_fuse_readdir(const char *path, void *buf,
fuse_fill_dir_t filler, off_t offset, fuse_fill_dir_t filler, off_t offset,
struct fuse_file_info *fi) struct fuse_file_info *fi,
enum fuse_readdir_flags flags)
{ {
(void)offset; (void)offset;
(void)fi; (void)fi;
(void)flags;
if (strcmp(path, ROOT_DIR) != 0) if (strcmp(path, ROOT_DIR) != 0)
return -ENOENT; return -ENOENT;
/* We have only one file */ /* We have only one file */
filler(buf, ".", NULL, 0); filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0); filler(buf, "..", NULL, 0, 0);
filler(buf, VMCORE_FILE, NULL, 0); filler(buf, VMCORE_FILE, NULL, 0, 0);
return 0; return 0;
} }
+2 -1
View File
@@ -23,10 +23,11 @@
#define INITRD_SIZE _AC(0x10410, UL) #define INITRD_SIZE _AC(0x10410, UL)
#define OLDMEM_BASE _AC(0x10418, UL) #define OLDMEM_BASE _AC(0x10418, UL)
#define OLDMEM_SIZE _AC(0x10420, UL) #define OLDMEM_SIZE _AC(0x10420, UL)
#define MAX_COMMAND_LINE_SIZE _AC(0x10430, UL)
#define COMMAND_LINE _AC(0x10480, UL) #define COMMAND_LINE _AC(0x10480, UL)
/* Parameter sizes */ /* Parameter sizes */
#define COMMAND_LINE_SIZE 896 #define LEGACY_COMMAND_LINE_SIZE 896
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
+106
View File
@@ -0,0 +1,106 @@
/* Copyright IBM Corp. 2022
*
* 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 LIBCPUMF_H
#define LIBCPUMF_H
#include <sched.h>
#include <stdbool.h>
#define S390_CPUMF_CF "/sys/devices/cpum_cf/"
#define S390_CPUMF_CFDIAG "/sys/devices/cpum_cf_diag/"
#define S390_CPUMF_SF "/sys/devices/cpum_sf/"
#define S390_CPUS_POSSIBLE "/sys/devices/system/cpu/possible"
#define S390_CPUS_ONLINE "/sys/devices/system/cpu/online"
#define S390_CPUMSF_BUFFERSZ "/sys/module/kernel/parameters/cpum_sfb_size"
/**
* Read out the PMU type from a given file.
*
* Return the PMU type number assigned to this PMU by the kernel. This is
* a non zero number.
* If the PMU does not exist return -1 and set errno.
*
* @param[in] dirname Name of the event directory in sysfs
*/
int libcpumf_pmutype(const char *dirname);
/**
* Read out the CPU list from a given file name, for example from files
* /sys/devices/system/cpu/online or /sys/devices/system/cpu/possible.
*
* Return the cpu_set_t created from parsing the CPU list in the second
* parameter.
* Return code of zero indicates proper conversion and -1 indicates an
* error.
*
* @param[in] buffer Comma separated string of a CPU list
* @param[in] filename Name of a sysfs CPU list file name
* @param[out] mask Converted buffer into cpu_set_t mask structure
*/
int libcpumf_cpuset(const char *buffer, cpu_set_t *mask);
int libcpumf_cpuset_fn(const char *filename, cpu_set_t *mask);
/**
* Read CPU Measurement Counting Facility hardware information
*
* Return true if CPU Measurement Counter facility information has been
* retrieved and is valid.
*
* Return false if the information could not be extracted from the file.
*
* @param[out] cfvn Contains CPUMF counter first version number
* @param[out] csvn Contains CPUMF counter second version number
* @param[out] auth Contains CPUMF counter set authorization level
*/
bool libcpumf_cpumcf_info(int *cfvn, int *csvn, int *auth);
/**
* Return true if CPU Measurement Counter Facility is available.
*/
bool libcpumf_have_cpumcf(void);
/**
* Read CPU Measurement Sampling Facility hardware information
*
* Read all necessary information from /sysfs file /proc/service_levels
* to return CPU Measurement Counter Sampling facility information
* characteristics.
* Return true on success and false when the data can not be retrieved.
*
* @param[out] min Minimum supported sampling interval
* @param[out] max Maximum supported sampling interval
* @param[out] speed Current CPU speed, number of CPU cylces per
* microsecond
* @param[out] basic_sz Basic sample size in bytes
* @param[out] diag_sz Diagnostic sample size in bytes
*/
bool libcpumf_cpumsf_info(unsigned long *min, unsigned long *max,
unsigned long *speed, int *basic_sz, int *diag_sz);
/**
* Return true if CPU Measurement Sampling Facility is available.
*/
bool libcpumf_have_cpumsf(void);
/**
* Return true if CPU Measurement Sampling Facility buffer sizes are
* available.
*/
bool libcpumf_have_sfb(void);
/**
* Read CPU Measurement Sampling Facility supported sampling buffer sizes.
*
* Return the minimum and maximum CPU Measurement sampling facitity buffer
* sizes supported.
* Return true on success and false otherwise.
*
* @param[out] min Minimum supported sampling buffer size
* @param[out] max Maximum supported sampling buffer size
*/
bool libcpumf_sfb_info(unsigned long *min, unsigned long *max);
#endif
+19
View File
@@ -0,0 +1,19 @@
include ../common.mak
lib = libcpumf.a
examples = libcpumf_example
all: $(lib)
examples: $(lib) $(examples)
objects = libcpumf_pmutype.o libcpumf_cpuset.o libcpumf_support.o
$(lib): $(objects)
install: all
libcpumf_example: libcpumf_example.o $(lib)
clean:
rm -f *.o $(lib) $(examples)
+75
View File
@@ -0,0 +1,75 @@
/* Copyright IBM Corp. 2022
*
* 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 <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "lib/libcpumf.h"
int libcpumf_cpuset(const char *parm, cpu_set_t *mask)
{
char *cp, *buffer = strdup(parm);
int to, from, rc;
if (!buffer) /* Errno set to ENOMEM */
return -1;
/* Check for invalid characters, such as 11.12 instead 11-12
* but allow blanks and newline. Newline is appended
* when the string is taken from sysfs files, for example
* /sys/devices/system/cpu/online
*/
if (strspn(buffer, "0123456789-,\n ") != strlen(buffer)) {
errno = EINVAL;
return -1;
}
CPU_ZERO(mask);
for (; (cp = strtok(buffer, ",")); buffer = NULL) {
char *dash = strchr(cp, '-'); /* Range character? */
bool is_ok;
if (dash) {
rc = sscanf(cp, "%d-%d", &from, &to);
is_ok = rc == 2;
} else {
rc = sscanf(cp, "%d", &to);
from = to;
is_ok = rc == 1;
}
if (!is_ok) {
errno = ERANGE;
rc = -1;
goto out;
}
for (; from <= to; ++from)
CPU_SET(from, mask);
}
rc = 0;
out:
free(buffer);
return rc;
}
int libcpumf_cpuset_fn(const char *filename, cpu_set_t *mask)
{
char *txt = NULL;
ssize_t ret = -1;
size_t len = 0;
FILE *fp;
fp = fopen(filename, "r");
if (!fp)
return ret;
/* Read out file, one line expected */
ret = getline(&txt, &len, fp);
fclose(fp);
if (ret > 0)
ret = libcpumf_cpuset(txt, mask);
free(txt);
return ret;
}
+76
View File
@@ -0,0 +1,76 @@
/* Copyright IBM Corp. 2022
*
* 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 <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include "lib/libcpumf.h"
int main(void)
{
unsigned long min, max, speed, sfb_min, sfb_max;
int rc, pmu, cfvn, csvn, auth;
cpu_set_t set;
pmu = libcpumf_pmutype(S390_CPUMF_CF);
if (pmu >= 0)
printf("PMU %stype %d\n", S390_CPUMF_CF, pmu);
else
printf("PMU %stype error %d\n", S390_CPUMF_CF, errno);
pmu = libcpumf_pmutype(S390_CPUMF_SF);
if (pmu >= 0)
printf("PMU %stype %d\n", S390_CPUMF_SF, pmu);
else
printf("PMU %stype error %d\n", S390_CPUMF_SF, errno);
pmu = libcpumf_pmutype(S390_CPUMF_CFDIAG);
if (pmu >= 0)
printf("PMU %stype %d\n", S390_CPUMF_CFDIAG, pmu);
else
printf("PMU %stype error %d\n", S390_CPUMF_CFDIAG, errno);
rc = libcpumf_cpuset_fn(S390_CPUS_ONLINE, &set);
if (rc == 0) {
puts("Online CPUs:");
for (int i = 0; i < CPU_SETSIZE; ++i)
if (CPU_ISSET(i, &set))
printf("%d ", i);
putchar('\n');
}
rc = libcpumf_cpuset("0-7,9,11-12 ,15", &set);
if (rc == 0) {
puts("String CPUs:");
for (int i = 0; i < CPU_SETSIZE; ++i)
if (CPU_ISSET(i, &set))
printf("%d ", i);
putchar('\n');
} else {
printf("libcpumf_cpuset input invalid %d\n", errno);
}
printf("CPUMCF support %d\n", libcpumf_have_cpumcf());
rc = libcpumf_cpumcf_info(&cfvn, &csvn, &auth);
printf("libcpumf_cpumcf_info %d", rc);
if (rc)
printf(" cfvn %d csvn %d authorization %#x", cfvn, csvn, auth);
putchar('\n');
printf("CPUMSF support %d\n", libcpumf_have_cpumsf());
rc = libcpumf_cpumsf_info(&min, &max, &speed, &cfvn, &csvn);
printf("libcpumf_cpumsf_info %d", rc);
if (rc)
printf(" min %ld max %ld speed %#lx basic %d diag %d", min,
max, speed, cfvn, csvn);
putchar('\n');
printf("CPUMSF have sfb %d\n", libcpumf_have_sfb());
rc = libcpumf_sfb_info(&sfb_min, &sfb_max);
printf("libcpumf_sfb_info %d", rc);
if (rc)
printf(" sfb_min %lu sfb_max %lu", sfb_min, sfb_max);
putchar('\n');
return EXIT_SUCCESS;
}
+33
View File
@@ -0,0 +1,33 @@
/* Copyright IBM Corp. 2022
*
* 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "lib/libcpumf.h"
int libcpumf_pmutype(const char *dirname)
{
FILE *file;
char *fn;
int ret;
ret = asprintf(&fn, "%s/type", dirname);
if (ret == -1) /* No memory, errno set */
return ret;
file = fopen(fn, "r");
free(fn);
ret = -1; /* Errno set on file open error */
if (file) {
/* Read out a single number from that file */
if (fscanf(file, "%u", &ret) != 1)
/* Unexpected format error, set errno */
errno = -ERANGE;
fclose(file);
}
return ret;
}
+141
View File
@@ -0,0 +1,141 @@
/* Copyright IBM Corp. 2022
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "lib/libcpumf.h"
#define SERVICELEVEL "/proc/service_levels"
bool libcpumf_cpumcf_info(int *cfvn, int *csvn, int *auth)
{
char *linep = NULL;
bool rc = false;
size_t line_sz;
ssize_t nbytes;
FILE *fp;
fp = fopen(SERVICELEVEL, "r");
if (!fp)
err(EXIT_FAILURE, SERVICELEVEL);
while ((nbytes = getline(&linep, &line_sz, fp)) != EOF) {
if (!strncmp(linep, "CPU-MF: Counter facility:", 25)) {
int cnt = sscanf(linep, "CPU-MF: Counter facility:"
" version=%d.%d authorization=%x",
cfvn, csvn, auth);
if (cnt != 3) {
warnx("Can not parse line %s", linep);
goto out;
}
rc = true;
break;
}
}
out:
fclose(fp);
free(linep);
return rc;
}
bool libcpumf_have_cpumcf(void)
{
int cfvn, csvn, auth;
return libcpumf_cpumcf_info(&cfvn, &csvn, &auth);
}
bool libcpumf_cpumsf_info(unsigned long *min, unsigned long *max,
unsigned long *speed, int *basic_sz, int *diag_sz)
{
char *linep = NULL;
bool rc = true;
size_t line_sz;
ssize_t nbytes;
int hit = 0;
FILE *fp;
fp = fopen(SERVICELEVEL, "r");
if (!fp)
err(EXIT_FAILURE, SERVICELEVEL);
while ((nbytes = getline(&linep, &line_sz, fp)) != EOF) {
int ok;
if (!strncmp(linep, "CPU-MF: Sampling facility: min", 30)) {
ok = sscanf(linep, "CPU-MF: Sampling facility:"
" min_rate=%ld max_rate=%ld cpu_speed=%ld",
min, max, speed);
if (ok != 3) {
warnx("Can not parse line %s", linep);
goto out;
}
hit += 1;
}
if (!strncmp(linep, "CPU-MF: Sampling facility: mode=basic", 37)) {
ok = sscanf(linep, "CPU-MF: Sampling facility:"
" mode=basic sample_size=%u", basic_sz);
if (ok != 1) {
warnx("Can not parse line %s", linep);
goto out;
}
hit += 1;
}
if (!strncmp(linep, "CPU-MF: Sampling facility: mode=diag", 36)) {
ok = sscanf(linep, "CPU-MF: Sampling facility:"
" mode=diagnostic sample_size=%u",
diag_sz);
if (ok != 1) {
warnx("Can not parse line %s", linep);
goto out;
}
hit += 1;
}
}
out:
fclose(fp);
free(linep);
if (hit != 3)
rc = false;
return rc;
}
bool libcpumf_have_cpumsf(void)
{
unsigned long a, b, c;
int basic_sz, diag_sz;
return libcpumf_cpumsf_info(&a, &b, &c, &basic_sz, &diag_sz);
}
bool libcpumf_have_sfb(void)
{
unsigned long a, b;
return libcpumf_sfb_info(&a, &b);
}
bool libcpumf_sfb_info(unsigned long *min, unsigned long *max)
{
int rc = false;
FILE *fp;
fp = fopen(S390_CPUMSF_BUFFERSZ, "r");
if (!fp)
err(EXIT_FAILURE, "%s", S390_CPUMSF_BUFFERSZ);
if (fscanf(fp, "%lu,%lu", min, max) == 2)
rc = true;
fclose(fp);
return rc;
}
+1 -1
View File
@@ -96,7 +96,7 @@ int dasd_sys_ese(char *devnode)
return (rc == 1) ? 1 : 0; return (rc == 1) ? 1 : 0;
} }
int dasd_get_pm_from_chpid(char *busid, unsigned int chpid, int *mask) static int dasd_get_pm_from_chpid(char *busid, unsigned int chpid, int *mask)
{ {
unsigned int val; unsigned int val;
int count, i; int count, i;
+53
View File
@@ -1549,6 +1549,59 @@ int SK_EP11_reencipher_key(const struct sk_ext_ep11_lib *ep11_lib,
return -EIO; return -EIO;
} }
memcpy(blob, lrb.payload, lrb.pllen);
/* re-encipher MACed SPKI */
rb.domain = domain;
lrb.domain = domain;
resp_len = sizeof(resp);
req_len = ep11.dll_xcpa_cmdblock(req, sizeof(req), XCP_ADM_REENCRYPT,
&rb, NULL, key_token + hdr->len,
key_token_length - hdr->len);
if (req_len < 0) {
sk_debug(debug, "Failed to build XCP command block");
return -EIO;
}
rv = ep11.dll_m_admin(resp, &resp_len, NULL, NULL, req, req_len, NULL,
0, ep11_lib->target);
if (rv != CKR_OK || resp_len == 0) {
sk_debug(debug, "Command XCP_ADM_REENCRYPT failed. "
"rc = 0x%lx, resp_len = %ld", rv, resp_len);
return -EIO;
}
rc = ep11.dll_xcpa_internal_rv(resp, resp_len, &lrb, &rv);
if (rc != 0) {
sk_debug(debug, "Failed to parse response. rc = %d", rc);
return -EIO;
}
if (rv != CKR_OK) {
sk_debug(debug, "Failed to re-encrypt the EP11 secure key. "
"rc = 0x%lx", rv);
switch (rv) {
case CKR_IBM_WKID_MISMATCH:
sk_debug(debug, "The EP11 secure key is currently "
"encrypted under a different master that does "
"not match the master key in the CURRENT "
"master key register of APQN %02X.%04X",
card, domain);
break;
}
return -EIO;
}
if (key_token_length - hdr->len != lrb.pllen) {
sk_debug(debug, "Re-encrypted EP11 secure key size has "
"changed: org-len: %lu, new-len: %lu",
hdr->len - sizeof(*hdr), lrb.pllen);
return -EIO;
}
memcpy(key_token + hdr->len, lrb.payload, lrb.pllen);
return 0; return 0;
} }
+1 -1
View File
@@ -20,7 +20,7 @@ install:
sed -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' cpictl > \ sed -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' cpictl > \
$(DESTDIR)$(TOOLS_LIBDIR)/cpictl $(DESTDIR)$(TOOLS_LIBDIR)/cpictl
chown $(OWNER):$(GROUP) $(DESTDIR)$(TOOLS_LIBDIR)/cpictl chown $(OWNER):$(GROUP) $(DESTDIR)$(TOOLS_LIBDIR)/cpictl
chmod 775 $(DESTDIR)$(TOOLS_LIBDIR)/cpictl chmod 755 $(DESTDIR)$(TOOLS_LIBDIR)/cpictl
@for i in $(MAN_PAGES); \ @for i in $(MAN_PAGES); \
do \ do \
+241 -9
View File
@@ -24,6 +24,9 @@ readonly SYSTEM_NAME_PATH="/sys/firmware/cpi/system_name"
readonly SYSPLEX_NAME_PATH="/sys/firmware/cpi/sysplex_name" readonly SYSPLEX_NAME_PATH="/sys/firmware/cpi/sysplex_name"
readonly CPI_SET="/sys/firmware/cpi/set" readonly CPI_SET="/sys/firmware/cpi/set"
# Location of os-release file - can be specified externally for testing purpose
readonly OS_RELEASE=${CPI_OS_RELEASE:-"/etc/os-release"}
declare LEVEL declare LEVEL
declare TYPE declare TYPE
declare NAME declare NAME
@@ -37,6 +40,16 @@ readonly EXIT_FAILURE=1
readonly EXIT_ARG_TOO_LONG=3 readonly EXIT_ARG_TOO_LONG=3
readonly EXIT_INVALID_CHARS=4 readonly EXIT_INVALID_CHARS=4
# Distro-IDs as supported by SE/HMC firmware
readonly DISTRO_GENERIC=0
readonly DISTRO_RHEL=1
readonly DISTRO_SLES=2
readonly DISTRO_UBUNTU=3
readonly DISTRO_FEDORA=4
readonly DISTRO_OPENSUSE=5
readonly DISTRO_DEBIAN=6
readonly DISTRO_RHCOS=7
print_help_and_exit() print_help_and_exit()
{ {
cat <<EndHelp cat <<EndHelp
@@ -49,7 +62,8 @@ Configure the Control-Program-Information (CPI) settings.
sysplex name with values taken from environment sysplex name with values taken from environment
variables variables
-h, --help Print this help, then exit -h, --help Print this help, then exit
-L, --level LEVEL Set and commit OS level to LEVEL (format xx.yy.zzABCD) -L, --level LEVEL Set and commit OS level to LEVEL. Format: 0x<level> or
[[[flags:]distro_id:distro_version:]kernel_version]
-N, --name SYSTEM Set and commit the system name to SYSTEM -N, --name SYSTEM Set and commit the system name to SYSTEM
-S, --sysplex SYSPLEX Set and commit the sysplex name to SYSPLEX -S, --sysplex SYSPLEX Set and commit the sysplex name to SYSPLEX
-T, --type TYPE Set and commit OS type to TYPE -T, --type TYPE Set and commit OS type to TYPE
@@ -109,7 +123,7 @@ fail_with()
cpi_commit() cpi_commit()
{ {
echo 1 > "$CPI_SET" echo 1 > "$CPI_SET" 2> /dev/null
} }
do_length_check() do_length_check()
@@ -129,15 +143,233 @@ cpi_set_bit()
LEVEL=$(printf '0x%x' $((LEVEL | (1 << (63 - $1)) )) ) LEVEL=$(printf '0x%x' $((LEVEL | (1 << (63 - $1)) )) )
} }
#
# split_version - Split generic version string into array of sub-versions
#
# @version: Version string
# @delim: Characters that delimit sub-versions in version string
# @num: Number of sub-versions
#
# Print @num sub-versions of @version where each sub-version is delimited by
# any of the characters in @delim. Print 0 in place of non-decimal or missing
# sub-versions.
#
# Examples:
# version=10 delim=. num=3 => 10 0 0
# version=4.8 delim=. num=2 => 4 8
#
split_version()
{
local version="$1" delim="$2" num="$3"
local list i subver
IFS="$delim" read -r -a list <<< "$version"
for (( i=0; i<num; i++ )) ; do
subver="${list[i]:-0}"
# Handle non-number sub-versions
[[ "$subver" =~ ^[0-9]+$ ]] || subver=0
# Force decimal interpretation in case of leading zeroes
subver=$(( 10#$subver ))
printf "%s " "$subver"
done
}
#
# split_kver - Split Linux kernel version string into array of sub-versions
#
# @version: Linux kernel version string
# @num: Number of sub-versions
#
# Print @num sub-versions of the specified kernel @version. Print 0 in place
# of non-decimal or missing sub-versions.
#
# Examples:
# version=2.4-13 num=4 => 2 4 0 13
# version=3.0.93_3.0.101-0.8.2_0.8.1 num=6 => 3 0 93 3 0 101
# version=4.12.14-lp150.11.4 num=5 => 4 12 14 0 11
#
split_kver()
{
local version="$1" num="$2"
local main extra
# Separate extra version to handle short main version (e.g. 2.4-13)
IFS="-_" read -r main extra <<< "$version"
split_version "$main" "." $(( num > 3 ? 3 : num ))
[[ "$num" -gt 3 ]] && split_version "$extra" ".-_" $(( num - 3 ))
}
#
# bytes_to_word - Convert byte array to hexadecimal word
#
# @bytes: List of numbers representing byte values
#
# Print a big-endian hexadecimal representation of the word that results from
# combining the specified byte values.
#
bytes_to_word()
{
printf "0x"
printf "%02x" "$@"
}
#
# get_system_level - Print system level word for specified distribution version
#
# @distro: Distro ID (ID value from /etc/os-release)
# @ver_str: Distro version string (VERSION_ID from /etc/os-release)
# @kver_str: Kernel version string (output of 'uname -r')
# @flags: Optional statistics flags
#
# Print a 64 bit hexadecimal system level in a format as understood by firmware.
#
# The format is 0xabccddeeeeffgghh, where
# - a=statistics flags
# - b=distro id
# - c=distro major version
# - d=distro minor version(s)
# - e=kernel sublevel 2
# - f=kernel version
# - g=kernel patchlevel
# - h=kernel sublevel 1
#
get_system_level()
{
local distro="$1" ver_str="$2" kver_str="$3" flags="${4:-0}"
local distro_id d_major d_minor d_minor2
local k_ver k_patchlvl k_sublvl k_sublvl2 bytes=()
# Extract list of sub-version numbers from version strings
read -r d_major d_minor d_minor2 <<< "$(split_version "$ver_str" "._-" 3)"
read -r k_ver k_patchlvl k_sublvl k_sublvl2 <<< "$(split_kver "$kver_str" 4)"
# Handle excessive sublevel numbers consistently
if [[ "$k_sublvl2" -gt 65535 ]] ; then
k_sublvl2=0
fi
# Apply distro-specific logic
case "$distro" in
"rhel")
distro_id=$DISTRO_RHEL
;;
"sles")
distro_id=$DISTRO_SLES
;;
"ubuntu")
distro_id=$DISTRO_UBUNTU
# Encode minor and update version numbers in minor field
(( d_minor=((d_minor & 0xf) * 0x10) + (d_minor2 & 0xf) ))
;;
"fedora")
distro_id=$DISTRO_FEDORA
;;
"opensuse-leap")
distro_id=$DISTRO_OPENSUSE
;;
"debian")
distro_id=$DISTRO_DEBIAN
;;
"rhcos")
distro_id=$DISTRO_RHCOS
;;
*)
distro_id=$DISTRO_GENERIC
# Reset unsupported fields
d_major=0
d_minor=0
k_sublvl2=0
;;
esac
# Assemble byte data
(( bytes[0] = (flags & 0xf) * 0x10 + distro_id ))
(( bytes[1] = d_major ))
(( bytes[2] = d_minor ))
(( bytes[3] = (k_sublvl2 / 256) & 0xff ))
(( bytes[4] = k_sublvl2 & 0xff ))
(( bytes[5] = k_ver ))
(( bytes[6] = k_patchlvl ))
(( bytes[7] = k_sublvl ))
# Print as single hex word
bytes_to_word "${bytes[@]}"
}
get_distro()
{
local line ID="linux" VERSION_ID="0" VERSION="" update
[[ ! -e "$OS_RELEASE" ]] && return
# Only import required variables
while read -r line ; do
if [[ "$line" =~ ^ID= ]] || [[ "$line" =~ ^VERSION_ID= ]] ||
[[ "$line" =~ ^VERSION= ]] ; then
eval "$line"
fi
done <"$OS_RELEASE"
if [[ "$ID" == "ubuntu" ]] ; then
# Extract update version number only found in VERSION, e.g.
# VERSION_ID="18.04" VERSION="18.04.5 LTS"
update="${VERSION/*$VERSION_ID/}"
update="${update%% *}"
VERSION_ID="$VERSION_ID$update"
fi
echo "$ID:$VERSION_ID"
}
cpi_set_oslevel() cpi_set_oslevel()
{ {
local kver=$(echo "${1:-$(uname -r)}" | grep -E -o '^[0-9]+[.][0-9]+[.][0-9]+') local level="${1:-}"
local maj=$((${kver%%.*} % 256)) local flags list distro_id distro_ver kver id ver
local min=${kver#*.}
min=$((${min%.*} % 256)) if [[ "$level" =~ ^0x ]] && ! [[ "$level" =~ : ]] ; then
local rev=$((${kver##*.} % 256)) # Format: level=0x<hex>
local hexlevel=$(printf '0x%02x%02x%02x' $maj $min $rev) printf -v LEVEL "0x%016x" "$level" 2>/dev/null ||
LEVEL=$(printf '0x%016x' $(((LEVEL & 0xFFFFFFFFFF000000) | hexlevel))) fail_with "$PRG: Invalid hexadecimal number in $level" \
$EXIT_INVALID_CHARS
return
fi
# Format: level=[[[flags:]distro_id:distro_ver:]kver]
IFS=":" read -r -a list <<< "$level:"
kver="${list[*]: -1: 1}"
distro_ver="${list[*]: -2: 1}"
distro_id="${list[*]: -3: 1}"
flags="${list[*]: -4: 1}"
if [[ -z "$kver" ]] ; then
# Use version of currently running kernel
kver="$(uname -r)"
fi
if [[ -z "$distro_ver" ]] || [[ -z "$distro_id" ]] ; then
# Use distro ID and version from os-release file
IFS=":" read -r id ver <<< "$(get_distro)"
distro_id=${distro_id:-$id}
distro_ver=${distro_ver:-$ver}
fi
if [[ -z "$flags" ]] ; then
# Keep statistics flags from current system level
flags=$(( (LEVEL >> 60) & 0xf ))
fi
LEVEL=$(get_system_level "$distro_id" "$distro_ver" "$kver" "$flags")
} }
cpi_set_type() cpi_set_type()
+679 -596
View File
File diff suppressed because it is too large Load Diff
+37 -5
View File
@@ -1,6 +1,6 @@
.\" lszcrypt.8 .\" lszcrypt.8
.\" .\"
.\" Copyright 2019 IBM Corp. .\" Copyright IBM Corp. 2019, 2022
.\" s390-tools is free software; you can redistribute it and/or modify .\" s390-tools is free software; you can redistribute it and/or modify
.\" it under the terms of the MIT license. See LICENSE for details. .\" it under the terms of the MIT license. See LICENSE for details.
.\" .\"
@@ -10,13 +10,14 @@
.\" nroff -man lszcrypt.8 .\" nroff -man lszcrypt.8
.\" to process this source .\" to process this source
.\" .\"
.TH LSZCRYPT 8 "OCT 2020" "s390-tools" .TH LSZCRYPT 8 "FEB 2022" "s390-tools"
.SH NAME .SH NAME
lszcrypt \- display zcrypt device and configuration information lszcrypt \- display zcrypt device and configuration information
.SH SYNOPSIS .SH SYNOPSIS
.TP 9 .TP 9
.B lszcrypt .B lszcrypt
.RB "[ " -V " ] " .RB "[" <filteroptions> "]"
.RB "[" -V "]"
[ [
.I <device-id> .I <device-id>
[...]] [...]]
@@ -31,7 +32,12 @@ lszcrypt \- display zcrypt device and configuration information
.TP .TP
.B lszcrypt -h .B lszcrypt -h
.TP .TP
.B lszcrypt -s
.TP
.B lszcrypt -v .B lszcrypt -v
. TP
.B <filteroptions>
[--accelonly|--ccaonly|--ep11only] [--cardonly|--queueonly]
.SH DESCRIPTION .SH DESCRIPTION
The The
.B lszcrypt .B lszcrypt
@@ -109,8 +115,26 @@ B - indicate both (control and usage domain)
.B -h, --help .B -h, --help
Displays help text and exits. Displays help text and exits.
.TP 8 .TP 8
.B -s, --serial
Shows the serial numbers for CCA and EP11 crypto cards.
.TP 8
.B -v, --version .B -v, --version
Displays version information and exits. Displays version information and exits.
.TP 8
.B --accelonly
Show only information for cards/queues in Accelerator mode.
.TP 8
.B --ccaonly
Show only information for cards/queues in CCA-Coprocessor mode.
.TP 8
.B --ep11only
Show only information for cards/queues in EP11-Coprocessor mode.
.TP 8
.B --cardonly
Show only information for cards but no queue info.
.TP 8
.B --queueonly
Show only information for queues but no card info.
.SH LISTING DETAILS .SH LISTING DETAILS
Here is an explanation of the columns displayed. Please note that some Here is an explanation of the columns displayed. Please note that some
of the columns show up in verbose mode only. of the columns show up in verbose mode only.
@@ -123,7 +147,7 @@ dot for a queue line.
.B TYPE and HWTYPE .B TYPE and HWTYPE
The HWTYPE is a numeric value showing which type of hardware the zcrypt The HWTYPE is a numeric value showing which type of hardware the zcrypt
device driver presumes that this crypto card is. The currently known values device driver presumes that this crypto card is. The currently known values
are 7=CEX3C, 8=CEX3A, 10=CEX4, 11=CEX5, 12=CEX6 and 13=CEX7. are 7=CEX3C, 8=CEX3A, 10=CEX4, 11=CEX5, 12=CEX6, 13=CEX7 and 14=CEX8.
.br .br
The TYPE is a human readable value showing the hardware type and the basic The TYPE is a human readable value showing the hardware type and the basic
function type (A=Accelerator, C=CCA Coprocessor, P=EP11 Coprocessor). So function type (A=Accelerator, C=CCA Coprocessor, P=EP11 Coprocessor). So
@@ -154,6 +178,9 @@ cryptographic operations. 'offline' is displayed when a card or queue
is switched to (software) offline. If a card is 'deconfigured' via is switched to (software) offline. If a card is 'deconfigured' via
HMC, SE or chzcrypt the field shows 'deconfig'. HMC, SE or chzcrypt the field shows 'deconfig'.
.br .br
A crypto card may also reach a 'checkstopped' state. lszcrypt shows
this as 'chkstop'.
.br
If a queue is not bound to a device driver there is no detailed If a queue is not bound to a device driver there is no detailed
information available and thus the status shows only '-'. information available and thus the status shows only '-'.
.br .br
@@ -204,12 +231,17 @@ operations within the guests.
.B DRIVER .B DRIVER
.br .br
Shows which card or queue device driver currently handles this crypto Shows which card or queue device driver currently handles this crypto
resource. Currently known drivers are cex4card/cex4queue (CEX4-CEX7 resource. Currently known drivers are cex4card/cex4queue (CEX4-CEX8
hardware), cex2card/cex2cqueue (CEX2C and CEX3C hardware), hardware), cex2card/cex2cqueue (CEX2C and CEX3C hardware),
cex2acard/cex2aqueue (CEX2A and CEX3A hardware) and vfio_ap (queue reserved cex2acard/cex2aqueue (CEX2A and CEX3A hardware) and vfio_ap (queue reserved
for use by kvm hypervisor for kvm guests and not accessible to host for use by kvm hypervisor for kvm guests and not accessible to host
applications). It is also valid to have no driver handling a queue which is applications). It is also valid to have no driver handling a queue which is
shown as a -no-driver- entry. shown as a -no-driver- entry.
.SH NOTES
Use only one of the mode filtering options --accelonly, --ccaonly, --ep11only.
Same with card/queue filtering: Use only one of --cardonly, --queueonly.
However, one of the mode filtering options and one of the card/queue filtering
can be combined.
.SH EXAMPLES .SH EXAMPLES
.TP .TP
.B lszcrypt .B lszcrypt
+210 -20
View File
@@ -1,7 +1,7 @@
/** /**
* lszcrypt - Display zcrypt devices and configuration settings * lszcrypt - Display zcrypt devices and configuration settings
* *
* Copyright IBM Corp. 2008, 2020 * Copyright IBM Corp. 2008, 2022
* *
* s390-tools is free software; you can redistribute it and/or modify * s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
@@ -29,6 +29,11 @@
*/ */
static struct lszcrypt_l { static struct lszcrypt_l {
int verbose; int verbose;
int showaccel;
int showcca;
int showep11;
int showcard;
int showqueue;
} l; } l;
/* /*
@@ -39,6 +44,7 @@ static struct lszcrypt_l {
#define CAP_CCA "CCA Secure Key" #define CAP_CCA "CCA Secure Key"
#define CAP_RNG "Long RNG" #define CAP_RNG "Long RNG"
#define CAP_EP11 "EP11 Secure Key" #define CAP_EP11 "EP11 Secure Key"
#define CAP_APMMS "AP bus max message size limit %ld Kb"
/* /*
* Card types * Card types
@@ -95,6 +101,13 @@ static const struct util_prg prg = {
/* /*
* Configuration of command line options * Configuration of command line options
*/ */
#define OPT_ACCELONLY 0x81
#define OPT_CCAONLY 0x82
#define OPT_EP11ONLY 0x83
#define OPT_CARDONLY 0x84
#define OPT_QUEUEONLY 0x85
static struct util_opt opt_vec[] = { static struct util_opt opt_vec[] = {
{ {
.option = {"bus", 0, NULL, 'b'}, .option = {"bus", 0, NULL, 'b'},
@@ -113,6 +126,35 @@ static struct util_opt opt_vec[] = {
.option = {"verbose", 0, NULL, 'V'}, .option = {"verbose", 0, NULL, 'V'},
.desc = "Print verbose messages", .desc = "Print verbose messages",
}, },
{
.option = {"accelonly", 0, NULL, OPT_ACCELONLY},
.flags = UTIL_OPT_FLAG_NOSHORT,
.desc = "Show only information from cards/queues in Accelerator mode",
},
{
.option = {"ccaonly", 0, NULL, OPT_CCAONLY},
.flags = UTIL_OPT_FLAG_NOSHORT,
.desc = "Show only information from cards/queues in CCA-Coprocessor mode",
},
{
.option = {"ep11only", 0, NULL, OPT_EP11ONLY},
.flags = UTIL_OPT_FLAG_NOSHORT,
.desc = "Show only information from cards/queues in EP11-Coprocessor mode",
},
{
.option = {"cardonly", 0, NULL, OPT_CARDONLY},
.flags = UTIL_OPT_FLAG_NOSHORT,
.desc = "Show only information from cards but no queue info",
},
{
.option = {"queueonly", 0, NULL, OPT_QUEUEONLY},
.flags = UTIL_OPT_FLAG_NOSHORT,
.desc = "Show only information from queues but no card info",
},
{
.option = {"serial", 0, NULL, 's'},
.desc = "Show the serial numbers for CCA and EP11 crypto cards",
},
UTIL_OPT_HELP, UTIL_OPT_HELP,
UTIL_OPT_VERSION, UTIL_OPT_VERSION,
UTIL_OPT_END UTIL_OPT_END
@@ -247,13 +289,94 @@ static void show_domains(void)
show_domains_util_rec(domain_array); show_domains_util_rec(domain_array);
} }
/*
* Show serialnumbers
*/
static void show_serialnumbers(void)
{
struct util_rec *rec = util_rec_new_wide("-");
struct dirent **dev_vec;
int i, count;
char *ap, *path, *device, *grp_dev, card[16], buf[256];
long config = -1, online = -1, chkstop = -1;
unsigned long facility;
/* check if ap driver is available */
ap = util_path_sysfs("bus/ap");
if (!util_path_is_dir(ap))
errx(EXIT_FAILURE, "Crypto device driver not available.");
/* define the record */
util_rec_def(rec, "card", UTIL_REC_ALIGN_LEFT, 8, "CARD.DOM");
util_rec_def(rec, "type", UTIL_REC_ALIGN_LEFT, 5, "TYPE");
util_rec_def(rec, "mode", UTIL_REC_ALIGN_LEFT, 11, "MODE");
util_rec_def(rec, "status", UTIL_REC_ALIGN_LEFT, 10, "STATUS");
util_rec_def(rec, "serialnr", UTIL_REC_ALIGN_LEFT, 8, "SERIALNR");
/* scan the devices */
path = util_path_sysfs("devices/ap/");
count = util_scandir(&dev_vec, alphasort, path, "card[0-9a-fA-F]+");
if (count < 1)
errx(EXIT_FAILURE, "No crypto card devices found.");
util_rec_print_hdr(rec);
for (i = 0; i < count; i++) {
device = dev_vec[i]->d_name;
grp_dev = util_path_sysfs("devices/ap/%s", device);
if (!util_path_is_dir(grp_dev))
errx(EXIT_FAILURE, "Error - cryptographic device %s does not exist.", device);
if (!util_path_is_readable("%s/type", grp_dev) ||
!util_path_is_readable("%s/online", grp_dev))
goto next;
strcpy(card, device + 4);
util_rec_set(rec, "card", card);
util_file_read_line(buf, sizeof(buf), "%s/type", grp_dev);
util_rec_set(rec, "type", buf);
util_file_read_ul(&facility, 16, "%s/ap_functions", grp_dev);
if (facility & MASK_COPRO)
util_rec_set(rec, "mode", "CCA-Coproc");
else if (facility & MASK_EP11)
util_rec_set(rec, "mode", "EP11-Coproc");
else
goto next;
if (util_path_is_readable("%s/config", grp_dev))
util_file_read_l(&config, 10, "%s/config", grp_dev);
if (util_path_is_readable("%s/chkstop", grp_dev))
util_file_read_l(&chkstop, 10, "%s/chkstop", grp_dev);
if (util_path_is_readable("%s/online", grp_dev))
util_file_read_l(&online, 10, "%s/online", grp_dev);
if (config == 0) {
util_rec_set(rec, "status", "deconfig");
} else {
if (chkstop > 0)
util_rec_set(rec, "status", "chkstop");
else if (online > 0)
util_rec_set(rec, "status", "online");
else if (online == 0)
util_rec_set(rec, "status", "offline");
else
util_rec_set(rec, "status", "-");
}
if (util_file_read_line(buf, sizeof(buf), "%s/serialnr", grp_dev))
util_rec_set(rec, "serialnr", "-");
else {
buf[8] = '\0';
util_rec_set(rec, "serialnr", buf);
}
util_rec_print(rec);
next:
free(grp_dev);
}
free(path);
}
/* /*
* Show capability * Show capability
*/ */
static void show_capability(const char *id_str) static void show_capability(const char *id_str)
{ {
unsigned long func_val; unsigned long func_val;
long hwtype, id; long hwtype, id, max_msg_size;
char *p, *ap, *dev, card[16], cbuf[256]; char *p, *ap, *dev, card[16], cbuf[256];
/* check if ap driver is available */ /* check if ap driver is available */
@@ -272,6 +395,9 @@ static void show_capability(const char *id_str)
/* If sysfs attribute is missing, set functions to 0 */ /* If sysfs attribute is missing, set functions to 0 */
if (util_file_read_ul(&func_val, 16, "%s/ap_functions", dev)) if (util_file_read_ul(&func_val, 16, "%s/ap_functions", dev))
func_val = 0x00000000; func_val = 0x00000000;
/* try to read the ap bus max message size for this card */
if (util_file_read_l(&max_msg_size, 10, "%s/max_msg_size", dev))
max_msg_size = 0;
/* Skip devices, which are not supported by zcrypt layer */ /* Skip devices, which are not supported by zcrypt layer */
if (!util_path_is_readable("%s/type", dev) || if (!util_path_is_readable("%s/type", dev) ||
!util_path_is_readable("%s/online", dev)) { !util_path_is_readable("%s/online", dev)) {
@@ -289,9 +415,9 @@ static void show_capability(const char *id_str)
case 6: case 6:
case 8: case 8:
if (func_val & MASK_RSA4K) if (func_val & MASK_RSA4K)
printf("%s", CAP_RSA4K); printf("%s\n", CAP_RSA4K);
else else
printf("%s", CAP_RSA2K); printf("%s\n", CAP_RSA2K);
break; break;
case 7: case 7:
case 9: case 9:
@@ -300,37 +426,39 @@ static void show_capability(const char *id_str)
printf("%s (%s)\n", CAP_CCA, cbuf); printf("%s (%s)\n", CAP_CCA, cbuf);
else else
printf("%s\n", CAP_CCA); printf("%s\n", CAP_CCA);
printf("%s", CAP_RNG); printf("%s\n", CAP_RNG);
break; break;
case 10: /* CEX4S */ case 10: /* CEX4S */
case 11: /* CEX5S */ case 11: /* CEX5S */
case 12: /* CEX6S */ case 12: /* CEX6S */
case 13: /* CEX7S */ case 13: /* CEX7S */
case 14: /* CEX8S */
if (func_val & MASK_ACCEL) { if (func_val & MASK_ACCEL) {
if (func_val & MASK_RSA4K) if (func_val & MASK_RSA4K)
printf("%s", CAP_RSA4K); printf("%s\n", CAP_RSA4K);
else else
printf("%s", CAP_RSA2K); printf("%s\n", CAP_RSA2K);
} else if (func_val & MASK_COPRO) { } else if (func_val & MASK_COPRO) {
printf("%s\n", CAP_RSA4K); printf("%s\n", CAP_RSA4K);
if (cbuf[0]) if (cbuf[0])
printf("%s (%s)\n", CAP_CCA, cbuf); printf("%s (%s)\n", CAP_CCA, cbuf);
else else
printf("%s\n", CAP_CCA); printf("%s\n", CAP_CCA);
printf("%s", CAP_RNG); printf("%s\n", CAP_RNG);
} else if (func_val & MASK_EP11) { } else if (func_val & MASK_EP11) {
printf("%s", CAP_EP11); printf("%s\n", CAP_EP11);
} else { } else {
printf("Detailed capability information for %s (hardware type %ld) is not available.", printf("Detailed capability information for %s (hardware type %ld) is not available.\n",
card, hwtype); card, hwtype);
} }
if (max_msg_size > 0)
printf(CAP_APMMS "\n", max_msg_size / 1024);
break; break;
default: default:
printf("Detailed capability information for %s (hardware type %ld) is not available.", printf("Detailed capability information for %s (hardware type %ld) is not available.\n",
card, hwtype); card, hwtype);
break; break;
} }
printf("\n");
} }
/* /*
@@ -375,7 +503,7 @@ static int read_driver(const char *dir, const char *subdir, char *buf, size_t bu
static void read_subdev_rec_default(struct util_rec *rec, const char *grp_dev, static void read_subdev_rec_default(struct util_rec *rec, const char *grp_dev,
const char *sub_dev) const char *sub_dev)
{ {
long config = -1, online = -1; long config = -1, online = -1, chkstop = -1;
char buf[256]; char buf[256];
unsigned long facility; unsigned long facility;
@@ -386,6 +514,8 @@ static void read_subdev_rec_default(struct util_rec *rec, const char *grp_dev,
if (util_path_is_readable("%s/%s/config", grp_dev, sub_dev)) if (util_path_is_readable("%s/%s/config", grp_dev, sub_dev))
util_file_read_l(&config, 10, "%s/%s/config", grp_dev, sub_dev); util_file_read_l(&config, 10, "%s/%s/config", grp_dev, sub_dev);
if (util_path_is_readable("%s/%s/chkstop", grp_dev, sub_dev))
util_file_read_l(&chkstop, 10, "%s/%s/chkstop", grp_dev, sub_dev);
if (util_path_is_readable("%s/%s/online", grp_dev, sub_dev)) if (util_path_is_readable("%s/%s/online", grp_dev, sub_dev))
util_file_read_l(&online, 10, "%s/%s/online", grp_dev, sub_dev); util_file_read_l(&online, 10, "%s/%s/online", grp_dev, sub_dev);
@@ -393,7 +523,9 @@ static void read_subdev_rec_default(struct util_rec *rec, const char *grp_dev,
if (config == 0) { if (config == 0) {
util_rec_set(rec, "status", "deconfig"); util_rec_set(rec, "status", "deconfig");
} else { } else {
if (online > 0) if (chkstop > 0)
util_rec_set(rec, "status", "chkstop");
else if (online > 0)
util_rec_set(rec, "status", "online"); util_rec_set(rec, "status", "online");
else if (online == 0) else if (online == 0)
util_rec_set(rec, "status", "offline"); util_rec_set(rec, "status", "offline");
@@ -489,6 +621,9 @@ static void show_subdevice(struct util_rec *rec, const char *grp_dev,
!util_path_is_readable("%s/%s/online", grp_dev, sub_dev))) !util_path_is_readable("%s/%s/online", grp_dev, sub_dev)))
return; return;
if (!l.showqueue)
return;
util_rec_set(rec, "card", sub_dev); util_rec_set(rec, "card", sub_dev);
read_subdev_rec_default(rec, grp_dev, sub_dev); read_subdev_rec_default(rec, grp_dev, sub_dev);
read_subdev_rec_verbose(rec, grp_dev, sub_dev); read_subdev_rec_verbose(rec, grp_dev, sub_dev);
@@ -516,7 +651,7 @@ static void show_subdevices(struct util_rec *rec, const char *grp_dev)
*/ */
static void read_rec_default(struct util_rec *rec, const char *grp_dev) static void read_rec_default(struct util_rec *rec, const char *grp_dev)
{ {
long config = -1, online = -1; long config = -1, online = -1, chkstop = -1;
char buf[256]; char buf[256];
unsigned long facility; unsigned long facility;
@@ -537,12 +672,16 @@ static void read_rec_default(struct util_rec *rec, const char *grp_dev)
if (util_path_is_readable("%s/config", grp_dev)) if (util_path_is_readable("%s/config", grp_dev))
util_file_read_l(&config, 10, "%s/config", grp_dev); util_file_read_l(&config, 10, "%s/config", grp_dev);
if (util_path_is_readable("%s/chkstop", grp_dev))
util_file_read_l(&chkstop, 10, "%s/chkstop", grp_dev);
if (util_path_is_readable("%s/online", grp_dev)) if (util_path_is_readable("%s/online", grp_dev))
util_file_read_l(&online, 10, "%s/online", grp_dev); util_file_read_l(&online, 10, "%s/online", grp_dev);
if (config == 0) { if (config == 0) {
util_rec_set(rec, "status", "deconfig"); util_rec_set(rec, "status", "deconfig");
} else { } else {
if (online > 0) if (chkstop > 0)
util_rec_set(rec, "status", "chkstop");
else if (online > 0)
util_rec_set(rec, "status", "online"); util_rec_set(rec, "status", "online");
else if (online == 0) else if (online == 0)
util_rec_set(rec, "status", "offline"); util_rec_set(rec, "status", "offline");
@@ -603,7 +742,7 @@ static void read_rec_verbose(struct util_rec *rec, const char *grp_dev)
*/ */
static void show_device(struct util_rec *rec, const char *device) static void show_device(struct util_rec *rec, const char *device)
{ {
char *grp_dev, card[16]; char *grp_dev, card[16], type[16], t = '\0';
strcpy(card, &device[4]); strcpy(card, &device[4]);
grp_dev = util_path_sysfs("devices/ap/%s", device); grp_dev = util_path_sysfs("devices/ap/%s", device);
@@ -621,11 +760,21 @@ static void show_device(struct util_rec *rec, const char *device)
} }
util_rec_set(rec, "card", card); util_rec_set(rec, "card", card);
if (util_file_read_line(type, sizeof(type), "%s/type", grp_dev) == 0)
t = type[strlen(type) - 1];
if ((t == 'A' && !l.showaccel) ||
(t == 'C' && !l.showcca) ||
(t == 'P' && !l.showep11))
goto out_free;
read_rec_default(rec, grp_dev); read_rec_default(rec, grp_dev);
read_rec_verbose(rec, grp_dev); read_rec_verbose(rec, grp_dev);
util_rec_print(rec); if (l.showcard)
show_subdevices(rec, grp_dev); util_rec_print(rec);
if (l.showqueue)
show_subdevices(rec, grp_dev);
out_free: out_free:
free(grp_dev); free(grp_dev);
} }
@@ -799,9 +948,27 @@ int main(int argc, char **argv)
case 'd': case 'd':
show_domains(); show_domains();
return EXIT_SUCCESS; return EXIT_SUCCESS;
case 's':
show_serialnumbers();
return EXIT_SUCCESS;
case 'V': case 'V':
l.verbose++; l.verbose++;
break; break;
case OPT_ACCELONLY:
l.showaccel = 1;
break;
case OPT_CCAONLY:
l.showcca = 1;
break;
case OPT_EP11ONLY:
l.showep11 = 1;
break;
case OPT_CARDONLY:
l.showcard = 1;
break;
case OPT_QUEUEONLY:
l.showqueue = 1;
break;
case 'h': case 'h':
util_prg_print_help(); util_prg_print_help();
util_opt_print_help(); util_opt_print_help();
@@ -815,6 +982,29 @@ int main(int argc, char **argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
switch (l.showaccel + l.showcca + l.showep11) {
case 0:
l.showaccel = l.showcca = l.showep11 = 1;
break;
case 1:
break;
default:
warnx("Only one of --accelonly or --ccaonly or --ep11only can be specified");
return EXIT_FAILURE;
}
switch (l.showcard + l.showqueue) {
case 0:
l.showcard = l.showqueue = 1;
break;
case 1:
break;
default:
warnx("Only one of --cardonly or --queueonly can be specified");
return EXIT_FAILURE;
}
if (optind == argc) if (optind == argc)
show_devices_all(); show_devices_all();
else else
+33 -7
View File
@@ -1,6 +1,6 @@
.\" zcryptctl.8 .\" zcryptctl.8
.\" .\"
.\" Copyright 2018 IBM Corp. .\" Copyright 2018, 2022 IBM Corp.
.\" s390-tools is free software; you can redistribute it and/or modify .\" s390-tools is free software; you can redistribute it and/or modify
.\" it under the terms of the MIT license. See LICENSE for details. .\" it under the terms of the MIT license. See LICENSE for details.
.\" .\"
@@ -10,7 +10,7 @@
.\" nroff -man zcryptctl.8 .\" nroff -man zcryptctl.8
.\" to process this source .\" to process this source
.\" .\"
.TH ZCRYPTCTL 8 "AUG 2018" "s390-tools" .TH ZCRYPTCTL 8 "JAN 2022" "s390-tools"
.SH NAME .SH NAME
zcryptctl \- display information and administrate zcrypt multiple device nodes zcryptctl \- display information and administrate zcrypt multiple device nodes
.SH SYNOPSIS .SH SYNOPSIS
@@ -35,6 +35,11 @@ zcryptctl \- display information and administrate zcrypt multiple device nodes
.B deldom .B deldom
.I node-name domain-nr .I node-name domain-nr
.TP .TP
.B zcryptctl addctrl
.R |
.B delctrl
.I node-name domain-nr
.TP
.B zcryptctl addioctl .B zcryptctl addioctl
.R | .R |
.B delioctl .B delioctl
@@ -57,6 +62,7 @@ driver. Each zcrypt device node can be restricted in terms of crypto
cards, domains, and available ioctls. Such a device node can be used cards, domains, and available ioctls. Such a device node can be used
as a base for container solutions like Docker to control and restrict as a base for container solutions like Docker to control and restrict
the access to crypto resources. the access to crypto resources.
See the NOTES section below for information on control domains.
.SH COMMANDS .SH COMMANDS
.TP 8 .TP 8
.B zcryptctl list .B zcryptctl list
@@ -96,6 +102,14 @@ Update the filter for the specified zcrypt device node and add or
delete a domain to be accessible through this node. The symbol delete a domain to be accessible through this node. The symbol
\fBALL\fP can be used to enable or disable all domains. \fBALL\fP can be used to enable or disable all domains.
.TP .TP
.B zcryptctl addctrl
.R |
.B delctrl
.I node-name domain-nr
Update the filter for the specified zcrypt device node and add or
delete a control domain to be accessible through this node. The symbol
\fBALL\fP can be used to enable or disable all domains.
.TP
.B zcryptctl addioctl .B zcryptctl addioctl
.R | .R |
.B delioctl .B delioctl
@@ -116,19 +130,20 @@ line and the settings are applied. Syntax is simple:
.IP "node=<node-name>" .IP "node=<node-name>"
.IP "aps=<list of ap numbers separated by space, tab or ','>" .IP "aps=<list of ap numbers separated by space, tab or ','>"
.IP "doms=<list of domain numbers separated by space, tab or ','>" .IP "doms=<list of domain numbers separated by space, tab or ','>"
.IP "ctrls=<list of control domain numbers separated by space, tab or ','>"
.IP "ioctls=<list of ioctl as numeric or symbolic number separated by space, tab or ','>" .IP "ioctls=<list of ioctl as numeric or symbolic number separated by space, tab or ','>"
.LP .LP
Empty lines are ignored and the '#' marks the rest of the Empty lines are ignored and the '#' marks the rest of the
line as comment. line as comment.
.LP .LP
The \fBnode=\fP line creates a new zcrypt device node, the \fBaps=\fP, The \fBnode=\fP line creates a new zcrypt device node, the \fBaps=\fP,
\fBdoms=\fP and \fBioctls=\fP lines customize the previously created \fBdoms=\fP, \fBctrls=\fP and \fBioctls=\fP lines customize the
node. The symbol \fBALL\fP is also recognized for aps, doms, and previously created node. The symbol \fBALL\fP is also recognized for
ioctls. aps, doms, and ioctls.
.LP .LP
Each action must fit into one line, spreading over multiple lines is Each action must fit into one line, spreading over multiple lines is
not supported. But you can use more than one \fBaps=\fP, \fBdoms=\fP not supported. But you can use more than one \fBaps=\fP, \fBdoms=\fP,
and \fBioctls=\fP lines to customize the very same node. \fBctrls=\fP and \fBioctls=\fP lines to customize the very same node.
.LP .LP
Processing stops when a line cannot be parsed or the current action Processing stops when a line cannot be parsed or the current action
fails. In this case the exit status is non zero but the successful fails. In this case the exit status is non zero but the successful
@@ -139,6 +154,17 @@ actions until the failure occurs are not rolled back.
List the current configuration in a form suitable for input to the List the current configuration in a form suitable for input to the
\fBzcryptctl config\fP command. \fBzcryptctl config\fP command.
.LP .LP
.SH NOTES
Control domain filtering is only supported for custom device
<nodename> if the \fBadmask\fP file in sysfs under
/sys/class/zcrypt/<nodename>/admask exists. If this file does not
exist, the kernel is too old and does not support control command
filtering. This is the same effect as setting the control domain mask
to ALL. Note that, even though you can allow more than available to
the system, you can only send control commands to control domains
available to the system.
.SH EXIT STATUS .SH EXIT STATUS
On successful completion of the command the exit status is 0. A non On successful completion of the command the exit status is 0. A non
zero return code (and some kind of failure message) is emitted if the zero return code (and some kind of failure message) is emitted if the
+121 -4
View File
@@ -2,7 +2,7 @@
* zcryptctl - Maintain zcrypt multi device nodes. * zcryptctl - Maintain zcrypt multi device nodes.
* *
* by Harald Freudenberger <freude@linux.ibm.com> * by Harald Freudenberger <freude@linux.ibm.com>
* Copyright IBM Corp. 2018 * Copyright IBM Corp. 2018, 2022
* *
* s390-tools is free software; you can redistribute it and/or modify * s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
@@ -58,6 +58,8 @@
#define CMD_DEL_IOCTL 0x0009 #define CMD_DEL_IOCTL 0x0009
#define CMD_CONFIG 0x000A #define CMD_CONFIG 0x000A
#define CMD_LISTCONFIG 0x000B #define CMD_LISTCONFIG 0x000B
#define CMD_ADD_CTRL 0x000C
#define CMD_DEL_CTRL 0x000D
/* /*
* Program configuration * Program configuration
@@ -70,7 +72,7 @@ static const struct util_prg prg = {
{ {
.owner = "IBM Corp.", .owner = "IBM Corp.",
.pub_first = 2018, .pub_first = 2018,
.pub_last = 2018, .pub_last = 2022,
}, },
UTIL_PRG_COPYRIGHT_END UTIL_PRG_COPYRIGHT_END
} }
@@ -345,6 +347,18 @@ static int cmd_list(int cmd,
if (test_bit(i, buf)) if (test_bit(i, buf))
printf("%c%d", n++ == 0 ? tab : ',', i); printf("%c%d", n++ == 0 ? tab : ',', i);
putchar('\n'); putchar('\n');
if (cmd == CMD_LISTCONFIG)
printf(" ctrls =");
else
printf(" control domains:");
if (read_dn_attr(de->d_name, "admask", buf, sizeof(buf)) != 0)
errx(EXIT_FAILURE,
"Could not fetch admask attribute from sysfs for zcrypt node '%s'",
de->d_name);
for (i = n = 0; i < MAX_ZDEV_DOMAINS_EXT; i++)
if (test_bit(i, buf))
printf("%c%d", n++ == 0 ? tab : ',', i);
putchar('\n');
if (cmd == CMD_LISTCONFIG) if (cmd == CMD_LISTCONFIG)
printf(" ioctls ="); printf(" ioctls =");
else else
@@ -526,6 +540,52 @@ static int cmd_add_del_dom(int cmd, const char *node, const char *arg)
return 0; return 0;
} }
static void add_del_ctrl(int cmd, const char *node, int dom)
{
int rc;
char buf[PATH_MAX];
if (cmd == CMD_ADD_CTRL)
sprintf(buf, "+%d", dom);
else
sprintf(buf, "-%d", dom);
rc = write_dn_attr(node, "admask", buf);
if (rc != 0)
errx(EXIT_FAILURE,
"Could not write into sysfs entry to %s domain %d for zdev node '%s'",
cmd == CMD_ADD_CTRL ? "add" : "remove", dom, node);
}
static int cmd_add_del_ctrl(int cmd, const char *node, const char *arg)
{
int dom, all = 0;
if (strcasecmp(arg, "ALL") == 0) {
all = 1;
} else {
if (sscanf(arg, "%i", &dom) != 1)
errx(EXIT_FAILURE,
"Invalid domain argument '%s'", arg);
if (dom < 0 || dom >= MAX_ZDEV_DOMAINS_EXT)
errx(EXIT_FAILURE,
"Domain argument '%s' out of range [0..%d]",
arg, MAX_ZDEV_DOMAINS_EXT - 1);
}
if (!all) {
add_del_ctrl(cmd, node, dom);
printf("Control domain %d %s\n", dom,
(cmd == CMD_ADD_CTRL ? "added" : "removed"));
} else {
for (dom = 0; dom < MAX_ZDEV_DOMAINS_EXT; dom++)
add_del_ctrl(cmd, node, dom);
printf("All control domains %s\n",
(cmd == CMD_ADD_CTRL ? "added" : "removed"));
}
return 0;
}
static void add_del_ioctl(int cmd, const char *node, int ioctlnr) static void add_del_ioctl(int cmd, const char *node, int ioctlnr)
{ {
int rc; int rc;
@@ -694,12 +754,34 @@ static int cmd_config(int cmd _UNUSED_,
break; break;
if (!_match_string(&p, buf)) if (!_match_string(&p, buf))
errx(EXIT_FAILURE, errx(EXIT_FAILURE,
"Missing argument(s) for aps=... at '%-8.8s...' in line %d '%s'", "Missing argument(s) for doms=... at '%-8.8s...' in line %d '%s'",
p, nr, line); p, nr, line);
cmd_add_del_dom(CMD_ADD_DOM, node, buf); cmd_add_del_dom(CMD_ADD_DOM, node, buf);
while (isblank(*p) || *p == ',') while (isblank(*p) || *p == ',')
p++; p++;
} }
} else if (_match_keyword(&p, "ctrls")) {
if (!havenode)
errx(EXIT_FAILURE,
"Missing node=... before processing any ctrls=... statements in line %d '%s'",
nr, line);
if (!_match_character(&p, '='))
errx(EXIT_FAILURE,
"Missing '=' at '%-8.8s...' in line %d '%s'",
p, nr, line);
while (1) {
while (isspace(*p))
p++;
if (*p == '\0' || *p == '#')
break;
if (!_match_string(&p, buf))
errx(EXIT_FAILURE,
"Missing argument(s) for ctrls=... at '%-8.8s...' in line %d '%s'",
p, nr, line);
cmd_add_del_ctrl(CMD_ADD_CTRL, node, buf);
while (isblank(*p) || *p == ',')
p++;
}
} else if (_match_keyword(&p, "ioctls")) { } else if (_match_keyword(&p, "ioctls")) {
if (!havenode) if (!havenode)
errx(EXIT_FAILURE, errx(EXIT_FAILURE,
@@ -810,13 +892,35 @@ static struct zcryptctl_cmds_s {
.cmd = CMD_DEL_DOM, .cmd = CMD_DEL_DOM,
.command = "deldom", .command = "deldom",
.function = cmd_add_del_dom, .function = cmd_add_del_dom,
.usage = "zcryptctl deldom <adapter>", .usage = "zcryptctl deldom <domain>",
.description = .description =
"Update the filter for the specified zcrypt device node and\n" "Update the filter for the specified zcrypt device node and\n"
"remove a crypto domain from the allowed domains list. The\n" "remove a crypto domain from the allowed domains list. The\n"
"domain argument may be a number in the range 0-255 or the\n" "domain argument may be a number in the range 0-255 or the\n"
"symbol ALL.", "symbol ALL.",
}, },
{
.cmd = CMD_ADD_CTRL,
.command = "addctrl",
.function = cmd_add_del_ctrl,
.usage = "zcryptctl addctrl <domain>",
.description =
"Update the filter for the specified zcrypt device node and\n"
"add a crypto control domain to be accessible via this node.\n"
"The domain argument may be a number in the range 0-255 or\n"
"the symbol ALL.",
},
{
.cmd = CMD_DEL_CTRL,
.command = "delctrl",
.function = cmd_add_del_ctrl,
.usage = "zcryptctl delctrl <domain>",
.description =
"Update the filter for the specified zcrypt device node and\n"
"remove a crypto control domain from the allowed domains list.\n"
"The domain argument may be a number in the range 0-255 or\n"
"the symbol ALL.",
},
{ {
.cmd = CMD_ADD_IOCTL, .cmd = CMD_ADD_IOCTL,
.command = "addioctl", .command = "addioctl",
@@ -1003,6 +1107,19 @@ int main(int argc, char *argv[])
argv[optind + 1], argv[optind + 1],
argv[optind + 2]); argv[optind + 2]);
break; break;
case CMD_ADD_CTRL:
case CMD_DEL_CTRL:
if (optind + 1 >= argc)
errx(EXIT_FAILURE, "Missing node name argument");
if (optind + 2 >= argc)
errx(EXIT_FAILURE, "Missing domain argument");
if (check_nodename(argv[optind + 1]) != 0)
errx(EXIT_FAILURE, "Invalid or unknown nodename '%s'",
argv[optind + 1]);
rc = zcryptctl_cmds[cmdindex].function(c,
argv[optind + 1],
argv[optind + 2]);
break;
case CMD_ADD_IOCTL: case CMD_ADD_IOCTL:
case CMD_DEL_IOCTL: case CMD_DEL_IOCTL:
if (optind + 1 >= argc) if (optind + 1 >= argc)
+16 -14
View File
@@ -1,7 +1,7 @@
/* /*
* zcryptstats - Show usage statistics of IBM Crypto Express adapters * zcryptstats - Show usage statistics of IBM Crypto Express adapters
* *
* Copyright IBM Corp. 2019 * Copyright IBM Corp. 2019, 2022
* *
* s390-tools is free software; you can redistribute it and/or modify * s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
@@ -148,8 +148,9 @@ struct chsc_cmb_area {
#define CRYPTO_TYPE_CEX5S 11 #define CRYPTO_TYPE_CEX5S 11
#define CRYPTO_TYPE_CEX6S 12 #define CRYPTO_TYPE_CEX6S 12
#define CRYPTO_TYPE_CEX7S 13 #define CRYPTO_TYPE_CEX7S 13
#define CRYPTO_TYPE_CEX8S 14
#define CRYPTO_TYPE_TOLERATION CRYPTO_TYPE_CEX7S #define CRYPTO_TYPE_TOLERATION CRYPTO_TYPE_CEX8S
struct crypto_counter { struct crypto_counter {
const char *name; const char *name;
@@ -236,8 +237,8 @@ static const struct crypto_mode mode_pcica[1] = {
.counters = counter_pcica }, .counters = counter_pcica },
}; };
#define NUM_CEX4567_MODES 11 #define NUM_CEX45678_MODES 11
static const struct crypto_mode mode_cex4567[NUM_CEX4567_MODES] = { static const struct crypto_mode mode_cex45678[NUM_CEX45678_MODES] = {
{ 0 }, { 0 },
{ 0 }, { 0 },
{ 0 }, { 0 },
@@ -257,7 +258,7 @@ static const struct crypto_mode mode_cex4567[NUM_CEX4567_MODES] = {
.counters = counter_ep11 }, .counters = counter_ep11 },
}; };
#define NUM_CRYPTO_TYPES 14 #define NUM_CRYPTO_TYPES 15
static const struct crypto_type crypto_types[NUM_CRYPTO_TYPES] = { static const struct crypto_type crypto_types[NUM_CRYPTO_TYPES] = {
{ 0 }, { 0 },
{ 0 }, { 0 },
@@ -276,14 +277,16 @@ static const struct crypto_type crypto_types[NUM_CRYPTO_TYPES] = {
.modes = mode_accel }, .modes = mode_accel },
{ .name = "CEX3C", .num_modes = NUM_COPROC_MODES, { .name = "CEX3C", .num_modes = NUM_COPROC_MODES,
.modes = mode_coproc }, .modes = mode_coproc },
{ .name = "CEX4", .num_modes = NUM_CEX4567_MODES, { .name = "CEX4", .num_modes = NUM_CEX45678_MODES,
.modes = mode_cex4567 }, .modes = mode_cex45678 },
{ .name = "CEX5", .num_modes = NUM_CEX4567_MODES, { .name = "CEX5", .num_modes = NUM_CEX45678_MODES,
.modes = mode_cex4567 }, .modes = mode_cex45678 },
{ .name = "CEX6", .num_modes = NUM_CEX4567_MODES, { .name = "CEX6", .num_modes = NUM_CEX45678_MODES,
.modes = mode_cex4567 }, .modes = mode_cex45678 },
{ .name = "CEX7", .num_modes = NUM_CEX4567_MODES, { .name = "CEX7", .num_modes = NUM_CEX45678_MODES,
.modes = mode_cex4567 }, .modes = mode_cex45678 },
{ .name = "CEX8", .num_modes = NUM_CEX45678_MODES,
.modes = mode_cex45678 },
}; };
@@ -2424,4 +2427,3 @@ out:
return rc; return rc;
} }
+56 -8
View File
@@ -7,6 +7,7 @@
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -16,6 +17,7 @@
#include "misc.h" #include "misc.h"
#define LSBLK_CMDLINE "lsblk -P -o NAME,MAJ:MIN,FSTYPE,UUID,MOUNTPOINT,PKNAME 2>/dev/null" #define LSBLK_CMDLINE "lsblk -P -o NAME,MAJ:MIN,FSTYPE,UUID,MOUNTPOINT,PKNAME 2>/dev/null"
#define LSBLK_CMDLINE2 "lsblk -P -o NAME,MAJ:MIN,FSTYPE,UUID,MOUNTPOINTS,PKNAME 2>/dev/null"
struct blkinfo { struct blkinfo {
struct devnode *devnode; struct devnode *devnode;
@@ -82,6 +84,26 @@ void blkinfo_print(struct blkinfo *blkinfo, int level)
printf("%*sparent=%s\n", level, "", blkinfo->parent); printf("%*sparent=%s\n", level, "", blkinfo->parent);
} }
/* Convert each occurrence of '\xnn' in @str to character with hex code <nn>. */
static void hex_unescape(char *str)
{
unsigned int c;
while ((str = strstr(str, "\\x"))) {
if (isxdigit(str[2]) && isxdigit(str[3]) &&
sscanf(str + 2, "%2x", &c) == 1) {
str[0] = (char)c;
/* Move remainder of str including nul behind <c>. */
memmove(str + /* <c> */ 1,
str + /* '\xnn' */ 4,
strlen(str + 4) + /* <nul> */ 1);
}
str++;
}
}
static char *isolate_keyword(char **line_ptr, const char *keyword) static char *isolate_keyword(char **line_ptr, const char *keyword)
{ {
char *start, *end; char *start, *end;
@@ -102,30 +124,58 @@ static char *isolate_keyword(char **line_ptr, const char *keyword)
return start; return start;
} }
static struct blkinfo *blkinfo_from_line(char *line) static void add_blkinfos_from_line(struct util_list *blkinfos,
char *line)
{ {
char *name, *majmin, *fstype, *uuid, *mountpoint, *parent; char *name, *majmin, *fstype, *uuid, *mountpoint, *mountpoints, *parent;
struct blkinfo *blkinfo;
name = isolate_keyword(&line, "NAME=\""); name = isolate_keyword(&line, "NAME=\"");
majmin = isolate_keyword(&line, "MAJ:MIN=\""); majmin = isolate_keyword(&line, "MAJ:MIN=\"");
if (!majmin)
majmin = isolate_keyword(&line, "MAJ_MIN=\"");
fstype = isolate_keyword(&line, "FSTYPE=\""); fstype = isolate_keyword(&line, "FSTYPE=\"");
uuid = isolate_keyword(&line, "UUID=\""); uuid = isolate_keyword(&line, "UUID=\"");
mountpoint = isolate_keyword(&line, "MOUNTPOINT=\""); mountpoint = isolate_keyword(&line, "MOUNTPOINT=\"");
mountpoints = isolate_keyword(&line, "MOUNTPOINTS=\"");
parent = isolate_keyword(&line, "PKNAME=\""); parent = isolate_keyword(&line, "PKNAME=\"");
return blkinfo_new(name, majmin, fstype, uuid, mountpoint, parent); if (!mountpoints) {
/* Handle old lsblk output format. */
blkinfo = blkinfo_new(name, majmin, fstype, uuid, mountpoint,
parent);
ptrlist_add(blkinfos, blkinfo);
return;
}
/* Restore newline mount point separator encoded as hex. */
hex_unescape(mountpoints);
/* Represent each mount point as a separate blkinfo to support
* resolution of multi-mount point file systems like btrfs
* subvolumes. */
while ((mountpoint = strsep(&mountpoints, "\n"))) {
blkinfo = blkinfo_new(name, majmin, fstype, uuid, mountpoint,
parent);
ptrlist_add(blkinfos, blkinfo);
}
} }
static struct util_list *blkinfos_read(void) static struct util_list *blkinfos_read(void)
{ {
char *output, *curr, *next; char *output, *curr, *next;
struct util_list *blkinfos; struct util_list *blkinfos;
struct blkinfo *blkinfo;
if (cached_blkinfos) if (cached_blkinfos)
return cached_blkinfos; return cached_blkinfos;
output = misc_read_cmd_output(LSBLK_CMDLINE, 0, 1); output = misc_read_cmd_output(LSBLK_CMDLINE2, 0, 1);
if (output && !*output) {
/* No output might indicate no support for new lsblk command-
* line format - fall back to old format. */
free(output);
output = misc_read_cmd_output(LSBLK_CMDLINE, 0, 1);
}
if (!output) if (!output)
return NULL; return NULL;
@@ -134,9 +184,7 @@ static struct util_list *blkinfos_read(void)
/* Iterate over each line. */ /* Iterate over each line. */
next = output; next = output;
while ((curr = strsep(&next, "\n"))) { while ((curr = strsep(&next, "\n"))) {
blkinfo = blkinfo_from_line(curr); add_blkinfos_from_line(blkinfos, curr);
if (blkinfo)
ptrlist_add(blkinfos, blkinfo);
} }
free(output); free(output);
+6 -6
View File
@@ -804,17 +804,17 @@ void ccw_unblacklist_id_range(const char *range)
static char ***id_bitmap_new(void) static char ***id_bitmap_new(void)
{ {
return misc_malloc(sizeof(char **) * CSSID_MAX); return misc_malloc(sizeof(char **) * (CSSID_MAX + 1));
} }
static void id_bitmap_free(char ***id_bitmap) static void id_bitmap_free(char ***id_bitmap)
{ {
unsigned int cssid, ssid; unsigned int cssid, ssid;
for (cssid = 0; cssid < CSSID_MAX; cssid++) { for (cssid = 0; cssid <= CSSID_MAX; cssid++) {
if (!id_bitmap[cssid]) if (!id_bitmap[cssid])
continue; continue;
for (ssid = 0; ssid < SSID_MAX; ssid++) for (ssid = 0; ssid <= SSID_MAX; ssid++)
free(id_bitmap[cssid][ssid]); free(id_bitmap[cssid][ssid]);
free(id_bitmap[cssid]); free(id_bitmap[cssid]);
} }
@@ -965,15 +965,15 @@ static struct util_list *cio_ignore_get_ranges(bool autoconf)
ranges = strlist_new(); ranges = strlist_new();
id_bitmap = id_bitmap_collect(autoconf); id_bitmap = id_bitmap_collect(autoconf);
for (cssid = 0; cssid < CSSID_MAX; cssid++) { for (cssid = 0; cssid <= CSSID_MAX; cssid++) {
if (!id_bitmap[cssid]) if (!id_bitmap[cssid])
continue; continue;
for (ssid = 0; ssid < SSID_MAX; ssid++) { for (ssid = 0; ssid <= SSID_MAX; ssid++) {
if (!id_bitmap[cssid][ssid]) if (!id_bitmap[cssid][ssid])
continue; continue;
first = NULL; first = NULL;
last = NULL; last = NULL;
for (devno = 0; devno < DEVNO_MAX; devno++) { for (devno = 0; devno <= DEVNO_MAX; devno++) {
if (!id_bitmap_get(id_bitmap, cssid, ssid, if (!id_bitmap_get(id_bitmap, cssid, ssid,
devno)) { devno)) {
if (first) { if (first) {
+11 -4
View File
@@ -2088,12 +2088,18 @@ static exit_code_t devtype_remove_settings(struct devtype *dt, config_t config,
found = strlist_new(); found = strlist_new();
notfound = strlist_new(); notfound = strlist_new();
if (SCOPE_ACTIVE(config)) if (SCOPE_ACTIVE(config)) {
remove_settings(dt->active_settings, names, found, notfound, 1); rc = remove_settings(dt->active_settings, names, found,
notfound, 1);
if (rc)
goto out;
}
if (SCOPE_PERSISTENT(config)) { if (SCOPE_PERSISTENT(config)) {
remove_settings(dt->persistent_settings, names, found, rc = remove_settings(dt->persistent_settings, names, found,
notfound, 0); notfound, 0);
if (rc)
goto out;
} }
if (!util_list_is_empty(notfound)) { if (!util_list_is_empty(notfound)) {
@@ -2104,6 +2110,7 @@ static exit_code_t devtype_remove_settings(struct devtype *dt, config_t config,
rc = EXIT_SETTING_NOT_FOUND; rc = EXIT_SETTING_NOT_FOUND;
} }
out:
strlist_free(found); strlist_free(found);
strlist_free(notfound); strlist_free(notfound);
+7 -6
View File
@@ -30,8 +30,9 @@ check_dep:
$(call check_dep, \ $(call check_dep, \
"zdsfs", \ "zdsfs", \
"fuse.h", \ "fuse.h", \
"fuse-devel or libfuse-dev", \ "fuse3-devel or libfuse3-dev", \
"HAVE_FUSE=0") "HAVE_FUSE=0", \
"-DFUSE_USE_VERSION=30")
$(call check_dep, \ $(call check_dep, \
"zdsfs", \ "zdsfs", \
"curl/curl.h", \ "curl/curl.h", \
@@ -39,13 +40,13 @@ check_dep:
"HAVE_CURL=0") "HAVE_CURL=0")
ifneq ($(shell sh -c 'command -v pkg-config'),) ifneq ($(shell sh -c 'command -v pkg-config'),)
FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse) FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse3)
FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse) FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse3)
CURL_CFLAGS = $(shell pkg-config --silence-errors --cflags libcurl) CURL_CFLAGS = $(shell pkg-config --silence-errors --cflags libcurl)
CURL_LDLIBS = $(shell pkg-config --silence-errors --libs libcurl) CURL_LDLIBS = $(shell pkg-config --silence-errors --libs libcurl)
else else
FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse3
FUSE_LDLIBS = -lfuse FUSE_LDLIBS = -lfuse3
CURL_CFLAGS = -I/usr/include/s390x-linux-gnu/curl CURL_CFLAGS = -I/usr/include/s390x-linux-gnu/curl
CURL_LDLIBS = -lcurl CURL_LDLIBS = -lcurl
endif endif
-3
View File
@@ -227,9 +227,6 @@ Allow access by other users
\fB\-o\fR allow_root \fB\-o\fR allow_root
Allow access by root Allow access by root
.TP .TP
\fB\-o\fR nonempty
Allow mounts over non\-empty file/dir
.TP
\fB\-o\fR default_permissions \fB\-o\fR default_permissions
Enable permission checking by kernel Enable permission checking by kernel
.TP .TP
+12 -10
View File
@@ -8,7 +8,7 @@
*/ */
/* The fuse version define tells fuse that we want to use the new API */ /* The fuse version define tells fuse that we want to use the new API */
#define FUSE_USE_VERSION 26 #define FUSE_USE_VERSION 30
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@@ -312,7 +312,8 @@ void keepalive_start(void)
setup_timer(zdsfsinfo.keepalive); setup_timer(zdsfsinfo.keepalive);
} }
static int zdsfs_getattr(const char *path, struct stat *stbuf) static int zdsfs_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *UNUSED(fi))
{ {
char normds[MAXDSNAMELENGTH]; char normds[MAXDSNAMELENGTH];
size_t dssize; size_t dssize;
@@ -524,7 +525,8 @@ static int zdsfs_update_vtoc(void)
} }
static int zdsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, static int zdsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t UNUSED(offset), struct fuse_file_info *UNUSED(fi)) off_t UNUSED(offset), struct fuse_file_info *UNUSED(fi),
enum fuse_readdir_flags UNUSED(flags))
{ {
char normds[MAXDSNAMELENGTH]; char normds[MAXDSNAMELENGTH];
char *mbrname; char *mbrname;
@@ -544,9 +546,9 @@ static int zdsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
* type one: the root directory contains all data sets * type one: the root directory contains all data sets
*/ */
if (strcmp(path, "/") == 0) { if (strcmp(path, "/") == 0) {
filler(buf, ".", NULL, 0); filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0); filler(buf, "..", NULL, 0, 0);
filler(buf, METADATAFILE, NULL, 0); filler(buf, METADATAFILE, NULL, 0, 0);
/* note that we do not need to distinguish between /* note that we do not need to distinguish between
* normal files and directories here, that is done * normal files and directories here, that is done
* in the rdf_getattr function * in the rdf_getattr function
@@ -558,7 +560,7 @@ static int zdsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
lzds_dataset_get_is_supported(ds, &issupported); lzds_dataset_get_is_supported(ds, &issupported);
if (issupported) { if (issupported) {
lzds_dataset_get_name(ds, &dsname); lzds_dataset_get_name(ds, &dsname);
filler(buf, dsname, NULL, 0); filler(buf, dsname, NULL, 0, 0);
} }
} }
lzds_dsiterator_free(dsit); lzds_dsiterator_free(dsit);
@@ -572,14 +574,14 @@ static int zdsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
return -ENOENT; return -ENOENT;
lzds_dataset_get_is_PDS(ds, &ispds); lzds_dataset_get_is_PDS(ds, &ispds);
if (ispds) { if (ispds) {
filler(buf, ".", NULL, 0); filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0); filler(buf, "..", NULL, 0, 0);
rc = lzds_dataset_alloc_memberiterator(ds, &it); rc = lzds_dataset_alloc_memberiterator(ds, &it);
if (rc) if (rc)
return -ENOMEM; return -ENOMEM;
while (!lzds_memberiterator_get_next_member(it, &member)) { while (!lzds_memberiterator_get_next_member(it, &member)) {
lzds_pdsmember_get_name(member, &mbrname); lzds_pdsmember_get_name(member, &mbrname);
filler(buf, mbrname, NULL, 0); filler(buf, mbrname, NULL, 0, 0);
} }
lzds_memberiterator_free(it); lzds_memberiterator_free(it);
} else } else
+11 -10
View File
@@ -15,8 +15,9 @@ check_dep_fuse:
$(call check_dep, \ $(call check_dep, \
"zgetdump mount support", \ "zgetdump mount support", \
"fuse.h", \ "fuse.h", \
"fuse-devel or libfuse-dev", \ "fuse3-devel or libfuse3-dev", \
"HAVE_FUSE=0") "HAVE_FUSE=0", \
"-DFUSE_USE_VERSION=30")
endif endif
# #
@@ -41,28 +42,28 @@ check_dep_zlib:
all: check_dep_fuse check_dep_zlib zgetdump all: check_dep_fuse check_dep_zlib zgetdump
OBJECTS = zgetdump.o opts.o zg.o \ OBJECTS = zgetdump.o opts.o zg.o zg_error.o zg_print.o \
dfi.o dfi_mem_chunk.o dfi_vmcoreinfo.o \ dfi.o dfi_mem_chunk.o dfi_vmcoreinfo.o \
dfi_lkcd.o dfi_elf.o \ dfi_lkcd.o dfi_elf.o \
dfi_s390.o dfi_s390_ext.o\ dfi_s390.o dfi_s390_ext.o\
dfi_s390mv.o dfi_s390mv_ext.o \ dfi_s390mv.o dfi_s390mv_ext.o \
dfi_s390tape.o dfi_kdump.o \ dfi_s390tape.o dfi_kdump.o \
dfi_devmem.o dfo.o \ dfi_devmem.o dfo.o dfo_mem_chunk.o \
dfo_elf.o dfo_s390.o \ dfo_elf.o dfo_s390.o \
df_s390.o \ df_elf.o df_s390.o \
dt.o dt_s390sv.o dt_s390sv_ext.o \ dt.o dt_s390sv.o dt_s390sv_ext.o \
dt_s390mv.o dt_s390mv_ext.o \ dt_s390mv.o dt_s390mv_ext.o \
dt_scsi.o stdout.o \ dt_scsi.o output.o
ifeq ("$(HAVE_FUSE)","0") ifeq ("$(HAVE_FUSE)","0")
FUSE_CFLAGS = -DHAVE_FUSE=0 -D_FILE_OFFSET_BITS=64 FUSE_CFLAGS = -DHAVE_FUSE=0 -D_FILE_OFFSET_BITS=64
FUSE_LDLIBS = FUSE_LDLIBS =
else ifneq ($(shell sh -c 'command -v pkg-config'),) else ifneq ($(shell sh -c 'command -v pkg-config'),)
FUSE_CFLAGS = -DHAVE_FUSE=1 $(shell pkg-config --silence-errors --cflags fuse) FUSE_CFLAGS = -DHAVE_FUSE=1 $(shell pkg-config --silence-errors --cflags fuse3)
FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse) FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse3)
else else
FUSE_CFLAGS = -DHAVE_FUSE=1 -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse FUSE_CFLAGS = -DHAVE_FUSE=1 -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse3
FUSE_LDLIBS = -lfuse FUSE_LDLIBS = -lfuse3
endif endif
LDLIBS += -lz $(FUSE_LDLIBS) LDLIBS += -lz $(FUSE_LDLIBS)
ALL_CFLAGS += $(FUSE_CFLAGS) ALL_CFLAGS += $(FUSE_CFLAGS)
+191
View File
@@ -0,0 +1,191 @@
/*
* Copyright IBM Corp. 2001, 2018, 2021
*
* 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 <string.h>
#include "df_elf.h"
#define NOTE_NAME_CORE "CORE"
#define NOTE_NAME_LINUX "LINUX"
#define NOTE_NAME_VMCOREINFO "VMCOREINFO"
/*
* Initialize ELF header
*/
void *ehdr_init(Elf64_Ehdr *ehdr, Elf64_Half phnum)
{
memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
ehdr->e_ident[EI_CLASS] = ELFCLASS64;
ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
ehdr->e_ident[EI_VERSION] = EV_CURRENT;
ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
ehdr->e_ident[EI_ABIVERSION] = 0;
memset(ehdr->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
ehdr->e_type = ET_CORE;
ehdr->e_machine = EM_S390;
ehdr->e_version = EV_CURRENT;
ehdr->e_entry = 0;
ehdr->e_phoff = sizeof(Elf64_Ehdr);
ehdr->e_shoff = 0;
ehdr->e_flags = 0;
ehdr->e_ehsize = sizeof(Elf64_Ehdr);
ehdr->e_phentsize = sizeof(Elf64_Phdr);
ehdr->e_phnum = phnum;
ehdr->e_shentsize = 0;
ehdr->e_shnum = 0;
ehdr->e_shstrndx = 0;
return ehdr + 1;
}
/*
* Initialize ELF note
*/
void *nt_init(void *buf, Elf64_Word type, const void *desc, int d_len,
const char *name)
{
Elf64_Nhdr *note;
u64 len;
note = (Elf64_Nhdr *)buf;
note->n_namesz = strlen(name) + 1;
note->n_descsz = d_len;
note->n_type = type;
len = sizeof(Elf64_Nhdr);
memcpy(buf + len, name, note->n_namesz);
len = ROUNDUP(len + note->n_namesz, 4);
memcpy(buf + len, desc, note->n_descsz);
len = ROUNDUP(len + note->n_descsz, 4);
return PTR_ADD(buf, len);
}
/*
* Initialize prstatus note
*/
void *nt_prstatus(void *ptr, const struct dfi_cpu *cpu)
{
struct nt_prstatus_64 nt_prstatus;
static int cpu_nr = 1;
memset(&nt_prstatus, 0, sizeof(nt_prstatus));
memcpy(&nt_prstatus.gprs, cpu->gprs, sizeof(cpu->gprs));
memcpy(&nt_prstatus.psw, cpu->psw, sizeof(cpu->psw));
memcpy(&nt_prstatus.acrs, cpu->acrs, sizeof(cpu->acrs));
nt_prstatus.pr_pid = cpu_nr;
cpu_nr++;
return nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus),
NOTE_NAME_CORE);
}
/*
* Initialize fpregset (floating point) note
*/
void *nt_fpregset(void *ptr, const struct dfi_cpu *cpu)
{
struct nt_fpregset_64 nt_fpregset;
memset(&nt_fpregset, 0, sizeof(nt_fpregset));
memcpy(&nt_fpregset.fpc, &cpu->fpc, sizeof(cpu->fpc));
memcpy(&nt_fpregset.fprs, &cpu->fprs, sizeof(cpu->fprs));
return nt_init(ptr, NT_FPREGSET, &nt_fpregset, sizeof(nt_fpregset),
NOTE_NAME_CORE);
}
/*
* Initialize timer note
*/
void *nt_s390_timer(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_TIMER, &cpu->timer, sizeof(cpu->timer),
NOTE_NAME_LINUX);
}
/*
* Initialize TOD clock comparator note
*/
void *nt_s390_tod_cmp(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_TODCMP, &cpu->todcmp,
sizeof(cpu->todcmp), NOTE_NAME_LINUX);
}
/*
* Initialize TOD programmable register note
*/
void *nt_s390_tod_preg(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_TODPREG, &cpu->todpreg,
sizeof(cpu->todpreg), NOTE_NAME_LINUX);
}
/*
* Initialize control register note
*/
void *nt_s390_ctrs(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_CTRS, &cpu->ctrs, sizeof(cpu->ctrs),
NOTE_NAME_LINUX);
}
/*
* Initialize prefix register note
*/
void *nt_s390_prefix(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_PREFIX, &cpu->prefix,
sizeof(cpu->prefix), NOTE_NAME_LINUX);
}
/*
* Initialize vxrs_low register note
*/
void *nt_s390_vxrs_low(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_VXRS_LOW, &cpu->vxrs_low,
sizeof(cpu->vxrs_low), NOTE_NAME_LINUX);
}
/*
* Initialize vxrs_high register note
*/
void *nt_s390_vxrs_high(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_VXRS_HIGH, &cpu->vxrs_high,
sizeof(cpu->vxrs_high), NOTE_NAME_LINUX);
}
/*
* Initialize prpsinfo note
*/
void *nt_prpsinfo(void *ptr)
{
struct nt_prpsinfo_64 prpsinfo;
memset(&prpsinfo, 0, sizeof(prpsinfo));
prpsinfo.pr_state = 0;
prpsinfo.pr_sname = 'R';
prpsinfo.pr_zomb = 0;
strcpy(prpsinfo.pr_fname, "vmlinux");
return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo),
NOTE_NAME_CORE);
}
/*
* Initialize vmcoreinfo note
*/
void *nt_vmcoreinfo(void *ptr, const char *vmcoreinfo)
{
if (!vmcoreinfo)
return ptr;
return nt_init(ptr, 0, vmcoreinfo, strlen(vmcoreinfo),
NOTE_NAME_VMCOREINFO);
}
+17 -1
View File
@@ -17,8 +17,8 @@
#include "lib/zt_common.h" #include "lib/zt_common.h"
#include "dfo.h"
#include "zg.h" #include "zg.h"
#include "dfi.h"
/* /*
* S390 CPU timer note (u64) * S390 CPU timer note (u64)
@@ -116,4 +116,20 @@ static inline void df_elf_ensure_s390x(void)
#endif #endif
} }
void *ehdr_init(Elf64_Ehdr *ehdr, Elf64_Half phnum);
void *nt_init(void *buf, Elf64_Word type, const void *desc, int d_len,
const char *name);
void *nt_prstatus(void *ptr, const struct dfi_cpu *cpu);
void *nt_fpregset(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_timer(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_tod_cmp(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_tod_preg(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_ctrs(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_prefix(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_vxrs_low(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_vxrs_high(void *ptr, const struct dfi_cpu *cpu);
void *nt_prpsinfo(void *ptr);
void *nt_vmcoreinfo(void *ptr, const char *vmcoreinfo);
#endif /* DF_ELF_H */ #endif /* DF_ELF_H */
+2
View File
@@ -286,6 +286,7 @@ const char *dfi_arch_str(enum dfi_arch arch)
return "unknown"; return "unknown";
} }
ABORT("dfi_arch_str: Invalid dfi arch: %d", arch); ABORT("dfi_arch_str: Invalid dfi arch: %d", arch);
return NULL; /* UNREACHABLE */
} }
/* /*
@@ -784,6 +785,7 @@ int dfi_init(void)
i++; i++;
} }
ERR_EXIT("No valid dump found on \"%s\"", g.opts.device); ERR_EXIT("No valid dump found on \"%s\"", g.opts.device);
return -1; /* UNREACHABLE */
} }
/* /*
-1
View File
@@ -556,7 +556,6 @@ static int open_dump(void)
} }
if (mv_dumper_read() != 0) if (mv_dumper_read() != 0)
return -ENODEV; return -ENODEV;
zg_close(g.fh);
return 0; return 0;
} }
+11 -108
View File
@@ -9,16 +9,13 @@
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#include <time.h> #include <string.h>
#include <errno.h>
#include "lib/util_list.h" #include "zg.h"
#include "dfo_mem_chunk.h"
#include "dfi_mem_chunk.h"
#include "dfo.h" #include "dfo.h"
#define dfo_chunk_iterate(dfo_chunk) \
util_list_iterate(&l.dump.chunk_list, dfo_chunk)
/* /*
* DFO vector * DFO vector
*/ */
@@ -28,70 +25,14 @@ static struct dfo *dfo_vec[] = {
NULL, NULL,
}; };
/*
* Dump (output) information
*/
struct dump {
u64 off; /* Current file offset in dump */
u64 size; /* Size of dump in bytes */
unsigned int chunk_cnt; /* Number of dump chunks */
struct util_list chunk_list; /* DFO chunk list */
};
/* /*
* File local static data * File local static data
*/ */
static struct { static struct {
struct dump dump; u64 off; /* Current file offset in dump */
struct dfo *dfo; struct dfo *dfo;
} l; } l;
/*
* Add dump chunk
*/
void dfo_chunk_add(u64 start, u64 size, void *data, dfo_chunk_read_fn read_fn)
{
struct dfo_chunk *dfo_chunk;
dfo_chunk = zg_alloc(sizeof(*dfo_chunk));
dfo_chunk->start = start;
dfo_chunk->end = start + size - 1;
dfo_chunk->data = data;
dfo_chunk->read_fn = read_fn;
util_list_add_head(&l.dump.chunk_list, dfo_chunk);
l.dump.chunk_cnt++;
l.dump.size = MAX(l.dump.size, dfo_chunk->end + 1);
}
/*
* Dump chunk function: Copy zero pages for chunk
*/
void dfo_chunk_zero_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
{
(void) dfo_chunk;
(void) off;
memset(buf, 0, cnt);
}
/*
* Dump chunk function: Copy given buffer for chunk
*/
void dfo_chunk_buf_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
{
memcpy(buf, dfo_chunk->data + off, cnt);
}
/*
* Dump chunk function: Copy given memory range for chunk
*/
void dfo_chunk_mem_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
{
struct dfi_mem_chunk *mem_chunk = dfo_chunk->data;
mem_chunk->read_fn(mem_chunk, off, buf, cnt);
}
/* /*
* Get DFO name * Get DFO name
*/ */
@@ -125,55 +66,17 @@ void dfo_init(void)
{ {
if (!l.dfo) if (!l.dfo)
ABORT("DFO not set"); ABORT("DFO not set");
util_list_init(&l.dump.chunk_list, struct dfo_chunk, list); if (dfo_chunk_init())
ABORT("DFO memory chunk init failed");
l.dfo->init(); l.dfo->init();
} }
/*
* Find dump chunk for offset "off"
*
* This function is a bit hacky. DFO chunks can overlap. If two DFO chunks
* overlap, the last registered chunk wins. The dfo_chunk_find() function
* reflects that by returning the first memory chunk that is found in
* the dfo chunk list.
*
* In addition to that it calculates the "virtual end" of that chunk. An
* overlapping chunk can limit the "virtual end" of an underlying chunk so
* that the "virtual end" of that chunk is lower than the "real end".
*
* Example:
*
* chunk 1.: |------|
* chunk 2.: |---------------------|
* off.....: ^
* virt end: ^
* real end: ^
*
* In this case chunk 2 will be returned and "end" is set to the start of
* chunk 1.
*/
static struct dfo_chunk *dfo_chunk_find(u64 off, u64 *end)
{
struct dfo_chunk *dfo_chunk;
*end = U64_MAX;
dfo_chunk_iterate(dfo_chunk) {
if (dfo_chunk->start <= off && dfo_chunk->end >= off) {
*end = MIN(*end, dfo_chunk->end);
return dfo_chunk;
} else if (dfo_chunk->start > off) {
*end = MIN(*end, dfo_chunk->start - 1);
}
}
return NULL;
}
/* /*
* Seek to output dump offset "off" * Seek to output dump offset "off"
*/ */
void dfo_seek(u64 off) void dfo_seek(u64 off)
{ {
l.dump.off = off; l.off = off;
} }
/* /*
@@ -183,7 +86,7 @@ u64 dfo_read(void *buf, u64 cnt)
{ {
struct dfo_chunk *dfo_chunk; struct dfo_chunk *dfo_chunk;
u64 copied = 0, end, size; u64 copied = 0, end, size;
u64 off = l.dump.off; u64 off = l.off;
while (copied != cnt) { while (copied != cnt) {
dfo_chunk = dfo_chunk_find(off, &end); dfo_chunk = dfo_chunk_find(off, &end);
@@ -196,7 +99,7 @@ u64 dfo_read(void *buf, u64 cnt)
off += size; off += size;
} }
out: out:
l.dump.off = off; l.off = off;
return copied; return copied;
} }
@@ -205,5 +108,5 @@ out:
*/ */
u64 dfo_size(void) u64 dfo_size(void)
{ {
return l.dump.size; return dfo_chunk_dump_size();
} }
+6 -31
View File
@@ -12,37 +12,12 @@
#ifndef DFO_H #ifndef DFO_H
#define DFO_H #define DFO_H
#include "lib/util_list.h" u64 dfo_read(void *buf, u64 cnt);
#include "zg.h" void dfo_seek(u64 addr);
u64 dfo_size(void);
struct dfo_chunk; const char *dfo_name(void);
void dfo_init(void);
typedef void (*dfo_chunk_read_fn)(struct dfo_chunk *chunk, u64 off, int dfo_set(const char *dfo_name);
void *buf, u64 cnt);
struct dfo_chunk {
struct util_list_node list;
u64 start;
u64 end;
dfo_chunk_read_fn read_fn;
void *data;
};
extern void dfo_chunk_zero_fn(struct dfo_chunk *chunk, u64 off, void *buf,
u64 cnt);
extern void dfo_chunk_buf_fn(struct dfo_chunk *chunk, u64 off, void *buf,
u64 cnt);
extern void dfo_chunk_mem_fn(struct dfo_chunk *chunk, u64 off, void *buf,
u64 cnt);
extern void dfo_chunk_add(u64 start, u64 size, void *data,
dfo_chunk_read_fn read_fn);
extern u64 dfo_read(void *buf, u64 cnt);
extern void dfo_seek(u64 addr);
extern u64 dfo_size(void);
extern const char *dfo_name(void);
extern void dfo_init(void);
extern int dfo_set(const char *dfo_name);
/* /*
* DFO operations * DFO operations
+26 -211
View File
@@ -19,6 +19,7 @@
#include "df_elf.h" #include "df_elf.h"
#include "dfi.h" #include "dfi.h"
#include "dfi_mem_chunk.h" #include "dfi_mem_chunk.h"
#include "dfo_mem_chunk.h"
#include "dfi_vmcoreinfo.h" #include "dfi_vmcoreinfo.h"
#include "dfo.h" #include "dfo.h"
@@ -27,55 +28,19 @@
#define HDR_BASE_SIZE 0x2000 #define HDR_BASE_SIZE 0x2000
/* /*
* File local static data * Initialize ELF loads program headers
*/ */
static struct { static u64 load_phdrs_init(Elf64_Phdr *phdr, u64 elf_offset)
void *hdr;
u32 hdr_size;
} l;
/*
* Initialize ELF header
*/
static void *ehdr_init(Elf64_Ehdr *ehdr)
{
memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
ehdr->e_ident[EI_CLASS] = ELFCLASS64;
ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
ehdr->e_ident[EI_VERSION] = EV_CURRENT;
ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
ehdr->e_ident[EI_ABIVERSION] = 0;
memset(ehdr->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
ehdr->e_type = ET_CORE;
ehdr->e_machine = EM_S390;
ehdr->e_version = EV_CURRENT;
ehdr->e_entry = 0;
ehdr->e_phoff = sizeof(Elf64_Ehdr);
ehdr->e_shoff = 0;
ehdr->e_flags = 0;
ehdr->e_ehsize = sizeof(Elf64_Ehdr);
ehdr->e_phentsize = sizeof(Elf64_Phdr);
ehdr->e_phnum = dfi_mem_chunk_cnt() + 1;
ehdr->e_shentsize = 0;
ehdr->e_shnum = 0;
ehdr->e_shstrndx = 0;
return ehdr + 1;
}
/*
* Initialize ELF loads
*/
static u64 loads_init(Elf64_Phdr *phdr, u64 loads_offset)
{ {
struct dfi_mem_chunk *mem_chunk; struct dfi_mem_chunk *mem_chunk;
u64 mem_size = 0; u64 mem_size = 0;
dfi_mem_chunk_iterate(mem_chunk) { dfi_mem_chunk_iterate(mem_chunk) {
phdr->p_type = PT_LOAD; phdr->p_type = PT_LOAD;
phdr->p_offset = loads_offset; phdr->p_offset = elf_offset;
phdr->p_vaddr = mem_chunk->start; phdr->p_vaddr = mem_chunk->start;
phdr->p_paddr = mem_chunk->start; phdr->p_paddr = phdr->p_vaddr;
phdr->p_memsz = mem_chunk->end - mem_chunk->start + 1; phdr->p_memsz = mem_chunk->size;
if (mem_chunk->read_fn == dfi_mem_chunk_read_zero) if (mem_chunk->read_fn == dfi_mem_chunk_read_zero)
/* Zero memory chunk */ /* Zero memory chunk */
phdr->p_filesz = 0; phdr->p_filesz = 0;
@@ -83,7 +48,7 @@ static u64 loads_init(Elf64_Phdr *phdr, u64 loads_offset)
phdr->p_filesz = phdr->p_memsz; phdr->p_filesz = phdr->p_memsz;
phdr->p_flags = PF_R | PF_W | PF_X; phdr->p_flags = PF_R | PF_W | PF_X;
phdr->p_align = PAGE_SIZE; phdr->p_align = PAGE_SIZE;
loads_offset += phdr->p_filesz; elf_offset += phdr->p_filesz;
mem_size += phdr->p_memsz; mem_size += phdr->p_memsz;
phdr++; phdr++;
} }
@@ -91,160 +56,12 @@ static u64 loads_init(Elf64_Phdr *phdr, u64 loads_offset)
} }
/* /*
* Initialize ELF note * Initialize the program header entries for the notes and the related segment
* data.
*/ */
static void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len, static void *notes_init(Elf64_Phdr *phdr, void *segment_start, u64 elf_offset)
const char *name)
{ {
Elf64_Nhdr *note; void *ptr = segment_start;
u64 len;
note = (Elf64_Nhdr *)buf;
note->n_namesz = strlen(name) + 1;
note->n_descsz = d_len;
note->n_type = type;
len = sizeof(Elf64_Nhdr);
memcpy(buf + len, name, note->n_namesz);
len = ROUNDUP(len + note->n_namesz, 4);
memcpy(buf + len, desc, note->n_descsz);
len = ROUNDUP(len + note->n_descsz, 4);
return PTR_ADD(buf, len);
}
/*
* Initialize prstatus note
*/
static void *nt_prstatus(void *ptr, struct dfi_cpu *cpu)
{
struct nt_prstatus_64 nt_prstatus;
static int cpu_nr = 1;
memset(&nt_prstatus, 0, sizeof(nt_prstatus));
memcpy(&nt_prstatus.gprs, cpu->gprs, sizeof(cpu->gprs));
memcpy(&nt_prstatus.psw, cpu->psw, sizeof(cpu->psw));
memcpy(&nt_prstatus.acrs, cpu->acrs, sizeof(cpu->acrs));
nt_prstatus.pr_pid = cpu_nr;
cpu_nr++;
return nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus),
"CORE");
}
/*
* Initialize fpregset (floating point) note
*/
static void *nt_fpregset(void *ptr, struct dfi_cpu *cpu)
{
struct nt_fpregset_64 nt_fpregset;
memset(&nt_fpregset, 0, sizeof(nt_fpregset));
memcpy(&nt_fpregset.fpc, &cpu->fpc, sizeof(cpu->fpc));
memcpy(&nt_fpregset.fprs, &cpu->fprs, sizeof(cpu->fprs));
return nt_init(ptr, NT_FPREGSET, &nt_fpregset, sizeof(nt_fpregset),
"CORE");
}
/*
* Initialize timer note
*/
static void *nt_s390_timer(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_TIMER, &cpu->timer, sizeof(cpu->timer),
"LINUX");
}
/*
* Initialize TOD clock comparator note
*/
static void *nt_s390_tod_cmp(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_TODCMP, &cpu->todcmp,
sizeof(cpu->todcmp), "LINUX");
}
/*
* Initialize TOD programmable register note
*/
static void *nt_s390_tod_preg(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_TODPREG, &cpu->todpreg,
sizeof(cpu->todpreg), "LINUX");
}
/*
* Initialize control register note
*/
static void *nt_s390_ctrs(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_CTRS, &cpu->ctrs, sizeof(cpu->ctrs),
"LINUX");
}
/*
* Initialize prefix register note
*/
static void *nt_s390_prefix(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_PREFIX, &cpu->prefix,
sizeof(cpu->prefix), "LINUX");
}
/*
* Initialize vxrs_low register note
*/
static void *nt_s390_vxrs_low(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_VXRS_LOW, &cpu->vxrs_low,
sizeof(cpu->vxrs_low), "LINUX");
}
/*
* Initialize vxrs_high register note
*/
static void *nt_s390_vxrs_high(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_VXRS_HIGH, &cpu->vxrs_high,
sizeof(cpu->vxrs_high), "LINUX");
}
/*
* Initialize prpsinfo note
*/
static void *nt_prpsinfo(void *ptr)
{
struct nt_prpsinfo_64 prpsinfo;
memset(&prpsinfo, 0, sizeof(prpsinfo));
prpsinfo.pr_state = 0;
prpsinfo.pr_sname = 'R';
prpsinfo.pr_zomb = 0;
strcpy(prpsinfo.pr_fname, "vmlinux");
return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo), "CORE");
}
/*
* Initialize vmcoreinfo note
*/
static void *nt_vmcoreinfo(void *ptr)
{
char *vmcoreinfo = dfi_vmcoreinfo_get();
if (!vmcoreinfo)
return ptr;
return nt_init(ptr, 0, vmcoreinfo, strlen(vmcoreinfo), "VMCOREINFO");
}
/*
* Initialize notes
*/
static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
{
void *ptr_start = ptr;
struct dfi_cpu *cpu; struct dfi_cpu *cpu;
ptr = nt_prpsinfo(ptr); ptr = nt_prpsinfo(ptr);
@@ -266,24 +83,24 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
} }
} }
out: out:
ptr = nt_vmcoreinfo(ptr); ptr = nt_vmcoreinfo(ptr, dfi_vmcoreinfo_get());
memset(phdr, 0, sizeof(*phdr)); memset(phdr, 0, sizeof(*phdr));
phdr->p_type = PT_NOTE; phdr->p_type = PT_NOTE;
phdr->p_offset = notes_offset; phdr->p_offset = elf_offset;
phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start); phdr->p_filesz = PTR_DIFF(ptr, segment_start);
return ptr; return ptr;
} }
/* /*
* Setup dump chunks * Setup dump chunks
*/ */
static void dump_chunks_init(void) static void dump_chunks_init(void *hdr, u64 hdr_size)
{ {
struct dfi_mem_chunk *mem_chunk; struct dfi_mem_chunk *mem_chunk;
u64 off = 0; u64 off = 0;
dfo_chunk_add(0, l.hdr_size, l.hdr, dfo_chunk_buf_fn); dfo_chunk_add(off, hdr_size, hdr, dfo_chunk_buf_fn);
off = l.hdr_size; off += hdr_size;
dfi_mem_chunk_iterate(mem_chunk) { dfi_mem_chunk_iterate(mem_chunk) {
if (mem_chunk->read_fn == dfi_mem_chunk_read_zero) if (mem_chunk->read_fn == dfi_mem_chunk_read_zero)
/* Zero memory chunk */ /* Zero memory chunk */
@@ -312,31 +129,29 @@ static void dfo_elf_init(void)
{ {
Elf64_Phdr *phdr_notes, *phdr_loads; Elf64_Phdr *phdr_notes, *phdr_loads;
u32 alloc_size; u32 alloc_size;
void *buf, *ptr;
u64 hdr_off; u64 hdr_off;
void *ptr;
ensure_s390x(); ensure_s390x();
alloc_size = HDR_BASE_SIZE + alloc_size = HDR_BASE_SIZE +
dfi_cpu_cnt() * HDR_PER_CPU_SIZE + dfi_cpu_cnt() * HDR_PER_CPU_SIZE +
dfi_mem_chunk_cnt() * HDR_PER_MEMC_SIZE; dfi_mem_chunk_cnt() * HDR_PER_MEMC_SIZE;
l.hdr = zg_alloc(alloc_size); buf = zg_alloc(alloc_size);
/* Init elf header */ /* Init elf header */
ptr = ehdr_init(l.hdr); ptr = ehdr_init(buf, dfi_mem_chunk_cnt() + 1);
/* Init program headers */ /* Init program headers */
phdr_notes = ptr; phdr_notes = ptr;
ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr)); ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr));
phdr_loads = ptr; phdr_loads = ptr;
ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr) * dfi_mem_chunk_cnt()); ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr) * dfi_mem_chunk_cnt());
/* Init notes */ /* Init notes */
hdr_off = PTR_DIFF(ptr, l.hdr); hdr_off = PTR_DIFF(ptr, buf);
ptr = notes_init(phdr_notes, ptr, hdr_off); ptr = notes_init(phdr_notes, ptr, hdr_off);
/* Init loads */ hdr_off = PTR_DIFF(ptr, buf);
hdr_off = PTR_DIFF(ptr, l.hdr); load_phdrs_init(phdr_loads, hdr_off);
loads_init(phdr_loads, hdr_off); if (hdr_off > alloc_size)
l.hdr_size = hdr_off; ABORT("hdr_size=%llu alloc_size=%u", hdr_off, alloc_size);
if (l.hdr_size > alloc_size) dump_chunks_init(buf, hdr_off);
ABORT("hdr_size=%u alloc_size=%u", l.hdr_size, alloc_size);
dump_chunks_init();
} }
/* /*
+128
View File
@@ -0,0 +1,128 @@
/*
* Copyright IBM Corp. 2001, 2017, 2021
*
* 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 <string.h>
#include "zg.h"
#include "dfi_mem_chunk.h"
#include "dfo_mem_chunk.h"
/*
* File local static data
*/
static struct {
u64 size; /* Size of dump in bytes */
unsigned int chunk_cnt; /* Number of dump chunks */
struct util_list chunk_list; /* DFO chunk list */
} l;
/*
* Add dump chunk
*/
void dfo_chunk_add(u64 start, u64 size, void *data, dfo_chunk_read_fn read_fn)
{
struct dfo_chunk *dfo_chunk;
dfo_chunk = zg_alloc(sizeof(*dfo_chunk));
dfo_chunk->start = start;
dfo_chunk->end = start + size - 1;
dfo_chunk->data = data;
dfo_chunk->read_fn = read_fn;
util_list_add_head(&l.chunk_list, dfo_chunk);
l.chunk_cnt++;
l.size = MAX(l.size, dfo_chunk->end + 1);
}
/*
* Dump chunk function: Copy zero pages for chunk
*/
void dfo_chunk_zero_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
{
(void) dfo_chunk;
(void) off;
memset(buf, 0, cnt);
}
/*
* Dump chunk function: Copy given buffer for chunk
*/
void dfo_chunk_buf_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
{
memcpy(buf, dfo_chunk->data + off, cnt);
}
/*
* Dump chunk function: Copy given memory range for chunk
*/
void dfo_chunk_mem_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
{
struct dfi_mem_chunk *mem_chunk = dfo_chunk->data;
mem_chunk->read_fn(mem_chunk, off, buf, cnt);
}
/*
* Find dump chunk for offset "off"
*
* This function is a bit hacky. DFO chunks can overlap. If two DFO chunks
* overlap, the last registered chunk wins. The dfo_chunk_find() function
* reflects that by returning the first memory chunk that is found in
* the dfo chunk list.
*
* In addition to that it calculates the "virtual end" of that chunk. An
* overlapping chunk can limit the "virtual end" of an underlying chunk so
* that the "virtual end" of that chunk is lower than the "real end".
*
* Example:
*
* chunk 1.: |------|
* chunk 2.: |---------------------|
* off.....: ^
* virt end: ^
* real end: ^
*
* In this case chunk 2 will be returned and "end" is set to the start of
* chunk 1.
*/
struct dfo_chunk *dfo_chunk_find(u64 off, u64 *end)
{
struct dfo_chunk *dfo_chunk;
*end = U64_MAX;
dfo_chunk_iterate(dfo_chunk) {
if (dfo_chunk->start <= off && dfo_chunk->end >= off) {
*end = MIN(*end, dfo_chunk->end);
return dfo_chunk;
} else if (dfo_chunk->start > off) {
*end = MIN(*end, dfo_chunk->start - 1);
}
}
return NULL;
}
struct util_list *dfo_chunk_list(void)
{
return &l.chunk_list;
}
u64 dfo_chunk_dump_size(void)
{
return l.size;
}
int dfo_chunk_init(void)
{
util_list_init(&l.chunk_list, struct dfo_chunk, list);
return 0;
}
void dfo_chunk_deinit(void)
{
memset(&l, 0, sizeof(l));
}
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright IBM Corp. 2001, 2017, 2021
*
* 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 DFO_MEM_CHUNK_H
#define DFO_MEM_CHUNK_H
#include "lib/zt_common.h"
#include "lib/util_list.h"
struct dfo_chunk;
typedef void (*dfo_chunk_read_fn)(struct dfo_chunk *chunk, u64 off,
void *buf, u64 cnt);
struct dfo_chunk {
struct util_list_node list;
u64 start;
u64 end;
dfo_chunk_read_fn read_fn;
void *data;
};
void dfo_chunk_zero_fn(struct dfo_chunk *chunk, u64 off, void *buf, u64 cnt);
void dfo_chunk_buf_fn(struct dfo_chunk *chunk, u64 off, void *buf, u64 cnt);
void dfo_chunk_mem_fn(struct dfo_chunk *chunk, u64 off, void *buf, u64 cnt);
void dfo_chunk_add(u64 start, u64 size, void *data, dfo_chunk_read_fn read_fn);
struct dfo_chunk *dfo_chunk_find(u64 off, u64 *end);
struct util_list *dfo_chunk_list(void);
#define dfo_chunk_iterate(dfo_chunk) \
util_list_iterate(dfo_chunk_list(), dfo_chunk)
u64 dfo_chunk_dump_size(void);
int dfo_chunk_init(void);
void dfo_chunk_deinit(void);
#endif /* DFO_MEM_CHUNK_H */
+1
View File
@@ -19,6 +19,7 @@
#include "df_s390.h" #include "df_s390.h"
#include "dfi_mem_chunk.h" #include "dfi_mem_chunk.h"
#include "dfo_mem_chunk.h"
#include "dfo.h" #include "dfo.h"
/* /*
+18
View File
@@ -40,6 +40,7 @@ static const char optstr[] = "hvVidmus:f:X";
*/ */
static const char help_text[] = static const char help_text[] =
"Usage: zgetdump DUMP [-s SYS] [-f FMT] > DUMP_FILE\n" "Usage: zgetdump DUMP [-s SYS] [-f FMT] > DUMP_FILE\n"
" DUMP [-s SYS] [-f FMT] DUMP_FILE\n"
" -m DUMP [-s SYS] [-f FMT] DIR\n" " -m DUMP [-s SYS] [-f FMT] DIR\n"
" -i DUMP [-s SYS]\n" " -i DUMP [-s SYS]\n"
" -d DUMPDEV\n" " -d DUMPDEV\n"
@@ -86,6 +87,7 @@ static void init_defaults(struct options *opts)
{ {
opts->prog_name = "zgetdump"; opts->prog_name = "zgetdump";
opts->action = ZG_ACTION_COPY; opts->action = ZG_ACTION_COPY;
opts->output_path = NULL;
#ifdef __s390x__ #ifdef __s390x__
opts->fmt = "elf"; opts->fmt = "elf";
#else #else
@@ -166,6 +168,14 @@ static void device_set(struct options *opts, const char *path)
opts->device = zg_strdup(path); opts->device = zg_strdup(path);
} }
/*
* Set output path
*/
static void output_set(struct options *opts, const char *path)
{
opts->output_path = zg_strdup(path);
}
/* /*
* Set FUSE debug options * Set FUSE debug options
*/ */
@@ -229,6 +239,14 @@ static void parse_pos_args(struct options *opts, char *argv[], int argc)
switch (opts->action) { switch (opts->action) {
case ZG_ACTION_COPY: case ZG_ACTION_COPY:
if (pos_args == 0)
ERR_EXIT("No device or dump specified");
if (pos_args > 2)
ERR_EXIT("Too many positional parameters specified");
device_set(opts, argv[optind]);
if (pos_args > 1)
output_set(opts, argv[optind + 1]);
break;
case ZG_ACTION_DUMP_INFO: case ZG_ACTION_DUMP_INFO:
case ZG_ACTION_DEVICE_INFO: case ZG_ACTION_DEVICE_INFO:
if (pos_args == 0) if (pos_args == 0)
+2
View File
@@ -18,6 +18,8 @@ struct options {
int action_specified; int action_specified;
enum zg_action action; enum zg_action action;
char *device; char *device;
/* If `output_path == NULL` the output is written to `stdout` */
const char *output_path;
char *mount_point; char *mount_point;
int fmt_specified; int fmt_specified;
const char *fmt; const char *fmt;
+7 -9
View File
@@ -1,7 +1,7 @@
/* /*
* zgetdump - Tool for copying and converting System z dumps * zgetdump - Tool for copying and converting System z dumps
* *
* Write dump to standard output (stdout) * Write dump to the file descriptor (fd)
* *
* Copyright IBM Corp. 2001, 2017 * Copyright IBM Corp. 2001, 2017
* *
@@ -12,9 +12,9 @@
#include "zg.h" #include "zg.h"
#include "dfi.h" #include "dfi.h"
#include "dfo.h" #include "dfo.h"
#include "stdout.h" #include "output.h"
int stdout_write_dump(void) int write_dump(FILE *stream)
{ {
const u64 output_size = dfo_size(); const u64 output_size = dfo_size();
char buf[8UL * PAGE_SIZE]; char buf[8UL * PAGE_SIZE];
@@ -28,15 +28,13 @@ int stdout_write_dump(void)
STDERR("\n"); STDERR("\n");
zg_progress_init("Copying dump", output_size); zg_progress_init("Copying dump", output_size);
while (written != output_size) { while (written != output_size) {
ssize_t rc; size_t rc;
u64 cnt; u64 cnt;
cnt = dfo_read(buf, sizeof(buf)); cnt = dfo_read(buf, sizeof(buf));
rc = write(STDOUT_FILENO, buf, cnt); rc = fwrite(buf, cnt, 1, stream);
if (rc == -1) if (rc != 1 && ferror(stream))
ERR_EXIT_ERRNO("Error: Write failed"); ERR_EXIT("Error: Write failed");
if (rc != (ssize_t) cnt)
ERR_EXIT("Error: Could not write full block");
written += cnt; written += cnt;
zg_progress(written); zg_progress(written);
}; };
+6 -4
View File
@@ -5,9 +5,11 @@
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#ifndef STDOUT_H #ifndef OUTPUT_H
#define STDOUT_H #define OUTPUT_H
int stdout_write_dump(void); #include <stdio.h>
#endif /* STDOUT_H */ int write_dump(FILE *stream);
#endif /* OUTPUT_H */
+13 -8
View File
@@ -9,7 +9,7 @@
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#define FUSE_USE_VERSION 25 #define FUSE_USE_VERSION 30
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@@ -84,8 +84,11 @@ static void stat_dump_init(void)
/* /*
* FUSE callback: Getattr * FUSE callback: Getattr
*/ */
static int zfuse_getattr(const char *path, struct stat *stat) static int zfuse_getattr(const char *path, struct stat *stat,
struct fuse_file_info *fi)
{ {
(void) fi;
if (strcmp(path, "/") == 0) { if (strcmp(path, "/") == 0) {
*stat = l.stat_root; *stat = l.stat_root;
return 0; return 0;
@@ -101,17 +104,19 @@ static int zfuse_getattr(const char *path, struct stat *stat)
* FUSE callback: Readdir - Return ".", ".." and dump file * FUSE callback: Readdir - Return ".", ".." and dump file
*/ */
static int zfuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, static int zfuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi) off_t offset, struct fuse_file_info *fi,
enum fuse_readdir_flags flags)
{ {
(void) offset; (void) offset;
(void) fi; (void) fi;
(void) flags;
if (strcmp(path, "/") != 0) if (strcmp(path, "/") != 0)
return -ENOENT; return -ENOENT;
filler(buf, ".", NULL, 0); filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0); filler(buf, "..", NULL, 0, 0);
filler(buf, &l.path[1], NULL, 0); filler(buf, &l.path[1], NULL, 0, 0);
return 0; return 0;
} }
@@ -206,7 +211,7 @@ int zfuse_mount_dump(void)
fuse_opt_add_arg(&args, "zgetdump"); fuse_opt_add_arg(&args, "zgetdump");
fuse_opt_add_arg(&args, "-s"); fuse_opt_add_arg(&args, "-s");
snprintf(tmp_str, sizeof(tmp_str), snprintf(tmp_str, sizeof(tmp_str),
"-ofsname=%s,ro,default_permissions,nonempty", "-ofsname=%s,ro,default_permissions",
g.opts.device); g.opts.device);
fuse_opt_add_arg(&args, tmp_str); fuse_opt_add_arg(&args, tmp_str);
fuse_opt_add_arg(&args, g.opts.mount_point); fuse_opt_add_arg(&args, g.opts.mount_point);
@@ -214,7 +219,7 @@ int zfuse_mount_dump(void)
stat_root_init(); stat_root_init();
stat_dump_init(); stat_dump_init();
snprintf(l.path, sizeof(l.path), "/dump.%s", dfo_name()); snprintf(l.path, sizeof(l.path), "/dump.%s", dfo_name());
return fuse_main(args.argc, args.argv, &zfuse_ops); return fuse_main(args.argc, args.argv, &zfuse_ops, NULL);
} }
/* /*
+1 -1
View File
@@ -280,7 +280,7 @@ off_t zg_seek(struct zg_fh *zg_fh, off_t off, enum zg_check check)
{ {
off_t rc; off_t rc;
if (off >= zg_fh->sb.st_size) if (S_ISREG(zg_fh->sb.st_mode) && off >= zg_fh->sb.st_size)
ERR_EXIT("Trying to seek past file end \"%s\"", zg_fh->path); ERR_EXIT("Trying to seek past file end \"%s\"", zg_fh->path);
rc = lseek(zg_fh->fh, off, SEEK_SET); rc = lseek(zg_fh->fh, off, SEEK_SET);
+42 -71
View File
@@ -45,79 +45,50 @@
/* /*
* Memory functions * Memory functions
*/ */
extern void *zg_alloc(unsigned int size); void *zg_alloc(unsigned int size);
extern void *zg_realloc(void *ptr, unsigned int size); void *zg_realloc(void *ptr, unsigned int size);
extern void zg_free(void *ptr); void zg_free(void *ptr);
extern char *zg_strdup(const char *str); char *zg_strdup(const char *str);
/* /*
* At exit functions * At exit functions
*/ */
typedef void (*zg_atexit_fn_t)(void); typedef void (*zg_atexit_fn_t)(void);
extern void zg_atexit(zg_atexit_fn_t fn); void zg_atexit(zg_atexit_fn_t fn);
extern void __noreturn zg_exit(int rc); void __noreturn zg_exit(int rc);
/* /*
* Temporary device node functions * Temporary device node functions
*/ */
extern char *zg_devnode_create(dev_t dev); char *zg_devnode_create(dev_t dev);
/* /*
* Progress bar functions * Progress bar functions
*/ */
extern void zg_progress_init(const char *msg, u64 mem_size); void zg_progress_init(const char *msg, u64 mem_size);
extern void zg_progress(u64 addr); void zg_progress(u64 addr);
/* /*
* Error and print functions * Error and print functions
*/ */
#define ERR(x...) \
do { \
fprintf(stderr, "%s: ", "zgetdump"); \
fprintf(stderr, x); \
fprintf(stderr, "\n"); \
} while (0)
#define ERR_EXIT(x...) \ void zg_err(const char *fmt, ...);
do { \ void zg_err_exit(const char *fmt, ...);
ERR(x); \ void zg_err_exit_errno(const char *fmt, ...);
zg_exit(1); \ void zg_abort(const char *fmt, ...);
} while (0)
#define ABORT(x...) \ #define ERR(fmt, ...) zg_err(fmt, ## __VA_ARGS__)
do { \ #define ERR_EXIT(fmt, ...) zg_err_exit(fmt, ## __VA_ARGS__)
ERR("Internal Error: " x); \ #define ERR_EXIT_ERRNO(fmt, ...) zg_err_exit_errno(fmt, ## __VA_ARGS__)
abort(); \ #define ABORT(fmt, ...) zg_abort(fmt, ## __VA_ARGS__)
} while (0)
#define ERR_EXIT_ERRNO(x...) \ void zg_stderr(const char *fmt, ...);
do { \ void zg_stderr_pr(const char *fmt, ...);
fflush(stdout); \ void zg_stdout(const char *fmt, ...);
fprintf(stderr, "%s: ", "zgetdump"); \
fprintf(stderr, x); \
fprintf(stderr, " (%s)", strerror(errno)); \
fprintf(stderr, "\n"); \
zg_exit(1); \
} while (0)
#define STDERR(x...) \
do { \
fprintf(stderr, x); \
fflush(stderr); \
} while (0)
#define STDERR_PR(x...) \
do { \
fprintf(stderr, "\r%s: ", "zgetdump"); \
fprintf(stderr, x); \
} while (0)
#define STDOUT(x...) \
do { \
fprintf(stdout, x); \
fflush(stdout); \
} while (0)
#define STDERR(fmt, ...) zg_stderr(fmt, ## __VA_ARGS__)
#define STDERR_PR(fmt, ...) zg_stderr_pr(fmt, ## __VA_ARGS__)
#define STDOUT(fmt, ...) zg_stdout(fmt, ## __VA_ARGS__)
/* /*
* Misc * Misc
*/ */
@@ -140,9 +111,9 @@ static inline u32 zg_csum_partial(const void *buf, int len, u32 sum)
/* /*
* Pointer atrithmetic * Pointer atrithmetic
*/ */
#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y))) #define PTR_SUB(x, y) ((void *)(((char *) (x)) - ((unsigned long) (y))))
#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y))) #define PTR_ADD(x, y) ((void *)(((char *) (x)) + ((unsigned long) (y))))
#define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y)))) #define PTR_DIFF(x, y) ((unsigned long)PTR_SUB(x, y))
/* /*
* File functions * File functions
@@ -167,22 +138,22 @@ enum zg_check {
ZG_CHECK_NONE, ZG_CHECK_NONE,
}; };
extern const char *zg_path(struct zg_fh *zg_fh); const char *zg_path(struct zg_fh *zg_fh);
extern const struct stat *zg_stat(struct zg_fh *zg_fh); const struct stat *zg_stat(struct zg_fh *zg_fh);
extern struct zg_fh *zg_open(const char *path, int flags, enum zg_check check); struct zg_fh *zg_open(const char *path, int flags, enum zg_check check);
extern void zg_close(struct zg_fh *zg_fh); void zg_close(struct zg_fh *zg_fh);
extern ssize_t zg_read(struct zg_fh *zg_fh, void *buf, size_t cnt, ssize_t zg_read(struct zg_fh *zg_fh, void *buf, size_t cnt,
enum zg_check check); enum zg_check check);
extern ssize_t zg_gets(struct zg_fh *zg_fh, void *buf, size_t cnt, ssize_t zg_gets(struct zg_fh *zg_fh, void *buf, size_t cnt,
enum zg_check check); enum zg_check check);
extern u64 zg_size(struct zg_fh *zg_fh); u64 zg_size(struct zg_fh *zg_fh);
extern off_t zg_tell(struct zg_fh *zg_fh, enum zg_check check); off_t zg_tell(struct zg_fh *zg_fh, enum zg_check check);
extern off_t zg_seek(struct zg_fh *zg_fh, off_t off, enum zg_check check); off_t zg_seek(struct zg_fh *zg_fh, off_t off, enum zg_check check);
extern off_t zg_seek_end(struct zg_fh *zg_fh, off_t off, enum zg_check check); off_t zg_seek_end(struct zg_fh *zg_fh, off_t off, enum zg_check check);
extern off_t zg_seek_cur(struct zg_fh *zg_fh, off_t off, enum zg_check check); off_t zg_seek_cur(struct zg_fh *zg_fh, off_t off, enum zg_check check);
extern int zg_ioctl(struct zg_fh *zg_fh, int rq, void *data, const char *op, int zg_ioctl(struct zg_fh *zg_fh, int rq, void *data, const char *op,
enum zg_check check); enum zg_check check);
extern enum zg_type zg_type(struct zg_fh *zg_fh); enum zg_type zg_type(struct zg_fh *zg_fh);
/* /*
* zgetdump actions * zgetdump actions
+72
View File
@@ -0,0 +1,72 @@
/*
* Copyright IBM Corp. 2001, 2017, 2021
*
* 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 <stdarg.h>
#include "lib/util_libc.h"
#include "zg.h"
static inline void _zg_err(const char *fmt, va_list ap)
{
fprintf(stderr, "%s: ", "zgetdump");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
}
static inline void _zg_err_errno(const char *fmt, va_list ap)
{
const int errno_backup = errno;
fflush(stdout);
fprintf(stderr, "%s: ", "zgetdump");
vfprintf(stderr, fmt, ap);
fprintf(stderr, " (%s)", strerror(errno_backup));
fprintf(stderr, "\n");
}
void zg_err(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_zg_err(fmt, ap);
va_end(ap);
}
void zg_err_exit(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_zg_err(fmt, ap);
va_end(ap);
zg_exit(1);
}
void zg_err_exit_errno(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_zg_err_errno(fmt, ap);
va_end(ap);
zg_exit(1);
}
void zg_abort(const char *fmt, ...)
{
char *newfmt;
va_list ap;
newfmt = util_strcat_realloc(util_strdup("Internal Error: "), fmt);
va_start(ap, fmt);
_zg_err(newfmt, ap);
va_end(ap);
free(newfmt);
abort();
}
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright IBM Corp. 2001, 2017, 2021
*
* 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 <stdarg.h>
#include "zg.h"
static inline void _zg_stderr(const char *fmt, va_list ap)
{
vfprintf(stderr, fmt, ap);
fflush(stderr);
}
static inline void _zg_stderr_pr(const char *fmt, va_list ap)
{
fprintf(stderr, "\r%s: ", "zgetdump");
vfprintf(stderr, fmt, ap);
}
static inline void _zg_stdout(const char *fmt, va_list ap)
{
vfprintf(stdout, fmt, ap);
fflush(stdout);
}
void zg_stderr(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_zg_stderr(fmt, ap);
va_end(ap);
}
void zg_stderr_pr(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_zg_stderr_pr(fmt, ap);
va_end(ap);
}
void zg_stdout(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_zg_stdout(fmt, ap);
va_end(ap);
}
+2
View File
@@ -8,6 +8,8 @@ zgetdump \- Tool for copying and converting System z dumps
.SH SYNOPSIS .SH SYNOPSIS
\fBzgetdump\fR DUMP [-s SYS] [-f FMT] > DUMP_FILE \fBzgetdump\fR DUMP [-s SYS] [-f FMT] > DUMP_FILE
.br
DUMP [-s SYS] [-f FMT] DUMP_FILE
.br .br
-m DUMP [-s SYS] [-f FMT] DIR -m DUMP [-s SYS] [-f FMT] DIR
.br .br
+35 -7
View File
@@ -30,7 +30,7 @@
#include "dt.h" #include "dt.h"
#include "dfi.h" #include "dfi.h"
#include "dfo.h" #include "dfo.h"
#include "stdout.h" #include "output.h"
#include "zfuse.h" #include "zfuse.h"
/* /*
@@ -156,18 +156,46 @@ static int do_mount(void)
return rc; return rc;
} }
/* static FILE *open_file_for_writing(const char *output)
* Run "copy to stdout" action
*/
static int do_copy(void)
{ {
FILE *stream;
int fd;
if (output) {
fd = open(output,
O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC,
0600);
if (fd == -1)
ERR_EXIT_ERRNO("Could not open '%s' exclusively", output);
} else {
fd = dup(STDOUT_FILENO);
if (fd == -1)
ERR_EXIT_ERRNO("Could not dup() stdout");
}
stream = fdopen(fd, "w");
if (!stream)
ERR_EXIT_ERRNO("Could not fdopen()");
fd = -1;
return stream;
}
/*
* Run "copy to output" action
*/
static int do_copy(const char *output)
{
FILE *stream;
int rc; int rc;
if (dfi_init() != 0) if (dfi_init() != 0)
ERR_EXIT("Dump cannot be processed (is not complete)"); ERR_EXIT("Dump cannot be processed (is not complete)");
dfo_init(); dfo_init();
kdump_select_check(); kdump_select_check();
rc = stdout_write_dump(); stream = open_file_for_writing(output);
rc = write_dump(stream);
fclose(stream);
dfi_exit(); dfi_exit();
return rc; return rc;
} }
@@ -185,7 +213,7 @@ int main(int argc, char *argv[])
switch (g.opts.action) { switch (g.opts.action) {
case ZG_ACTION_COPY: case ZG_ACTION_COPY:
return do_copy(); return do_copy(g.opts.output_path);
case ZG_ACTION_DUMP_INFO: case ZG_ACTION_DUMP_INFO:
return do_dump_info(); return do_dump_info();
case ZG_ACTION_DEVICE_INFO: case ZG_ACTION_DEVICE_INFO:
+6 -6
View File
@@ -68,11 +68,11 @@ stage3.exec: head.o stage3.o kdump3.o libc.o ebcdic.o ebcdic_conv.o sclp.o \
}' \ }' \
); \ ); \
case $$STAGE in \ case $$STAGE in \
0) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-Ttext,0";; \ 0) SFLAGS="$(NO_PIE_LDFLAGS) -nostdlib -Wl,-Ttext,0";; \
1) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-Ttext,0x18";; \ 1) SFLAGS="$(NO_PIE_LDFLAGS) -nostdlib -Wl,-Ttext,0x18";; \
1b) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-Ttext,0xE000";; \ 1b) SFLAGS="$(NO_PIE_LDFLAGS) -nostdlib -Wl,-Ttext,0xE000";; \
2) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage2.lds";; \ 2) SFLAGS="$(NO_PIE_LDFLAGS) -nostdlib -Wl,-T,stage2.lds";; \
3) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3.lds";; \ 3) SFLAGS="$(NO_PIE_LDFLAGS) -nostdlib -Wl,-T,stage3.lds";; \
esac; \ esac; \
$(LINK) $$SFLAGS -m64 $(filter %.o, $^) -o $@ $(LINK) $$SFLAGS -m64 $(filter %.o, $^) -o $@
@@ -110,7 +110,7 @@ stage3.bin: stage3.exec
$< $@ $< $@
data.o: $(FILES) data.o: $(FILES)
$(LD) $(NO_PIE_LDFLAGS) -r -b binary -o data.o $(FILES) $(LINK) $(NO_PIE_LDFLAGS) -static -nostdlib -Wl,--relocatable -Wl,--format,binary -o data.o $(FILES)
data.h: data.o data.h: data.o
rm -f data.h rm -f data.h
+27
View File
@@ -97,6 +97,33 @@ char *strcpy(char *dest, const char *src)
return dest; return dest;
} }
/**
* Copy \a src to buffer \a dest of size \a size. At most size - 1
* chars will be copied. \a dest will always be NUL terminated.
*
* Note: If the return value is greater than or equal to size truncation
* occurred.
*
* @param[in] dest Destination buffer
* @param[in] src Source string
* @param[in] size Size of destination buffer
*
* @returns strlen Length of \a src string
*/
size_t strlcpy(char *dest, const char *src, size_t size)
{
size_t str_len = strlen(src);
size_t len;
if (size) {
len = MIN(size - 1, str_len);
memcpy(dest, src, len);
dest[len] = '\0';
}
return str_len;
}
/* /*
* Return string length * Return string length
*/ */
+2 -1
View File
@@ -54,13 +54,14 @@ char *strcat(char *, const char *);
int strncmp(const char *, const char *, unsigned long); int strncmp(const char *, const char *, unsigned long);
int strlen(const char *); int strlen(const char *);
char *strcpy(char *, const char *); char *strcpy(char *, const char *);
size_t strlcpy(char *dest, const char *src, size_t size);
char *strchr(const char *str, char c); char *strchr(const char *str, char c);
unsigned int strhash(unsigned char *str, unsigned int hash_size); unsigned int strhash(unsigned char *str, unsigned int hash_size);
unsigned long get_zeroed_page(void); unsigned long get_zeroed_page(void);
void free_page(unsigned long); void free_page(unsigned long);
void initialize(void); void initialize(void);
void libc_stop(unsigned long) __noreturn; void libc_stop(unsigned long) __noreturn;
void start(void); void __noreturn start(void);
void pgm_check_handler(void); void pgm_check_handler(void);
void pgm_check_handler_fn(void); void pgm_check_handler_fn(void);
void panic_notify(unsigned long reason); void panic_notify(unsigned long reason);
+1 -1
View File
@@ -188,7 +188,7 @@ boot:
/* append 'BOOT_IMAGE=<num>' to parmline */ /* append 'BOOT_IMAGE=<num>' to parmline */
snprintf(endstring, sizeof(endstring), " BOOT_IMAGE=%u", value); snprintf(endstring, sizeof(endstring), " BOOT_IMAGE=%u", value);
if ((strlen(cmd_line_extra) + strlen(endstring)) < COMMAND_LINE_SIZE) if ((strlen(cmd_line_extra) + strlen(endstring)) < LEGACY_COMMAND_LINE_SIZE)
strcat(cmd_line_extra, endstring); strcat(cmd_line_extra, endstring);
sclp_setup(SCLP_DISABLE); sclp_setup(SCLP_DISABLE);
+3 -2
View File
@@ -75,15 +75,16 @@ out_free_page:
} }
static void execute(uint64_t psw) static __noreturn void execute(uint64_t psw)
{ {
asm volatile( asm volatile(
" lpsw %[psw]\n" " lpsw %[psw]\n"
: : [psw] "Q" (psw) : "cc" : : [psw] "Q" (psw) : "cc"
); );
__builtin_unreachable();
} }
void start(void) void __noreturn start(void)
{ {
struct stage2_descr stage2_descr; struct stage2_descr stage2_descr;
struct subchannel_id subchannel_id; struct subchannel_id subchannel_id;
+3 -2
View File
@@ -393,7 +393,7 @@ static void store_status(void)
* Block followed by a valid checksum (as defined in lowcore.h and set * Block followed by a valid checksum (as defined in lowcore.h and set
* by ipl.c). In case of match use diag308 to IPL. * by ipl.c). In case of match use diag308 to IPL.
*/ */
static void dump_exit(unsigned long code) static __noreturn void dump_exit(unsigned long code)
{ {
struct ipib_info *ipib_info = (struct ipib_info *)&S390_lowcore.ipib; struct ipib_info *ipib_info = (struct ipib_info *)&S390_lowcore.ipib;
uint32_t ipib_len, csum; uint32_t ipib_len, csum;
@@ -406,6 +406,7 @@ static void dump_exit(unsigned long code)
libc_stop(code); libc_stop(code);
diag308(DIAG308_SET, (void *) ipib_info->ipib); diag308(DIAG308_SET, (void *) ipib_info->ipib);
diag308(DIAG308_IPL, NULL); diag308(DIAG308_IPL, NULL);
__builtin_unreachable();
} }
/* /*
@@ -420,7 +421,7 @@ void panic_notify(unsigned long code)
/* /*
* Create stand-alone dump * Create stand-alone dump
*/ */
void start(void) void __noreturn start(void)
{ {
init_early(); init_early();
dt_device_parm_setup(); dt_device_parm_setup();
+66 -69
View File
@@ -159,8 +159,8 @@ static void hash_table_add(struct env_hash_entry *items,
(*new_idx)++; (*new_idx)++;
} }
struct env_hash_entry *hash_table_find(struct env_hash_entry **buckets, static struct env_hash_entry *hash_table_find(struct env_hash_entry **buckets,
char *name) char *name)
{ {
struct env_hash_entry *item; struct env_hash_entry *item;
@@ -232,7 +232,8 @@ static void parse_envblk(struct env_hash_entry *items,
* CMDL_LEN: length of the command line to be processed * CMDL_LEN: length of the command line to be processed
* BUCKETS: hash table of pairs (NAME, VALUE) * BUCKETS: hash table of pairs (NAME, VALUE)
*/ */
void process_parm_line(struct env_hash_entry **buckets, unsigned int cmdl_len) void process_parm_line(struct env_hash_entry **buckets, unsigned int cmdl_len,
unsigned int max_len)
{ {
struct env_hash_entry *item; struct env_hash_entry *item;
char empty_str = 0; char empty_str = 0;
@@ -282,7 +283,7 @@ void process_parm_line(struct env_hash_entry **buckets, unsigned int cmdl_len)
*/ */
len = strlen(val); len = strlen(val);
if (cmdl_len + len - (end - start + 1) >= COMMAND_LINE_SIZE) if (cmdl_len + len - (end - start + 1) >= max_len)
/* VALUE doesn't fit */ /* VALUE doesn't fit */
break; break;
/* /*
@@ -306,7 +307,7 @@ void process_parm_line(struct env_hash_entry **buckets, unsigned int cmdl_len)
/** /**
* LEN: length of the command line to be processed * LEN: length of the command line to be processed
*/ */
static void handle_environment(unsigned int len) static void handle_environment(unsigned int len, unsigned int max_len)
{ {
struct env_hash_entry *buckets[STR_HASH_SIZE]; struct env_hash_entry *buckets[STR_HASH_SIZE];
struct env_hash_entry *items; struct env_hash_entry *items;
@@ -326,30 +327,76 @@ static void handle_environment(unsigned int len)
* find environment variables in the command line and * find environment variables in the command line and
* replace them with their values as found in the hash table * replace them with their values as found in the hash table
*/ */
process_parm_line(buckets, len); process_parm_line(buckets, len, max_len);
free_page((unsigned long)items); free_page((unsigned long)items);
} }
void start(void) static void verify_secure_boot(void)
{ {
unsigned int subchannel_id;
unsigned char *cextra = (unsigned char *)COMMAND_LINE_EXTRA;
unsigned char *cmdline = (unsigned char *)COMMAND_LINE;
unsigned int cmdline_len = 0, cextra_len = 0;
/* /*
* IPL process is secure we have to use default IPL values and * IPL process is secure we have to use default IPL values and
* check if the psw jump address is within at the start of a * check if the psw jump address is within at the start of a
* verified component. If it is not IPL is aborted. * verified component. If it is not IPL is aborted.
*/ */
if (secure_boot_enabled()) { if (_stage3_parms.image_addr != IMAGE_LOAD_ADDRESS ||
if (_stage3_parms.image_addr != IMAGE_LOAD_ADDRESS || _stage3_parms.load_psw != DEFAULT_PSW_LOAD)
_stage3_parms.load_psw != DEFAULT_PSW_LOAD) panic(ESECUREBOOT, "%s", msg_sipl_inval);
panic(ESECUREBOOT, "%s", msg_sipl_inval);
if (!is_verified_address(_stage3_parms.load_psw & PSW32_ADDR_MASK)) if (!is_verified_address(_stage3_parms.load_psw & PSW32_ADDR_MASK))
panic(ESECUREBOOT, "%s", msg_sipl_unverified); panic(ESECUREBOOT, "%s", msg_sipl_unverified);
}
static void setup_cmdline(void)
{
char *cextra = (char *)COMMAND_LINE_EXTRA;
char *cmdline = (char *)COMMAND_LINE;
unsigned int cmdline_len = 0;
unsigned int max_cmdline_len = *(unsigned long *)MAX_COMMAND_LINE_SIZE;
if (!max_cmdline_len)
max_cmdline_len = LEGACY_COMMAND_LINE_SIZE;
/* if valid command line is given, copy it into new kernel space */
if (_stage3_parms.parm_addr != UNSPECIFIED_ADDRESS) {
strlcpy(cmdline, (void *)(unsigned long *)_stage3_parms.parm_addr,
max_cmdline_len);
} }
/* determine length of original parm line */
cmdline_len = MIN((unsigned int)strlen(cmdline), max_cmdline_len - 1);
/* convert extra parameter to ascii */
if (!_stage3_parms.extra_parm || !*cextra)
goto noextra;
/* Handle extra kernel parameters specified in DASD boot menu. */
ebcdic_to_ascii((unsigned char *)cextra, (unsigned char *)cextra, COMMAND_LINE_EXTRA_SIZE);
while (isspace(*cextra))
cextra++;
/*
* if extra parm string starts with '=' replace original string,
* else append
*/
if (*cextra == 0x3d) {
strlcpy(cmdline, cextra+1, max_cmdline_len);
} else if (*cextra && cmdline_len + 1 <= max_cmdline_len - 1) {
/* add blank */
cmdline[cmdline_len++] = 0x20;
strlcpy(cmdline + cmdline_len, cextra, max_cmdline_len - cmdline_len);
}
noextra:
handle_environment(strlen(cmdline), max_cmdline_len);
}
void start(void)
{
unsigned int subchannel_id;
if (secure_boot_enabled())
verify_secure_boot();
/* /*
* cut the kernel header * cut the kernel header
*/ */
@@ -362,57 +409,7 @@ void start(void)
*(unsigned int *)__LC_IPLDEV = subchannel_id; *(unsigned int *)__LC_IPLDEV = subchannel_id;
*(unsigned long long *)IPL_DEVICE = subchannel_id; *(unsigned long long *)IPL_DEVICE = subchannel_id;
/* if valid command line is given, copy it into new kernel space */ setup_cmdline();
if (_stage3_parms.parm_addr != UNSPECIFIED_ADDRESS) {
memcpy(cmdline,
(void *)(unsigned long *)_stage3_parms.parm_addr,
COMMAND_LINE_SIZE);
/* terminate \0 */
cmdline[COMMAND_LINE_SIZE - 1] = 0;
}
/* determine length of original parm line */
cmdline_len = MIN(strlen((const char *)cmdline),
COMMAND_LINE_SIZE - 1);
/* convert extra parameter to ascii */
if (!_stage3_parms.extra_parm || !*cextra)
goto noextra;
/* Handle extra kernel parameters specified in DASD boot menu. */
ebcdic_to_ascii(cextra, cextra, COMMAND_LINE_SIZE);
/* determine length of extra parameter */
cextra_len = MIN(strlen((const char *)cextra), COMMAND_LINE_SIZE - 1);
/* remove leading whitespace of extra parameter */
while (cextra_len > 0 && *cextra == 0x20) {
cextra++;
cextra_len--;
}
/*
* if extra parm string starts with '=' replace original string,
* else append
*/
if (*cextra == 0x3d && cextra_len >= 1) {
/* skip '=' */
cextra++;
cextra_len--;
memcpy(cmdline, cextra, cextra_len);
cmdline[cextra_len] = 0;
} else if (cmdline_len + 1 <= COMMAND_LINE_SIZE - 1) {
/* add blank */
cmdline[cmdline_len] = 0x20;
cmdline_len++;
/* check if length is within max value */
cextra_len = (cmdline_len + cextra_len <= COMMAND_LINE_SIZE - 1) ?
cextra_len : (COMMAND_LINE_SIZE - 1 - cmdline_len);
/* append string */
memcpy(cmdline + cmdline_len, cextra, cextra_len);
/* terminate 0 */
cmdline[cmdline_len + cextra_len] = 0;
}
noextra:
handle_environment(cmdline_len + cextra_len);
/* copy initrd start address and size intop new kernle space */ /* copy initrd start address and size intop new kernle space */
*(unsigned long long *)INITRD_START = _stage3_parms.initrd_addr; *(unsigned long long *)INITRD_START = _stage3_parms.initrd_addr;
+36 -89
View File
@@ -218,12 +218,25 @@ iplstart:
la %r2,_initrd_addr # store ramdisk address la %r2,_initrd_addr # store ramdisk address
mvc INITRD_START-PARMAREA(8,%r12),0(%r2) mvc INITRD_START-PARMAREA(8,%r12),0(%r2)
# copy kernel to final destination
l %r6,.Lkernsize
sl %r6,.Lkernoff
l %r2,.Lkernoff # 0x10000
lr %r3,%r6
l %r4,.Loffset # 0x4000
a %r4,.Lkernoff
lr %r5,%r6
mvcl %r2,%r4
l %r12,.Lparmarea
# #
# Load parameter file # Load parameter file
# #
l %r4,_parm_addr+4 l %r4,_parm_addr+4
chi %r4,-1
be .Lnopf
.Lagain1: .Lagain1:
lr %r2,%r4 # load parmfile lr %r2,%r4 # load parmfile
bas %r14,.Lloader bas %r14,.Lloader
@@ -236,31 +249,35 @@ iplstart:
clc 0(3,%r4),.L_eof # if it is EOFx clc 0(3,%r4),.L_eof # if it is EOFx
bz .Lagain1 # skip dateset trailer bz .Lagain1 # skip dateset trailer
chi %r2,COMMAND_LINE_SIZE-1 # truncate if line too long lt %r3,MAX_COMMAND_LINE_SIZE-PARMAREA+4(%r12)
jnz 0f
lhi %r3,LEGACY_COMMAND_LINE_SIZE
0: cr %r2,%r3 # truncate if line too long
bnh .Lnotrunc bnh .Lnotrunc
la %r2,COMMAND_LINE_SIZE-1 lr %r2,%r3
.Lnotrunc: .Lnotrunc:
la %r5,0(%r4,%r2) # search for EBCDIC chars la %r5,0(%r4,%r2) # search for EBCDIC chars
lr %r3,%r2 ahi %r5,-1
lr %r6,%r2
.Lidebc: .Lidebc:
tm 0(%r5),0x80 # high order bit set ? tm 0(%r5),0x80 # high order bit set ?
bo .Ldocv # yes -> convert from EBCDIC bo .Ldocv # yes -> convert from EBCDIC
ahi %r5,-1 ahi %r5,-1
bct %r3,.Lidebc bct %r6,.Lidebc
b .Lnocv b .Lnocv
.Ldocv: .Ldocv:
la %r3,_ebcasc lr %r6,%r2
tr 0(256,%r4),0(%r3) # convert parameters to ascii la %r5,_ebcasc
tr 256(256,%r4),0(%r3) 0: tr 0(1,%r4),0(%r5)
tr 512(256,%r4),0(%r3) ahi %r4,1
tr 768(127,%r4),0(%r3) brct %r6,0b
l %r4,_parm_addr+4
.Lnocv: .Lnocv:
la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line lr %r5,%r2
mvc 0(256,%r3),0(%r4) ahi %r5,-1
mvc 256(256,%r3),256(%r4) la %r6,COMMAND_LINE-PARMAREA(%r12)
mvc 512(256,%r3),512(%r4) lr %r7,%r2
mvc 768(127,%r3),768(%r4) mvcl %r6,%r4
slr %r0,%r0 slr %r0,%r0
b .Lcntlp b .Lcntlp
.Ldelspc: .Ldelspc:
@@ -284,6 +301,8 @@ iplstart:
.Lagain2: .Lagain2:
l %r2,INITRD_START-PARMAREA+4(%r12) # load ramdisk l %r2,INITRD_START-PARMAREA+4(%r12) # load ramdisk
chi %r2,-1
be .Lnoinitrd
bas %r14,.Lloader bas %r14,.Lloader
st %r2,INITRD_SIZE-PARMAREA+4(%r12) # store ramdisk size st %r2,INITRD_SIZE-PARMAREA+4(%r12) # store ramdisk size
@@ -298,86 +317,14 @@ iplstart:
clc 0(3,%r2),.L_eof clc 0(3,%r2),.L_eof
bz .Lagain2 bz .Lagain2
# .Lnoinitrd:
# Copy kernel image to final position mvc 0(8,0),_load_psw # copy load psw
#
la %r2,_load_psw # prepare copy code
la %r3,.Lcopypsw
mvc 0(8,%r3),0(%r2) # copy load psw
l %r4,_initrd_addr+4
ahi %r4,-0x100
la %r2,.Lcopystart # get copy code addr (from)
mvc 0(.Lcopyend-.Lcopystart,%r4),0(%r2) # copy code
l %r1,.Loffset # temp kernel address (from)
l %r2,4(%r3) # get kernel addr from psw (to)
n %r2,.Lpswmask
s %r2,.Lkernoff
l %r3,.Lkernsize # (length)
br %r4 # branch to copy routine
#
# Copy kernel, then load PSW
#
# R1 = from
# R2 = to
# R3 = length
#
.align 8
.Lcopystart:
clr %r1,%r2
je .Lcopyfinish # kernel is already at dest
jh .Lcopytolower # need move to lower address
# Copy last to first
ar %r1,%r3 # start from last long
ar %r2,%r3
lhi %r4,-4 # set addr increment to -4
j .Lcopygo
# Copy first to last
.Lcopytolower:
lhi %r4,4 # set addr increment to 4
.Lcopygo:
ahi %r3,3 # get size in longs
srl %r3,2
.Lcopyloop:
l %r0,0(%r1) # copy longs
st %r0,0(%r2)
ar %r1,%r4
ar %r2,%r4
brct %r3,.Lcopyloop
.Lcopyfinish:
bras %r13,.Lcopyload # set up base register
.Lcopyload:
sr %r0,%r0
la %r1,.Lcopypsw-.Lcopyload(%r13)
mvc 0(8,%r0),0(%r1) # copy load psw to 0
lm %r0,%r15,.Lvmparam-.Lcopyload(%r13) # load saved registers
lpsw 0 # start kernel lpsw 0 # start kernel
.align 8 .align 8
.Lcopypsw:
.quad 0
.Lvmparam: .Lvmparam:
.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 # vm parameter space .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 # vm parameter space
.Lcopyend:
.Lpswmask:
.long 0x7fffffff
.Lkernsize: .Lkernsize:
.long 0 .long 0
.Lkernoff: .Lkernoff:
+11 -13
View File
@@ -13,6 +13,8 @@
#ifndef JOB_H #ifndef JOB_H
#define JOB_H #define JOB_H
#include <stdbool.h>
#include "disk.h" #include "disk.h"
#include "zipl.h" #include "zipl.h"
@@ -39,13 +41,19 @@ struct job_target_data {
blocknum_t targetoffset; blocknum_t targetoffset;
}; };
struct job_ipl_data { struct job_common_ipl_data {
char* image; char* image;
char* parmline; char* parmline;
char* ramdisk; char* ramdisk;
address_t image_addr; address_t image_addr;
address_t parm_addr; address_t parm_addr;
address_t ramdisk_addr; address_t ramdisk_addr;
bool optional;
bool ignore;
};
struct job_ipl_data {
struct job_common_ipl_data common;
address_t envblk_addr; address_t envblk_addr;
int is_kdump; int is_kdump;
}; };
@@ -61,13 +69,8 @@ struct job_segment_data {
}; };
struct job_dump_data { struct job_dump_data {
struct job_common_ipl_data common;
char* device; char* device;
char* image;
char* parmline;
char* ramdisk;
address_t image_addr;
address_t parm_addr;
address_t ramdisk_addr;
uint64_t mem; uint64_t mem;
}; };
@@ -80,13 +83,8 @@ struct job_mvdump_data {
}; };
struct job_ipl_tape_data { struct job_ipl_tape_data {
struct job_common_ipl_data common;
char* device; char* device;
char* image;
char* parmline;
char* ramdisk;
address_t image_addr;
address_t parm_addr;
address_t ramdisk_addr;
}; };
+2 -1
View File
@@ -16,7 +16,7 @@
#define SCAN_SECTION_NUM 9 #define SCAN_SECTION_NUM 9
#define SCAN_KEYWORD_NUM 22 #define SCAN_KEYWORD_NUM 23
#define SCAN_KEYWORD_ONLY_NUM 1 #define SCAN_KEYWORD_ONLY_NUM 1
#define SCAN_AUTOMENU_NAME "zipl-automatic-menu" #define SCAN_AUTOMENU_NAME "zipl-automatic-menu"
@@ -52,6 +52,7 @@ enum scan_keyword_id {
scan_keyword_defaultauto = 19, scan_keyword_defaultauto = 19,
scan_keyword_kdump = 20, scan_keyword_kdump = 20,
scan_keyword_secure = 21, scan_keyword_secure = 21,
scan_keyword_optional = 22,
}; };
enum scan_section_type { enum scan_section_type {
+2 -1
View File
@@ -23,7 +23,8 @@
#define ADDRESS_LIMIT 0x80000000UL #define ADDRESS_LIMIT 0x80000000UL
#define UNSPECIFIED_ADDRESS -1UL #define UNSPECIFIED_ADDRESS -1UL
#define MAXIMUM_PARMLINE_SIZE 0x380UL #define LEGACY_MAXIMUM_PARMLINE_SIZE 0x380UL
#define MAXIMUM_PARMLINE_SIZE 0x10000UL
#define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000UL #define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000UL
#define BOOTMAP_FILENAME "bootmap" #define BOOTMAP_FILENAME "bootmap"
+17
View File
@@ -447,6 +447,23 @@ This option cannot be used together with either
.BR 'segment' . .BR 'segment' .
.PP .PP
.B optional
=
.IR 0 / 1
(configuration only)
.IP
.B Configuration section:
.br
If this option is set to 1 the configuration section will only be included in
the boot menu if the referenced image file exists, and running
.B zipl
will not fail if the image file is missing.
The default value for
.B 'optional'
is 0.
.PP
.B parameters .B parameters
= =
.I kernel\-parameters .I kernel\-parameters
+4
View File
@@ -394,6 +394,10 @@ store_stage2_menu(void* data, size_t size, struct job_data* job)
return 0; return 0;
/* Config texts */ /* Config texts */
for (i = 0; i < job->data.menu.num; i++) { for (i = 0; i < job->data.menu.num; i++) {
if (job->data.menu.entry[i].data.ipl.common.ignore) {
params->config[job->data.menu.entry[i].pos] = 0;
continue;
}
const char *kdump_str = ""; const char *kdump_str = "";
if (job->data.menu.entry[i].data.ipl.is_kdump) if (job->data.menu.entry[i].data.ipl.is_kdump)
kdump_str = " (kdump)"; kdump_str = " (kdump)";

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