Compare commits

..

68 Commits

Author SHA1 Message Date
Jan Höppner
c217f6be6a New release s390-tools-2.30.0
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-01 15:03:39 +01:00
Steffen Eiden
21662d38e6 rust/pv: Update mockito to version 1
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-12-01 10:24:48 +01:00
Niklas Schnelle
19f3842292 libutil: fix util_file_read_*() using wrong format specifiers
The sscanf() format specifiers for signed and unsigned int mistakenly
used "%d"/"%u" prefix analogous to "%l" for long but those do not exist.

Fixes: 37348ef662 ("libutil: add util_file_read_i()/util_file_read_ui()")
Acked-by: Sven Schnelle <svens@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-12-01 10:24:48 +01:00
Steffen Eiden
ae0cbf00b1 rust: Use default panic behaviour
Reviewed-by: Marc Hartmayer <marc@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-12-01 10:24:48 +01:00
Steffen Eiden
9019c6864a rust: Sanitize minimal dependencies
The crate dependencies were a bit to slack. Due to the rust dependency
resolver's strategy of always selecting the latest version this never
lead to any issues.

This has no impact on the workspaces Cargo.lock

Reviewed-by: Marc Hartmayer <marc@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-12-01 10:24:48 +01:00
Steffen Eiden
d1b61c37fa rust: Update dependency files
With the last patch introducing the rust workspace the location of
Cargo.lock has changed. Therefore, remove all crate level lock-files and
add rust/Cargo.lock as the only lock-file.

Steps to reproduce:
```
cd rust
mv pvsecret/Cargo.lock .
cargo build
cargo update -p openssl
cargo update -p curl-sys
cargo update -p rustix

```

While at it update some dependencies to get fixes for security issues.

Reviewed-by: Marc Hartmayer <marc@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-12-01 10:24:48 +01:00
Steffen Eiden
32b68a5fad rust: Create workspace
A workspaces simplifies the build and packaging process significantly.
All build artifacts and binaries are now built in a single location
(e.g., rust/target/release/*), and a unified dependency resolution is
used. Hence one Cargo.lock for all crates at rust/Cargo.lock.

Closes: https://github.com/ibm-s390-linux/s390-tools/issues/156
Reviewed-by: Marc Hartmayer <marc@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-12-01 10:24:48 +01:00
Matthew Rosato
55fdb17b18 ap_tools/ap-check: handle get-attributes between pre and post event
Since mdevctl commit acf78c1ff6c9 it is now possible for the
get-attributes event to occur between a pre-define and post-define.
This is done in order to obtain the active attributes for the device
before writing them to the config file, and implies that the
get-attributes cannot re-obtain the file lock.  For other cases
where mdevctl calls get-attributes, the file lock is not already
held and must be obtained by ap-check before reading attributes from
active devices.
To solve this, let's use the knowledge that mdevctl is a single-threaded
tool and add a test to detect this scenario.  If the file lock is
already held by the parent during a get-attributes, don't attempt to
re-acquire it.

Reported-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-12-01 10:24:48 +01:00
Matthew Rosato
af730c79a6 libutil/util_lockfile: add routine to return owning pid of file lock
Provide a mechanism via which a caller can query the pid of the process
currently holding the file lock.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-12-01 10:24:48 +01:00
Marc Hartmayer
041e6131d1 genprotimg/boot: stage3b: check cmdline for null-termination
Add a check to the stage3b that the kernel cmdline is always
null-terminated. While at it, ensure the coding style is consistent.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-12-01 10:24:48 +01:00
Marc Hartmayer
5a7d7e05b8 genprotimg: make sure the kernel command line is always null-terminated
Make sure that the kernel command line used for the Secure Execution
boot image is always null-terminated. Before this change, users had to
ensure that the provided kernel cmdline was null-terminated, which was
error-prone. But since the default s390x Linux kernel command line is
set to `root=/dev/ram0 ro` the remaining reserved memory for the kernel
command line is zeroed out. Therefore, the problem only shows up if the
used kernel command line is shorter than the default kernel command
line.

Fixes: 65b9fc442c ("genprotimg: introduce new tool for the creation of PV images")
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-12-01 10:24:48 +01:00
Steffen Eiden
71b93d55ef rust/pv: fix Invalid write of size 1
Fix a valgrind finding. Fix an invalid read/write of one byte after the
actual struct to clear. Not fixing this may result in a illegal write or
memory corruption of the program. Fortunately, for the actual only user,
pvsecret this is not the case.

Fixes: c6f621d0 ("rust: Add library for pv tools")
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-12-01 10:24:40 +01:00
Thomas Richter
d2b5e1e2d6 cpumf/pai: Add command line option for realtime scheduling
Pai collects data from per CPU ring buffers and stores them in the
memory mapped output file. When data is collected from many CPUs at
the same time, writing data to output file can be slow.
Improve this and allow the pai recording to run with higher
real time priority. This is the same approach as done by the perf tool.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-12-01 09:58:47 +01:00
Mikhail Zaslonko
a3cb877c54 README: Add info about bundled zlib
Update Dependencies section for zipl with the information of zlib
compression support for CCW-type standalone dump.

Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/157
Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Joern Siglen
6895a71cc4 dbginfo.sh: remove brakets on lsqeth device list
in customer situation we found lsqeth listing devices like:
Device name                      : (unnamed net_device)
Device name                      : enc2000
Device name                      : enc3000

- the braket around the "unnamed" device is braking the function call and
leads to stop the dbginfo.sh script.
- this patch removes brakets > the functions call works and call of osaoat
will report an unknown device instead of braking the dbginfo.sh script

Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Joern Siglen
d9034b01f1 dbginfo.sh: enhance ethtool collection for ROCE
collect module-info for new ROCE cards via ethtool

Suggested-by: Niklas Schnelle <schnelle@linux.ibm.com>
Reviewed-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Joern Siglen
488ac8c3f2 dbginfo.sh: fix shellcheck errors in double quoting
change use of double quote to fit the rules

Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Jan Höppner
ecf36d53c8 dasdfmt: Update -k/--keep_volser description
Make the description of the --keep_volser option more generic and avoid
mentioning specific tooling.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Jan Höppner
893ad920c5 dasdfmt: Fix trailing whitespace in man page
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Jan Höppner
0695c79f4e fdasd: Improve -k/--keep_volser description slightly
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Jan Höppner
8837ea24cb fdasd: Fix trailing whitespace in man page
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Marc Hartmayer
65222d03b9 zipl/boot: compile the bootloaders only if HOST_ARCH is s390x
The zipl bootloaders are s390x specific, so only build them if the
`HOST_ARCH' is set to s390x.

While at it, rename `INC_FILES` to `EMBEDDED_BOOTLOADERS`. Also
introduce `EXTERNAL_BOOTLOADERS` variable and use it in the `install`
Makefile target.

Reviewed-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>
2023-11-07 14:13:38 +01:00
Ingo Franzki
54937495e2 zkey: Also check for deconfigured and check-stopped cards
When checking if a card or an APQN is online, not only check the 'online'
sysfs attribute, but also check the 'config' and 'chkstop' attribute.
Cards and APQNs in check-stopped or deconfigured state can still be reported
as online via the sysfs attribute, although they are not available to be
used for zkey.

In case the 2 additional sysfs attributes are not available in sysfs, then
don't fail, but rely on the 'online' attribute only.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Marc Hartmayer
8a783b81a4 Provide a ShellCheck configuration
This patch adds a ShellCheck configuration for s390-tools. See
https://www.shellcheck.net/wiki/Directive for details.

Reviewed-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>
2023-11-07 14:13:38 +01:00
Marc Hartmayer
093da2a5a7 zipl: move responsibility for the stage3.bin installation to boot/Makefile
Move the code responsible for installing stage3.bin to the
boot/Makefile. In addition, remove the stage3.bin from the Makefile
`all` target prerequisites in src/Makefile, as zipl can be built without
it. While at it, use $(INSTALL) instead of $(CP) for the bootloader
installation.

Reviewed-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>
2023-11-07 14:13:38 +01:00
Ingo Franzki
b68ea5fc7d zkey: Fix typos in man page
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Eric Farman
90c587408f cpictl: Limit kernel sublevel to one byte
Linux stable kernels can reach greater than 256 sublevels [1],
which can cause the cpi tooling to generate an invalid string
that gets passed to the firmware and causes unusual responses:

  $ uname -r
  5.4.255
  $ cat /sys/firmware/cpi/system_level
  0x04260000000504ff

  --reboot--

  $ uname -r
  5.4.256
  $ cat /sys/firmware/cpi/system_level
  0x4260000000504100

The first sublevel field is defined as one byte, so ensure that
a value larger than that isn't included.

[1] https://lore.kernel.org/lkml/1612534196241236@kroah.com/

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Thorsten Winkler
90475fbaa5 common.mak: use eval only once for defining variables
Using eval only once at the top most function "define_toolchain_variables",
makes the other subsequent eval calls redundant.

“The result of the eval function is always the empty string; thus, it
can be placed virtually anywhere in a makefile without causing syntax
errors.” [1]

So this patch also prevents potential syntax errors using GNU Make <v4.2.
Since version 4.2 GNU Make introduced a less errorness function calling and
variable expanding with commit
e971597 ("[SV 46995] Strip leading/trailing space from variable names")

Reference: https://git.savannah.gnu.org/cgit/make.git/commit/?h=4.2&id=e97159745d3359285cef535af780cd8e2b6b0791

[1] https://www.gnu.org/software/make/manual/html_node/Eval-Function.html

Signed-off-by: Thorsten Winkler <twinkler@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Vineeth Vijayan
07ff9e1da0 zdev: limit the derivation of ZDEV_SITE_ID
Currently ZDEV_SITE_ID is derived with the help of an additional
udev-rule, 40-zdev-id.rules. The sole purpose of this rule is to
determine the ZDEV_SITE_ID environment value with the help of zdev_id
binary. This solution is minimal, but this has some unwanted side-
effects. The zdev_id logic get executed for all the events, even
those completely unrelated to zdev/or site, and imports the unneeded
envionment values to the udev-db.

Instead of having an additional rule file, add this logic as part of
the udev-rule of those devices which are configured with site-support.
The logic will then be available on all those rules with the
site-supported devices only.

Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Vineeth Vijayan
5637799c92 zdev: introduce dev_site_configured macro
Introduce dev_site_configured macro,which can be used to find the
availability of site configurations for the device during udev rule
creation.

Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Vineeth Vijayan
73c82441e7 zdev: move all site-related definitions to one file
Previously SITE_FALLBACK and other site-specific configuration support
macros were defined in device.h. Instead, move them to a relatively
smaller header file which is exclusive for site-related definitions.
This way, light-weight zdev_id also can use the same header file.

Reported-by: Steffen Maier<maier@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Alexandra Winter
6d06921276 zdev:qeth: adapt performance_stats attribute semantics
Behaviour of the qeth performance_stats sysfs attribute has changed
with kernel commit
b0abc4f5df76 ("s390/qeth: overhaul ethtool statistics")
that went into kernel v5.1.

Before the kernel commit
- collection of statistics was turned on and off by writing 1 or 0
- default after device activation was 0
- statistics were reset by writing 0

After the kernel commit:
- collection is always on
- attribute always reads 1
- statistics is reset by writing 1; writing 0 is a no-op

Problems of chzdev on new kernels:
chzdev cannot reset statistics ('performance_stats=1' does nothing).
'chzdev --export' always lists performance_stats.
'chzdev qeth --help-attribute performance_stats' reflects old behaviour.

This patch will do the following:
'chzdev qeth --help-attribute performance_stats' reflects new behaviour.
'chzdev --export' does not list performance_stats on new kernels.
'chzdev performance_stats=1' resets statistics on new kernels.
'chzdev performance_stats=0' still resets statistics on old kernels,
    does nothing on new kernels.

Suggested-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-11-07 14:13:38 +01:00
Steffen Maier
2996b34ddf dbginfo.sh: collect debug data for zdev site support
Complements v2.24.0 commit c8ad5f57d0 ("zdev: modify zdev_id to read the
site_id from loadparm") and commit 2e89722ef0 ("zdev: make site specific
udev-rule for ccw").

Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:07 +02:00
Steffen Maier
e5821301f6 dbginfo.sh: exclude (empty) cpu subdirs under zfcp sdev block mq sysfs
With many CPUs, such as triple digit counts, the by default many empty
sysfs directories are prohibitive to collect, especially if the number
of SCSI disk devices is also large, such as 4-digit counts.

Excluding them from being collected from sysfs saves hundreds times
thousands of archive entries and inodes on expansion.

Since the number device-mapper devices (multipath and other target types
such as LVM) is smaller and can include devices not backed by zfcp, keep
collecting
/sys/devices/virtual/block/dm-[0-9]*/mq/0/cpu[0-9]*/

Definitely keep collecting
/sys/kernel/debug/block/{sd,dm-}*/hctx0/cpu[0-9]*/
as it contains actual statistics files:
completed  default_rq_list  dispatched  merged  poll_rq_list  read_rq_list

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:07 +02:00
Steffen Maier
f4d1874ac5 dbginfo.sh: collect text export of udev data base
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:07 +02:00
Steffen Maier
f3428929a2 dbginfo.sh: collect potential kdump config under subdir /etc/kdump
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:07 +02:00
Mikhail Zaslonko
263d6950a1 zipl/boot/zlib: Replace static_assert() in zlib code
Replace static_assert() with STATIC_ASSERT macro from zt_common.h in order
to get rid of glibc dependencies in zipl/boot and comply with older
C standards.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Suggested-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:07 +02:00
Marc Hartmayer
8024f8e31a editorconfig: add settings for EDIT_DESCRIPTION
Set the maximum line length for branch description messages (`git branch
--edit-description`) to 72 characters.

Reviewed-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>
2023-09-27 18:29:07 +02:00
Marc Hartmayer
3849b29594 rust/**/*.rs: fix cargo clippy findings
Automatically fixed by the command `cargo clippy --fix` and `cargo fmt`.

Reviewed-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>
2023-09-27 18:29:07 +02:00
Mikhail Zaslonko
0e4d4da0e5 zdump: Update zgetdump man page
Update zgetdump man page with the information of compressed DASD dumps
support as well as new verbose 'zgetdump -i' output entries.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:07 +02:00
Mikhail Zaslonko
ca3cd51f91 zdump/dt_s390: Support new dumper version by 'zgetdump -d'
Add new dumper version support to 'zgetdump -d' command.

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
fda1e0d33d zdump: Move and rename DF_S390_DUMPER_SIZE constants
Move DF_S390_DUMPER_SIZE_* constants from zdump/df_s390.h to
boot/loaders_layout.h since ccw dumper size depends on the zipl boot
loader layout (to keep it all in one place).

Rename DF_S390_DUMPER_SIZE_* constants to STAGE2_DUMPER_SIZE_*

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
1a850392bc zdump/df_s390: Update 'zgetdump -i' output with zlib info
Update verbose 'zgetdump -i' output with zlib info (internal zlib version
and zlib compression unit size).

The following new entriees are to be dispalyed:
	Zlib version.......: 1
	Zlib compression unit: 1 MB

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
14a79eb142 zdump: Increase output buffer from 8 pages to 1 Mb
Increase the auxiliary buffer size from 8 pages to 1 megabyte in order to
significantly increase compressed dump processing speed.
For uncompressed dumps, the effect is minor.

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
271b809495 zdump/dfi_s390: Support reading compressed s390_ext dumps
Update dfi_s390.c to support reading of compressed dump segments.
For this, introduce a callback function for reading memory chunks
associated with compressed dump segments. Apart from the segment location
on disk this function requires the entry_offset array from the dump segment
header in order to process each compressed entry separately, thus allowing
fast seek processing for zgetdump (no need to decompress a big dump segment
to extract a single piece of data).

In addition, split mem_chunks_add_ext() in several functions.

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
2363269c1c zipl/boot: Set the new version in the dumper and in the dump header
Since we are using the existing s390 extended dump format for compressed
dumps as well, set the version of the s390_ext dumper with compression
support and also dump header of the compressed dump to '2' (in order for
zgetdump to distinguish).

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Acked-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
f1db473d11 zipl/boot: Fix progress_print to correctly display 'Dump file size'
- Adjust progress_print() calls to pass updated address after the set of
  blocks has been written to disk.
- Currently total_dump_size value is updated only after the entire dump
  segment is written to disk what leads to ambiguos Dump file size values
  displayed by progress_print(). Change write_addr_range() to re-calculate
  total_dump_size after each set of blocks has been written to disk thus
  printing the correct value at the end of each log entry.
- Avoid final log entry duplication.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Acked-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
e35d05a5e3 zipl/boot: Add print_progress parameter to write_addr_range()
With current implementation, printing progress while writing a compressed
data chunk might be very inaccurate. Thus, for compressed dump segments
skip progress_print() in write_addr_range() and call it after each
compressed memory chunk is written to disk. For that change
write_addr_range() to call progress_print() conditionally based on the new
print_progress parameter.

For non-compressed dump segments, call progress_print() from
write_addr_range() just as before.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Acked-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
c61783546b zipl: Add --no-compress option to zipl command
Add --no-compress option to explicitly omit compression for single-volume
DASD dumper. Used primarily for test purposes.

Since only the lowest byte of mvdump_force field (struct
stage2dump_parm_tail) has been used, split it in two byte fields and use
one for the new no_compress attribute.

Update zipl help and zipl man page with the new parameter info.

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
c08794bdfb zipl/src: Pass stage2dump_parm_tail struct to install_dump_ functions
Move struct stage2dump_parm_tail from stage2dump.h in to
include/dump/s390_dump.h

Pass the entire stage2dump_parm_tail structure to install_dump_* functions
instead of individual parameters.

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
4905975f81 zipl/boot: Adjust Makefile, loaders layout and a linker script
Use a separate linker script eckd2dump_sv.lds for single volume dumper with
compression support.

The new dump tool with zlib compression support now has a size of 8 pages.
Since DASD stand alone dump requires a block size of 4K, we are not
affected by the stage 2 size limitations and can load the dumper to
stage 2 as before. We just need to move the HEAP section for ECKD dumper
in the layout definitions up to 0xb000 address. Also expand the stack by
unused 0x400 bytes.

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
d53bfb9201 zipl/boot: Integrate zlib compression to single volume DASD dumper
Integrate zlib DFLTCC deflate compression to single volume dasd dumper
using the existing s390 extended dump format. Compression takes place
only if DFLTCC facility is available, otherwise dump is written
uncompressed as before.

First megabyte of memory is always written uncompressed and afterwards
this area is used for zlib workspace and for the compression output buffer.
The compression takes place in chunks of data of equal size (currently 1MB)
and the offset of each compressed chunk is stored in the dump segment
header. Since existing dump segment headers of 1 page size are used, we
need to limit the maximum size of compressed dump segments.
Chunk is written uncompressed in case of compression error or if
deflate compression only makes it bigger.

Thus every chunk of data is compressed separately and can be decompressed
independently. The main reason for that is to enable zgetdump to make fast
read seeks. Otherwise, zgetdump would need to decompress a big dump segment
in the worst case to extract a single piece of data.

Put compression related functions and structures to eckd2dump_zlib.c
and eckd2dump_zlib.h

Update zipl man page with the general information of zlib compression
support.

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
0dac47cb62 zipl/boot: Introduce write_addr_range() helper function
Move code from write_dump_segment() to write_addr_range() function to use
it later for writing compressed dump segments as well.

Verify that passed address range is a multiple of dasd block size.

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
7b68552359 zdump: Use global header s390_dump.h
Instead of using its own DF_S390_ constants and df_s390_ structs
in df_s390.h, include those from "dump/s390_dump.h" in order to minimize
duplicates. Adjust the code, where required, to use <stdint> types
instead of those defined in zt_common.h (e.g. use uint64_t instead of u64).

Adjust zdump include statements.

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
775495c7e7 include/dump: Create a global header s390_dump.h
Move common dump related structures and constants to the global header
"dump/s390_dump.h" in order to get rid of many duplicates in zgetdump code.

Adjust zipl include statements and update Copyright statements.

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
1057f13cdc zipl/zlib: Adjust zlib parts for zipl needs
Mainly zlib code remains unchanged for the sake of further maintenance.
Only minor adjustments of zlib deflate parts for build purposes:
- Make is_dfltcc_enabled() always return true
- Define CONFIG_ZLIB_DFLTCC in zlib.h to build zlib code with DFLTCC support
- Remove inflate related prototypes from zlib.h
- Adjust oesc_msg() to use snprintf from libc.h
- Remove BUG_ON from zlib_deflate_workspacesize()
- Replace bitrev32() with bi_reverse() from defutil.h
- Include <assert.h> to dfltcc.h header because of static_assert() calls
- Fix other include statements
- Adjust the text in zipl.h following Zlib License requirements

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>
2023-09-27 18:29:06 +02:00
Mikhail Zaslonko
ce59a299cb zipl/zlib: Copy required zlib_deflate parts
Add required zlib_deflate parts based on kernel zlib code in preparation
to DASD dumper DFLTCC deflate exploitation. Omit inflate modules in
order to minimize the dumper size (no decompression is required for the
dumping).

Adjust include statements leaving other code as is.

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>
2023-09-27 18:29:06 +02:00
Harald Freudenberger
8235e025d4 zcrypt/lszcrypt: Improve lszcrypt output on SE guests
The AP queue states within a SE guest may have a so called asynchronous
error pending. When that's the case, the sysfs read of some AP queue
attributes fails with EIO. lszcrypt was not really prepared for this
and instead showed some incorrect output.

This patch fixes this oddity and now lszcrypt -c shows "error" in case
of ap_bound or ap_associate read errors and lszcrypt -V shows also
"error" if the BS bits could not get fetched.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:06 +02:00
Marc Hartmayer
b301381f90 (genprotimg|zipl)/boot: remove executable bit
The bootloader binaries cannot be executed via `exec()` therefore remove
the executable bit.

Reviewed-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>
2023-09-27 18:29:06 +02:00
Jakub Čajka
c62f930634 osasnmpd: Fix missing semicolon
5.9.4 net-snmp started to require semicolon on the config_require there
are no docs covering this change.

Link: https://bugzilla.redhat.com/show_bug.cgi?id=2235734
Closes: https://github.com/ibm-s390-linux/s390-tools/pull/155
Signed-off-by: Jakub Čajka <jcajka@redhat.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:06 +02:00
Marc Hartmayer
85eb44ac95 lib(ekmfweb|kmipclient): use pkg-config instead of (curl|xml2)-config
`pkg-config` is mandatory for compiling s390-tools anyway therefore
let's replace `curl-config` and `xml2-config` calls whenever possible.
In addition, `pkg-config` has the advantage that cross-compilation is
supported. While at it, use `pkg-config` for libcrypto, json-c, and
libssl as well.

Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:06 +02:00
Steffen Eiden
d5f8063900 rust/README.md: Fix some typos
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:06 +02:00
Steffen Eiden
ee66929465 rust/Makefile: Fix use of Cargoflags for 'make clean'
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-09-27 18:29:06 +02:00
Ingo Franzki
1b044b8a40 zkey: Support EP11 AES keys with prepended header to retain EP11 session
The pkey kernel module supports two key blob formats for EP11 AES keys.
The first one (PKEY_TYPE_EP11) contains a 16 bytes header that overlays
the first 32 bytes of the key blob which usually contain the ID of the
EP11 session to which the key is bound. For zkey/dm-crypt that session
ID used to be all zeros. The second blob format (PKEY_TYPE_EP11_AES)
prepends the 16 bytes header to the blob, an thus does not overlay the
blob. This format can be used for key blobs that are session-bound, i.e.
have a non-zero session ID in the first 32 bytes.

Change zkey to generate EP11 keys using the new format (i.e. pkey type
PKEY_TYPE_EP11_AES), but existing key blobs using the old format can
still be used.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-08-21 17:09:26 +02:00
Jan Höppner
f46f6d34d3 gitignore: Add cpumf/lspai
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-08-21 17:09:26 +02:00
Thomas Richter
3a96e8826f cpumf: Add lspai program and man page to display PAI counter sets
Add lspai program and man page to display Processor Activity
Information (PAI) facility counter sets in the same way as
lscpumf for the CPU Measurement Facility counter sets.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-08-21 17:09:23 +02:00
Mete Durlu
84738668ca hyptop/helper: fix smt utilization calculation
When calculating smt utiliziation field, subresults are capped to a
minimum value of zero to prevent wrap around while converting values
from signed to unsigned integers. The capping of subresults cause slight
inaccuracies therefore capping has been moved from intermediate steps
and done at the end.

Fixes: 0209c11bc1 ("hyptop: Add real SMT utilization field")

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Mete Durlu <meted@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2023-08-21 17:07:44 +02:00
Jan Höppner
dbea311aa8 Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-08-04 14:51:41 +02:00
116 changed files with 6754 additions and 717 deletions

View File

@@ -29,5 +29,5 @@ indent_size = 4
[{Makefile,*.mak}]
indent_style = tab
[COMMIT_EDITMSG]
[{COMMIT_EDITMSG,EDIT_DESCRIPTION}]
max_line_length = 72

1
.gitignore vendored
View File

@@ -32,6 +32,7 @@ cpacfstats/cpacfstatsd
cpumf/chcpumf
cpumf/lscpumf
cpumf/lshwc
cpumf/lspai
cpumf/pai
cpuplugd/cpuplugd
dasdfmt/dasdfmt

5
.shellcheckrc Normal file
View File

@@ -0,0 +1,5 @@
# Search in the current script's directory by default (since 0.7.0)
source-path=SCRIPTDIR
# Allow external-sources (since 0.8.0)
external-sources=true

View File

@@ -27,6 +27,7 @@ List of all individuals having contributed content to s390-tools
- Eberhard Pasch
- Eduard Shishkin
- Einar Lueck
- Eric Farman
- Eric Sandeen
- Erwin Vicari
- Eugene Crosser
@@ -56,6 +57,7 @@ List of all individuals having contributed content to s390-tools
- Horst Hummel
- Ingo Franzki
- Ingo Tuchscherer
- Jakub Čajka
- Jan Glauber
- Jan Höppner
- Jan Willeke
@@ -124,6 +126,7 @@ List of all individuals having contributed content to s390-tools
- Thomas Richter
- Thomas Spatzier
- Thomas Weber
- Thorsten Winkler
- Tuan Hoang
- Ursula Braun
- Utz Bacher

View File

@@ -1,6 +1,33 @@
Release history for s390-tools (MIT version)
--------------------------------------------
* __v2.30.0 (2023-12-01)__
For Linux kernel version: 6.6
Add new tools / libraries:
- lspai: Tool to display PAI counter sets
- s390-tools: Provide a ShellCheck configuration
Changes of existing tools / libraries:
- cpumf/pai: Add command line option for realtime scheduling
- dbginfo.sh: enhance ethtool collection for ROCE
- libutil/util_lockfile: add routine to return owning pid of file lock
- lszcrypt: Improve lszcrypt output on SE guests
- rust: Use a single workspace for all rust tools
- zdev: limit the derivation of ZDEV_SITE_ID
- zdump/df_s390: Update 'zgetdump -i' output with zlib info
- zdump/dfi_s390: Support reading compressed s390_ext dumps
- zipl/boot: Integrate zlib compression to single volume DASD dumper
- zipl/boot: compile the bootloaders only if HOST_ARCH is s390x
- zipl: Add --no-compress option to zipl command
- zkey: Also check for deconfigured and check-stopped cards
Bug Fixes:
- ap_tools/ap-check: handle get-attributes between pre and post event
- libutil: fix util_file_read_*() using wrong format specifiers
- rust/pv: fix Invalid write of size 1
* __v2.29.0 (2023-08-04)__
For Linux kernel version: 6.5

View File

@@ -386,6 +386,24 @@ the different tools are provided:
- Packages: blktrace, multipath-tools, sg3-utils
- Tools: rsync, tar, lsscsi
* zipl
For CCW-type DASD dump, zlib compression can be used to compress the dump
data before writing it to the DASD partition. It can benefit from
s390 on-chip compression accelerator (DFLTCC) and provide a faster dumping
process, hence lower system downtime.
The zlib version integrated with zipl (zipl/boot/zlib) is based on the Linux
kernel zlib (kernel version 6.3) which represents zlib version 1.1.3 with a
limited number of functions and a number of updates on top including s390
hardware compression (DFLTCC) support. Also, all memory allocations are
performed in advance, which aligns with zipl requirements.
The CCW-type standalone dumper is built as a single binary and must be
loaded to stage2 during boot. Hence, all required zlib functions must be
integrated into it, and its size is restricted. To limit the size, only
deflate-related parts are integrated (no decompression is required during
dumping).
Removing the inflate modules and function prototypes are the only major
modifications made to the kernel version of zlib.
* zgetdump
For building zgetdump you need OpenSSL version 1.1.0 or newer
installed (openssl-devel.rpm). Also required is glib2

View File

@@ -798,12 +798,34 @@ static int ap_check_handle_get_attributes(struct ap_check_anchor *anc)
FILE *f;
int rc;
rc = ap_get_lock_callout();
if (rc) {
fprintf(stderr, "Failed to acquire configuration lock %d\n", rc);
return -1;
/*
* For the get-attributes callout, we are typically called without the
* callout lock held. However, there is a particular scenario (define
* of an active mdev) where we may or may not be called with the lock
* already held on behalf of mdevctl, depending on the mdevctl version.
* Let's test for lock ownership first and, if already owned by the
* parent (mdevctl) proceed rather than waiting on the file lock.
*/
rc = ap_try_lock_callout();
switch (rc) {
case 0:
/* Lock acquired */
anc->cleanup_lock = true;
break;
case 1:
/* Lock held by parent -- trust the lock will remain held */
break;
default:
/* Lock not acquired or held by parent -- do a normal obtain */
rc = ap_get_lock_callout();
if (rc) {
fprintf(stderr,
"Failed to acquire configuration lock %d\n",
rc);
return -1;
}
anc->cleanup_lock = true;
}
anc->cleanup_lock = true;
/*
* Read the 'matrix' and 'control_domains' attributes to get the

View File

@@ -32,7 +32,7 @@ endif
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
VERSION = 2
RELEASE = 29
RELEASE = 30
PATCHLEVEL = 0
DISTRELEASE = build-$(shell date +%Y%m%d)
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
@@ -93,19 +93,19 @@ define cmd_define_and_export
endef
define define_toolchain_variables
$(eval $(call cmd_define_and_export, AS$(1)," AS$(1) ",$(2)as))
$(eval $(call cmd_define_and_export, CC$(1)," CC$(1) ",$(2)gcc))
$(eval $(call cmd_define_and_export, LINK$(1)," LINK$(1) ",$$(CC$(1))))
$(eval $(call cmd_define_and_export, CXX$(1)," CXX$(1) ",$(2)g++))
$(eval $(call cmd_define_and_export, LINKXX$(1)," LINKXX$(1) ",$$(CXX$(1))))
$(eval $(call cmd_define_and_export, CPP$(1)," CPP$(1) ",$(2)gcc -E))
$(eval $(call cmd_define_and_export, AR$(1)," AR$(1) ",$(2)ar))
$(eval $(call cmd_define_and_export, NM$(1)," NM$(1) ",$(2)nm))
$(eval $(call cmd_define_and_export, STRIP$(1)," STRIP$(1) ",$(2)strip))
$(eval $(call cmd_define_and_export,OBJCOPY$(1)," OBJCOPY$(1) ",$(2)objcopy))
$(eval $(call cmd_define_and_export,OBJDUMP$(1)," OBJDUMP$(1) ",$(2)objdump))
$(eval PKG_CONFIG$(1) = pkg-config)
$(eval export PKG_CONFIG$(1))
$(call cmd_define_and_export, AS$(1)," AS$(1) ",$(2)as)
$(call cmd_define_and_export, CC$(1)," CC$(1) ",$(2)gcc)
$(call cmd_define_and_export, LINK$(1)," LINK$(1) ",$$(CC$(1)))
$(call cmd_define_and_export, CXX$(1)," CXX$(1) ",$(2)g++)
$(call cmd_define_and_export, LINKXX$(1)," LINKXX$(1) ",$$(CXX$(1)))
$(call cmd_define_and_export, CPP$(1)," CPP$(1) ",$(2)gcc -E)
$(call cmd_define_and_export, AR$(1)," AR$(1) ",$(2)ar)
$(call cmd_define_and_export, NM$(1)," NM$(1) ",$(2)nm)
$(call cmd_define_and_export, STRIP$(1)," STRIP$(1) ",$(2)strip)
$(call cmd_define_and_export,OBJCOPY$(1)," OBJCOPY$(1) ",$(2)objcopy)
$(call cmd_define_and_export,OBJDUMP$(1)," OBJDUMP$(1) ",$(2)objdump)
PKG_CONFIG$(1) = pkg-config
export PKG_CONFIG$(1)
endef
# If the host architecture is not the same as the build architecture
@@ -119,8 +119,8 @@ ifneq ($(HOST_ARCH),$(BUILD_ARCH))
endif
endif
$(call define_toolchain_variables,_FOR_BUILD,)
$(call define_toolchain_variables,,$(CROSS_COMPILE))
$(eval $(call define_toolchain_variables,_FOR_BUILD,))
$(eval $(call define_toolchain_variables,,$(CROSS_COMPILE)))
$(eval $(call cmd_define, RUNTEST," RUNTEST ",$(S390_TEST_LIB_PATH)/s390_runtest))

View File

@@ -1,7 +1,7 @@
include ../common.mak
BIN_FILES = lscpumf chcpumf lshwc pai
MAN_FILES = lscpumf.8 chcpumf.8 lshwc.8 pai.8
BIN_FILES = lscpumf chcpumf lshwc pai lspai
MAN_FILES = lscpumf.8 chcpumf.8 lshwc.8 pai.8 lspai.8
all: $(BIN_FILES)
@@ -11,6 +11,7 @@ lscpumf: lscpumf.o $(libs)
chcpumf: chcpumf.o $(libs)
lshwc: lshwc.o $(libs)
pai: pai.o $(libs)
lspai: lspai.o $(libs)
install: all install-man
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man8

352
cpumf/lspai.c Normal file
View File

@@ -0,0 +1,352 @@
/* Copyright IBM Corp. 2023
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
/* List available Processor Assist Instrumentation (PAI) counters. */
#include <ctype.h>
#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "lib/util_opt.h"
#include "lib/util_prg.h"
#include "lib/util_base.h"
#include "lib/util_path.h"
#include "lib/util_scandir.h"
#include "lib/util_libc.h"
#include "lib/util_file.h"
#include "lib/util_list.h"
#include "lib/libcpumf.h"
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("OPTIONS"),
{
.option = { "numeric", no_argument, NULL, 'n' },
.desc = "Sort PAI counters by counter number"
},
{
.option = { "type", required_argument, NULL, 't' },
.argument = "TYPE",
.desc = "Type of PAI counters to show: crypto, nnpa"
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
static const struct util_prg prg = {
.desc = "List Processor Assist Information counter sets",
.copyright_vec = {
{
.owner = "IBM Corp.",
.pub_first = 2023,
.pub_last = 2023,
},
UTIL_PRG_COPYRIGHT_END
}
};
static bool numsort; /* If true sort counter numerically */
#define PAI_PATH "/bus/event_source/devices/%s"
enum pai_types { /* Bit mask for supported PAI counters */
pai_type_crypto = 0, /* PAI Crypto Counters */
pai_type_nnpa = 1, /* PAI NNPA Counters */
pai_type_max = 2, /* PAI maximum value, must be last */
};
static int pai_types_show;
struct pai_ctrname { /* List of defined counters */
char *name; /* Counter name */
unsigned long nr; /* Counter number */
};
struct pai_node { /* Head for PAI counter sets */
struct util_list_node node; /* Successor in PAI counter set list */
enum pai_types type; /* PAI type */
int pmu; /* Assigned PMU type number */
const char *name; /* Counter set name */
char *name_uc; /* Counter set name upper case */
const char *sysfs_name; /* Counter set name in /sysfs tree */
const char *filter_name; /* Counter set name for scandir filter */
struct pai_ctrname *ctrlist; /* List of counter names & numbers */
size_t ctrsize; /* Total size in bytes of ctrlist */
int ctridx; /* Index of last entry used in ctrlist */
unsigned long base; /* Base number for counter set */
};
static struct util_list pai_list;
/* Return base of counter set, this is the first counter of this set. */
static unsigned long pai_type_base(enum pai_types t)
{
switch (t) {
case pai_type_crypto:
return 0x1000;
case pai_type_nnpa:
return 0x1800;
case pai_type_max:
break;
}
return 0;
}
/* Test PAI counter name from command line option. */
static const char *pai_type_name(enum pai_types t)
{
switch (t) {
case pai_type_crypto:
return "crypto";
case pai_type_nnpa:
return "nnpa";
case pai_type_max:
break;
}
return "unknown";
}
/* Convert PAI counter type to sysfs directory name. Only validated
* input at this time.
*/
static const char *pai_type_sysfs(enum pai_types t)
{
if (t == pai_type_crypto)
return "pai_crypto";
return "pai_ext";
}
/* Convert PAI counter type to sysfs directory name filter for scandir(). */
static const char *pai_type_filter(enum pai_types t)
{
if (t == pai_type_nnpa)
return "^NNPA";
return "[^.]"; /* Matches anything but . and .. in sysfs */
}
/* Sort PAI counter names by assigned counter number. */
static int pai_ctrcmp(const void *p1, const void *p2)
{
struct pai_ctrname *l = (struct pai_ctrname *)p1;
struct pai_ctrname *r = (struct pai_ctrname *)p2;
return l->nr > r->nr ? 1 : -1;
}
/* Convert string to upper case. */
static char *str2uc(const char *s)
{
char *uc = util_strdup(s), *old_uc = uc;
for (; *uc; ++uc)
*uc = toupper(*uc);
return old_uc;
}
/* Read counter names and assigned event number from sysfs file tree.
* Exit when sysfs directory can not be scanned.
*/
static void read_counternames(struct pai_node *node)
{
int i, more = 0, ctr = 0, count = 0;
struct dirent **namelist = NULL;
char *path, *ctrpath;
/* Read counter names and assigned event number. */
path = util_path_sysfs(PAI_PATH "/events", node->sysfs_name);
count = util_scandir(&namelist, alphasort, path, node->filter_name);
if (count <= 0)
errx(EXIT_FAILURE, "Cannot open %s", path);
node->ctrsize = count * sizeof(*node->ctrlist);
node->ctrlist = util_malloc(node->ctrsize);
for (i = 0; i < count && ctr >= 0; i++) {
util_asprintf(&ctrpath, "%s/%s", path, namelist[i]->d_name);
if (util_file_read_va(ctrpath, "event=%x", &ctr) == 1) {
node->ctrlist[node->ctridx].name = util_strdup(namelist[i]->d_name);
node->ctrlist[node->ctridx++].nr = ctr;
more++;
} else {
warnx("Cannot parse %s", ctrpath);
}
free(ctrpath);
}
util_scandir_free(namelist, count);
free(path);
if (numsort && more > 1)
qsort(node->ctrlist, more, sizeof(*node->ctrlist), pai_ctrcmp);
}
static void show_painode(void)
{
struct pai_node *node;
int indent = 0;
int offset = 0;
util_list_iterate(&pai_list, node) {
for (int i = 0; i < node->ctridx; ++i)
indent = MAX((size_t)indent, strlen(node->ctrlist[i].name));
}
printf("RAW %*s NAME %*s DESCRIPTION\n", 3, "", indent - 5, "");
util_list_iterate(&pai_list, node) {
for (int i = 0; i < node->ctridx; ++i) {
printf("%d:%ld %s", node->pmu,
node->ctrlist[i].nr, node->ctrlist[i].name);
offset = indent - strlen(node->ctrlist[i].name) + 1;
printf("%*s", offset, "");
printf("Counter %ld / PAI %s counter set\n",
node->ctrlist[i].nr - node->base, node->name_uc);
}
}
}
/* Release all memory allocated at make_painode(). */
static void free_painode(void)
{
struct pai_node *next, *node;
util_list_iterate_safe(&pai_list, node, next) {
free(node->name_uc);
for (int i = 0; i < node->ctridx; ++i)
free(node->ctrlist[i].name);
free(node->ctrlist);
free(node);
}
}
static void make_painode(enum pai_types t)
{
struct pai_node *node = util_zalloc(sizeof(*node));
char *path;
node->type = t;
node->sysfs_name = pai_type_sysfs(t);
node->name = pai_type_name(t);
node->name_uc = str2uc(node->name);
node->filter_name = pai_type_filter(t);
node->base = pai_type_base(t);
/* Read PMU type number. */
path = util_path_sysfs(PAI_PATH, node->sysfs_name);
node->pmu = libcpumf_pmutype(path);
if (node->pmu < 0)
errx(EXIT_FAILURE, "Cannot open %s", path);
free(path);
read_counternames(node);
util_list_add_tail(&pai_list, node);
}
static int painode_cmp(void *a, void *b, void *UNUSED(data))
{
struct pai_node *n1 = (struct pai_node *)a;
struct pai_node *n2 = (struct pai_node *)b;
return n1->pmu < n2->pmu ? -1 : 1;
}
static void sort_painode(void)
{
util_list_sort(&pai_list, painode_cmp, NULL);
}
/* Check for hardware support and return false if not available. */
static bool have_support(enum pai_types t)
{
const char *sysfn = pai_type_sysfs(t);
char *path = util_path_sysfs(PAI_PATH, sysfn);
bool rc = true;
if (!util_path_is_dir(path)) {
warnx("No support for PAI %s facility", pai_type_name(t));
rc = false;
}
free(path);
return rc;
}
/*
* Check the argument for option -t. It must be a valid PAI counter set.
* Exit when an invalid PAI counter set name has been specified.
*/
static void check_type_name(const char *type)
{
bool no_match = true;
enum pai_types i;
const char *fn;
for (i = pai_type_crypto; i < pai_type_max; ++i) {
fn = pai_type_name(i);
if (!strcasecmp(fn, type)) {
pai_types_show |= (1 << i);
no_match = false;
}
}
if (no_match)
errx(EXIT_FAILURE, "Invalid argument for -t %s", type);
}
int main(int argc, char **argv)
{
int ch;
util_list_init(&pai_list, struct pai_node, node);
util_prg_init(&prg);
util_opt_init(opt_vec, NULL);
while ((ch = util_opt_getopt_long(argc, argv)) != -1) {
switch (ch) {
default:
util_opt_print_parse_error(ch, argv);
return EXIT_FAILURE;
case 'h':
util_prg_print_help();
util_opt_print_help();
return EXIT_SUCCESS;
case 'v':
util_prg_print_version();
return EXIT_SUCCESS;
case 'n':
numsort = true;
break;
case 't':
check_type_name(optarg);
break;
}
}
/* Nothing specified, show all PAI counters */
if (!pai_types_show)
pai_types_show = (1 << pai_type_crypto) | (1 << pai_type_nnpa);
/* Check for hardware support */
for (enum pai_types i = pai_type_crypto; i < pai_type_max; ++i) {
if ((pai_types_show & (1 << i))) {
if (!have_support(i))
pai_types_show &= ~(1 << i);
else
make_painode(i);
}
}
sort_painode();
show_painode();
free_painode();
return ch;
}

80
cpumf/man/lspai.8 Normal file
View File

@@ -0,0 +1,80 @@
.\" lspai.8
.\"
.\"
.\" Copyright IBM Corp. 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.
.\" ----------------------------------------------------------------------
.ds c \fBlspai\fP
.
.TH \*c "8" "August 2023" "s390-tools" "CPU-MF management programs"
.
.SH NAME
\*c \- list Processor Activity Instrumentation (PAI) counters
.
.SH SYNOPSIS
\*c
.RB [ \-n ]
.RB [ \-t
.IR "\ TYPE" ]
.br
\*c
.BR \-h | \-\-help
.br
\*c
.BR \-v | \-\-version
.
.
.SH DESCRIPTION
\*c displays the Processor Activity Instrumentation (PAI) counters
for Linux on IBM Z.
The output is a human-readable list of available PAI counter
names and numbers.
.SH OPTIONS
.TP
.BR \-h ", " \-\-help
Displays help information, then exits.
.
.TP
.BR \-v ", " \-\-version
Displays version information, then exits.
.
.TP
.BR \-t ", " \-\-type "\ TYPE"
Specifies the PAI counter set to list.
Valid counter set values are
.I crypto
and
.IR nnpa .
By default, the command lists all available PAI counter sets.
NNPA refers to the Neural Network Processing Assist facility counter set.
Crypto refers to the Cryptografic Processing Assist facility counter set.
.
.TP
.BR \-n ", " \-\-numeric
Shows the PAI counter sets sorted by counter number.
Default sort order is PAI counter name.
.
.SH "EXAMPLE"
The \*c invocation lists all PAI Neural Network Processing Assist Facility
(NNPA) counters in numeric order:
.nf
# lspai -t nnpa -n
RAW NAME DESCRIPTION
13:6144 NNPA_ALL Counter 0 / PAI NNPA counter set
13:6145 NNPA_ADD Counter 1 / PAI NNPA counter set
13:6146 NNPA_SUB Counter 2 / PAI NNPA counter set
13:6147 NNPA_MUL Counter 3 / PAI NNPA counter set
\&...
.fi
The first column shows the raw event number suitable for
.IR perf "(8)"
raw event specification.
The second column shows the PAI NNPA counter name,
suitable for
.IR perf "(8)"
event specification by name.
The third gives a short explanation, if available.
.SH "SEE ALSO"
.BR pai (8)
.BR lscpumf (8)

View File

@@ -18,6 +18,8 @@
.IR size ]
.RB [ \-i | \-\-interval
.IR ms ]
.RB [ \-R | \-\-realtime
.IR prio ]
.BR \-c | \-\-crypto [ \fIcpulist ][: \fIdata\fR "] [" \fIloops\fP ]
.br
\*c
@@ -25,6 +27,8 @@
.IR size ]
.RB [ \-i | \-\-interval
.IR ms ]
.RB [ \-R | \-\-realtime
.IR prio ]
.BR \-n | \-\-nnpa [ \fIcpulist ][: \fIdata\fR "] [" \fIloops\fP ]
.br
\*c
@@ -191,6 +195,14 @@ The ring buffer is created with the
.IR mmap (2)
system call.
.
.TP
.BR \-R ", " \-\-realtime "\ prio"
Collect data using the RT SCHED_FIFO priority specified by
.BR prio .
Valid values are integers in the range 1 (low) to 99 (high).
Use this option when gathering data from multiple CPUs
to prevent data loss.
.
.SH ARGUMENT
The command line options determine how command line
arguments are interpreted.

View File

@@ -944,6 +944,11 @@ static struct util_opt opt_vec[] = {
.option = { "report", no_argument, NULL, 'r' },
.desc = "Report file contents"
},
{
.option = { "realtime", required_argument, NULL, 'R' },
.argument = "PRIO",
.desc = "Collect data with this RT SCHED_FIFO priority"
},
{
.option = { "interval", required_argument, NULL, 'i' },
.argument = "NUMBER",
@@ -1007,6 +1012,19 @@ static unsigned long check_mapsize(unsigned long n)
return cnt == 1 ? n : 0;
}
static void setprio(const char *prio)
{
struct sched_param param;
char *endstr;
memset(&param, 0, sizeof(param));
param.sched_priority = strtoul(prio, &endstr, 0);
if (*endstr)
errno = EINVAL;
if (*endstr || sched_setscheduler(0, SCHED_FIFO, &param))
err(EXIT_FAILURE, "Could not set realtime priority");
}
int main(int argc, char **argv)
{
bool crypto_record = false, report = false;
@@ -1061,6 +1079,9 @@ int main(int argc, char **argv)
record_cpus_nnpa(optarg);
nnpa_record = true;
break;
case 'R':
setprio(optarg);
break;
case 'r':
report = true;
break;

View File

@@ -15,13 +15,13 @@ dasdfmt \- formatting of DASD (ECKD) disk drives.
.SH DESCRIPTION
\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
for usage with Linux for S/390.
for usage with Linux for S/390.
The \fIdevice\fR is the node of the device (e.g. '/dev/dasda').
Any device node created by udev for kernel 2.6 can be used
Any device node created by udev for kernel 2.6 can be used
(e.g. '/dev/dasd/0.0.b100/disc').
.br
\fBWARNING\fR: Careless usage of \fBdasdfmt\fR can result in
\fBWARNING\fR: Careless usage of \fBdasdfmt\fR can result in
\fBLOSS OF DATA\fR.
.SH OPTIONS
@@ -31,7 +31,7 @@ Print usage and exit.
.TP
\fB-t\fR or \fB--test\fR
Disables any modification of the disk drive.
Disables any modification of the disk drive.
.br
\fBdasdfmt\fR just prints
out, what it \fBwould\fR do.
@@ -41,7 +41,7 @@ out, what it \fBwould\fR do.
Increases verbosity.
.TP
\fB-y\fR
\fB-y\fR
Start formatting without further user-confirmation.
.TP
@@ -59,7 +59,7 @@ Omit the writing of a disk label after formatting.
.br
This makes only sense for the 'ldl' disk layout.
.br
The '-L' option has to be specified after the '-d ldl' option.
The '-L' option has to be specified after the '-d ldl' option.
.br
e.g. dasdfmt -d ldl -L /dev/...
@@ -84,13 +84,13 @@ Formats the device with compatible disk layout or linux disk layout.
\fIlayout\fR is either \fIcdl\fR for the compatible disk layout
(default) or \fIldl\fR for the linux disk layout.
.br
Compatible disk layout means a special handling of the
first two tracks of the volume. This enables other S/390 or zSeries
Compatible disk layout means a special handling of the
first two tracks of the volume. This enables other S/390 or zSeries
operating systems to access this device (e.g. for backup purposes).
.TP
\fB-p\fR or \fB--progressbar\fR
Print a progress bar while formatting.
Print a progress bar while formatting.
Do not use this option if you are using a 3270 console,
running in background or redirecting the output to a file.
@@ -164,30 +164,30 @@ and always be a power of two. The recommended blocksize is 4096 bytes.
.TP
\fB-l\fR \fIvolser\fR or \fB--label\fR=\fIvolser\fR
Specify the volume serial number or volume identifier to be written
to disk after formatting. If no label is specified, a sensible default
is used. \fIvolser\fR is interpreted as ASCII string and is automatically
Specify the volume serial number or volume identifier to be written
to disk after formatting. If no label is specified, a sensible default
is used. \fIvolser\fR is interpreted as ASCII string and is automatically
converted to uppercase and then to EBCDIC.
.br
e.g. -l LNX001 or --label=DASD01
.br
The \fIvolser\fR identifies by serial number the volume. A volume serial
The \fIvolser\fR identifies by serial number the volume. A volume serial
number is 1 through 6 alphanumeric or one of the following special
characters: $, #, @, %. Enclose a serial number that contains special
characters in apostrophes. If the number is shorter than six
characters: $, #, @, %. Enclose a serial number that contains special
characters in apostrophes. If the number is shorter than six
characters, it is padded with trailing blanks.
.br
.br
Do not code a volume serial number as SCRTCH, PRIVAT, or Lnnnnn (L with
five numbers); these are used in OS/390 messages to ask the operator to
mount a volume. Do not code a volume serial number as MIGRAT, which is
used by the OS/390 Hierarchical Storage Manager DFSMShsm for migrated
Do not code a volume serial number as SCRTCH, PRIVAT, or Lnnnnn (L with
five numbers); these are used in OS/390 messages to ask the operator to
mount a volume. Do not code a volume serial number as MIGRAT, which is
used by the OS/390 Hierarchical Storage Manager DFSMShsm for migrated
data sets.
.br
NOTE: Try to avoid using special characters in the volume serial. This may cause problems accessing a disk by volser.
NOTE: Try to avoid using special characters in the volume serial. This may cause problems accessing a disk by volser.
.br
In case you really have to use special characters, make sure you are using quotes. In addition there is a special handling for the '$' sign. Please specify it using '\\$' if necessary.
.br
@@ -197,9 +197,8 @@ e.g. -l 'a@b\\$c#' to get A@B$C#
.TP
\fB-k\fR or \fB--keep_volser\fR
Keeps the Volume Serial Number, when writing the Volume Label. This is
useful, if the Serial Number has been written with a VM Tool and should not
be overwritten.
Keeps the Volume Serial Number when writing the Volume Label. This is useful if
the volume already has a Serial Number that should not be overwritten.
.br
.SH SEE ALSO

View File

@@ -19,10 +19,10 @@ help:
.br
\fBfdasd\fR {-h|-v}
.SH DESCRIPTION
\fBfdasd\fR writes a partition table to a cdl (compatible disk layout)
\fBfdasd\fR writes a partition table to a cdl (compatible disk layout)
formatted DASD, in the form of
a VTOC (volume table of contents) for usage with Linux for S/390
or zSeries. If fdasd detects a valid \fBVOL1\fR volume label, it
or zSeries. If fdasd detects a valid \fBVOL1\fR volume label, it
will use it, otherwise it asks to write a new one.
.br
@@ -34,51 +34,51 @@ will use it, otherwise it asks to write a new one.
Print usage information, then exit.
.TP
\fB-v\fR or \fB--version\fR
\fB-v\fR or \fB--version\fR
Print version information, then exit.
.TP
\fB-s\fR or \fB--silent\fR
\fB-s\fR or \fB--silent\fR
Suppress messages in non-interactive mode.
.TP
\fB-r\fR or \fB--verbose\fR
\fB-r\fR or \fB--verbose\fR
Provide more verbose output.
.TP
\fB-a\fR or \fB--auto\fR
Automatically create a partition using the entire disk in non-interactive
\fB-a\fR or \fB--auto\fR
Automatically create a partition using the entire disk in non-interactive
mode.
.TP
\fB-k\fR or \fB--keep_volser\fR
Keeps the volume serial when writing the volume label.
Keeps the Volume Serial Number when writing the Volume Label.
.br
This is useful, if the volume serial has been written before and should not
be overwritten. This option is only applicable in non-interactive mode.
This is useful if the volume already has a Serial Number that should not be
overwritten. This option is only applicable in non-interactive mode.
.TP
\fB-l\fR \fIvolser\fR or \fB--label\fR \fIvolser\fR
Specify the volume serial.
.br
\fIvolser\fR is interpreted as ASCII string and is automatically converted to
\fIvolser\fR is interpreted as ASCII string and is automatically converted to
uppercase, padded with blanks and finally converted to EBCDIC to be written
to disk. This option is only applicable in non-interactive mode.
.br
Do not use the following reserved volume serial: SCRTCH, PRIVAT, MIGRAT,
or Lnnnnn (L with five digit number); These are used as keywords by
Do not use the following reserved volume serial: SCRTCH, PRIVAT, MIGRAT,
or Lnnnnn (L with five digit number); These are used as keywords by
other operating systems (OS/390).
.br
A volume serial is 1 through 6 alphanumeric characters or one of the
following special characters: $, #, @, %. All other characters are simply
ignored.
A volume serial is 1 through 6 alphanumeric characters or one of the
following special characters: $, #, @, %. All other characters are simply
ignored.
.br
Try to avoid using special characters in the volume serial.
This may cause problems accessing a disk by volser.
In case you really have to use special characters, make sure you are using
quotes. In addition there is a special handling for the '$' sign.
Try to avoid using special characters in the volume serial.
This may cause problems accessing a disk by volser.
In case you really have to use special characters, make sure you are using
quotes. In addition there is a special handling for the '$' sign.
Please specify it using '\\$' if necessary.
.br
@@ -124,14 +124,14 @@ partitions that use the entire disk:
.br
.TP
\fB-i\fR or \fB--volser\fR
\fB-i\fR or \fB--volser\fR
Print the volume serial, then exit.
.TP
\fB-p\fR or \fB--table\fR
Print partition table, then exit.
\fB-p\fR or \fB--table\fR
Print partition table, then exit.
.br
In combination with the -s option fdasd will display a short version of the
In combination with the -s option fdasd will display a short version of the
partition table.
.TP
@@ -179,7 +179,7 @@ In case your are not using the device file system, please specify:
.br
where \fIx\fR is one or more lowercase letter(s) or any other device
node specification configured by udev for kernel 2.6 or higher.
node specification configured by udev for kernel 2.6 or higher.
.SH SEE ALSO
.BR dasdfmt (8)

View File

@@ -79,6 +79,7 @@ stage3b.elf: head.o $(ZIPL_OBJS)
%.bin.debug: %.elf
$(OBJCOPY) --only-keep-debug $< $@
@chmod a-x $@
%.bin: %.elf
$(OBJCOPY) -O binary $< $@

View File

@@ -61,13 +61,17 @@ void __noreturn start(void)
if (cmdline->size > get_kernel_cmdline_size())
panic(EINTERNAL, "Command line is too large\n");
/* move the kernel cmdline */
memmove((void *)COMMAND_LINE,
(void *)cmdline->src,
cmdline->size);
if (cmdline->size > 0) {
/* make sure the cmdline is a null-terminated string */
if (((char *)cmdline->src)[cmdline->size - 1] != '\0')
panic(EINTERNAL, "Command line needs to be null-terminated\n");
/* move the kernel cmdline */
memmove((void *)COMMAND_LINE, (void *)cmdline->src, cmdline->size);
}
/* the initrd does not need to be moved */
if (initrd->size != 0) {
if (initrd->size > 0) {
/* copy initrd start address and size into new kernel space */
*(unsigned long long *)INITRD_START = initrd->src;
*(unsigned long long *)INITRD_SIZE = initrd->size;

View File

@@ -684,7 +684,26 @@ gint pv_img_add_component(PvImage *img, const PvArg *arg, GError **err)
{
g_autoptr(PvComponent) comp = NULL;
comp = pv_component_new_file(arg->type, arg->path, err);
switch (arg->type) {
case PV_COMP_TYPE_INITRD:
case PV_COMP_TYPE_KERNEL:
case PV_COMP_TYPE_STAGE3B:
comp = pv_component_new_file(arg->type, arg->path, err);
break;
case PV_COMP_TYPE_CMDLINE: {
g_autoptr(PvBuffer) buf = NULL;
g_autofree char *data = NULL;
gsize length;
if (!g_file_get_contents(arg->path, &data, &length, err))
return -1;
/* Add one for the null terminator */
buf = pv_buffer_take(g_steal_pointer(&data), length + 1);
comp = pv_component_new_buf(arg->type, buf, err);
} break;
}
if (!comp)
return -1;

View File

@@ -26,6 +26,15 @@ PvBuffer *pv_buffer_alloc(gsize size)
return ret;
}
PvBuffer *pv_buffer_take(char *data, gsize size)
{
PvBuffer *ret = g_new0(PvBuffer, 1);
ret->data = data;
ret->size = size;
return ret;
}
PvBuffer *pv_buffer_dup(const PvBuffer *buf, gboolean page_aligned)
{
PvBuffer *ret;

View File

@@ -21,6 +21,10 @@ typedef struct PvBuffer {
} PvBuffer;
PvBuffer *pv_buffer_alloc(gsize size);
/* After this call @data belongs to the PvBuffer and must no longer be modified
* by the caller.
*/
PvBuffer *pv_buffer_take(char *data, gsize size);
void pv_buffer_free(PvBuffer *buf);
void pv_buffer_clear(PvBuffer **buf);
gint pv_buffer_write(const PvBuffer *buf, FILE *file, GError **err);

View File

@@ -404,11 +404,11 @@ s64 ht_calculate_smt_util(u64 core_us, u64 thr_us, u64 mgm_us, int thread_per_co
s64 component1, component2, smt_us;
double smt_factor = g.o.smt_factor;
component1 = G0(thread_per_core * core_us - thr_us);
component1 = thread_per_core * core_us - thr_us;
if (thread_per_core > 1)
component1 /= smt_factor;
component2 = G0(thr_us - core_us);
smt_us = component1 + component2 + mgm_us;
component2 = thr_us - core_us;
smt_us = G0(component1 + component2 + mgm_us);
return smt_us;
}

View File

@@ -22,11 +22,19 @@
#define STAGE2_DESC _AC(0x78, UL)
#define STAGE2_ENTRY _AC(0x2018, UL)
#define STAGE2_HEAP_ADDRESS _AC(0x6000, UL)
#define ECKD2DUMP_SV_HEAP_ADDRESS _AC(0xb000, UL)
#define STAGE2_HEAP_SIZE _AC(0x3000, UL)
#define STAGE2_STACK_ADDRESS _AC(0xe400, UL)
#define STAGE2_STACK_SIZE _AC(0x1c00, UL)
#define ECKD2DUMP_SV_STACK_ADDRESS _AC(0xe000, UL)
#define ECKD2DUMP_SV_STACK_SIZE _AC(0x2000, UL)
#define STAGE2_MAX_SIZE _AC(0x3000, UL)
#define STAGE2_DUMPER_SIZE_V1 _AC(0x1000, UL)
#define STAGE2_DUMPER_SIZE_V2 _AC(0x2000, UL)
#define STAGE2_DUMPER_SIZE_V3 _AC(0x3000, UL)
#define STAGE2_DUMPER_SIZE_ZLIB _AC(0x8000, UL)
#define STAGE3_ENTRY _AC(0xa000, UL)
#define STAGE2_LOAD_ADDRESS _AC(0x2000, UL)

View File

@@ -25,6 +25,7 @@
#define STACK_FRAME_OVERHEAD _AC(160, U)
/* Facilities */
#define DFLTCC_FACILITY _AC(151, U)
#define UNPACK_FACILITY _AC(161, U)
#ifndef __ASSEMBLER__

134
include/dump/s390_dump.h Normal file
View File

@@ -0,0 +1,134 @@
/*
* s390 related definitions and functions.
*
* Copyright IBM Corp. 2013, 2023
*
* 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 S390_DUMP_H
#define S390_DUMP_H
#include <stdint.h>
#include "boot/page.h"
#include "lib/zt_common.h"
/*
* S390 dump format defines
*/
#define DF_S390_MAGIC 0xa8190173618f23fdULL
#define DF_S390_MAGIC_EXT 0xa8190173618f23feULL
#define DF_S390_HDR_SIZE 0x1000
#define DF_S390_EM_SIZE 16
#define DF_S390_EM_MAGIC 0x44554d505f454e44ULL
#define DF_S390_EM_STR "DUMP_END"
#define DF_S390_CPU_MAX 512
#define DF_S390_MAGIC_BLK_ECKD 3
/*
* Architecture of dumped system
*/
enum df_s390_arch {
DF_S390_ARCH_32 = 1,
DF_S390_ARCH_64 = 2,
};
/*
* zipl parameters passed at tail of dump tools
*/
struct stage2dump_parm_tail {
char reserved[6];
uint8_t no_compress;
uint8_t mvdump_force;
uint64_t mem_upper_limit;
} __packed;
/*
* s390 dump header format
*/
struct df_s390_hdr {
uint64_t magic; /* 0x000 */
uint32_t version; /* 0x008 */
uint32_t hdr_size; /* 0x00c */
uint32_t dump_level; /* 0x010 */
uint32_t page_size; /* 0x014 */
uint64_t mem_size; /* 0x018 */
uint64_t mem_start; /* 0x020 */
uint64_t mem_end; /* 0x028 */
uint32_t num_pages; /* 0x030 */
uint32_t pad; /* 0x034 */
uint64_t tod; /* 0x038 */
uint64_t cpu_id; /* 0x040 */
uint32_t arch; /* 0x048 */
uint32_t volnr; /* 0x04c */
uint32_t build_arch; /* 0x050 */
uint64_t mem_size_real; /* 0x054 */
uint8_t mvdump; /* 0x05c */
uint16_t cpu_cnt; /* 0x05d */
uint16_t real_cpu_cnt; /* 0x05f */
uint8_t zlib_version_s390; /* 0x061 */
uint32_t zlib_entry_size; /* 0x062 */
uint8_t end_pad1[0x200 - 0x066]; /* 0x066 */
uint64_t mvdump_sign; /* 0x200 */
uint64_t mvdump_zipl_time; /* 0x208 */
uint8_t end_pad2[0x800 - 0x210]; /* 0x210 */
uint32_t lc_vec[DF_S390_CPU_MAX]; /* 0x800 */
} __packed __aligned(16);
/*
* End marker: Should be at the end of every valid s390 crash dump
*/
struct df_s390_em {
union {
uint64_t magic;
char str[8];
};
uint64_t tod;
} __packed __aligned(16);
/*
* Dump segment header
*/
struct df_s390_dump_segm_hdr {
union {
struct {
uint64_t start; /* 0x000 */
uint64_t len; /* 0x008 */
uint64_t stop_marker; /* 0x010 */
/* Size in blocks of compressed dump segment written to disk */
uint32_t size_on_disk; /* 0x018 */
uint8_t reserved_pad[0x30 - 0x1c]; /* 0x01c */
/*
* Number of compressed entries in this dump segment (up to
* 1011 entries)
*/
uint32_t entry_count; /* 0x030 */
/*
* Offsets in blocks to compressed entries written to disk
* from the start of the dump segment.
* High-order bit is set if the entry has been written
* uncompressed.
*/
uint32_t entry_offset[]; /* 0x034 */
} __packed;
uint8_t padding[PAGE_SIZE];
};
};
/* Data compression granularity (size of input data chunk for zlib deflate) */
#define DUMP_SEGM_ZLIB_ENTSIZE (1 * MIB)
/* Maximum number of compressed entries in one dump segment */
#define DUMP_SEGM_ZLIB_MAXENTS ((sizeof(struct df_s390_dump_segm_hdr) \
- offsetof(struct df_s390_dump_segm_hdr, entry_offset)) \
/ sizeof(uint32_t))
/*
* Maximum length of compressed dump segment considering the size of
* a single input chunk
*/
#define DUMP_SEGM_ZLIB_MAXLEN (DUMP_SEGM_ZLIB_MAXENTS * DUMP_SEGM_ZLIB_ENTSIZE)
/* Bitmask to mark uncompressed chunks */
#define DUMP_SEGM_ENTRY_UNCOMPRESSED 0x80000000
#endif /* S390_DUMP_H */

View File

@@ -89,6 +89,7 @@ void ap_list_remove_all(struct util_list *list);
/* Lock Functions */
int ap_get_lock(void);
int ap_get_lock_callout(void);
int ap_try_lock_callout(void);
int ap_release_lock(void);
int ap_release_lock_callout(void);

View File

@@ -23,4 +23,6 @@ int util_lockfile_parent_lock(char *lockfile, int retries);
int util_lockfile_release(char *lockfile);
int util_lockfile_parent_release(char *lockfile);
int util_lockfile_peek_owner(char *lockfile, int *pid);
#endif /** LIB_UTIL_LOCKFILE_H @} */

View File

@@ -722,6 +722,34 @@ int ap_get_lock_callout(void)
return util_lockfile_parent_lock(AP_LOCKFILE, AP_LOCK_RETRIES);
}
/**
* Attempt to acquire the ap config lock using the Parent Process ID without
* waiting/retries. Detect if the attempt was rejected because the lock is
* already held by the Parent Process ID.
*
* @retval 0 Lock acquired on behalf of parent process
* @retval 1 Lock not obtained, already held by parent
* @retval != 0 Lock was not obtained, other error
*/
int ap_try_lock_callout(void)
{
int pid, ppid, rc;
if (util_lockfile_parent_lock(AP_LOCKFILE, 0)) {
/* Lock is already held, let's peek at the owner */
ppid = getppid();
rc = util_lockfile_peek_owner(AP_LOCKFILE, &pid);
if (rc || pid != ppid) {
/* We didn't get the lock, unknown or other owner */
return 2;
}
/* Signify that the lock is already held by the caller */
return 1;
}
return 0;
}
/**
* Release the ap config lock
*

View File

@@ -55,7 +55,7 @@ check-dep-libekmfweb: detect-openssl-version.dep
"detect-openssl-version.dep", \
"openssl-devel version >= 1.1.1", \
"HAVE_OPENSSL=0", \
-I. -lcrypto -DOPENSSL_SUPPRESS_DEPRECATED)
-I. `$(PKG_CONFIG) --cflags --libs libcrypto` -DOPENSSL_SUPPRESS_DEPRECATED)
$(call check_dep, \
"libekmfweb", \
"json-c/json.h", \
@@ -66,7 +66,7 @@ check-dep-libekmfweb: detect-openssl-version.dep
"curl/curl.h", \
"libcurl-devel", \
"HAVE_LIBCURL=0" \
`$(CURL_CONFIG) --cflags` `$(CURL_CONFIG) --libs`)
`$(PKG_CONFIG) --cflags --libs libcurl`)
$(CURL_CONFIG) --ssl-backends | grep OpenSSL >/dev/null 2>&1 || { echo "Error: libcurl is not built with the OpenSSL backend"; exit 1; }
touch check-dep-libekmfweb
@@ -85,8 +85,8 @@ ekmfweb.o: check-dep-libekmfweb ekmfweb.c utilities.h cca.h $(rootdir)include/ek
utilities.o: check-dep-libekmfweb utilities.c utilities.h $(rootdir)include/ekmfweb/ekmfweb.h
cca.o: check-dep-libekmfweb cca.c cca.h utilities.h $(rootdir)include/ekmfweb/ekmfweb.h
libekmfweb.so.$(VERSION): ALL_CFLAGS += -fPIC `$(CURL_CONFIG) --cflags`
libekmfweb.so.$(VERSION): LDLIBS = -ljson-c -lcrypto -lssl `$(CURL_CONFIG) --libs` -ldl
libekmfweb.so.$(VERSION): ALL_CFLAGS += -fPIC `$(PKG_CONFIG) --cflags json-c libcurl libcrypto libssl`
libekmfweb.so.$(VERSION): LDLIBS = `$(PKG_CONFIG) --libs json-c libcurl libcrypto libssl` -ldl
libekmfweb.so.$(VERSION): ALL_LDFLAGS += -shared -Wl,--version-script=libekmfweb.map \
-Wl,-z,defs,-Bsymbolic -Wl,-soname,libekmfweb.so.$(VERM)
libekmfweb.so.$(VERSION): ekmfweb.o utilities.o cca.o $(libs)

View File

@@ -51,7 +51,6 @@ detect-openssl-version.dep:
mv $(TMPFILE) $@
CURL_CONFIG ?= curl-config
XML2_CONFIG ?= xml2-config
check-dep-libkmipclient: detect-openssl-version.dep
$(call check_dep, \
@@ -59,7 +58,7 @@ check-dep-libkmipclient: detect-openssl-version.dep
"detect-openssl-version.dep", \
"openssl-devel version >= 1.1.1", \
"HAVE_OPENSSL=0", \
-I. -lcrypto -DOPENSSL_SUPPRESS_DEPRECATED)
-I. `$(PKG_CONFIG) --cflags --libs libcrypto` -DOPENSSL_SUPPRESS_DEPRECATED)
$(call check_dep, \
"libkmipclient", \
"json-c/json.h", \
@@ -70,13 +69,13 @@ check-dep-libkmipclient: detect-openssl-version.dep
"libxml/tree.h", \
"libxml2-devel", \
"HAVE_LIBXML2=0", \
`$(XML2_CONFIG) --cflags` `$(XML2_CONFIG) --libs`)
`$(PKG_CONFIG) --cflags --libs libxml-2.0`)
$(call check_dep, \
"libkmipclient", \
"curl/curl.h", \
"libcurl-devel", \
"HAVE_LIBCURL=0" \
`$(CURL_CONFIG) --cflags` `$(CURL_CONFIG) --libs`)
`$(PKG_CONFIG) --cflags --libs libcurl`)
$(CURL_CONFIG) --ssl-backends | grep OpenSSL >/dev/null 2>&1 || { echo "Error: libcurl is not built with the OpenSSL backend"; exit 1; }
touch check-dep-libkmipclient
@@ -107,8 +106,8 @@ tls.o: check-dep-libkmipclient tls.c kmip.h utils.h $(rootdir)include/kmipclient
names.o: check-dep-libkmipclient names.c names.h utils.h $(rootdir)include/kmipclient/kmipclient.h
utils.o: check-dep-libkmipclient utils.c names.h utils.h $(rootdir)include/kmipclient/kmipclient.h
libkmipclient.so.$(VERSION): ALL_CFLAGS += -fPIC `$(XML2_CONFIG) --cflags` `$(CURL_CONFIG) --cflags`
libkmipclient.so.$(VERSION): LDLIBS = -ljson-c -lcrypto -lssl `$(XML2_CONFIG) --libs` `$(CURL_CONFIG) --libs`
libkmipclient.so.$(VERSION): ALL_CFLAGS += -fPIC `$(PKG_CONFIG) --cflags json-c libcrypto libssl libxml-2.0 libcurl`
libkmipclient.so.$(VERSION): LDLIBS = `$(PKG_CONFIG) --libs json-c libcrypto libssl libxml-2.0 libcurl`
libkmipclient.so.$(VERSION): ALL_LDFLAGS += -shared -Wl,--version-script=libkmipclient.map \
-Wl,-z,defs,-Bsymbolic -Wl,-soname,libkmipclient.so.$(VERM)
libkmipclient.so.$(VERSION): kmip.o request.o response.o attribute.o key.o ttlv.o json.o \

View File

@@ -311,13 +311,13 @@ int util_file_read_i(int *val, int base, const char *fmt, ...)
return -1;
switch (base) {
case 8:
count = sscanf(buf, "%do", val);
count = sscanf(buf, "%o", val);
break;
case 10:
count = sscanf(buf, "%dd", val);
count = sscanf(buf, "%d", val);
break;
case 16:
count = sscanf(buf, "%dx", val);
count = sscanf(buf, "%x", val);
break;
default:
util_panic("Invalid base: %d\n", base);
@@ -425,13 +425,13 @@ int util_file_read_ui(unsigned int *val, int base, const char *fmt, ...)
return -1;
switch (base) {
case 8:
count = sscanf(buf, "%uo", val);
count = sscanf(buf, "%o", val);
break;
case 10:
count = sscanf(buf, "%uu", val);
count = sscanf(buf, "%u", val);
break;
case 16:
count = sscanf(buf, "%ux", val);
count = sscanf(buf, "%x", val);
break;
default:
util_panic("Invalid base: %d\n", base);

View File

@@ -299,3 +299,35 @@ int util_lockfile_parent_release(char *lockfile)
{
return do_lockfile_release(lockfile, getppid());
}
/**
* Return the pid that owns the specified lockfile.
*
* @param[in] lockfile Path to the lock file
* @param[in,out] pid Buffer to place owning pid
*
* @retval 0 pid provided in buffer
* @retval !=0 Error, no pid provided
*/
int util_lockfile_peek_owner(char *lockfile, int *pid)
{
char buf[BUFSIZE];
int fd, len;
if (!lockfile || !pid)
return UTIL_LOCKFILE_ERR;
/* Open lockfile, read the owning pid if it exists */
fd = open(lockfile, O_RDONLY);
if (fd < 0)
return UTIL_LOCKFILE_ERR;
len = read(fd, buf, sizeof(buf));
close(fd);
if (len <= 0)
return UTIL_LOCKFILE_ERR;
buf[len] = 0;
*pid = atoi(buf);
return 0;
}

View File

@@ -16,7 +16,7 @@
/* we may use header_generic and header_simple_table from the util_funcs module */
config_require(util_funcs)
config_require(util_funcs);
/* function prototypes */

3
rust/.gitignore vendored
View File

@@ -9,6 +9,3 @@ target/
# Generated during make build can be removed at any point
.check-dep-pvtools
.check-cargo
# Ignore lock files by default
Cargo.lock

View File

@@ -2,6 +2,30 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]]
name = "anstream"
version = "0.3.2"
@@ -57,24 +81,61 @@ version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]]
name = "assert-json-diff"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cc"
version = "1.0.79"
@@ -106,7 +167,7 @@ checksum = "c1458a1df40e1e2afebb7ab60ce55c1fa8f431146205aa5f4887e0b111c27636"
dependencies = [
"anstream",
"anstyle",
"bitflags",
"bitflags 1.3.2",
"clap_lex",
"strsim",
"terminal_size",
@@ -147,15 +208,15 @@ dependencies = [
"openssl-probe",
"openssl-sys",
"schannel",
"socket2",
"socket2 0.4.9",
"winapi",
]
[[package]]
name = "curl-sys"
version = "0.4.63+curl-8.1.2"
version = "0.4.68+curl-8.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aeb0fef7046022a1e2ad67a004978f0e3cacb9e3123dc62ce768f92197b771dc"
checksum = "b4a0d18d88360e374b16b2273c832b5e57258ffc1d4aa4f96b108e0738d5752f"
dependencies = [
"cc",
"libc",
@@ -163,9 +224,15 @@ dependencies = [
"openssl-sys",
"pkg-config",
"vcpkg",
"winapi",
"windows-sys 0.48.0",
]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.1"
@@ -187,6 +254,12 @@ dependencies = [
"libc",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
@@ -202,12 +275,152 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
dependencies = [
"percent-encoding",
]
[[package]]
name = "futures"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
[[package]]
name = "futures-executor"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
[[package]]
name = "futures-macro"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.18",
]
[[package]]
name = "futures-sink"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
[[package]]
name = "futures-task"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
[[package]]
name = "futures-util"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "getrandom"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "h2"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap 2.1.0",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "heck"
version = "0.4.1"
@@ -220,6 +433,64 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "http"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "http-body"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
dependencies = [
"bytes",
"http",
"pin-project-lite",
]
[[package]]
name = "httparse"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
version = "0.14.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
dependencies = [
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"socket2 0.4.9",
"tokio",
"tower-service",
"tracing",
"want",
]
[[package]]
name = "indexmap"
version = "1.9.3"
@@ -227,7 +498,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown",
"hashbrown 0.12.3",
]
[[package]]
name = "indexmap"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
dependencies = [
"equivalent",
"hashbrown 0.14.3",
]
[[package]]
@@ -259,6 +540,12 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.146"
@@ -283,12 +570,85 @@ version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "lock_api"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
[[package]]
name = "memchr"
version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "miniz_oxide"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
"libc",
"wasi",
"windows-sys 0.48.0",
]
[[package]]
name = "mockito"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8d3038e23466858569c2d30a537f691fa0d53b51626630ae08262943e3bbb8b"
dependencies = [
"assert-json-diff",
"futures",
"hyper",
"log",
"rand",
"regex",
"serde_json",
"serde_urlencoded",
"similar",
"tokio",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "object"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.18.0"
@@ -297,11 +657,11 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "openssl"
version = "0.10.54"
version = "0.10.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69b3f656a17a6cbc115b5c7a40c616947d213ba182135b014d6051b73ab6f019"
checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800"
dependencies = [
"bitflags",
"bitflags 2.4.1",
"cfg-if",
"foreign-types",
"libc",
@@ -329,9 +689,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.88"
version = "0.9.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2ce0f250f34a308dcfdbb351f511359857d4ed2134ba715a4eadd46e1ffd617"
checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f"
dependencies = [
"cc",
"libc",
@@ -350,12 +710,59 @@ dependencies = [
"openssl-sys",
]
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
]
[[package]]
name = "percent-encoding"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "pin-project-lite"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.60"
@@ -373,11 +780,14 @@ dependencies = [
"cfg-if",
"clap",
"curl",
"lazy_static",
"libc",
"log",
"mockito",
"openssl",
"openssl_extensions",
"serde",
"serde_test",
"thiserror",
"zerocopy",
]
@@ -404,12 +814,86 @@ dependencies = [
]
[[package]]
name = "rustix"
version = "0.37.20"
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"bitflags",
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "regex"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustix"
version = "0.37.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2"
dependencies = [
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc",
@@ -432,6 +916,12 @@ dependencies = [
"windows-sys 0.42.0",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.164"
@@ -452,19 +942,81 @@ dependencies = [
"syn 2.0.18",
]
[[package]]
name = "serde_json"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_test"
version = "1.0.176"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a2f49ace1498612d14f7e0b8245519584db8299541dfe31a06374a828d620ab"
dependencies = [
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_yaml"
version = "0.9.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c"
dependencies = [
"indexmap",
"indexmap 1.9.3",
"itoa",
"ryu",
"serde",
"unsafe-libyaml",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc",
]
[[package]]
name = "similar"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]]
name = "socket2"
version = "0.4.9"
@@ -475,6 +1027,16 @@ dependencies = [
"winapi",
]
[[package]]
name = "socket2"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
dependencies = [
"libc",
"windows-sys 0.48.0",
]
[[package]]
name = "strsim"
version = "0.10.0"
@@ -533,6 +1095,81 @@ dependencies = [
"syn 2.0.18",
]
[[package]]
name = "tokio"
version = "1.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2 0.5.4",
"tokio-macros",
"windows-sys 0.48.0",
]
[[package]]
name = "tokio-macros"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.18",
]
[[package]]
name = "tokio-util"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
"tracing",
]
[[package]]
name = "tower-service"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"pin-project-lite",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
]
[[package]]
name = "try-lock"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "unicode-ident"
version = "1.0.9"
@@ -561,6 +1198,21 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "want"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
dependencies = [
"try-lock",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"

14
rust/Cargo.toml Normal file
View File

@@ -0,0 +1,14 @@
[workspace]
members = [
"pv",
"pvsecret",
"utils",
]
resolver = "2"
[workspace.package]
edition = "2021"
license = "MIT"
[profile.release]
lto = true

View File

@@ -15,16 +15,17 @@ ifneq (${HAVE_CARGO},0)
BUILD_TARGETS = $(CARGO_TARGETS)
INSTALL_TARGETS := install-rust-tools install-man
CARGO_TEST_TARGETS = $(addsuffix, _test, $(CARGO_TARGETS))
CARGO_TEST_TARGETS = $(addsuffix .test, $(CARGO_TARGETS))
ifneq (${HAVE_OPENSSL},0)
ifneq (${HAVE_LIBCURL},0)
PV_TARGETS := pvsecret
PV_BUILD_TARGETS = $(PV_TARGETS)
CARGO_TEST_TARGETS += $(addsuffix, _test, $(PV_TARGETS)) pv
PV_BUILD_TARGETS := $(PV_TARGETS)
CARGO_TEST_TARGETS += $(addsuffix .test,pv $(PV_TARGETS))
endif #LIBCURL
endif #OPENSSL
TEST_TARGETS := $(addsuffix _build,$(CARGO_TEST_TARGETS))
endif #CARGO
BUILD_TARGETS += $(PV_BUILD_TARGETS)
@@ -39,18 +40,15 @@ endif
$(BUILD_TARGETS) rust-test: CC = $(CC_SILENT)
$(BUILD_TARGETS) rust-test: AR = $(AR_SILENT)
$(CARGO_TARGETS): .check-cargo .no-cross-compile
$(CARGO_BUILD) --manifest-path=$@/Cargo.toml $(ALL_CARGOFLAGS)
.PHONY: $(CARGO_TARGETS)
$(PV_TARGETS): .check-dep-pvtools
$(PV_TARGETS) $(CARGO_TARGETS): .check-cargo .no-cross-compile
$(CARGO_BUILD) --bin $@ $(ALL_CARGOFLAGS)
.PHONY: $(PV_TARGETS) $(CARGO_TARGETS)
$(CARGO_TEST_TARGETS): .check-cargo .no-cross-compile
$(CARGO_TEST) --manifest-path=$@/Cargo.toml --all-features $(CARGOFLAGS)
.PHONY: $(CARGO_TEST_TARGETS)
$(PV_TARGETS): .check-cargo .no-cross-compile .check-dep-pvtools
$(CARGO_BUILD) --manifest-path=$@/Cargo.toml $(ALL_CARGOFLAGS)
.PHONY: $(PV_TARGETS)
$(TEST_TARGETS): ALL_CARGOFLAGS += --no-run
$(CARGO_TEST_TARGETS) $(TEST_TARGETS): .check-cargo .no-cross-compile
$(CARGO_TEST) --package $(basename $@) --all-features $(ALL_CARGOFLAGS)
.PHONY: $(TEST_TARGETS) $(CARGO_TEST_TARGETS)
skip-build:
echo " SKIP rust-tools due to unresolved dependencies"
@@ -65,22 +63,17 @@ print-rust-targets:
echo $(BUILD_TARGETS)
clean:
$(foreach target,$(CARGO_TARGETS),\
$(CARGO_CLEAN) --manifest-path=$(target)/Cargo.toml ${ALL_CARGOFLAGS} ;)
$(foreach target,$(PV_TARGETS),\
$(CARGO_CLEAN) --manifest-path=$(target)/Cargo.toml ${CARGOFLAGS} ;)
$(CARGO_CLEAN) ${ALL_CARGOFLAGS}
$(RM) -- .check-dep-pvtools .detect-openssl.dep.c .check-cargo
rust-test: .check-cargo .no-cross-compile
$(foreach target,$(CARGO_TEST_TARGETS),\
$(CARGO_TEST) --manifest-path=$(target)/Cargo.toml --all-features ${ALL_CARGOFLAGS} ;)
rust-test: $(CARGO_TEST_TARGETS)
install-rust-tools: $(BUILD_TARGETS)
$(INSTALL) -d -m 755 $(DESTDIR)$(USRBINDIR)
$(foreach target,$(CARGO_TARGETS),\
$(INSTALL) $(target)/target/release/$(target) $(DESTDIR)$(USRBINDIR);)
$(INSTALL) target/release/$(target) $(DESTDIR)$(USRBINDIR);)
$(foreach target,$(PV_TARGETS),\
$(INSTALL) $(target)/target/release/$(target) $(DESTDIR)$(USRBINDIR);)
$(INSTALL) target/release/$(target) $(DESTDIR)$(USRBINDIR);)
install-man:
$(foreach target,$(CARGO_TARGETS),\
@@ -118,13 +111,13 @@ endif
.check-dep-pvtools: .detect-openssl.dep.c
$(call check_dep, \
"$(BIN_PROGRAM)", \
"Rust-pv", \
$^, \
"openssl-devel / libssl-dev version >= 1.1.1", \
"HAVE_OPENSSL=0", \
"-I.")
$(call check_dep, \
"$(BIN_PROGRAM)", \
"Rust-pv", \
"curl/curl.h", \
"libcurl-devel", \
"HAVE_LIBCURL=0")

View File

@@ -7,21 +7,21 @@ https://www.rust-lang.org/learn/get-started
## Building rust code
### s390-tools build system
If `cargo` is installed a simple `make` should do the job. Note that,
compiling rust programs take significaltly longer than C code. To closely
monitor the prgress use `make V=1` By default release builds are made.
compiling rust programs take significantly longer than C code. To closely
monitor the progress use `make V=1` By default release builds are made.
With `make CARGOFLAGS=<flags>` one can pass additional flags to cargo.
With `make HAVE_CARGO=0` one can turn of any compilation that requires cargo.
With `make CARGO=<...>` one can set the cargo binary
### cargo
If you need to run cargo directly, cd to each project you want to build and
If you need to run cargo directly, `cd` to each project you want to build and
issue your cargo commands. Do **NOT** forget to specify `--release` if you are
building tools for a release. The s390-tools expect the environment variable
`S390_TOOLS_RELEASE` to be present at build time. This is the version string the
rust tools provide.
Tpp: You can use `make version` to get the version string.
Tip: You can use `make version` to get the version string.
## Internal Libraries
* __utils__ _Library for rust tools that bundles common stuff for the 390-tools_
@@ -43,7 +43,7 @@ Exiting tools may be rewritten in Rust.
### What (third-party) crates can be used for s390-tools?
A huge list of libraries are made available through Rusts' ecosystem and is one
of many upsides. However, just like with Coding Style Guidlines, it is
of many upsides. However, just like with Coding Style Guidelines, it is
important to limit the usage of those libraries so that within a project,
everyone is on the same page and that code written in Rust uses similar
approaches. It makes it easier for code review and maintainability in general.
@@ -81,11 +81,27 @@ is a start, but can change over time.
Dependencies used by the crates listed above can be used, too.
### Add new tool
To add a new tool issue `cargo new <TOOLNAME>` in the `rust` directory.
To add a new tool issue `cargo new $TOOLNAME` in the `rust` directory.
Add the tool to the _s390-tools_ build system:
```Makefile
CARGO_TARGETS := TOOLNAME
CARGO_TARGETS := $TOOLNAME
```
Add the library to the _s390-tools_ test list:
```Makefile
CARGO_TEST_TARGETS := $LIBNAME
```
Add the tool/library to the cargo workspace:
```toml
[workspace]
members = [
"pv",
"pvsecret",
"$TOOLNAME",
"$LIBNAME"
"utils",
]
```
### Versions
@@ -98,8 +114,8 @@ use utils::release_string;
fn print_version() {
println!(
"{} version {}\nCopyright IBM Corp. 2023",
env!("CARGO_PKG_NAME"), // collapes into the crates name
release_string!() // this (very likely) collapes into a compile time constant
env!("CARGO_PKG_NAME"), // collapses into the crates name
release_string!() // this (very likely) collapses into a compile time constant
);
}
```

View File

@@ -1,36 +1,32 @@
[package]
name = "pv"
version = "0.9.0"
edition = "2021"
license = "MIT"
edition.workspace = true
license.workspace = true
[dependencies]
libc = "0.2"
log = { version = "0.4", features = ["std", "release_max_level_debug"] }
thiserror = "1"
libc = "0.2.49"
log = { version = "0.4.6", features = ["std", "release_max_level_debug"] }
thiserror = "1.0.33"
zerocopy = "0.6"
cfg-if = "1.0.0"
# dependencies for request feature
clap = { version ="4", features = ["derive", "wrap_help"], optional = true }
curl = { version ="0.4", optional = true }
openssl = {version = "0.10", optional = true }
curl = { version ="0.4.7", optional = true }
openssl = {version = "0.10.49", optional = true }
openssl_extensions = { path = "openssl_extensions", optional = true }
serde = { version = "1", features = ["derive"], optional = true }
serde = { version = "1.0.139", features = ["derive"], optional = true }
# misc optional dependencies
byteorder = {version = "1", optional = true }
byteorder = {version = "1.3", optional = true }
[dev-dependencies]
mockito = {version = "0.31", default-features = false }
mockito = {version = "1", default-features = false }
serde_test = "1"
lazy_static = "1"
lazy_static = "1.1"
[features]
default = []
request = ["dep:openssl", "dep:curl", "dep:openssl_extensions", "dep:serde", "dep:clap"]
uvsecret = ["dep:byteorder", "dep:serde"]
[profile.release]
lto = true
panic = "abort" # release builds now do not clean up stack after panics. .1 Mb

View File

@@ -1,12 +1,12 @@
[package]
name = "openssl_extensions"
version = "0.1.0"
edition = "2021"
license = "MIT"
edition.workspace = true
license.workspace = true
[dependencies]
foreign-types = "0.3"
libc = {version = "0.2", features = [ "extra_traits"] }
log = { version = "0.4", features = ["std", "release_max_level_debug"] }
openssl = "0.10"
openssl-sys = "0.9"
foreign-types = "0.3.1"
libc = {version = "0.2.49", features = [ "extra_traits"] }
log = { version = "0.4.6", features = ["std", "release_max_level_debug"] }
openssl = "0.10.49"
openssl-sys = "0.9.85"

View File

@@ -205,7 +205,7 @@ mod tests {
#[test]
fn from_se_image_hdr() {
let bin_hdr = get_test_asset!("exp/secure_guest.hdr");
let hdr_tags = BootHdrTags::from_se_image(&mut Cursor::new(bin_hdr.clone())).unwrap();
let hdr_tags = BootHdrTags::from_se_image(&mut Cursor::new(*bin_hdr)).unwrap();
assert_eq!(hdr_tags, EXP_HDR);
}
@@ -220,7 +220,7 @@ mod tests {
));
// mess up magic
let mut bin_hdr_copy = bin_hdr.clone();
let mut bin_hdr_copy = *bin_hdr;
bin_hdr_copy.swap(0, 1);
assert!(matches!(
BootHdrTags::from_se_image(&mut Cursor::new(bin_hdr_copy)),

View File

@@ -315,7 +315,7 @@ mod tests {
];
let res = encrypt_aes(
&&SymKey::Aes256(aes_gcm_key.into()),
&SymKey::Aes256(aes_gcm_key.into()),
&aes_gcm_iv,
&aes_gcm_plain,
)

View File

@@ -451,7 +451,7 @@ mod tests {
let ks = vec![
Keyslot::new(host_key.clone()),
Keyslot::new(host_key.clone()),
Keyslot::new(host_key.clone()),
Keyslot::new(host_key),
];
let mut aad = Vec::<Aad>::new();
ks.iter().for_each(|ks| aad.push(Aad::Ks(ks)));

View File

@@ -34,8 +34,8 @@ impl Zeroize for Vec<u8> {
// * Vec allocated at least capacity elements continuously
// * dst points always to a valid location
unsafe {
std::ptr::write_volatile(dst, 0);
dst = dst.add(1);
std::ptr::write_volatile(dst, 0)
}
}
std::sync::atomic::compiler_fence(std::sync::atomic::Ordering::SeqCst);

View File

@@ -105,7 +105,7 @@ mod test {
0xef, 0xc7, 0x3c, 0x62,
];
let name = "association secret".to_string();
let secret = GuestSecret::association("association secret", secret_value.clone()).unwrap();
let secret = GuestSecret::association("association secret", secret_value).unwrap();
let exp = GuestSecret::Association {
name,
id: exp_id,

View File

@@ -117,7 +117,7 @@ impl Display for SecretEntry {
writeln!(f, "{} {}:", self.index, stype_str(self.stype.get()))?;
write!(f, " ")?;
for b in self.id {
write!(f, "{:02x}", b)?;
write!(f, "{b:02x}")?;
}
Ok(())
}

View File

@@ -484,20 +484,20 @@ mod test {
let ibm_wrong_subj = load_gen_cert("ibm_wrong_subject.crt");
let no_sign_crt = load_gen_cert("inter_ca.crt");
assert!(super::get_ibm_z_sign_key(&vec!(ibm_crt.clone())).is_ok());
assert!(super::get_ibm_z_sign_key(&[ibm_crt.clone()]).is_ok());
assert!(matches!(
super::get_ibm_z_sign_key(&vec!(ibm_crt.clone(), ibm_crt.clone())),
super::get_ibm_z_sign_key(&[ibm_crt.clone(), ibm_crt.clone()]),
Err(Error::HkdVerify(ManyIbmSignKeys))
));
assert!(matches!(
super::get_ibm_z_sign_key(&vec!(ibm_wrong_subj)),
super::get_ibm_z_sign_key(&[ibm_wrong_subj]),
Err(Error::HkdVerify(NoIbmSignKey))
));
assert!(matches!(
super::get_ibm_z_sign_key(&vec!(no_sign_crt.clone())),
super::get_ibm_z_sign_key(&[no_sign_crt.clone()]),
Err(Error::HkdVerify(NoIbmSignKey))
));
assert!(super::get_ibm_z_sign_key(&vec!(ibm_crt.clone(), no_sign_crt.clone())).is_ok(),);
assert!(super::get_ibm_z_sign_key(&[ibm_crt, no_sign_crt]).is_ok(),);
}
#[test]

View File

@@ -14,7 +14,9 @@ use crate::test_utils::*;
pub fn mock_endpt(res: &str) -> mockito::Mock {
let res_path = get_cert_asset_path(res);
mockito::mock("GET", format!("/crl/{res}").as_str())
let mut server = mockito::Server::new();
server
.mock("GET", format!("/crl/{res}").as_str())
.with_header("content-type", "application/pkix-crl")
.with_body_from_file(res_path)
.create()
@@ -26,7 +28,7 @@ fn verify_sign_error(exp_raw: libc::c_int, obs: Error) {
}
fn verify_sign_error_slice(exp_raw: &[libc::c_int], obs: Error) {
if exp_raw
.into_iter()
.iter()
.filter(|e| match &obs {
Error::HkdVerify(ty) => match ty {
IbmSignInvalid(err, _d) => &&err.as_raw() == e,
@@ -51,7 +53,7 @@ fn store_setup() {
let ibm_str = get_cert_asset_path_string("ibm.crt");
let inter_str = get_cert_asset_path_string("inter.crt");
let store = helper::store_setup(&None, &vec![], &vec![ibm_str, inter_str]);
let store = helper::store_setup(&None, &[], &[ibm_str, inter_str]);
assert!(store.is_ok());
}
@@ -63,7 +65,7 @@ fn verify_chain_online() {
let mock_inter = mock_endpt("inter_ca.crl");
let mut store = helper::store_setup(&Some(root_crt), &vec![], &vec![]).unwrap();
let mut store = helper::store_setup(&Some(root_crt), &[], &[]).unwrap();
download_crls_into_store(&mut store, slice::from_ref(&ibm_crt)).unwrap();
let store = store.build();
@@ -71,8 +73,8 @@ fn verify_chain_online() {
let mut sk = Stack::<X509>::new().unwrap();
sk.push(inter_crt).unwrap();
verify_chain(&store, &sk, &vec![ibm_crt.clone()]).unwrap();
assert!(verify_chain(&store, &sk, &vec!(ibm_crt)).is_ok());
verify_chain(&store, &sk, &[ibm_crt.clone()]).unwrap();
assert!(verify_chain(&store, &sk, &[ibm_crt]).is_ok());
}
#[test]
@@ -82,13 +84,13 @@ fn verify_chain_offline() {
let inter_crt = load_gen_cert("inter_ca.crt");
let root_crt = get_cert_asset_path_string("root_ca.chained.crt");
let store = helper::store_setup(&Some(root_crt), &vec![inter_crl], &vec![])
let store = helper::store_setup(&Some(root_crt), &[inter_crl], &[])
.unwrap()
.build();
let mut sk = Stack::<X509>::new().unwrap();
sk.push(inter_crt).unwrap();
assert!(verify_chain(&store, &sk, &vec![ibm_crt]).is_ok());
assert!(verify_chain(&store, &sk, &[ibm_crt]).is_ok());
}
#[test]
@@ -107,8 +109,8 @@ fn verify_online() {
let inter_crl = get_cert_asset_path_string("inter_ca.crl");
let ibm_crl = get_cert_asset_path_string("ibm.crl");
let verifier = CertVerifier::new(
&vec![ibm_crt, inter_crt],
&vec![ibm_crl, inter_crl],
&[ibm_crt, inter_crt],
&[ibm_crl, inter_crl],
&Some(root_crt),
false,
)
@@ -148,8 +150,8 @@ fn verify_offline() {
let hkd = load_gen_cert("host.crt");
let verifier = CertVerifier::new(
&vec![ibm_crt, inter_crt],
&vec![ibm_crl, inter_crl],
&[ibm_crt, inter_crt],
&[ibm_crl, inter_crl],
&Some(root_crt),
true,
)
@@ -186,25 +188,20 @@ fn verifier_new() {
let ibm_rev_crt = get_cert_asset_path_string("ibm_rev.crt");
// To many signing keys
let verifier = CertVerifier::new(
&vec![ibm_crt.clone(), ibm_rev_crt.clone()],
&vec![],
&None,
true,
);
let verifier = CertVerifier::new(&[ibm_crt.clone(), ibm_rev_crt.clone()], &[], &None, true);
assert!(matches!(verifier, Err(Error::HkdVerify(ManyIbmSignKeys))));
// no CRL for each X509
let verifier = CertVerifier::new(
&vec![inter_crt.clone(), ibm_crt.clone()],
&vec![inter_crl.clone()],
&Some(root_crt.clone()),
&[inter_crt.clone(), ibm_crt.clone()],
&[inter_crl.clone()],
&Some(root_crt),
false,
);
verify_sign_error(3, verifier.unwrap_err());
let verifier = CertVerifier::new(
&vec![inter_crt.clone(), ibm_crt.clone()],
&vec![],
&[inter_crt.clone(), ibm_crt.clone()],
&[],
&Some(root_chn_crt.clone()),
false,
);
@@ -212,8 +209,8 @@ fn verifier_new() {
// wrong intermediate (or ibm key)
let verifier = CertVerifier::new(
&vec![inter_fake_crt, ibm_crt.clone()],
&vec![inter_fake_crl],
&[inter_fake_crt, ibm_crt.clone()],
&[inter_fake_crl],
&Some(root_chn_crt.clone()),
true,
);
@@ -222,8 +219,8 @@ fn verifier_new() {
//wrong root ca
let verifier = CertVerifier::new(
&vec![inter_crt.clone(), ibm_crt.clone()],
&vec![inter_crl.clone()],
&[inter_crt.clone(), ibm_crt.clone()],
&[inter_crl.clone()],
&None,
true,
);
@@ -231,33 +228,28 @@ fn verifier_new() {
//correct signing key + intermediate cert
let _verifier = CertVerifier::new(
&vec![inter_crt.clone(), ibm_crt.clone()],
&vec![inter_crl.clone()],
&[inter_crt.clone(), ibm_crt.clone()],
&[inter_crl.clone()],
&Some(root_chn_crt.clone()),
false,
)
.unwrap();
// no intermediate key
let verifier = CertVerifier::new(
&vec![ibm_crt.clone()],
&vec![],
&Some(root_chn_crt.clone()),
false,
);
let verifier = CertVerifier::new(&[ibm_crt], &[], &Some(root_chn_crt.clone()), false);
verify_sign_error(20, verifier.unwrap_err());
//Ibm Sign outdated
let verifier = CertVerifier::new(
&vec![inter_crt.clone(), ibm_early_crt.clone()],
&vec![inter_crl.clone()],
&[inter_crt.clone(), ibm_early_crt],
&[inter_crl.clone()],
&Some(root_chn_crt.clone()),
false,
);
assert!(matches!(verifier, Err(Error::HkdVerify(NoIbmSignKey))));
let verifier = CertVerifier::new(
&vec![inter_crt.clone(), ibm_late_crt.clone()],
&vec![inter_crl.clone()],
&[inter_crt.clone(), ibm_late_crt],
&[inter_crl.clone()],
&Some(root_chn_crt.clone()),
false,
);
@@ -265,9 +257,9 @@ fn verifier_new() {
// revoked
let verifier = CertVerifier::new(
&vec![inter_crt.clone(), ibm_rev_crt.clone()],
&vec![inter_crl.clone()],
&Some(root_chn_crt.clone()),
&[inter_crt, ibm_rev_crt],
&[inter_crl],
&Some(root_chn_crt),
false,
);
verify_sign_error(23, verifier.unwrap_err());

View File

@@ -18,7 +18,7 @@ use pv::{
const TAGS: BootHdrTags = BootHdrTags::new([1; 64], [2; 64], [3; 64], [4; 16]);
const CUID: ConfigUid = [0x42u8; 16];
const ASSOC_SECRET: [u8; 32] = [0x11; 32];
const ASSOC_ID: &'static str = "add_secret_request";
const ASSOC_ID: &str = "add_secret_request";
fn create_asrcb(
guest_secret: GuestSecret,
@@ -38,7 +38,7 @@ fn create_asrcb(
};
asrcb.add_hostkey(hkd);
Ok(asrcb.encrypt(ctx)?)
asrcb.encrypt(ctx)
}
fn get_crypto() -> (PKey<Public>, ReqEncrCtx) {
@@ -63,17 +63,10 @@ where
{
let (host_key, ctx) = get_crypto();
let cuid = match cuid {
true => Some(CUID.into()),
true => Some(CUID),
false => None,
};
create_asrcb(
guest_secret,
ext_secret.into(),
flags,
cuid.into(),
host_key,
&ctx,
)
create_asrcb(guest_secret, ext_secret.into(), flags, cuid, host_key, &ctx)
}
fn association() -> GuestSecret {
@@ -156,7 +149,7 @@ fn null_none_default_cuid_seven() {
let mut asrcb =
AddSecretRequest::new(AddSecretVersion::One, GuestSecret::Null, TAGS, no_flag());
(0..7).for_each(|_| asrcb.add_hostkey(hkd.clone()));
asrcb.set_cuid(CUID.into());
asrcb.set_cuid(CUID);
let asrcb = asrcb.encrypt(&ctx).unwrap();
let exp = get_test_asset!("exp/asrcb/null_none_default_cuid_seven");

View File

@@ -1,18 +1,14 @@
[package]
name = "pvsecret"
version = "0.9.0"
edition = "2021"
license = "MIT"
edition.workspace = true
license.workspace = true
[dependencies]
anyhow = { version = "1", features = ["std"] }
anyhow = { version = "1.0.70", features = ["std"] }
clap = { version ="4", features = ["derive", "wrap_help"]}
log = { version = "0.4", features = ["std", "release_max_level_debug"] }
log = { version = "0.4.6", features = ["std", "release_max_level_debug"] }
serde_yaml = "0.9"
pv = { path = "../pv", features = ["uvsecret", "request"] }
utils = { path = "../utils" }
[profile.release]
lto = true
panic = "abort" # release builds now do not clean up stack after panics. .1 Mb

View File

@@ -1,5 +1,5 @@
[package]
name = "utils"
version = "0.1.0"
edition = "2021"
license = "MIT"
edition.workspace = true
license.workspace = true

View File

@@ -246,6 +246,9 @@ get_system_level()
read -r k_ver k_patchlvl k_sublvl k_sublvl2 <<< "$(split_kver "$kver_str" 4)"
# Handle excessive sublevel numbers consistently
if [[ "$k_sublvl" -gt 255 ]] ; then
k_sublvl=0
fi
if [[ "$k_sublvl2" -gt 65535 ]] ; then
k_sublvl2=0
fi

View File

@@ -262,6 +262,7 @@ readonly OUTPUT_FILE_OVS="${WORKPATH}network.out"
readonly OUTPUT_FILE_ISW="${WORKPATH}installed_sw.out"
readonly OUTPUT_FILE_TC="${WORKPATH}network.out"
readonly OUTPUT_FILE_VMCMD="${WORKPATH}zvm_runtime.out"
readonly OUTPUT_FILE_UDEVDB="${WORKPATH}udevdb.out"
# Base file names for different output files - no extension !
readonly OUTPUT_FILE_KUBERNETES="${WORKPATH}kubernetes"
readonly OUTPUT_FILE_OSAOAT="${WORKPATH}network"
@@ -400,6 +401,7 @@ CONFIGFILES="\
/etc/hosts*\
/etc/iscsi\
/etc/inittab\
/etc/kdump\
/etc/libvirt\
/etc/logrotate.d\
/etc/lvm\
@@ -439,6 +441,7 @@ CONFIGFILES="\
/run/modules-load.d/*.conf\
/run/udev/chreiplzfcpmp-ipl-volume-id\
/run/udev/rules.d\
/run/zdev_id.env\
"
########################################
@@ -555,6 +558,7 @@ CMDS="${CMDS}\
>> '${OUTPUT_FILE_JOURNALCTL}'\
:lsof >> '${OUTPUT_FILE_LSOF}'\
:rpm -qa | sort >> '${OUTPUT_FILE_ISW}'\
:udevadm info --export-db >> '${OUTPUT_FILE_UDEVDB}'\
"
########################################
@@ -833,6 +837,7 @@ collect_sysfs() {
-x '*/page_idle/bitmap*' \
-x '*/tracing/per_cpu/*' \
-x '*/tracing/free_buffer' \
-x '*/devices/css[0-9]*/[0-9]*.*.*/[0-9]*.*.*/host[0-9]*/rport-[0-9]*:*-*/target[0-9]*:*:*/[0-9]*:*:*:*/block/sd*/mq/0/cpu[0-9]*' \
--ignore-failed-read -J 1 -T 5 2>>${OUTPUT_FILE_SYSFS}.err
rc=$?
else
@@ -860,6 +865,7 @@ collect_sysfs() {
-a -not \( -path '*page_idle*' -a -name 'bitmap*' \) \
-a -not -path '*tracing/per_cpu*' \
-a -not -path '*/tracing/free_buffer' \
-a -not -path '*/devices/css[0-9]*/[0-9]*.*.*/[0-9]*.*.*/host[0-9]*/rport-[0-9]*:*-*/target[0-9]*:*:*/[0-9]*:*:*:*/block/sd*/mq/0/cpu[0-9]*' \
2>/dev/null | while IFS= read -r file_name; do
echo " ${file_name}"
if ! dd if="${file_name}" status=noxfer iflag=nonblock \
@@ -904,7 +910,8 @@ collect_osaoat() {
local network_device
network_devices=$(lsqeth 2>/dev/null | grep "Device name" \
| sed 's/D.*:[[:space:]]*\([^[:space:]]*\)[[:space:]]\+/\1/g')
| sed 's/D.*:[[:space:]]*\([^[:space:]]*\)[[:space:]]\+/\1/g' \
| sed 's/[()]//g' )
if type qethqoat >/dev/null; then
if test -n "${network_devices}"; then
pr_collect_output "osa oat"
@@ -954,6 +961,8 @@ collect_ethtool() {
"${OUTPUT_FILE_ETHTOOL}"
call_run_command "ethtool -T ${network_device}" \
"${OUTPUT_FILE_ETHTOOL}"
call_run_command "ethtool --module-info ${network_device}" \
"${OUTPUT_FILE_ETHTOOL}"
done
else
pr_skip "ethtool: no devices"
@@ -1389,7 +1398,7 @@ pr_log_stdout() {
pr_syslog_stdout() {
echo "$@" >&8
echo
echo "$(date +%H:%M:%S.%N) - $@"
echo "$(date +%H:%M:%S.%N) - " "$@"
logger -t "${SCRIPTNAME}" "$@"
}
@@ -1402,13 +1411,13 @@ pr_collect_output() {
########################################
# print "Collecting ..." like fs
pr_collect() {
pr_syslog_stdout ${step_num} "Collecting" $@
pr_syslog_stdout ${step_num} "Collecting" "$@"
}
########################################
# print "Skipping ..." info with reason
pr_skip() {
pr_syslog_stdout ${step_num} "Skip" $@
pr_syslog_stdout ${step_num} "Skip" "$@"
}
###############################################################################

View File

@@ -486,12 +486,16 @@ static void show_queue_capability(int id, int dom)
printf("queue %02x.%04x capabilities:\n", id, dom);
if (util_path_is_reg_file("%s/se_bind", dev)) {
util_file_read_line(buf, sizeof(buf), "%s/se_bind", dev);
printf("SE bind state: %s\n", buf);
if (util_file_read_line(buf, sizeof(buf), "%s/se_bind", dev))
printf("SE bind state: error\n");
else
printf("SE bind state: %s\n", buf);
}
if (util_path_is_reg_file("%s/se_associate", dev)) {
util_file_read_line(buf, sizeof(buf), "%s/se_associate", dev);
printf("SE association state: %s\n", buf);
if (util_file_read_line(buf, sizeof(buf), "%s/se_associate", dev))
printf("SE association state: error\n");
else
printf("SE association state: %s\n", buf);
}
if (util_path_is_reg_file("%s/mkvps", dev)) {
char *mkvps = util_path_sysfs("devices/ap/%s/%s/mkvps", card, queue);
@@ -674,16 +678,21 @@ static void read_subdev_rec_verbose(struct util_rec *rec, const char *grp_dev,
util_file_read_l(&depth, 10, "%s/depth", grp_dev);
util_rec_set(rec, "depth", "%02d", depth + 1);
if (util_path_is_readable("%s/%s/ap_functions", grp_dev, sub_dev))
util_file_read_ul(&facility, 16, "%s/%s/ap_functions", grp_dev, sub_dev);
else
util_file_read_ul(&facility, 16, "%s/ap_functions", grp_dev);
if (util_file_read_ul(&facility, 16, "%s/ap_functions", grp_dev))
errx(EXIT_FAILURE,
"Error - Read of sysfs attribute %s/ap_functions failed.",
grp_dev);
for (i = 0; i < MAX_FAC_BITS; i++)
buf[i] = facility & fac_bits[i].mask ? fac_bits[i].c : '-';
buf[i] = '\0';
util_rec_set(rec, "facility", buf);
if (ap_bus_has_SB_support()) {
if (util_file_read_ul(&facility, 16, "%s/%s/ap_functions",
grp_dev, sub_dev)) {
util_rec_set(rec, "sestat", "error");
return;
}
switch (EXTRACT_BS_BITS(facility)) {
case 0:
util_rec_set(rec, "sestat", "usable");

View File

@@ -15,24 +15,11 @@
#include "exit_code.h"
#include "hash.h"
#include "misc.h"
#include "site.h"
struct subtype;
struct setting_list;
/**
* Currently zdev supports 10 sites. Which means, zdev support 10 different
* set of attributes which are specific to each site. When the user does
* not provide any site information, the common set will be used which is
* not specific to any site. So, total we have 11 persistent attribute sets
* Where,
* 0- 9: Site specific attributes
* 10: Common attributes which do not belong to any sites
*/
#define NUM_SITES 11
#define NUM_USER_SITES (NUM_SITES - 1)
#define SITE_FALLBACK NUM_USER_SITES
/**
* struct device_state - Represent the state of a device in a configuration
* @settings: List of attribute settings

View File

@@ -18,7 +18,6 @@
#define MODPROBE_PREFIX "s390x"
#define UDEV_PREFIX "41"
#define UDEV_SUFFIX ".rules"
#define ZDEV_PREFIX "40"
#define PATH_MODPROBE_CONF "/etc/modprobe.d"
#define PATH_MODPROBE "/sbin/modprobe"
@@ -66,7 +65,6 @@ char *path_get_zfcp_lun_dev(struct zfcp_lun_devid *);
char *path_get_zfcp_port_dev(struct zfcp_lun_devid *);
char *path_get_scsi_hctl_dev(const char *);
char *path_get_bus_attr(const char *, const char *);
char *path_get_zdev_rule(const char *name);
exit_code_t path_for_each(const char *,
exit_code_t (*callback)(const char *, const char *,

31
zdev/include/site.h Normal file
View File

@@ -0,0 +1,31 @@
/*
* zdev - Information regarding site-specific configurations used for
* zdev tools.
*
* Copyright IBM Corp. 2023
*
* 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 SITE_H
#define SITE_H
/**
* Currently zdev supports 10 sites. Which means, zdev support 10 different
* set of attributes which are specific to each site. When the user does
* not provide any site information, the common set will be used which is
* not specific to any site. So, total we have 11 persistent attribute sets
* Where,
* 0- 9: Site specific attributes
* 10: Common attributes which do not belong to any sites
*/
#define NUM_SITES 11
#define NUM_USER_SITES (NUM_SITES - 1)
#define SITE_FALLBACK NUM_USER_SITES
/* Helper to find the availability of site-configuration */
#define dev_site_configured(dev, x) (dev->site_specific[(x)].exists && \
!dev->site_specific[(x)].deconfigured)
#endif /* SITE_H */

View File

@@ -34,7 +34,6 @@ void udev_add_internal_from_entry(struct setting_list *list,
struct util_udev_entry_node *entry,
struct attrib **attribs);
exit_code_t udev_write_site_rule(void);
bool is_legacy_rule(struct util_udev_file *file);
#endif /* UDEV_H */

View File

@@ -404,13 +404,3 @@ char *path_get_bus_attr(const char *bus, const char *attr)
{
return path_get("/sys/bus/%s/%s", bus, attr);
}
/* Return path will be with ZDEV_PREFIX oon PATH_UDEV_RULES */
char *path_get_zdev_rule(const char *name)
{
const char *path = PATH_UDEV_RULES;
/* Create file. */
return path_get("%s/%s-%s%s", path,
ZDEV_PREFIX, name, UDEV_SUFFIX);
}

View File

@@ -413,13 +413,16 @@ static struct attrib qeth_attr_isolation = {
static struct attrib qeth_attr_performance_stats = {
.name = "performance_stats",
.title = "Control performance statistics collection",
.title = "Reset the statistic values",
.desc =
"Control the collection of QETH performance statistics data:\n"
" 0: Performance statistics data is not collected\n"
" 1: Performance statistics data is collected\n",
.defval = "0",
"Write '1' to this attribute to reset the statistic values to 0.\n"
"Use the ethtool command to display the statistics.\n",
/* read will always return 1 */
.defval = "1",
/* writing 0 is possible, but has no effect */
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
.activeonly = 1,
.rewrite = 1,
.st_data = QETH_DATA(layer_any, group_none),
};

View File

@@ -139,53 +139,6 @@ out:
free(copy);
}
/*
* Write the UDEV rule that determines the active SITE_ID
*/
exit_code_t udev_write_site_rule(void)
{
char *path, *name = "zdev-id";
exit_code_t rc = EXIT_OK;
FILE *fd;
/* Create file. */
path = path_get_zdev_rule(name);
if (!util_path_exists(path)) {
rc = path_create(path);
if (rc)
goto out;
}
fd = misc_fopen(path, "w");
if (!fd) {
error("Could not write to file %s: %s\n", path,
strerror(errno));
rc = EXIT_RUNTIME_ERROR;
goto out;
}
fprintf(fd, "# Generated by chzdev\n");
fprintf(fd, "\n");
/* We have to make sure that we are not trying to determine the SITE_ID
* for all the corresponding uevent. Check if the SITE_ID is already
* determined by reading the file /run/zdev_site_id; and if it is not
* available, execute the zdev_id program and determine the SITE_ID and
* create the new zdev_site_id file for next run.
*/
fprintf(fd, "TEST!=\"%s\", IMPORT{program}="
"\"%s/zdev_id\",GOTO=\"end\"\n", ZDEV_SITE_ID_FILE,
TOOLS_LIBDIR);
fprintf(fd, "IMPORT{file}=\"%s\"\n", ZDEV_SITE_ID_FILE);
fprintf(fd, "LABEL=\"end\"\n");
if (misc_fclose(fd))
warn("Could not close file %s: %s\n", path, strerror(errno));
out:
free(path);
return rc;
}
bool is_legacy_rule(struct util_udev_file *file)
{
struct util_udev_line_node *line;

View File

@@ -25,6 +25,7 @@
#include "setting.h"
#include "udev.h"
#include "udev_ccw.h"
#include "zdev_id.h"
#define SITE_FALLBACK_SUFFIX "fb"
@@ -323,7 +324,7 @@ static exit_code_t udev_ccw_write_device_new(struct device *dev)
char *path, *cfg_label = NULL, *end_label = NULL;
exit_code_t rc = EXIT_OK;
FILE *fd;
int i, configured = 0;
int i, configured = 0, site_configured = 0;
/*
* Remove the previous file; The new udev rule will be created based on the
@@ -338,9 +339,10 @@ static exit_code_t udev_ccw_write_device_new(struct device *dev)
dev_state_copy(&dev->site_specific[global_site_id], &dev->persistent);
for (i = 0; i < NUM_SITES; i++) {
configured += dev->site_specific[i].exists;
configured -= dev->site_specific[i].deconfigured;
configured += dev_site_configured(dev, i) ? 1 : 0;
}
site_configured = configured - (dev_site_configured(dev, SITE_FALLBACK) ?
1 : 0);
/*
* If there is no configuration settings available, do not create the new
@@ -386,21 +388,41 @@ static exit_code_t udev_ccw_write_device_new(struct device *dev)
fprintf(fd, "\n");
fprintf(fd, "LABEL=\"%s\"\n", cfg_label);
/*
* Determine the ZDEV_SITE_ID here. If ZDEV_SITE_ID_FILE available,
* simply import the content. If not, execute zdev_id and import the
* output of the same.
*/
if (site_configured) {
fprintf(fd, "# Determine ZDEV_SITE_ID to continue\n");
fprintf(fd, "TEST==\"%s\",IMPORT{file}=\"%s\"\n",
ZDEV_SITE_ID_FILE, ZDEV_SITE_ID_FILE);
fprintf(fd, "TEST!=\"%s\",IMPORT{program}=\"%s/zdev_id\"\n\n",
ZDEV_SITE_ID_FILE, TOOLS_LIBDIR);
}
/* site comparison block */
for (i = 0; i < NUM_USER_SITES; i++) {
if (dev->site_specific[i].exists &&
!dev->site_specific[i].deconfigured) {
if (dev_site_configured(dev, i)) {
fprintf(fd, "ENV{ZDEV_SITE_ID}==\"%d\",GOTO=\"%s_site%d\"\n", i,
cfg_label, i);
}
}
/*
* If no site configurations are available, then we need to make sure that
* the udev-rule stays as compact as possible. We do not want to add any
* extra labels on it.
*/
if (!site_configured)
goto fallback;
/*
* If we have a generic configuration available, then use that setting as a
* fail-over incase of no site-id information in LOADPARM
*/
if (dev->site_specific[SITE_FALLBACK].exists &&
!dev->site_specific[SITE_FALLBACK].deconfigured)
if (dev_site_configured(dev, SITE_FALLBACK))
fprintf(fd, "GOTO=\"%s_site_fb\"\n", cfg_label);
else
fprintf(fd, "GOTO=\"%s\"\n", end_label);
@@ -408,8 +430,7 @@ static exit_code_t udev_ccw_write_device_new(struct device *dev)
/* Write the site blocks for all the available configurations */
for (i = 0; i < NUM_USER_SITES; i++) {
if (dev->site_specific[i].exists &&
!dev->site_specific[i].deconfigured) {
if (dev_site_configured(dev, i)) {
fprintf(fd, "# site_start_%d\n", i);
fprintf(fd, "LABEL=\"%s_site%d\"\n", cfg_label, i);
@@ -420,11 +441,12 @@ static exit_code_t udev_ccw_write_device_new(struct device *dev)
fprintf(fd, "\n");
}
}
if (dev->site_specific[SITE_FALLBACK].exists &&
!dev->site_specific[SITE_FALLBACK].deconfigured) {
fprintf(fd, "# site_start_fb\n");
fprintf(fd, "LABEL=\"%s_site_fb\"\n", cfg_label);
fallback:
if (dev_site_configured(dev, SITE_FALLBACK)) {
fprintf(fd, "# site_start_fb\n");
if (site_configured)
fprintf(fd, "LABEL=\"%s_site_fb\"\n", cfg_label);
write_attr_to_file(fd, &dev->site_specific[i], id);
/* Write udev rule epilog. */
fprintf(fd, "GOTO=\"%s\"\n", end_label);
@@ -439,9 +461,6 @@ static exit_code_t udev_ccw_write_device_new(struct device *dev)
if (misc_fclose(fd))
warn("Could not close file %s: %s\n", path, strerror(errno));
rc = udev_write_site_rule();
if (rc)
goto out;
out:
free(end_label);
free(cfg_label);

View File

@@ -13,6 +13,7 @@
#include <string.h>
#include <ctype.h>
#include "site.h"
#include "zdev_id.h"
#define SYSINFO "/proc/sysinfo"
@@ -20,7 +21,6 @@
#define LOADPARM "/sys/firmware/ipl/loadparm"
#define IPL_DEV_ID "/sys/firmware/ipl/device"
#define IPL_DEV_TYPE "/sys/firmware/ipl/ipl_type"
#define SITE_FALLBACK 10
#define WHITESPACE " \t\n"

View File

@@ -17,6 +17,8 @@
#include <time.h>
#include <unistd.h>
#include "dump/s390_dump.h"
#include "df_s390.h"
/*
@@ -100,6 +102,8 @@ void df_s390_hdr_add(struct df_s390_hdr *hdr)
if ((hdr->version >= 5 || hdr->magic == DF_S390_MAGIC_EXT) &&
hdr->real_cpu_cnt)
dfi_attr_real_cpu_cnt_set(hdr->real_cpu_cnt);
if (!hdr->mvdump && hdr->zlib_version_s390 && hdr->zlib_entry_size)
dfi_attr_zlib_info_set(hdr->zlib_version_s390, hdr->zlib_entry_size);
}
/*
@@ -151,16 +155,19 @@ void df_s390_dumper_read(struct zg_fh *fh, int blk_size,
case 1:
if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC_EXT, 7) == 0 ||
strncmp(dumper->magic, DF_S390_DUMPER_MAGIC_MV_EXT, 7) == 0)
dumper->size = DF_S390_DUMPER_SIZE_V3;
dumper->size = STAGE2_DUMPER_SIZE_V3;
else
dumper->size = DF_S390_DUMPER_SIZE_V1;
dumper->size = STAGE2_DUMPER_SIZE_V1;
break;
case 2:
dumper->size = DF_S390_DUMPER_SIZE_V2;
if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC_EXT, 7) == 0)
dumper->size = STAGE2_DUMPER_SIZE_ZLIB;
else
dumper->size = STAGE2_DUMPER_SIZE_V2;
break;
case 3:
default:
dumper->size = DF_S390_DUMPER_SIZE_V3;
dumper->size = STAGE2_DUMPER_SIZE_V3;
}
/* Read force and mem fields in the end of the dumper */
bytes_to_read = sizeof(dumper->force) + sizeof(dumper->mem);

View File

@@ -13,74 +13,12 @@
#define DF_S390_H
#include "lib/zt_common.h"
#include "dump/s390_dump.h"
#include "boot/loaders_layout.h"
#include "dt.h"
#include "zg.h"
#define DF_S390_MAGIC 0xa8190173618f23fdULL
#define DF_S390_MAGIC_EXT 0xa8190173618f23feULL
#define DF_S390_HDR_SIZE 0x1000
#define DF_S390_EM_SIZE 16
#define DF_S390_EM_STR "DUMP_END"
#define DF_S390_CPU_MAX 512
#define DF_S390_MAGIC_BLK_ECKD 3
/*
* Architecture of dumped system
*/
enum df_s390_arch {
DF_S390_ARCH_32 = 1,
DF_S390_ARCH_64 = 2,
};
/*
* s390 dump header format
*/
struct df_s390_hdr {
u64 magic; /* 0x000 */
u32 version; /* 0x008 */
u32 hdr_size; /* 0x00c */
u32 dump_level; /* 0x010 */
u32 page_size; /* 0x014 */
u64 mem_size; /* 0x018 */
u64 mem_start; /* 0x020 */
u64 mem_end; /* 0x028 */
u32 num_pages; /* 0x030 */
u32 pad; /* 0x034 */
u64 tod; /* 0x038 */
u64 cpu_id; /* 0x040 */
u32 arch; /* 0x048 */
u32 volnr; /* 0x04c */
u32 build_arch; /* 0x050 */
u64 mem_size_real; /* 0x054 */
u8 mvdump; /* 0x05c */
u16 cpu_cnt; /* 0x05d */
u16 real_cpu_cnt; /* 0x05f */
u8 end_pad1[0x200-0x061]; /* 0x061 */
u64 mvdump_sign; /* 0x200 */
u64 mvdump_zipl_time; /* 0x208 */
u8 end_pad2[0x800-0x210]; /* 0x210 */
u32 lc_vec[DF_S390_CPU_MAX]; /* 0x800 */
} __packed;
/*
* End marker: Should be at the end of every valid s390 crash dump.
*/
struct df_s390_em {
char str[8];
u64 tod;
} __packed;
/*
* Segment header for s390 extended dump format
*/
struct df_s390_dump_segm_hdr {
u64 start;
u64 len;
u64 stop_marker;
u8 reserved[0x1000 - 24];
} __packed;
/*
* Convert DFI arch to s390 arch
*/
@@ -97,9 +35,6 @@ static inline enum dfi_arch df_s390_to_dfi_arch(enum df_s390_arch df_s390_arch)
return df_s390_arch == DF_S390_ARCH_64 ? DFI_ARCH_64 : DFI_ARCH_32;
}
#define DF_S390_DUMPER_SIZE_V1 0x1000
#define DF_S390_DUMPER_SIZE_V2 0x2000
#define DF_S390_DUMPER_SIZE_V3 0x3000
#define DF_S390_DUMPER_MAGIC32 "ZECKD31"
#define DF_S390_DUMPER_MAGIC64 "ZECKD64"
#define DF_S390_DUMPER_MAGIC_EXT "XECKD64"

View File

@@ -74,6 +74,8 @@ struct attr {
struct new_utsname *utsname;
char *dump_method;
u64 *file_size;
u8 *zlib_version;
u32 *zlib_entsize;
};
/*
@@ -146,6 +148,11 @@ void dfi_info_print(void)
if (l.attr.file_size)
STDERR(" Dump file size.....: %lld MB\n",
TO_MIB(*l.attr.file_size));
if (g.opts.verbose && l.attr.zlib_version && l.attr.zlib_entsize) {
STDERR(" Zlib version.......: %lld\n", *l.attr.zlib_version);
STDERR(" Zlib compression unit: %lld MB\n",
TO_MIB(*l.attr.zlib_entsize));
}
if (dfi_mem_range())
dfi_mem_map_print(g.opts.verbose);
if (l.dfi->info_dump) {
@@ -426,6 +433,26 @@ u64 *dfi_attr_file_size(void)
return l.attr.file_size;
}
/*
* Attribute: Zlib version and zlib entry size
*/
void dfi_attr_zlib_info_set(u8 version, u32 entry_size)
{
l.attr.zlib_version = zg_alloc(sizeof(*l.attr.zlib_version));
*l.attr.zlib_version = version;
l.attr.zlib_entsize = zg_alloc(sizeof(*l.attr.zlib_entsize));
*l.attr.zlib_entsize = entry_size;
}
u8 *dfi_attr_zlib_version(void)
{
return l.attr.zlib_version;
}
u32 *dfi_attr_zlib_entsize(void)
{
return l.attr.zlib_entsize;
}
/*
* Attribute: Build architecture

View File

@@ -182,6 +182,10 @@ u64 *dfi_attr_mem_size_real(void);
void dfi_attr_file_size_set(u64 dump_size);
u64 *dfi_attr_file_size(void);
void dfi_attr_zlib_info_set(u8 version, u32 entry_size);
u8 *dfi_attr_zlib_version(void);
u32 *dfi_attr_zlib_entsize(void);
void dfi_attr_vol_nr_set(unsigned int vol_nr);
unsigned int *dfi_attr_vol_nr(void);

View File

@@ -18,8 +18,10 @@
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <zlib.h>
#include "lib/util_log.h"
#include "dump/s390_dump.h"
#include "zgetdump.h"
#include "zg.h"
@@ -35,8 +37,21 @@ static struct {
struct df_s390_hdr hdr; /* s390 dump header */
struct df_s390_em em; /* s390 end marker */
bool extended; /* Extended input dump format */
int blk_size; /* Dump device block size */
} l;
struct mem_chunk_compressed_data {
/* Offset of the dump segment data on disk in bytes */
u64 offset_on_disk;
/* Number of compressed entries */
u32 entry_count;
/*
* Offsets to compressed entries from
* the start of mem_chunk in blocks
*/
u32 entry_offset[];
};
/*
* s390 mem chunk read callback
*/
@@ -56,11 +71,118 @@ static void dfi_s390_ext_mem_chunk_read(struct dfi_mem_chunk *mem_chunk,
u64 off, void *buf, u64 cnt)
{
u64 *mem_chunk_off = mem_chunk->data;
util_log_print(UTIL_LOG_DEBUG,
"DFI S390 mem_chunk_read: start=0x%016lx, off=0x%016lx, cnt=0x%08lx\n",
mem_chunk->start, off, cnt);
zg_seek(g.fh, *mem_chunk_off + off, ZG_CHECK);
zg_read(g.fh, buf, cnt, ZG_CHECK);
}
static inline unsigned long b2m(unsigned long blk)
{
return blk * l.blk_size;
}
/*
* Read compressed data entry using global file handle and decompress up to
* count bytes to the output buffer. The size of the output buffer considered
* to be enough to fit the decompressed data.
*/
static unsigned long read_decompress_entry(void *buf_out, u64 count)
{
unsigned char buf_in[8 * PAGE_SIZE];
z_stream strm = { 0 };
u64 total_out;
int rc;
/* Initialize inflate stream */
strm.next_in = NULL;
strm.avail_in = 0;
rc = inflateInit2(&strm, MAX_WBITS);
if (rc != Z_OK)
ERR_EXIT("Decompression failed, inflateInit RC = %d", rc);
strm.next_out = buf_out;
strm.avail_out = count;
/* Decompress data entry to the output buffer */
while (rc != Z_STREAM_END) {
/* Read in more compressed data */
if (strm.avail_in == 0) {
strm.next_in = buf_in;
rc = zg_read(g.fh, buf_in, sizeof(buf_in), ZG_CHECK_NONE);
if (rc < 0)
ERR_EXIT("Decompression failed, read error encountered");
strm.avail_in = rc;
}
rc = inflate(&strm, Z_SYNC_FLUSH);
if (rc != Z_OK && rc != Z_STREAM_END)
ERR_EXIT("Decompression failed, inflate RC = %d", rc);
/* No need to decompress more data */
if (strm.avail_out == 0)
break;
}
total_out = strm.total_out;
inflateEnd(&strm);
return total_out;
}
/*
* s390_ext compressed mem chunk read callback
*/
static void dfi_s390_ext_mem_chunk_read_decompress(struct dfi_mem_chunk *mem_chunk,
u64 off, void *buf, u64 cnt)
{
u64 bytes_to_copy, start_offset, compressed_data_addr, copied, decompressed_out;
struct mem_chunk_compressed_data *data = mem_chunk->data;
u32 uncompressed, entry_size, entry_index;
void *buf_out;
util_log_print(UTIL_LOG_DEBUG,
"DFI S390 mem_chunk_read_decomp: start=0x%016lx, offset_on_disk=0x%016lx, off=0x%016lx, cnt=0x%08lx\n",
mem_chunk->start, data->offset_on_disk, off, cnt);
/*
* The dump is compressed in data pieces of equal size (stored in the dump header).
* Identify the first compressed entry of interest within a memory chunk.
*/
entry_size = l.hdr.zlib_entry_size;
entry_index = off / entry_size;
/* Offset within the decompressed data of the first entry */
start_offset = off % entry_size;
buf_out = zg_alloc(entry_size);
copied = 0;
while (copied < cnt) {
if (entry_index >= data->entry_count)
ERR_EXIT("Decompression failed, compressed entry index out of bounds");
/* Check if the entry is actually compressed */
uncompressed = data->entry_offset[entry_index] & DUMP_SEGM_ENTRY_UNCOMPRESSED;
/* Calculate entry location on disk */
compressed_data_addr = data->offset_on_disk +
b2m(~DUMP_SEGM_ENTRY_UNCOMPRESSED & data->entry_offset[entry_index]);
if (uncompressed) {
/* Read entire uncompressed entry from disk */
zg_seek(g.fh, compressed_data_addr + start_offset, ZG_CHECK);
bytes_to_copy = MIN(cnt - copied, entry_size - start_offset);
zg_read(g.fh, buf + copied, bytes_to_copy, ZG_CHECK);
} else {
/*
* Decompress entry to the output buffer. Limit the size of the
* output data if needed.
*/
zg_seek(g.fh, compressed_data_addr, ZG_CHECK);
decompressed_out = MIN(start_offset + cnt - copied, entry_size);
decompressed_out = read_decompress_entry(buf_out, decompressed_out);
/* Copy the decompressed output produced so far */
bytes_to_copy = MIN(decompressed_out - start_offset, cnt - copied);
memcpy(buf + copied, buf_out + start_offset, bytes_to_copy);
}
copied += bytes_to_copy;
entry_index++;
/* For further entries, copy from the start of the decompressed data */
start_offset = 0;
}
zg_free(buf_out);
}
/*
* Read s390 dump header
@@ -78,6 +200,8 @@ static int read_s390_hdr(void)
return -ENODEV;
if (l.hdr.cpu_cnt > DF_S390_CPU_MAX)
return -ENODEV;
if (l.hdr.zlib_version_s390 && l.hdr.version != 2)
return -ENODEV;
util_log_print(UTIL_LOG_INFO, "DFI S390 version %u\n", l.hdr.version);
df_s390_hdr_add(&l.hdr);
return 0;
@@ -121,6 +245,44 @@ static int mem_chunks_add(void)
return read_s390_em();
}
/*
* Add memory chunk for a compressed dump segment. Set file handle position
* and return the offset to the next dump segment.
*/
static void create_compressed_mem_chunk(const struct df_s390_dump_segm_hdr *dump_segm,
u64 offset)
{
/*
* Need to preserve entry_offset array from the header of a
* compressed segment along with the segment offset on disk
* for the read callback function.
*/
struct mem_chunk_compressed_data *data = zg_alloc(sizeof(*data) +
dump_segm->entry_count * sizeof(u32));
data->offset_on_disk = offset;
data->entry_count = dump_segm->entry_count;
memcpy(&data->entry_offset, &dump_segm->entry_offset,
data->entry_count * sizeof(u32));
dfi_mem_chunk_add(dump_segm->start, dump_segm->len, data,
dfi_s390_ext_mem_chunk_read_decompress, zg_free);
data = NULL;
}
/*
* Add memory chunk for a non-compressed dump segment. Set file handle position
* and return the offset to the next dump segment.
*/
static void create_uncompressed_mem_chunk(const struct df_s390_dump_segm_hdr *dump_segm,
u64 offset)
{
/* For non-compressed segment just an offset is needed for a callback */
u64 *off_ptr = zg_alloc(sizeof(*off_ptr));
*off_ptr = offset;
dfi_mem_chunk_add(dump_segm->start, dump_segm->len, off_ptr,
dfi_s390_ext_mem_chunk_read, zg_free);
off_ptr = NULL;
}
/*
* Register memory chunks (extended dump format) and verify the end marker
*/
@@ -132,26 +294,30 @@ static int mem_chunks_add_ext(void)
off = zg_seek(g.fh, DF_S390_HDR_SIZE, ZG_CHECK_NONE);
if (off != DF_S390_HDR_SIZE)
return -EINVAL;
while (off < DF_S390_HDR_SIZE + l.hdr.mem_size - PAGE_SIZE) {
rc = zg_read(g.fh, &dump_segm, PAGE_SIZE, ZG_CHECK_ERR);
if (rc != PAGE_SIZE)
while (off < DF_S390_HDR_SIZE + l.hdr.mem_size) {
rc = zg_read(g.fh, &dump_segm, sizeof(dump_segm), ZG_CHECK_ERR);
if (rc != sizeof(dump_segm))
return -EINVAL;
util_log_print(UTIL_LOG_DEBUG,
"DFI S390 dump segment start 0x%016lx size 0x%016lx stop marker %d\n",
dump_segm.start, dump_segm.len, dump_segm.stop_marker);
off += PAGE_SIZE;
"DFI S390 dump segment start 0x%016lx size 0x%016lx compr_size 0x%08lx stop marker %d\n",
dump_segm.start, dump_segm.len, b2m(dump_segm.size_on_disk),
dump_segm.stop_marker ? 1 : 0);
off += sizeof(dump_segm);
/* Add zero memory chunk */
dfi_mem_chunk_add(old, dump_segm.start - old, NULL,
dfi_mem_chunk_read_zero, NULL);
/* Add memory chunk for a dump segment */
u64 *off_ptr = zg_alloc(sizeof(*off_ptr));
*off_ptr = off;
dfi_mem_chunk_add(dump_segm.start, dump_segm.len, off_ptr,
dfi_s390_ext_mem_chunk_read, zg_free);
off_ptr = NULL;
if (dump_segm.size_on_disk) {
/* Compressed dump segment detected */
create_compressed_mem_chunk(&dump_segm, off);
off = zg_seek_cur(g.fh, b2m(dump_segm.size_on_disk), ZG_CHECK_NONE);
dump_size += b2m(dump_segm.size_on_disk);
} else {
create_uncompressed_mem_chunk(&dump_segm, off);
off = zg_seek_cur(g.fh, dump_segm.len, ZG_CHECK_NONE);
dump_size += dump_segm.len;
}
old = dump_segm.start + dump_segm.len;
dump_size += dump_segm.len;
off = zg_seek_cur(g.fh, dump_segm.len, ZG_CHECK_NONE);
if (dump_segm.stop_marker)
break;
}
@@ -180,6 +346,7 @@ int dfi_s390_init_gen(bool extended)
l.extended = extended;
if (read_s390_hdr() != 0)
return -ENODEV;
zg_ioctl(g.fh, BLKSSZGET, &l.blk_size, "BLKSSZGET", ZG_CHECK);
if (!extended)
rc = mem_chunks_add();
else

View File

@@ -24,6 +24,7 @@
#include "lib/util_file.h"
#include "lib/util_path.h"
#include "dump/s390_dump.h"
#include "zgetdump.h"
#include "dt.h"

View File

@@ -19,6 +19,8 @@
#include <unistd.h>
#include <errno.h>
#include "dump/s390_dump.h"
#include "zgetdump.h"
#include "df_s390.h"
#include "dfi.h"

View File

@@ -17,6 +17,8 @@
#include <time.h>
#include <unistd.h>
#include "dump/s390_dump.h"
#include "df_s390.h"
#include "dfi_mem_chunk.h"
#include "dfo_mem_chunk.h"
@@ -69,7 +71,7 @@ static void cpu2lc_32(void *lc_32, struct dfi_cpu *cpu_64)
/*
* Convert timeval to s390 TOD clock
*/
static void timeval2tod(u64 *tod, struct timeval *xtime)
static void timeval2tod(uint64_t *tod, struct timeval *xtime)
{
u64 us = xtime->tv_sec * 1000000 + xtime->tv_usec;
*tod = (us << 12);

View File

@@ -109,11 +109,11 @@ static int dumper_read_validate_fba(int size, struct df_s390_dumper *dumper)
*/
static int dumper_read_fba(void)
{
if (dumper_read_validate_fba(DF_S390_DUMPER_SIZE_V3, &l.dumper) == 0)
if (dumper_read_validate_fba(STAGE2_DUMPER_SIZE_V3, &l.dumper) == 0)
return 0;
if (dumper_read_validate_fba(DF_S390_DUMPER_SIZE_V2, &l.dumper) == 0)
if (dumper_read_validate_fba(STAGE2_DUMPER_SIZE_V2, &l.dumper) == 0)
return 0;
if (dumper_read_validate_fba(DF_S390_DUMPER_SIZE_V1, &l.dumper) == 0)
if (dumper_read_validate_fba(STAGE2_DUMPER_SIZE_V1, &l.dumper) == 0)
return 0;
return -ENODEV;
}

View File

@@ -14,10 +14,12 @@
#include "dfo.h"
#include "output.h"
#define BUFFER_SIZE (1 * MIB)
int write_dump(FILE *stream)
{
const u64 output_size = dfo_size();
char buf[8UL * PAGE_SIZE];
char *buf = zg_alloc(BUFFER_SIZE);
u64 written = 0;
if (!dfi_feat_copy())
@@ -31,7 +33,7 @@ int write_dump(FILE *stream)
size_t rc;
u64 cnt;
cnt = dfo_read(buf, sizeof(buf));
cnt = dfo_read(buf, BUFFER_SIZE);
rc = fwrite(buf, cnt, 1, stream);
if (rc != 1 && ferror(stream))
ERR_EXIT("Error: Write failed");
@@ -40,5 +42,6 @@ int write_dump(FILE *stream)
};
STDERR("\n");
STDERR("Success: Dump has been copied\n");
zg_free(buf);
return 0;
}

View File

@@ -194,6 +194,7 @@ The following dump formats are supported for the source dump only:
.TP
.BR "s390_ext"
This dump format is IBM zSystems specific and is used for DASD dumps only.
Starting with s390_ext format version 2, dumps also support zlib compression.
.TP
.BR "vmdump"
Dumps with this format are created by the z/VM vmdump command
@@ -277,7 +278,16 @@ tool (see man zipl).
.TP
.BR "Dump file size"
Actual size of dump file on disk in megabytes. "Dump file size" may differ from
the "dump memory range" because of zero memory chunks.
the "dump memory range" because of zero memory chunks or dump compression.
.TP
.BR "Zlib version"
The version of zlib used for compressed dumps.
.TP
.BR "Zlib compression unit"
Size of the input data chunks that has been used for the dump zlib compression
by the dump tool. Every chunk of data is compressed separately and can be
decompressed independently, allowing zgetdump to make fast read seeks.
.br
.TP
.BR "Memory map"
Available memory chunks in the dump. Some dump tools create multiple memory

View File

@@ -6,6 +6,7 @@ all:
$(MAKE) -C src
install: all
$(MAKE) -C boot install
$(MAKE) -C src install
$(MAKE) -C man install
$(MAKE) -C dracut install

View File

@@ -1,6 +1,27 @@
# Common definitions
include ../../common.mak
EMBEDDED_BOOTLOADERS := fba0.bin fba1b.bin fba2.bin \
eckd0_ldl.bin eckd0_cdl.bin \
eckd1.bin eckd1b.bin eckd2.bin \
tape0.bin \
eckd2dump_sv.bin tape2dump.bin fba2dump.bin eckd2dump_mv.bin
DEBUG_EMBEDDED_BOOTLOADERS := $(addsuffix .debug,$(EMBEDDED_BOOTLOADERS))
EXTERNAL_BOOTLOADERS := stage3.bin
DEBUG_EXTERNAL_BOOTLOADERS := $(addsuffix .debug,$(EXTERNAL_BOOTLOADERS))
.loaders: $(EMBEDDED_BOOTLOADERS) $(DEBUG_EMBEDDED_BOOTLOADERS)
touch .loaders
.DEFAULT_GOAL := all
all: .loaders $(EXTERNAL_BOOTLOADERS) $(DEBUG_EXTERNAL_BOOTLOADERS)
clean:
rm -f -- ./**/*.o *.o *.exec *.bin *.lds .*.lds.d .loaders *.debug
.PHONY: all clean
ifeq ($(HOST_ARCH),s390x)
INCLUDE_PATHS := $(rootdir)/zipl/include $(rootdir)/include
INCLUDE_PARMS := $(addprefix -I,$(INCLUDE_PATHS))
@@ -13,19 +34,6 @@ ALL_CFLAGS = $(NO_PIE_CFLAGS) -Os -g $(INCLUDE_PARMS) \
-W -Wall -Wformat-security -fno-sanitize=all -Wno-array-bounds
ALL_LDFLAGS += -fno-sanitize=all
INC_FILES := fba0.bin fba1b.bin fba2.bin \
eckd0_ldl.bin eckd0_cdl.bin \
eckd1.bin eckd1b.bin eckd2.bin \
tape0.bin \
eckd2dump_sv.bin tape2dump.bin fba2dump.bin eckd2dump_mv.bin
FILES := $(INC_FILES) stage3.bin
DEBUG_FILES := $(addsuffix .debug,$(FILES))
all: .loaders $(FILES) $(DEBUG_FILES)
.loaders: $(INC_FILES)
touch .loaders
# Prevent make from using some default rules...
%: %.S
@@ -56,8 +64,9 @@ eckd1b.exec fba1b.exec: \
stage1b.lds
eckd2dump_sv.exec: \
head.o stage2dump.o cio.o eckd2dump.o eckd2dump_sv.o \
libc.o ebcdic.o sclp.o entry.o stage2.lds
head.o stage2dump.o cio.o eckd2dump.o eckd2dump_sv.o eckd2dump_zlib.o \
zlib/deflate.o zlib/deftree.o zlib/dfltcc.o zlib/dfltcc_deflate.o \
libc.o ebcdic.o sclp.o entry.o eckd2dump_sv.lds
eckd2dump_mv.exec: \
head.o stage2dump.o cio.o eckd2dump.o eckd2dump_mv.o \
libc.o ebcdic.o sclp.o entry.o stage2.lds
@@ -76,15 +85,27 @@ stage3.exec: head.o stage3.o kdump3.o libc.o ebcdic.o ebcdic_conv.o sclp.o \
%.exec: %.o
$(LINK) -Wl,-T,$(filter %.lds,$^) $(NO_PIE_LDFLAGS) $(NO_WARN_RWX_SEGMENTS_LDFLAGS) -Wl,--build-id=none -m64 -static -nostdlib $(filter %.o, $^) -o $@
@chmod a-x $@
%.bin.debug: %.exec
$(OBJCOPY) --only-keep-debug $< $@
@chmod a-x $@
%.bin: %.exec
$(OBJCOPY) -O binary $< $@
@chmod a-x $@
install: $(EXTERNAL_BOOTLOADERS)
$(INSTALL) -d -m 755 "$(DESTDIR)$(TOOLS_LIBDIR)"
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 $(EXTERNAL_BOOTLOADERS) "$(DESTDIR)$(TOOLS_LIBDIR)"
else
# Don't generate the dependency files (see `common.mak` for the
# `-include $(dependencies_c)` statement).
.PHONY: $(dependencies_c)
clean:
rm -f -- *.o *.exec *.bin *.lds .*.lds.d .loaders *.debug
$(EMBEDDED_BOOTLOADERS) $(DEBUG_EMBEDDED_BOOTLOADERS) $(EXTERNAL_BOOTLOADERS) $(DEBUG_EXTERNAL_BOOTLOADERS):
echo " SKIP $@ due to HOST_ARCH != s390x"
.PHONY: all clean
install:
echo " SKIP Bootloader installation due to HOST_ARCH != s390x"
endif

View File

@@ -3,12 +3,14 @@
*
* Common ECKD dump I/O functions
*
* Copyright IBM Corp. 2013, 2018
* Copyright IBM Corp. 2013, 2023
*
* 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 "dump/s390_dump.h"
#include "cio.h"
#include "eckd2dump.h"
#include "boot/error.h"
@@ -444,6 +446,38 @@ void readblock(unsigned long blk, unsigned long addr, unsigned long blk_count)
io_block(cmd, blk, addr, blk_count, 0, 1);
}
/*
* Write len/device.blk_size blocks of data at start address starting from
* given block and return the next free block number. The len value must be
* a multiple of a block size (4096 bytes).
*/
unsigned long write_addr_range(unsigned long blk, unsigned long start,
unsigned long len, int print_progress)
{
unsigned long addr, start_blk, blk_count, zero_page;
/* Verify the range is a multiple of a block size */
if (len % device.blk_size)
panic(EINTERNAL, "Invalid address range: [%016x, %016x]",
start, start + len);
addr = start;
start_blk = blk;
while (addr < start + len) {
/* Remaining blocks to write */
blk_count = m2b(len) - (blk - start_blk);
blk_count = MIN(blk_count, eckd_blk_max);
zero_page = get_zeroed_page();
writeblock(blk, addr, blk_count, zero_page);
free_page(zero_page);
blk += blk_count;
addr += b2m(blk_count);
total_dump_size += b2m(blk_count);
if (print_progress)
progress_print(addr);
}
return blk;
}
/*
* Write dump segment with the header to DASD and return the next free
* block number
@@ -451,28 +485,16 @@ void readblock(unsigned long blk, unsigned long addr, unsigned long blk_count)
unsigned long write_dump_segment(unsigned long blk,
struct df_s390_dump_segm_hdr *segm)
{
unsigned long addr, start_blk, blk_count, zero_page;
unsigned long zero_page;
/* Write the dump segment header itself (1 page) */
zero_page = get_zeroed_page();
writeblock(blk, (unsigned long)segm, m2b(PAGE_SIZE), zero_page);
writeblock(blk, (unsigned long)segm,
m2b(sizeof(struct df_s390_dump_segm_hdr)), zero_page);
free_page(zero_page);
blk += m2b(PAGE_SIZE);
/* Write the dump segment */
addr = segm->start;
start_blk = blk;
while (addr < segm->start + segm->len) {
/* Remaining blocks to write */
blk_count = m2b(segm->len) - (blk - start_blk);
blk_count = MIN(blk_count, eckd_blk_max);
zero_page = get_zeroed_page();
writeblock(blk, addr, blk_count, zero_page);
free_page(zero_page);
progress_print(addr);
blk += blk_count;
addr += b2m(blk_count);
}
return blk;
return write_addr_range(blk, segm->start, segm->len, PRINT_PROGRESS);
}
/*

View File

@@ -3,7 +3,7 @@
*
* Common ECKD dump I/O functions
*
* Copyright IBM Corp. 2013, 2018
* Copyright IBM Corp. 2013, 2023
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -11,6 +11,8 @@
#ifndef ECKD2DUMP_H
#define ECKD2DUMP_H
#include "dump/s390_dump.h"
#include "cio.h"
#include "stage2dump.h"
@@ -49,5 +51,9 @@ void writeblock(unsigned long blk, unsigned long addr, unsigned long blk_count,
void readblock(unsigned long blk, unsigned long addr, unsigned long blk_count);
unsigned long write_dump_segment(unsigned long blk,
struct df_s390_dump_segm_hdr *segm);
#define NO_PROGRESS 0
#define PRINT_PROGRESS 1
unsigned long write_addr_range(unsigned long blk, unsigned long addr,
unsigned long len, int print_progress);
#endif /* ECKD2DUMP_H */

View File

@@ -3,7 +3,7 @@
*
* Multi-volume ECKD DASD dump tool
*
* Copyright IBM Corp. 2013, 2018
* Copyright IBM Corp. 2013, 2023
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -11,6 +11,7 @@
#include "lib/zt_common.h"
#include "boot/error.h"
#include "dump/s390_dump.h"
#include "eckd2dump.h"
#include "stage2dump.h"
@@ -268,7 +269,6 @@ static unsigned long write_volume(unsigned long addr,
/* Reserve one block for the next segment header */
if (free_space)
free_space -= b2m(1);
total_dump_size += dump_segm->len;
/* Check if no more dump segments follow */
if (dump_segm->stop_marker) {
/* Write end marker */

View File

@@ -3,7 +3,7 @@
*
* Single-volume ECKD DASD dump tool
*
* Copyright IBM Corp. 2013, 2018
* Copyright IBM Corp. 2013, 2023
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -12,14 +12,16 @@
#include "lib/zt_common.h"
#include "boot/boot_defs.h"
#include "boot/error.h"
#include "dump/s390_dump.h"
#include "eckd2dump.h"
#include "eckd2dump_zlib.h"
#include "stage2dump.h"
/*
* Magic number at start of dump record
*/
const uint64_t __section(.stage2.head) magic = 0x5845434b44363401ULL; /* "XECKD64", version 1 */
const uint64_t __section(.stage2.head) magic = 0x5845434b44363402ULL; /* "XECKD64", version 2 */
/*
* Get device characteristics from zipl parameter block
@@ -46,40 +48,113 @@ void dt_device_enable(void)
stage2dump_eckd_init();
}
/*
* Dump all memory to DASD partition
*/
void dt_dump_mem(void)
static unsigned long dt_dump_mem_non_compressed(unsigned long addr,
unsigned long blk)
{
unsigned long blk, addr, end, page;
struct df_s390_dump_segm_hdr *dump_segm;
unsigned long end;
blk = device.blk_start;
dump_segm = (void *)get_zeroed_page();
/* Write dump header */
writeblock(blk, __pa(dump_hdr), m2b(DF_S390_HDR_SIZE), 0);
blk += m2b(DF_S390_HDR_SIZE);
/* Write memory */
addr = 0;
total_dump_size = 0;
/* Write memory uncompressed */
end = dump_hdr->mem_size;
while (addr < end) {
addr = find_dump_segment(addr, end, 0, dump_segm);
blk = write_dump_segment(blk, dump_segm);
total_dump_size += dump_segm->len;
if (dump_segm->stop_marker) {
addr = end;
if (dump_segm->start + dump_segm->len < end)
progress_print(addr);
break;
}
}
free_page(__pa(dump_segm));
progress_print(addr);
return blk;
}
static unsigned long dt_dump_mem_compressed(unsigned long addr,
unsigned long blk)
{
struct df_s390_dump_segm_hdr *dump_segm;
unsigned long end;
z_stream strm;
/* Write memory compressed with zlib deflate */
dump_segm = (void *)get_zeroed_page();
end = dump_hdr->mem_size;
/*
* Always write first megabyte of memory uncompressed in
* order to use it as zlib workarea
*/
dump_segm->start = addr;
dump_segm->len = ZLIB_WORKSPACE_LIMIT;
blk = write_dump_segment(blk, dump_segm);
addr += dump_segm->len;
/* Initialize zlib workarea, return value 0 is expected */
if (zlib_workarea_init(dump_segm->start, &strm)) {
printf("Zlib workarea initialization failed! Dumping without compression");
free_page(__pa(dump_segm));
return dt_dump_mem_non_compressed(addr, blk);
}
/*
* Compress on level 1 (hardware only) using default zlib
* wrapped stream.
*/
if (zlib_deflateInit2(&strm, 1, Z_DEFLATED, MAX_WBITS,
DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) {
/*
* Could not allocate or initialyze a workarea for zlib deflate,
* continue dumping without compression.
*/
printf("Deflate initialization failed! Dumping without compression");
free_page(__pa(dump_segm));
return dt_dump_mem_non_compressed(addr, blk);
}
while (addr < end) {
/*
* Limit the max size of compressed dump segment in order to
* fit all the compressed chunk entries in the segment header.
*/
addr = find_dump_segment(addr, end, DUMP_SEGM_ZLIB_MAXLEN,
dump_segm);
blk = write_compressed_dump_segment(blk, dump_segm, &strm);
if (dump_segm->stop_marker) {
addr = end;
if (dump_segm->start + dump_segm->len < end)
progress_print(addr);
break;
}
}
zlib_deflateEnd(&strm);
free_page(__pa(dump_segm));
return blk;
}
/*
* Dump all memory to DASD partition.
* Use zlib compression if DFLTCC facility is available.
*/
void dt_dump_mem(void)
{
unsigned long blk, start, page;
total_dump_size = 0;
/* Write dump header */
blk = device.blk_start;
writeblock(blk, __pa(dump_hdr), m2b(DF_S390_HDR_SIZE), 0);
blk += m2b(DF_S390_HDR_SIZE);
/* Write memory starting from zero address */
start = 0;
/* Check for zlib flag in the dump header */
if (dump_hdr->zlib_version_s390) {
printf("DFLTCC facility available, using zlib compression");
blk = dt_dump_mem_compressed(start, blk);
} else {
blk = dt_dump_mem_non_compressed(start, blk);
}
/* Write end marker */
page = get_zeroed_page();
df_s390_em_page_init(page);
writeblock(blk, page, 1, 0);
blk++;
free_page(page);
}

View File

@@ -0,0 +1,76 @@
/*
* Memory layout of stage 2 for single volume dasd
* dump tool with compression support
* ===============================================
*
* General memory layout
* ---------------------
*
* 0x0000-0x1fff Lowcore
* 0x2000-0x9fff Sections (load): head, text, data, rodata, rodata.str
* 0xa000-0xafff Sections: bss
* 0xb000-0xdfff Memory allocation (heap)
* 0xe000-0xffff Stack
*
* Special memory locations
* ------------------------
*
* 0x78 Stage 2 description parameters
* 0x2018 Stage 2 entry point
* 0x9ff8 Max mem dump parameter
*/
#include "boot/loaders_layout.h"
SECTIONS
{
. = STAGE2_DESC;
__stage2_desc = .;
. = STAGE2_LOAD_ADDRESS;
.stage2.head : { *(.stage2.head) }
. = STAGE2_ENTRY;
.text.start : {
*(.text.start)
}
.text : { *(.text) }
__ex_table_start = .;
.ex_table : { *(.ex_table) }
__ex_table_stop = .;
.rodata : {*(.rodata) }
.data : { *(.data) }
__stage2_params = .;
. = 0x9ff0;
.stage2dump.tail : { *(.stage2dump.tail) }
. = 0xa000;
__bss_start = .;
.bss : { *(.bss) }
__bss_stop = .;
. = ECKD2DUMP_SV_HEAP_ADDRESS;
__heap_start = .;
.heap : {
. += STAGE2_HEAP_SIZE;
ASSERT(__heap_stop - __heap_start == STAGE2_HEAP_SIZE,
"Heap section doesn't conform to the described memory layout");
}
__heap_stop = .;
. = ECKD2DUMP_SV_STACK_ADDRESS;
__stack_start = .;
.stack : {
. += ECKD2DUMP_SV_STACK_SIZE;
ASSERT(__stack_end - __stack_start == ECKD2DUMP_SV_STACK_SIZE,
"Stack section doesn't conform to the described memory layout");
}
__stack_end = .;
/* Sections to be discarded */
/DISCARD/ : {
*(.eh_frame)
*(.interp)
*(.note.GNU-stack)
}
}

183
zipl/boot/eckd2dump_zlib.c Normal file
View File

@@ -0,0 +1,183 @@
/*
* zipl - zSeries Initial Program Loader tool
*
* Common ECKD dump I/O functions
*
* Copyright IBM Corp. 2013, 2023
*
* 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 "cio.h"
#include "eckd2dump.h"
#include "eckd2dump_zlib.h"
#include "boot/linux_layout.h"
#include "boot/s390.h"
#include "stage2dump.h"
#include "dump/s390_dump.h"
/*
* The first megabyte of memory is used for zlib workspace and
* the output buffer for compressed data.
*/
static void *zlib_out_buf; // zlib output buffer
static unsigned long zlib_buf_size; // zlib output buffer size
/* Zlib workspace memory offset (skipping first 64K for the dumper itself) */
#define ZLIB_WORKSPACE_OFFSET IMAGE_ENTRY
/*
* Zlib workspace initialization.
* Return -1 if zlib deflate workspace requires more than half of the
* reserved memory area. Otherwise return 0.
*/
int zlib_workarea_init(unsigned long addr, z_stream *strm)
{
strm->workspace = (void *)MAX(addr, ZLIB_WORKSPACE_OFFSET);
zlib_out_buf = (void *)ROUND_UP((unsigned long)strm->workspace +
zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL),
PAGE_SIZE);
/* Make sure there is enough space left for zlib output buffer (at least half) */
if ((unsigned long)(zlib_out_buf - strm->workspace) > ZLIB_WORKSPACE_LIMIT / 2)
return -1;
/* Memory left for zlib output buffer (currently 692K) */
zlib_buf_size = addr + ZLIB_WORKSPACE_LIMIT - (unsigned long)zlib_out_buf;
return 0;
}
#define COMPRESSED 0
#define UNCOMPRESSED 1
#define COMPRESSION_ERROR -1
/*
* Compress chunk of data of given length at the given address using zlib
* deflate compression and write it starting from the given block number.
* Variable *blk is updated to the next free block number.
* Return 0 if memory chunk is successfully compressed and written.
* Return 1 if compression is ineffective and the entire chunk is written
* uncompressed.
* In case of deflate error, write the chunk uncompressed and return -1
*/
static int compress_write_next_chunk(unsigned long addr, unsigned long len,
unsigned long *blk, z_stream *strm)
{
unsigned long start_blk;
int rc;
/* Reset the stream for each new chunk */
zlib_deflateReset(strm);
strm->next_in = (void *)addr;
strm->avail_in = len;
strm->next_out = zlib_out_buf;
strm->avail_out = zlib_buf_size;
start_blk = *blk;
while (strm->avail_in != 0) {
rc = zlib_deflate(strm, Z_NO_FLUSH);
/*
* Compression error. Write this data chunk uncompressed and
* notify the caller.
*/
if (rc != Z_OK) {
*blk = write_addr_range(start_blk, addr, len, NO_PROGRESS);
return COMPRESSION_ERROR;
}
if (strm->avail_out == 0) {
/*
* If compressed output is larger than the input, write this chunk of
* data uncompressed and notify the caller with the return code.
* Do it only if no compressed output has been written yet.
*/
if (strm->total_out >= strm->total_in &&
*blk == start_blk) {
*blk = write_addr_range(start_blk, addr, len, NO_PROGRESS);
return UNCOMPRESSED;
}
*blk = write_addr_range(*blk, (unsigned long)zlib_out_buf,
zlib_buf_size, NO_PROGRESS);
strm->next_out = (void *)zlib_out_buf;
strm->avail_out = zlib_buf_size;
}
}
while (rc == Z_OK) {
strm->next_in = NULL;
strm->avail_in = 0;
rc = zlib_deflate(strm, Z_FINISH);
len = ROUND_UP(zlib_buf_size - strm->avail_out, PAGE_SIZE);
*blk = write_addr_range(*blk, (unsigned long)zlib_out_buf, len, NO_PROGRESS);
if (strm->avail_out == 0) {
strm->next_out = zlib_out_buf;
strm->avail_out = zlib_buf_size;
rc = Z_OK;
} else {
break;
}
}
return COMPRESSED;
}
/*
* Compress and write memory dump segment with the uncompressed header to DASD
* and return the next free block number.
* The compression takes place in chunks of data of equal size (currently 1MB)
* and the offset of each compressed chunk is stored in the dump segment
* header. Due to limited size of header, the maximum size of compressed dump
* segment is limited to DUMP_SEGM_ZLIB_MAXLEN.
* If compression of a memory chunk leads to the data expansion (due to
* incompressible input), the chunk of data is written uncompressed.
* Thus every chunk of data is compressed separately and can be
* decompressed independently. The main reason is to enable zgetdump to make
* fast read seeks. Otherwise, zgetdump would need to uncompress a big dump
* segment in the worst case to extract a single piece of data.
*/
unsigned long write_compressed_dump_segment(unsigned long blk,
struct df_s390_dump_segm_hdr *segm,
z_stream *strm)
{
unsigned long head_blk, start_blk, zero_page, len, offset = 0;
unsigned long chunk_size;
int rc;
head_blk = blk;
/* Skip one block for the header (written later on) */
blk += m2b(sizeof(struct df_s390_dump_segm_hdr));
/* Compress each data chunk of the dump segment separately */
chunk_size = dump_hdr->zlib_entry_size;
for (unsigned int i = 0; i <= segm->len / chunk_size; i++) {
/* Save starting block number */
start_blk = blk;
len = i < segm->len / chunk_size ?
chunk_size : segm->len % chunk_size;
if (len == 0)
break;
rc = compress_write_next_chunk(segm->start + i * chunk_size,
len, &blk, strm);
/*
* Store the offset to the compressed chunk of data written
* to disk in blocks.
*/
segm->entry_count++;
segm->entry_offset[i] = (uint32_t)offset;
/*
* Compression was ineffective or compression error ocurred,
* data chunk has benn written uncompressed.
*/
if (rc == UNCOMPRESSED || rc == COMPRESSION_ERROR)
segm->entry_offset[i] |= DUMP_SEGM_ENTRY_UNCOMPRESSED;
offset += blk - start_blk;
/* Print progress after each compressed chunk written */
progress_print(segm->start + i * chunk_size + len);
}
/* Compression successful, store compressed size in the segment header */
segm->size_on_disk = (uint32_t)offset;
/*
* Write the dump segment header itself (1 page, uncompressed) to
* the predefined location.
*/
zero_page = get_zeroed_page();
writeblock(head_blk, (unsigned long)segm,
m2b(sizeof(struct df_s390_dump_segm_hdr)), zero_page);
free_page(zero_page);
return blk;
}

View File

@@ -0,0 +1,25 @@
/*
* zipl - zSeries Initial Program Loader tool
*
* Common ECKD dump I/O functions for zlib compression support
*
* Copyright IBM Corp. 2013, 2023
*
* 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 ECKD2DUMP_ZLIB_H
#define ECKD2DUMP_ZLIB_H
#include "zlib/zlib.h"
#include "dump/s390_dump.h"
#define ZLIB_WORKSPACE_LIMIT (1 * MIB)
/* Compression related functions */
int zlib_workarea_init(unsigned long addr, z_stream *strm);
unsigned long write_compressed_dump_segment(unsigned long blk,
struct df_s390_dump_segm_hdr *segm,
z_stream *strm);
#endif /* ECKD2DUMP_ZLIB_H */

View File

@@ -3,7 +3,7 @@
*
* Single-volume FBA DASD dump tool
*
* Copyright IBM Corp. 2013, 2018
* Copyright IBM Corp. 2013, 2023
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -12,6 +12,7 @@
#include "lib/zt_common.h"
#include "boot/boot_defs.h"
#include "boot/error.h"
#include "dump/s390_dump.h"
#include "fba.h"
#include "stage2dump.h"
@@ -152,9 +153,10 @@ unsigned long write_dump_segment_fba(unsigned long blk,
zero_page = get_zeroed_page();
writeblock_fba(blk, addr, blk_count, zero_page);
free_page(zero_page);
progress_print(addr);
blk += blk_count;
addr += b2m(blk_count);
total_dump_size += b2m(blk_count);
progress_print(addr);
}
return blk;
}
@@ -206,7 +208,6 @@ void dt_dump_mem(void)
while (addr < end) {
addr = find_dump_segment(addr, end, 0, dump_segm);
blk = write_dump_segment_fba(blk, dump_segm);
total_dump_size += dump_segm->len;
if (dump_segm->stop_marker) {
addr = end;
break;

View File

@@ -3,7 +3,7 @@
*
* Common functions for stand-alone dump tools
*
* Copyright IBM Corp. 2013, 2018
* Copyright IBM Corp. 2013, 2023
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -13,12 +13,14 @@
#include "lib/zt_common.h"
#include "boot/error.h"
#include "dump/s390_dump.h"
#include "libc.h"
#include "sclp.h"
#include "stage2dump.h"
#include "boot/ipl.h"
#include "boot/os_info.h"
#include "boot/s390.h"
#define CPU_ADDRESS_MAX 1000
#define MACHINE_HAS_VX machine_has_vx
@@ -72,7 +74,6 @@ void progress_print(unsigned long addr)
}
if (time < next && addr != dump_hdr->mem_size)
return;
printf("%08lu / %08lu MB (Dump file size %08lu MB)", addr >> 20,
dump_hdr->mem_size >> 20, total_dump_size >> 20);
next = time + delta;
@@ -215,13 +216,23 @@ static void df_s390_dump_init(void)
dh->hdr_size = DF_S390_HDR_SIZE;
dh->page_size = PAGE_SIZE;
dh->dump_level = 4;
dh->version = 1;
dh->version = 2;
dh->mem_start = 0;
dh->arch = DF_S390_ARCH_64;
dh->build_arch = DF_S390_ARCH_64;
get_cpu_id((struct cpuid *) &dh->cpu_id);
dh->tod = get_tod_clock();
dh->volnr = 0;
dh->zlib_version_s390 = 0;
/*
* Ignore compression if --no-compress attribute has been specified
* or DFLTCC facility not available.
*/
if (test_facility(DFLTCC_FACILITY) &&
parm_tail.no_compress == 0) {
dh->zlib_version_s390 = 1; /* Indicate interlnal Zlib version */
dh->zlib_entry_size = DUMP_SEGM_ZLIB_ENTSIZE;
}
}
/*
@@ -444,10 +455,15 @@ void __noreturn start(void)
init_early();
dt_device_parm_setup();
sclp_setup(SCLP_INIT);
/* Store facility-list for future checks */
stfle(S390_lowcore.stfle_fac_list,
ARRAY_SIZE(S390_lowcore.stfle_fac_list));
dt_device_enable();
df_s390_dump_init();
printf("zIPL v%s dump tool (64 bit)", RELEASE_STRING);
printf("Dumping 64 bit OS");
if (parm_tail.no_compress)
printf("Dump compression prevented by the --no-compress attribute");
mem_and_cpu_init();
store_status();
dt_dump_mem();

View File

@@ -3,7 +3,7 @@
*
* Common dump functions
*
* Copyright IBM Corp. 2013, 2018
* Copyright IBM Corp. 2013, 2023
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -12,90 +12,16 @@
#ifndef STAGE2DUMP_H
#define STAGE2DUMP_H
#include "libc.h"
#include "boot/s390.h"
#include "dump/s390_dump.h"
#define IPL_SC S390_lowcore.tpi_info.schid
#define ROUND_DOWN(x, a) ((x) & ~((typeof(x))(a) - 1))
#define ROUND_UP(x, a) ROUND_DOWN((x) + (typeof(x))(a) - 1, a)
#define IS_ALIGNED(x, a) ~((x) & ((typeof(x))(a) - 1))
/*
* zipl parameters passed at tail of dump tools
*/
struct stage2dump_parm_tail {
char reserved[6];
uint16_t mvdump_force;
uint64_t mem_upper_limit;
} __packed;
extern struct stage2dump_parm_tail __section(.stage2dump.tail) parm_tail;
/*
* S390 dump format defines
*/
#define DF_S390_MAGIC 0xa8190173618f23fdULL
#define DF_S390_MAGIC_EXT 0xa8190173618f23feULL
#define DF_S390_HDR_SIZE 0x1000
#define DF_S390_EM_SIZE 16
#define DF_S390_EM_MAGIC 0x44554d505f454e44ULL
#define DF_S390_CPU_MAX 512
#define DF_S390_MAGIC_BLK_ECKD 3
/*
* Architecture of dumped system
*/
enum df_s390_arch {
DF_S390_ARCH_32 = 1,
DF_S390_ARCH_64 = 2,
};
/*
* s390 dump header format
*/
struct df_s390_hdr {
uint64_t magic; /* 0x000 */
uint32_t version; /* 0x008 */
uint32_t hdr_size; /* 0x00c */
uint32_t dump_level; /* 0x010 */
uint32_t page_size; /* 0x014 */
uint64_t mem_size; /* 0x018 */
uint64_t mem_start; /* 0x020 */
uint64_t mem_end; /* 0x028 */
uint32_t num_pages; /* 0x030 */
uint32_t pad; /* 0x034 */
uint64_t tod; /* 0x038 */
uint64_t cpu_id; /* 0x040 */
uint32_t arch; /* 0x048 */
uint32_t volnr; /* 0x04c */
uint32_t build_arch; /* 0x050 */
uint64_t mem_size_real; /* 0x054 */
uint8_t mvdump; /* 0x05c */
uint16_t cpu_cnt; /* 0x05d */
uint16_t real_cpu_cnt; /* 0x05f */
uint8_t end_pad1[0x200-0x061]; /* 0x061 */
uint64_t mvdump_sign; /* 0x200 */
uint64_t mvdump_zipl_time; /* 0x208 */
uint8_t end_pad2[0x800-0x210]; /* 0x210 */
uint32_t lc_vec[DF_S390_CPU_MAX]; /* 0x800 */
} __packed __aligned(16);
/*
* End marker: Should be at the end of every valid s390 crash dump
*/
struct df_s390_em {
uint64_t magic;
uint64_t tod;
} __packed __aligned(16);
/*
* Dump segment header
*/
struct df_s390_dump_segm_hdr {
uint64_t start;
uint64_t len;
uint64_t stop_marker;
};
/*
* Linker script defined symbols
*/
@@ -113,7 +39,6 @@ extern unsigned long total_dump_size;
*/
void create_ida_list(unsigned long *list, int len, unsigned long addr,
unsigned long zero_page);
void init_progress_print(void);
void progress_print(unsigned long addr);
void df_s390_em_page_init(unsigned long page);
void pgm_check_handler(void);

View File

@@ -3,7 +3,7 @@
*
* Dump tool for channel-attached tape devices
*
* Copyright IBM Corp. 2013, 2017
* Copyright IBM Corp. 2013, 2023
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -14,6 +14,7 @@
#include "boot/error.h"
#include "boot/loaders_layout.h"
#include "boot/s390.h"
#include "dump/s390_dump.h"
#include "cio.h"
#include "stage2dump.h"
@@ -205,13 +206,14 @@ void dt_dump_mem(void)
setup_idrc_compression();
ccw_write_tapemark();
total_dump_size = 0;
ccw_write_block((unsigned long) dump_hdr, DF_S390_HDR_SIZE, 0);
for (addr = 0; addr < dump_hdr->mem_size; addr += BLK_SIZE) {
ccw_write_block(addr, BLK_SIZE, page);
progress_print(addr);
progress_print_disp(addr);
total_dump_size += BLK_SIZE;
progress_print(addr + BLK_SIZE);
progress_print_disp(addr + BLK_SIZE);
}
progress_print(addr);
df_s390_em_page_init(page);
ccw_write_block(page, sizeof(struct df_s390_em), 0);
free_page(page);

1152
zipl/boot/zlib/deflate.c Normal file

File diff suppressed because it is too large Load Diff

1058
zipl/boot/zlib/deftree.c Normal file

File diff suppressed because it is too large Load Diff

446
zipl/boot/zlib/defutil.h Normal file
View File

@@ -0,0 +1,446 @@
#ifndef DEFUTIL_H
#define DEFUTIL_H
#include "zlib/zutil.h"
#include "../libc.h"
#define Assert(err, str)
#define Trace(dummy)
#define Tracev(dummy)
#define Tracecv(err, dummy)
#define Tracevv(dummy)
#define PAGE_SIZE 4096
#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
#define max(a, b) MAX(a, b)
#define LENGTH_CODES 29
/* number of length codes, not counting the special END_BLOCK code */
#define LITERALS 256
/* number of literal bytes 0..255 */
#define L_CODES (LITERALS+1+LENGTH_CODES)
/* number of Literal or Length codes, including the END_BLOCK code */
#define D_CODES 30
/* number of distance codes */
#define BL_CODES 19
/* number of codes used to transfer the bit lengths */
#define HEAP_SIZE (2*L_CODES+1)
/* maximum heap size */
#define MAX_BITS 15
/* All codes must not exceed MAX_BITS bits */
#define INIT_STATE 42
#define BUSY_STATE 113
#define FINISH_STATE 666
/* Stream status */
/* Data structure describing a single value and its code string. */
typedef struct ct_data_s {
union {
ush freq; /* frequency count */
ush code; /* bit string */
} fc;
union {
ush dad; /* father node in Huffman tree */
ush len; /* length of bit string */
} dl;
} ct_data;
#define Freq fc.freq
#define Code fc.code
#define Dad dl.dad
#define Len dl.len
typedef struct static_tree_desc_s static_tree_desc;
typedef struct tree_desc_s {
ct_data *dyn_tree; /* the dynamic tree */
int max_code; /* largest code with non zero frequency */
static_tree_desc *stat_desc; /* the corresponding static tree */
} tree_desc;
typedef ush Pos;
typedef unsigned IPos;
/* A Pos is an index in the character window. We use short instead of int to
* save space in the various tables. IPos is used only for parameter passing.
*/
typedef struct deflate_state {
z_streamp strm; /* pointer back to this zlib stream */
int status; /* as the name implies */
Byte *pending_buf; /* output still pending */
ulg pending_buf_size; /* size of pending_buf */
Byte *pending_out; /* next pending byte to output to the stream */
int pending; /* nb of bytes in the pending buffer */
int noheader; /* suppress zlib header and adler32 */
Byte data_type; /* UNKNOWN, BINARY or ASCII */
Byte method; /* STORED (for zip only) or DEFLATED */
int last_flush; /* value of flush param for previous deflate call */
/* used by deflate.c: */
uInt w_size; /* LZ77 window size (32K by default) */
uInt w_bits; /* log2(w_size) (8..16) */
uInt w_mask; /* w_size - 1 */
Byte *window;
/* Sliding window. Input bytes are read into the second half of the window,
* and move to the first half later to keep a dictionary of at least wSize
* bytes. With this organization, matches are limited to a distance of
* wSize-MAX_MATCH bytes, but this ensures that IO is always
* performed with a length multiple of the block size. Also, it limits
* the window size to 64K, which is quite useful on MSDOS.
* To do: use the user input buffer as sliding window.
*/
ulg window_size;
/* Actual size of window: 2*wSize, except when the user input buffer
* is directly used as sliding window.
*/
Pos *prev;
/* Link to older string with same hash index. To limit the size of this
* array to 64K, this link is maintained only for the last 32K strings.
* An index in this array is thus a window index modulo 32K.
*/
Pos *head; /* Heads of the hash chains or NIL. */
uInt ins_h; /* hash index of string to be inserted */
uInt hash_size; /* number of elements in hash table */
uInt hash_bits; /* log2(hash_size) */
uInt hash_mask; /* hash_size-1 */
uInt hash_shift;
/* Number of bits by which ins_h must be shifted at each input
* step. It must be such that after MIN_MATCH steps, the oldest
* byte no longer takes part in the hash key, that is:
* hash_shift * MIN_MATCH >= hash_bits
*/
long block_start;
/* Window position at the beginning of the current output block. Gets
* negative when the window is moved backwards.
*/
uInt match_length; /* length of best match */
IPos prev_match; /* previous match */
int match_available; /* set if previous match exists */
uInt strstart; /* start of string to insert */
uInt match_start; /* start of matching string */
uInt lookahead; /* number of valid bytes ahead in window */
uInt prev_length;
/* Length of the best match at previous step. Matches not greater than this
* are discarded. This is used in the lazy match evaluation.
*/
uInt max_chain_length;
/* To speed up deflation, hash chains are never searched beyond this
* length. A higher limit improves compression ratio but degrades the
* speed.
*/
uInt max_lazy_match;
/* Attempt to find a better match only when the current match is strictly
* smaller than this value. This mechanism is used only for compression
* levels >= 4.
*/
# define max_insert_length max_lazy_match
/* Insert new strings in the hash table only if the match length is not
* greater than this length. This saves time but degrades compression.
* max_insert_length is used only for compression levels <= 3.
*/
int level; /* compression level (1..9) */
int strategy; /* favor or force Huffman coding*/
uInt good_match;
/* Use a faster search when the previous match is longer than this */
int nice_match; /* Stop searching when current match exceeds this */
/* used by trees.c: */
/* Didn't use ct_data typedef below to suppress compiler warning */
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
struct tree_desc_s l_desc; /* desc. for literal tree */
struct tree_desc_s d_desc; /* desc. for distance tree */
struct tree_desc_s bl_desc; /* desc. for bit length tree */
ush bl_count[MAX_BITS+1];
/* number of codes at each bit length for an optimal tree */
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
int heap_len; /* number of elements in the heap */
int heap_max; /* element of largest frequency */
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
* The same heap array is used to build all trees.
*/
uch depth[2*L_CODES+1];
/* Depth of each subtree used as tie breaker for trees of equal frequency
*/
uch *l_buf; /* buffer for literals or lengths */
uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for
* limiting lit_bufsize to 64K:
* - frequencies can be kept in 16 bit counters
* - if compression is not successful for the first block, all input
* data is still in the window so we can still emit a stored block even
* when input comes from standard input. (This can also be done for
* all blocks if lit_bufsize is not greater than 32K.)
* - if compression is not successful for a file smaller than 64K, we can
* even emit a stored file instead of a stored block (saving 5 bytes).
* This is applicable only for zip (not gzip or zlib).
* - creating new Huffman trees less frequently may not provide fast
* adaptation to changes in the input data statistics. (Take for
* example a binary file with poorly compressible code followed by
* a highly compressible string table.) Smaller buffer sizes give
* fast adaptation but have of course the overhead of transmitting
* trees more frequently.
* - I can't count above 4
*/
uInt last_lit; /* running index in l_buf */
ush *d_buf;
/* Buffer for distances. To simplify the code, d_buf and l_buf have
* the same number of elements. To use different lengths, an extra flag
* array would be necessary.
*/
ulg opt_len; /* bit length of current block with optimal trees */
ulg static_len; /* bit length of current block with static trees */
ulg compressed_len; /* total bit length of compressed file */
uInt matches; /* number of string matches in current block */
int last_eob_len; /* bit length of EOB code for last block */
#ifdef DEBUG_ZLIB
ulg bits_sent; /* bit length of the compressed data */
#endif
ush bi_buf;
/* Output buffer. bits are inserted starting at the bottom (least
* significant bits).
*/
int bi_valid;
/* Number of valid bits in bi_buf. All bits above the last valid bit
* are always zero.
*/
} deflate_state;
#ifdef CONFIG_ZLIB_DFLTCC
#define zlib_deflate_window_memsize(windowBits) \
(2 * (1 << (windowBits)) * sizeof(Byte) + PAGE_SIZE)
#else
#define zlib_deflate_window_memsize(windowBits) \
(2 * (1 << (windowBits)) * sizeof(Byte))
#endif
#define zlib_deflate_prev_memsize(windowBits) \
((1 << (windowBits)) * sizeof(Pos))
#define zlib_deflate_head_memsize(memLevel) \
((1 << ((memLevel)+7)) * sizeof(Pos))
#define zlib_deflate_overlay_memsize(memLevel) \
((1 << ((memLevel)+6)) * (sizeof(ush)+2))
/* Output a byte on the stream.
* IN assertion: there is enough room in pending_buf.
*/
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
/* Minimum amount of lookahead, except at the end of the input file.
* See deflate.c for comments about the MIN_MATCH+1.
*/
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
/* In order to simplify the code, particularly on 16 bit machines, match
* distances are limited to MAX_DIST instead of WSIZE.
*/
/* in trees.c */
void zlib_tr_init (deflate_state *s);
int zlib_tr_tally (deflate_state *s, unsigned dist, unsigned lc);
ulg zlib_tr_flush_block (deflate_state *s, char *buf, ulg stored_len,
int eof);
void zlib_tr_align (deflate_state *s);
void zlib_tr_stored_block (deflate_state *s, char *buf, ulg stored_len,
int eof);
void zlib_tr_stored_type_only (deflate_state *);
/* ===========================================================================
* Output a short LSB first on the stream.
* IN assertion: there is enough room in pendingBuf.
*/
#define put_short(s, w) { \
put_byte(s, (uch)((w) & 0xff)); \
put_byte(s, (uch)((ush)(w) >> 8)); \
}
/* ===========================================================================
* Reverse the first len bits of a code, using straightforward code (a faster
* method would use a table)
* IN assertion: 1 <= len <= 15
*/
static inline unsigned bi_reverse(
unsigned code, /* the value to invert */
int len /* its bit length */
)
{
register unsigned res = 0;
do {
res |= code & 1;
code >>= 1, res <<= 1;
} while (--len > 0);
return res >> 1;
}
/* ===========================================================================
* Flush the bit buffer, keeping at most 7 bits in it.
*/
static inline void bi_flush(deflate_state *s)
{
if (s->bi_valid == 16) {
put_short(s, s->bi_buf);
s->bi_buf = 0;
s->bi_valid = 0;
} else if (s->bi_valid >= 8) {
put_byte(s, (Byte)s->bi_buf);
s->bi_buf >>= 8;
s->bi_valid -= 8;
}
}
/* ===========================================================================
* Flush the bit buffer and align the output on a byte boundary
*/
static inline void bi_windup(deflate_state *s)
{
if (s->bi_valid > 8) {
put_short(s, s->bi_buf);
} else if (s->bi_valid > 0) {
put_byte(s, (Byte)s->bi_buf);
}
s->bi_buf = 0;
s->bi_valid = 0;
#ifdef DEBUG_ZLIB
s->bits_sent = (s->bits_sent+7) & ~7;
#endif
}
typedef enum {
need_more, /* block not completed, need more input or more output */
block_done, /* block flush performed */
finish_started, /* finish started, need only more output at next deflate */
finish_done /* finish done, accept no more input or output */
} block_state;
#define Buf_size (8 * 2*sizeof(char))
/* Number of bits used within bi_buf. (bi_buf might be implemented on
* more than 16 bits on some systems.)
*/
/* ===========================================================================
* Send a value on a given number of bits.
* IN assertion: length <= 16 and value fits in length bits.
*/
#ifdef DEBUG_ZLIB
static void send_bits (deflate_state *s, int value, int length);
static void send_bits(
deflate_state *s,
int value, /* value to send */
int length /* number of bits */
)
{
Tracevv((stderr," l %2d v %4x ", length, value));
Assert(length > 0 && length <= 15, "invalid length");
s->bits_sent += (ulg)length;
/* If not enough room in bi_buf, use (valid) bits from bi_buf and
* (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
* unused bits in value.
*/
if (s->bi_valid > (int)Buf_size - length) {
s->bi_buf |= (value << s->bi_valid);
put_short(s, s->bi_buf);
s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
s->bi_valid += length - Buf_size;
} else {
s->bi_buf |= value << s->bi_valid;
s->bi_valid += length;
}
}
#else /* !DEBUG_ZLIB */
#define send_bits(s, value, length) \
{ int len = length;\
if (s->bi_valid > (int)Buf_size - len) {\
int val = value;\
s->bi_buf |= (val << s->bi_valid);\
put_short(s, s->bi_buf);\
s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
s->bi_valid += len - Buf_size;\
} else {\
s->bi_buf |= (value) << s->bi_valid;\
s->bi_valid += len;\
}\
}
#endif /* DEBUG_ZLIB */
static inline void zlib_tr_send_bits(
deflate_state *s,
int value,
int length
)
{
send_bits(s, value, length);
}
/* =========================================================================
* Flush as much pending output as possible. All deflate() output goes
* through this function so some applications may wish to modify it
* to avoid allocating a large strm->next_out buffer and copying into it.
* (See also read_buf()).
*/
static inline void flush_pending(
z_streamp strm
)
{
unsigned len;
deflate_state *s = (deflate_state *) strm->state;
bi_flush(s);
len = s->pending;
if (len > strm->avail_out) len = strm->avail_out;
if (len == 0) return;
if (strm->next_out != NULL) {
memcpy(strm->next_out, s->pending_out, len);
strm->next_out += len;
}
s->pending_out += len;
strm->total_out += len;
strm->avail_out -= len;
s->pending -= len;
if (s->pending == 0) {
s->pending_out = s->pending_buf;
}
}
#endif /* DEFUTIL_H */

37
zipl/boot/zlib/dfltcc.c Normal file
View File

@@ -0,0 +1,37 @@
// SPDX-License-Identifier: Zlib
/* dfltcc.c - SystemZ DEFLATE CONVERSION CALL support. */
#include "dfltcc_util.h"
#include "dfltcc.h"
char *oesc_msg(
char *buf,
int oesc
)
{
if (oesc == 0x00)
return NULL; /* Successful completion */
else {
#ifdef STATIC
return NULL; /* Ignore for pre-boot decompressor */
#else
snprintf(buf, 64, "Operation-Ending-Supplemental Code is 0x%.2X", oesc);
return buf;
#endif
}
}
void dfltcc_reset_state(struct dfltcc_state *dfltcc_state) {
/* Initialize available functions */
if (is_dfltcc_enabled()) {
dfltcc(DFLTCC_QAF, &dfltcc_state->param, NULL, NULL, NULL, NULL, NULL);
memmove(&dfltcc_state->af, &dfltcc_state->param, sizeof(dfltcc_state->af));
} else
memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
/* Initialize parameter block */
memset(&dfltcc_state->param, 0, sizeof(dfltcc_state->param));
dfltcc_state->param.nt = 1;
dfltcc_state->param.ribm = DFLTCC_RIBM;
}

123
zipl/boot/zlib/dfltcc.h Normal file
View File

@@ -0,0 +1,123 @@
// SPDX-License-Identifier: Zlib
#ifndef DFLTCC_H
#define DFLTCC_H
#include <stdint.h>
#include "lib/zt_common.h"
#include "defutil.h"
/*
* Tuning parameters.
*/
#define DFLTCC_LEVEL_MASK 0x2 /* DFLTCC compression for level 1 only */
#define DFLTCC_LEVEL_MASK_DEBUG 0x3fe /* DFLTCC compression for all levels */
#define DFLTCC_BLOCK_SIZE 1048576
#define DFLTCC_FIRST_FHT_BLOCK_SIZE 4096
#define DFLTCC_DHT_MIN_SAMPLE_SIZE 4096
#define DFLTCC_RIBM 0
#define DFLTCC_FACILITY 151
/*
* Parameter Block for Query Available Functions.
*/
struct dfltcc_qaf_param {
char fns[16];
char reserved1[8];
char fmts[2];
char reserved2[6];
};
STATIC_ASSERT(sizeof(struct dfltcc_qaf_param) == 32);
#define DFLTCC_FMT0 0
/*
* Parameter Block for Generate Dynamic-Huffman Table, Compress and Expand.
*/
struct dfltcc_param_v0 {
uint16_t pbvn; /* Parameter-Block-Version Number */
uint8_t mvn; /* Model-Version Number */
uint8_t ribm; /* Reserved for IBM use */
unsigned reserved32 : 31;
unsigned cf : 1; /* Continuation Flag */
uint8_t reserved64[8];
unsigned nt : 1; /* New Task */
unsigned reserved129 : 1;
unsigned cvt : 1; /* Check Value Type */
unsigned reserved131 : 1;
unsigned htt : 1; /* Huffman-Table Type */
unsigned bcf : 1; /* Block-Continuation Flag */
unsigned bcc : 1; /* Block Closing Control */
unsigned bhf : 1; /* Block Header Final */
unsigned reserved136 : 1;
unsigned reserved137 : 1;
unsigned dhtgc : 1; /* DHT Generation Control */
unsigned reserved139 : 5;
unsigned reserved144 : 5;
unsigned sbb : 3; /* Sub-Byte Boundary */
uint8_t oesc; /* Operation-Ending-Supplemental Code */
unsigned reserved160 : 12;
unsigned ifs : 4; /* Incomplete-Function Status */
uint16_t ifl; /* Incomplete-Function Length */
uint8_t reserved192[8];
uint8_t reserved256[8];
uint8_t reserved320[4];
uint16_t hl; /* History Length */
unsigned reserved368 : 1;
uint16_t ho : 15; /* History Offset */
uint32_t cv; /* Check Value */
unsigned eobs : 15; /* End-of-block Symbol */
unsigned reserved431: 1;
uint8_t eobl : 4; /* End-of-block Length */
unsigned reserved436 : 12;
unsigned reserved448 : 4;
uint16_t cdhtl : 12; /* Compressed-Dynamic-Huffman Table
Length */
uint8_t reserved464[6];
uint8_t cdht[288];
uint8_t reserved[32];
uint8_t csb[1152];
};
STATIC_ASSERT(sizeof(struct dfltcc_param_v0) == 1536);
#define CVT_CRC32 0
#define CVT_ADLER32 1
#define HTT_FIXED 0
#define HTT_DYNAMIC 1
/*
* Extension of inflate_state and deflate_state for DFLTCC.
*/
struct dfltcc_state {
struct dfltcc_param_v0 param; /* Parameter block */
struct dfltcc_qaf_param af; /* Available functions */
char msg[64]; /* Buffer for strm->msg */
};
/*
* Extension of inflate_state and deflate_state for DFLTCC.
*/
struct dfltcc_deflate_state {
struct dfltcc_state common; /* Parameter block */
uLong level_mask; /* Levels on which to use DFLTCC */
uLong block_size; /* New block each X bytes */
uLong block_threshold; /* New block after total_in > X */
uLong dht_threshold; /* New block only if avail_in >= X */
};
#define ALIGN_UP(p, size) (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) & ~((size) - 1))
/* Resides right after inflate_state or deflate_state */
#define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((char *)(state) + ALIGN_UP(sizeof(*state), 8)))
void dfltcc_reset_state(struct dfltcc_state *dfltcc_state);
static inline int is_dfltcc_enabled(void)
{
return 1; /* Consider DFLTCC facility always enabled */
}
#define DEFLATE_DFLTCC_ENABLED() is_dfltcc_enabled()
#endif /* DFLTCC_H */

View File

@@ -0,0 +1,300 @@
// SPDX-License-Identifier: Zlib
#include "defutil.h"
#include "dfltcc_util.h"
#include "dfltcc_deflate.h"
#include "zlib/zutil.h"
#define GET_DFLTCC_DEFLATE_STATE(state) ((struct dfltcc_deflate_state *)GET_DFLTCC_STATE(state))
/*
* Compress.
*/
int dfltcc_can_deflate(
z_streamp strm
)
{
deflate_state *state = (deflate_state *)strm->state;
struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state);
/* Unsupported compression settings */
if (!dfltcc_are_params_ok(state->level, state->w_bits, state->strategy,
dfltcc_state->level_mask))
return 0;
/* Unsupported hardware */
if (!is_bit_set(dfltcc_state->common.af.fns, DFLTCC_GDHT) ||
!is_bit_set(dfltcc_state->common.af.fns, DFLTCC_CMPR) ||
!is_bit_set(dfltcc_state->common.af.fmts, DFLTCC_FMT0))
return 0;
return 1;
}
void dfltcc_reset_deflate_state(z_streamp strm) {
deflate_state *state = (deflate_state *)strm->state;
struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state);
dfltcc_reset_state(&dfltcc_state->common);
/* Initialize tuning parameters */
dfltcc_state->level_mask = DFLTCC_LEVEL_MASK;
dfltcc_state->block_size = DFLTCC_BLOCK_SIZE;
dfltcc_state->block_threshold = DFLTCC_FIRST_FHT_BLOCK_SIZE;
dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE;
}
static void dfltcc_gdht(
z_streamp strm
)
{
deflate_state *state = (deflate_state *)strm->state;
struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
size_t avail_in = strm->avail_in;
dfltcc(DFLTCC_GDHT,
param, NULL, NULL,
&strm->next_in, &avail_in, NULL);
}
static dfltcc_cc dfltcc_cmpr(
z_streamp strm
)
{
deflate_state *state = (deflate_state *)strm->state;
struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
size_t avail_in = strm->avail_in;
size_t avail_out = strm->avail_out;
dfltcc_cc cc;
cc = dfltcc(DFLTCC_CMPR | HBT_CIRCULAR,
param, &strm->next_out, &avail_out,
&strm->next_in, &avail_in, state->window);
strm->total_in += (strm->avail_in - avail_in);
strm->total_out += (strm->avail_out - avail_out);
strm->avail_in = avail_in;
strm->avail_out = avail_out;
return cc;
}
static void send_eobs(
z_streamp strm,
const struct dfltcc_param_v0 *param
)
{
deflate_state *state = (deflate_state *)strm->state;
zlib_tr_send_bits(
state,
bi_reverse(param->eobs >> (15 - param->eobl), param->eobl),
param->eobl);
flush_pending(strm);
if (state->pending != 0) {
/* The remaining data is located in pending_out[0:pending]. If someone
* calls put_byte() - this might happen in deflate() - the byte will be
* placed into pending_buf[pending], which is incorrect. Move the
* remaining data to the beginning of pending_buf so that put_byte() is
* usable again.
*/
memmove(state->pending_buf, state->pending_out, state->pending);
state->pending_out = state->pending_buf;
}
#ifdef ZLIB_DEBUG
state->compressed_len += param->eobl;
#endif
}
int dfltcc_deflate(
z_streamp strm,
int flush,
block_state *result
)
{
deflate_state *state = (deflate_state *)strm->state;
struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state);
struct dfltcc_param_v0 *param = &dfltcc_state->common.param;
uInt masked_avail_in;
dfltcc_cc cc;
int need_empty_block;
int soft_bcc;
int no_flush;
if (!dfltcc_can_deflate(strm)) {
/* Clear history. */
if (flush == Z_FULL_FLUSH)
param->hl = 0;
return 0;
}
again:
masked_avail_in = 0;
soft_bcc = 0;
no_flush = flush == Z_NO_FLUSH;
/* No input data. Return, except when Continuation Flag is set, which means
* that DFLTCC has buffered some output in the parameter block and needs to
* be called again in order to flush it.
*/
if (strm->avail_in == 0 && !param->cf) {
/* A block is still open, and the hardware does not support closing
* blocks without adding data. Thus, close it manually.
*/
if (!no_flush && param->bcf) {
send_eobs(strm, param);
param->bcf = 0;
}
/* Let one of deflate_* functions write a trailing empty block. */
if (flush == Z_FINISH)
return 0;
/* Clear history. */
if (flush == Z_FULL_FLUSH)
param->hl = 0;
/* Trigger block post-processing if necessary. */
*result = no_flush ? need_more : block_done;
return 1;
}
/* There is an open non-BFINAL block, we are not going to close it just
* yet, we have compressed more than DFLTCC_BLOCK_SIZE bytes and we see
* more than DFLTCC_DHT_MIN_SAMPLE_SIZE bytes. Open a new block with a new
* DHT in order to adapt to a possibly changed input data distribution.
*/
if (param->bcf && no_flush &&
strm->total_in > dfltcc_state->block_threshold &&
strm->avail_in >= dfltcc_state->dht_threshold) {
if (param->cf) {
/* We need to flush the DFLTCC buffer before writing the
* End-of-block Symbol. Mask the input data and proceed as usual.
*/
masked_avail_in += strm->avail_in;
strm->avail_in = 0;
no_flush = 0;
} else {
/* DFLTCC buffer is empty, so we can manually write the
* End-of-block Symbol right away.
*/
send_eobs(strm, param);
param->bcf = 0;
dfltcc_state->block_threshold =
strm->total_in + dfltcc_state->block_size;
}
}
/* No space for compressed data. If we proceed, dfltcc_cmpr() will return
* DFLTCC_CC_OP1_TOO_SHORT without buffering header bits, but we will still
* set BCF=1, which is wrong. Avoid complications and return early.
*/
if (strm->avail_out == 0) {
*result = need_more;
return 1;
}
/* The caller gave us too much data. Pass only one block worth of
* uncompressed data to DFLTCC and mask the rest, so that on the next
* iteration we start a new block.
*/
if (no_flush && strm->avail_in > dfltcc_state->block_size) {
masked_avail_in += (strm->avail_in - dfltcc_state->block_size);
strm->avail_in = dfltcc_state->block_size;
}
/* When we have an open non-BFINAL deflate block and caller indicates that
* the stream is ending, we need to close an open deflate block and open a
* BFINAL one.
*/
need_empty_block = flush == Z_FINISH && param->bcf && !param->bhf;
/* Translate stream to parameter block */
param->cvt = CVT_ADLER32;
if (!no_flush)
/* We need to close a block. Always do this in software - when there is
* no input data, the hardware will not hohor BCC. */
soft_bcc = 1;
if (flush == Z_FINISH && !param->bcf)
/* We are about to open a BFINAL block, set Block Header Final bit
* until the stream ends.
*/
param->bhf = 1;
/* DFLTCC-CMPR will write to next_out, so make sure that buffers with
* higher precedence are empty.
*/
Assert(state->pending == 0, "There must be no pending bytes");
Assert(state->bi_valid < 8, "There must be less than 8 pending bits");
param->sbb = (unsigned int)state->bi_valid;
if (param->sbb > 0)
*strm->next_out = (Byte)state->bi_buf;
/* Honor history and check value */
param->nt = 0;
param->cv = strm->adler;
/* When opening a block, choose a Huffman-Table Type */
if (!param->bcf) {
if (strm->total_in == 0 && dfltcc_state->block_threshold > 0) {
param->htt = HTT_FIXED;
}
else {
param->htt = HTT_DYNAMIC;
dfltcc_gdht(strm);
}
}
/* Deflate */
do {
cc = dfltcc_cmpr(strm);
if (strm->avail_in < 4096 && masked_avail_in > 0)
/* We are about to call DFLTCC with a small input buffer, which is
* inefficient. Since there is masked data, there will be at least
* one more DFLTCC call, so skip the current one and make the next
* one handle more data.
*/
break;
} while (cc == DFLTCC_CC_AGAIN);
/* Translate parameter block to stream */
strm->msg = oesc_msg(dfltcc_state->common.msg, param->oesc);
state->bi_valid = param->sbb;
if (state->bi_valid == 0)
state->bi_buf = 0; /* Avoid accessing next_out */
else
state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1);
strm->adler = param->cv;
/* Unmask the input data */
strm->avail_in += masked_avail_in;
masked_avail_in = 0;
/* If we encounter an error, it means there is a bug in DFLTCC call */
Assert(cc != DFLTCC_CC_OP2_CORRUPT || param->oesc == 0, "BUG");
/* Update Block-Continuation Flag. It will be used to check whether to call
* GDHT the next time.
*/
if (cc == DFLTCC_CC_OK) {
if (soft_bcc) {
send_eobs(strm, param);
param->bcf = 0;
dfltcc_state->block_threshold =
strm->total_in + dfltcc_state->block_size;
} else
param->bcf = 1;
if (flush == Z_FINISH) {
if (need_empty_block)
/* Make the current deflate() call also close the stream */
return 0;
else {
bi_windup(state);
*result = finish_done;
}
} else {
if (flush == Z_FULL_FLUSH)
param->hl = 0; /* Clear history */
*result = flush == Z_NO_FLUSH ? need_more : block_done;
}
} else {
param->bcf = 1;
*result = need_more;
}
if (strm->avail_in != 0 && strm->avail_out != 0)
goto again; /* deflate() must use all input or all output */
return 1;
}

View File

@@ -0,0 +1,21 @@
// SPDX-License-Identifier: Zlib
#ifndef DFLTCC_DEFLATE_H
#define DFLTCC_DEFLATE_H
#include "dfltcc.h"
/* External functions */
int dfltcc_can_deflate(z_streamp strm);
int dfltcc_deflate(z_streamp strm,
int flush,
block_state *result);
void dfltcc_reset_deflate_state(z_streamp strm);
#define DEFLATE_RESET_HOOK(strm) \
dfltcc_reset_deflate_state((strm))
#define DEFLATE_HOOK dfltcc_deflate
#define DEFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_deflate((strm)))
#endif /* DFLTCC_DEFLATE_H */

View File

@@ -0,0 +1,104 @@
// SPDX-License-Identifier: Zlib
#ifndef DFLTCC_UTIL_H
#define DFLTCC_UTIL_H
#include <stddef.h>
#include "zlib/zutil.h"
/*
* C wrapper for the DEFLATE CONVERSION CALL instruction.
*/
typedef enum {
DFLTCC_CC_OK = 0,
DFLTCC_CC_OP1_TOO_SHORT = 1,
DFLTCC_CC_OP2_TOO_SHORT = 2,
DFLTCC_CC_OP2_CORRUPT = 2,
DFLTCC_CC_AGAIN = 3,
} dfltcc_cc;
#define DFLTCC_QAF 0
#define DFLTCC_GDHT 1
#define DFLTCC_CMPR 2
#define DFLTCC_XPND 4
#define HBT_CIRCULAR (1 << 7)
#define HB_BITS 15
#define HB_SIZE (1 << HB_BITS)
static inline dfltcc_cc dfltcc(
int fn,
void *param,
Byte **op1,
size_t *len1,
const Byte **op2,
size_t *len2,
void *hist
)
{
Byte *t2 = op1 ? *op1 : NULL;
size_t t3 = len1 ? *len1 : 0;
const Byte *t4 = op2 ? *op2 : NULL;
size_t t5 = len2 ? *len2 : 0;
register int r0 __asm__("r0") = fn;
register void *r1 __asm__("r1") = param;
register Byte *r2 __asm__("r2") = t2;
register size_t r3 __asm__("r3") = t3;
register const Byte *r4 __asm__("r4") = t4;
register size_t r5 __asm__("r5") = t5;
int cc;
__asm__ volatile(
".insn rrf,0xb9390000,%[r2],%[r4],%[hist],0\n"
"ipm %[cc]\n"
: [r2] "+r" (r2)
, [r3] "+r" (r3)
, [r4] "+r" (r4)
, [r5] "+r" (r5)
, [cc] "=r" (cc)
: [r0] "r" (r0)
, [r1] "r" (r1)
, [hist] "r" (hist)
: "cc", "memory");
t2 = r2; t3 = r3; t4 = r4; t5 = r5;
if (op1)
*op1 = t2;
if (len1)
*len1 = t3;
if (op2)
*op2 = t4;
if (len2)
*len2 = t5;
return (cc >> 28) & 3;
}
static inline int is_bit_set(
const char *bits,
int n
)
{
return bits[n / 8] & (1 << (7 - (n % 8)));
}
static inline void turn_bit_off(
char *bits,
int n
)
{
bits[n / 8] &= ~(1 << (7 - (n % 8)));
}
static inline int dfltcc_are_params_ok(
int level,
uInt window_bits,
int strategy,
uLong level_mask
)
{
return (level_mask & (1 << level)) != 0 &&
(window_bits == HB_BITS) &&
(strategy == Z_DEFAULT_STRATEGY);
}
char *oesc_msg(char *buf, int oesc);
#endif /* DFLTCC_UTIL_H */

View File

@@ -16,6 +16,7 @@
#include "boot/boot_defs.h"
#include "lib/zt_common.h"
#include "dump/s390_dump.h"
#include "disk.h"
#include "job.h"
@@ -185,12 +186,16 @@ int boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr,
address_t envblk_addr, size_t envblk_len);
int boot_get_tape_ipl(void** data, size_t* size, address_t parm_addr,
address_t initrd_addr, address_t image_addr);
int boot_get_tape_dump(void** data, size_t* size, uint64_t mem);
int boot_get_eckd_dump_stage2(void** data, size_t* size, uint64_t mem);
int boot_get_tape_dump(void **data, size_t *size,
const struct stage2dump_parm_tail *stage2dump_parms);
int boot_get_eckd_dump_stage2(void **data, size_t *size,
const struct stage2dump_parm_tail *stage2dump_parms);
int boot_get_eckd_ld_ipl_br(void **br_ptr, size_t *size_ptr,
disk_blockptr_t *table, struct disk_info *info);
int boot_get_eckd_mvdump_stage2(void** data, size_t* size, uint64_t mem,
uint8_t force, struct mvdump_parm_table);
int boot_get_fba_dump_stage2(void** data, size_t* size, uint64_t mem);
int boot_get_eckd_mvdump_stage2(void **data, size_t *size,
const struct stage2dump_parm_tail *stage2dump_parms,
const struct mvdump_parm_table *mv_parm_table);
int boot_get_fba_dump_stage2(void **data, size_t *size,
const struct stage2dump_parm_tail *stage2dump_parms);
#endif /* BOOT_H */

View File

@@ -120,8 +120,8 @@ int install_tapeloader(const char* device, const char* image,
const char* parmline, const char* ramdisk,
address_t image_addr, address_t parm_addr,
address_t initrd_addr);
int install_dump(const char* device, struct job_target_data* target,
uint64_t mem);
int install_dump(const char *device, struct job_target_data *target,
uint64_t mem, bool no_compress);
int install_mvdump(char* const device[], struct job_target_data* target,
int device_count, uint64_t mem, uint8_t force);

View File

@@ -72,6 +72,7 @@ struct job_dump_data {
struct job_common_ipl_data common;
char* device;
uint64_t mem;
bool no_compress;
};
struct job_mvdump_data {
@@ -87,7 +88,6 @@ struct job_ipl_tape_data {
char* device;
};
union job_menu_entry_data {
struct job_ipl_data ipl;
struct job_dump_data dump;

57
zipl/include/zlib/zconf.h Normal file
View File

@@ -0,0 +1,57 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-1998 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#ifndef _ZCONF_H
#define _ZCONF_H
/* The memory requirements for deflate are (in bytes):
(1 << (windowBits+2)) + (1 << (memLevel+9))
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus a few kilobytes
for small objects.
*/
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# define MAX_MEM_LEVEL 8
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
* created by gzip. (Files created by minigzip can still be extracted by
* gzip.)
*/
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* default windowBits for decompression. MAX_WBITS is for compression only */
#ifndef DEF_WBITS
# define DEF_WBITS MAX_WBITS
#endif
/* default memLevel */
#if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif
/* Type declarations */
typedef unsigned char Byte; /* 8 bits */
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
typedef void *voidp;
#endif /* _ZCONF_H */

385
zipl/include/zlib/zlib.h Normal file
View File

@@ -0,0 +1,385 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
The data format used by the zlib library is described by RFCs (Request for
Comments) 1950 to 1952 in the files https://www.ietf.org/rfc/rfc1950.txt
(zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
*/
#ifndef _ZLIB_H
#define _ZLIB_H
#include "zconf.h"
/* Always build with DFLTCC support */
#define CONFIG_ZLIB_DFLTCC
/* zlib deflate based on ZLIB_VERSION "1.1.3" */
/*
This is a modified version of zlib for use inside s390-tools for dump
compression. It contains deflate parts only. Inflate code and function
prototypes are removed.
All memory allocations are to be performed in advance.
*/
/*
The 'zlib' compression library provides in-memory compression and
decompression functions, including integrity checks of the uncompressed
data. This version of the library supports only one compression method
(deflation) but other algorithms will be added later and will have the same
stream interface.
Compression can be done in a single step if the buffers are large
enough (for example if an input file is mmap'ed), or can be done by
repeated calls of the compression function. In the latter case, the
application must provide more input and/or consume the output
(providing more output space) before each call.
The compressed data format used by default by the in-memory functions is
the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
around a deflate stream, which is itself documented in RFC 1951.
The library also supports reading and writing files in gzip (.gz) format
with an interface similar to that of stdio.
The zlib format was designed to be compact and fast for use in memory
and on communications channels. The gzip format was designed for single-
file compression on file systems, has a larger header than zlib to maintain
directory information, and uses a different, slower check method than zlib.
The library does not install any signal handler. The decoder checks
the consistency of the compressed data, so the library should never
crash even in case of corrupted input.
*/
struct internal_state;
typedef struct z_stream_s {
const Byte *next_in; /* next input byte */
uLong avail_in; /* number of bytes available at next_in */
uLong total_in; /* total nb of input bytes read so far */
Byte *next_out; /* next output byte should be put there */
uLong avail_out; /* remaining free space at next_out */
uLong total_out; /* total nb of bytes output so far */
char *msg; /* last error message, NULL if no error */
struct internal_state *state; /* not visible by applications */
void *workspace; /* memory allocated for this stream */
int data_type; /* best guess about the data type: ascii or binary */
uLong adler; /* adler32 value of the uncompressed data */
uLong reserved; /* reserved for future use */
} z_stream;
typedef z_stream *z_streamp;
/*
The application must update next_in and avail_in when avail_in has
dropped to zero. It must update next_out and avail_out when avail_out
has dropped to zero. The application must initialize zalloc, zfree and
opaque before calling the init function. All other fields are set by the
compression library and must not be updated by the application.
The opaque value provided by the application will be passed as the first
parameter for calls of zalloc and zfree. This can be useful for custom
memory management. The compression library attaches no meaning to the
opaque value.
zalloc must return NULL if there is not enough memory for the object.
If zlib is used in a multi-threaded application, zalloc and zfree must be
thread safe.
On 16-bit systems, the functions zalloc and zfree must be able to allocate
exactly 65536 bytes, but will not be required to allocate more than this
if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
pointers returned by zalloc for objects of exactly 65536 bytes *must*
have their offset normalized to zero. The default allocation function
provided by this library ensures this (see zutil.c). To reduce memory
requirements and avoid any allocation of 64K objects, at the expense of
compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
The fields total_in and total_out can be used for statistics or
progress reports. After compression, total_in holds the total size of
the uncompressed data and may be saved for use in the decompressor
(particularly if the decompressor wants to decompress everything in
a single step).
*/
/* constants */
#define Z_NO_FLUSH 0
#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
#define Z_PACKET_FLUSH 2
#define Z_SYNC_FLUSH 3
#define Z_FULL_FLUSH 4
#define Z_FINISH 5
#define Z_BLOCK 6 /* Only for inflate at present */
/* Allowed flush values; see deflate() and inflate() below for details */
#define Z_OK 0
#define Z_STREAM_END 1
#define Z_NEED_DICT 2
#define Z_ERRNO (-1)
#define Z_STREAM_ERROR (-2)
#define Z_DATA_ERROR (-3)
#define Z_MEM_ERROR (-4)
#define Z_BUF_ERROR (-5)
#define Z_VERSION_ERROR (-6)
/* Return codes for the compression/decompression functions. Negative
* values are errors, positive values are used for special but normal events.
*/
#define Z_NO_COMPRESSION 0
#define Z_BEST_SPEED 1
#define Z_BEST_COMPRESSION 9
#define Z_DEFAULT_COMPRESSION (-1)
/* compression levels */
#define Z_FILTERED 1
#define Z_HUFFMAN_ONLY 2
#define Z_DEFAULT_STRATEGY 0
/* compression strategy; see deflateInit2() below for details */
#define Z_BINARY 0
#define Z_ASCII 1
#define Z_UNKNOWN 2
/* Possible values of the data_type field */
#define Z_DEFLATED 8
/* The deflate compression method (the only one supported in this version) */
/* basic functions */
extern int zlib_deflate_workspacesize (int windowBits, int memLevel);
/*
Returns the number of bytes that needs to be allocated for a per-
stream workspace with the specified parameters. A pointer to this
number of bytes should be returned in stream->workspace before
you call zlib_deflateInit() or zlib_deflateInit2(). If you call
zlib_deflateInit(), specify windowBits = MAX_WBITS and memLevel =
MAX_MEM_LEVEL here. If you call zlib_deflateInit2(), the windowBits
and memLevel parameters passed to zlib_deflateInit2() must not
exceed those passed here.
*/
extern int zlib_deflate_dfltcc_enabled (void);
/*
Returns 1 if Deflate-Conversion facility is installed and enabled,
otherwise 0.
*/
/*
extern int deflateInit (z_streamp strm, int level);
Initializes the internal stream state for compression. The fields
zalloc, zfree and opaque must be initialized before by the caller.
If zalloc and zfree are set to NULL, deflateInit updates them to
use default allocation functions.
The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
1 gives best speed, 9 gives best compression, 0 gives no compression at
all (the input data is simply copied a block at a time).
Z_DEFAULT_COMPRESSION requests a default compromise between speed and
compression (currently equivalent to level 6).
deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_STREAM_ERROR if level is not a valid compression level,
Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
with the version assumed by the caller (ZLIB_VERSION).
msg is set to null if there is no error message. deflateInit does not
perform any compression: this will be done by deflate().
*/
extern int zlib_deflate (z_streamp strm, int flush);
/*
deflate compresses as much data as possible, and stops when the input
buffer becomes empty or the output buffer becomes full. It may introduce some
output latency (reading input without producing any output) except when
forced to flush.
The detailed semantics are as follows. deflate performs one or both of the
following actions:
- Compress more input starting at next_in and update next_in and avail_in
accordingly. If not all input can be processed (because there is not
enough room in the output buffer), next_in and avail_in are updated and
processing will resume at this point for the next call of deflate().
- Provide more output starting at next_out and update next_out and avail_out
accordingly. This action is forced if the parameter flush is non zero.
Forcing flush frequently degrades the compression ratio, so this parameter
should be set only when necessary (in interactive applications).
Some output may be provided even if flush is not set.
Before the call of deflate(), the application should ensure that at least
one of the actions is possible, by providing more input and/or consuming
more output, and updating avail_in or avail_out accordingly; avail_out
should never be zero before the call. The application can consume the
compressed output when it wants, for example when the output buffer is full
(avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
and with zero avail_out, it must be called again after making room in the
output buffer because there might be more output pending.
If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
flushed to the output buffer and the output is aligned on a byte boundary, so
that the decompressor can get all input data available so far. (In particular
avail_in is zero after the call if enough output space has been provided
before the call.) Flushing may degrade compression for some compression
algorithms and so it should be used only when necessary.
If flush is set to Z_FULL_FLUSH, all output is flushed as with
Z_SYNC_FLUSH, and the compression state is reset so that decompression can
restart from this point if previous compressed data has been damaged or if
random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
the compression.
If deflate returns with avail_out == 0, this function must be called again
with the same value of the flush parameter and more output space (updated
avail_out), until the flush is complete (deflate returns with non-zero
avail_out).
If the parameter flush is set to Z_FINISH, pending input is processed,
pending output is flushed and deflate returns with Z_STREAM_END if there
was enough output space; if deflate returns with Z_OK, this function must be
called again with Z_FINISH and more output space (updated avail_out) but no
more input data, until it returns with Z_STREAM_END or an error. After
deflate has returned Z_STREAM_END, the only possible operations on the
stream are deflateReset or deflateEnd.
Z_FINISH can be used immediately after deflateInit if all the compression
is to be done in a single step. In this case, avail_out must be at least
0.1% larger than avail_in plus 12 bytes. If deflate does not return
Z_STREAM_END, then it must be called again as described above.
deflate() sets strm->adler to the adler32 checksum of all input read
so far (that is, total_in bytes).
deflate() may update data_type if it can make a good guess about
the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
binary. This field is only for information purposes and does not affect
the compression algorithm in any manner.
deflate() returns Z_OK if some progress has been made (more input
processed or more output produced), Z_STREAM_END if all input has been
consumed and all output has been produced (only when flush is set to
Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
(for example avail_in or avail_out was zero).
*/
extern int zlib_deflateEnd (z_streamp strm);
/*
All dynamically allocated data structures for this stream are freed.
This function discards any unprocessed input and does not flush any
pending output.
deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
stream state was inconsistent, Z_DATA_ERROR if the stream was freed
prematurely (some input or output was discarded). In the error case,
msg may be set but then points to a static string (which must not be
deallocated).
*/
/* Advanced functions */
/*
The following functions are needed only in some special applications.
*/
/*
extern int deflateInit2 (z_streamp strm,
int level,
int method,
int windowBits,
int memLevel,
int strategy);
This is another version of deflateInit with more compression options. The
fields next_in, zalloc, zfree and opaque must be initialized before by
the caller.
The method parameter is the compression method. It must be Z_DEFLATED in
this version of the library.
The windowBits parameter is the base two logarithm of the window size
(the size of the history buffer). It should be in the range 8..15 for this
version of the library. Larger values of this parameter result in better
compression at the expense of memory usage. The default value is 15 if
deflateInit is used instead.
The memLevel parameter specifies how much memory should be allocated
for the internal compression state. memLevel=1 uses minimum memory but
is slow and reduces compression ratio; memLevel=9 uses maximum memory
for optimal speed. The default value is 8. See zconf.h for total memory
usage as a function of windowBits and memLevel.
The strategy parameter is used to tune the compression algorithm. Use the
value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
string match). Filtered data consists mostly of small values with a
somewhat random distribution. In this case, the compression algorithm is
tuned to compress them better. The effect of Z_FILTERED is to force more
Huffman coding and less string matching; it is somewhat intermediate
between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
the compression ratio but not the correctness of the compressed output even
if it is not set appropriately.
deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
method). msg is set to null if there is no error message. deflateInit2 does
not perform any compression: this will be done by deflate().
*/
extern int zlib_deflateReset (z_streamp strm);
/*
This function is equivalent to deflateEnd followed by deflateInit,
but does not free and reallocate all the internal compression state.
The stream will keep the same compression level and any other attributes
that may have been set by deflateInit2.
deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent (such as zalloc or state being NULL).
*/
static inline unsigned long deflateBound(unsigned long s)
{
return s + ((s + 7) >> 3) + ((s + 63) >> 6) + 11;
}
#define zlib_deflateInit(strm, level) \
zlib_deflateInit2((strm), (level), Z_DEFLATED, MAX_WBITS, \
DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY)
extern int zlib_deflateInit2(z_streamp strm, int level, int method,
int windowBits, int memLevel,
int strategy);
#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
struct internal_state {int dummy;}; /* hack for buggy compilers */
#endif
#endif /* _ZLIB_H */

105
zipl/include/zlib/zutil.h Normal file
View File

@@ -0,0 +1,105 @@
/* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-1998 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* @(#) $Id: zutil.h,v 1.1 2000/01/01 03:32:23 davem Exp $ */
#ifndef _Z_UTIL_H
#define _Z_UTIL_H
#include "zlib.h"
#include <stddef.h>
typedef unsigned char uch;
typedef unsigned short ush;
typedef unsigned long ulg;
/* common constants */
#define STORED_BLOCK 0
#define STATIC_TREES 1
#define DYN_TREES 2
/* The three kinds of block type */
#define MIN_MATCH 3
#define MAX_MATCH 258
/* The minimum and maximum match lengths */
#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
/* target dependencies */
/* Common defaults */
#ifndef OS_CODE
# define OS_CODE 0x03 /* assume Unix */
#endif
/* functions */
typedef uLong (*check_func) (uLong check, const Byte *buf,
uInt len);
/* checksum functions */
#define BASE 65521L /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
/* ========================================================================= */
/*
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
return the updated checksum. If buf is NULL, this function returns
the required initial value for the checksum.
An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
much faster. Usage example:
uLong adler = zlib_adler32(0L, NULL, 0);
while (read_buffer(buffer, length) != EOF) {
adler = zlib_adler32(adler, buffer, length);
}
if (adler != original_adler) error();
*/
static inline uLong zlib_adler32(uLong adler,
const Byte *buf,
uInt len)
{
unsigned long s1 = adler & 0xffff;
unsigned long s2 = (adler >> 16) & 0xffff;
int k;
if (buf == NULL) return 1L;
while (len > 0) {
k = len < NMAX ? len : NMAX;
len -= k;
while (k >= 16) {
DO16(buf);
buf += 16;
k -= 16;
}
if (k != 0) do {
s1 += *buf++;
s2 += s1;
} while (--k);
s1 %= BASE;
s2 %= BASE;
}
return (s2 << 16) | s1;
}
#endif /* _Z_UTIL_H */

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