Compare commits

...

61 Commits

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

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

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

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

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

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

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

 - 0x<level>

   Specifies the system level as 64 bit hex value

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

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

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

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

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

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

This patch adds an EditorConfig configuration for s390-tools.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Add a helper function to deduplicate that.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Snippet of terminal output:

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

Syslog before:

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

Syslog after:

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

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

This also removes a dependency for the build process.

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

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

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

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

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

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

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

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

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

e.g.

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

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

Suggested-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-17 15:48:22 +01:00
Jan Höppner ae305b5158 Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-11-10 17:05:37 +01:00
71 changed files with 1522 additions and 1144 deletions
+13
View File
@@ -0,0 +1,13 @@
# Check https://editorconfig.org for details
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = tab
tab_width = 8
[*.sh]
shell_variant = bash # used by `shfmt`
+3
View File
@@ -38,6 +38,7 @@ List of all individuals having contributed content to s390-tools
- Fritz Elfert - Fritz Elfert
- Gerald Schaefer - Gerald Schaefer
- Gerhard Tonn - Gerhard Tonn
- Graham Inggs
- Guevenc Guelce - Guevenc Guelce
- Hannes Reinecke - Hannes Reinecke
- Hans-Joachim Picht - Hans-Joachim Picht
@@ -74,6 +75,7 @@ List of all individuals having contributed content to s390-tools
- Martin Peschke - Martin Peschke
- Martin Petermann - Martin Petermann
- Martin Schwidefsky - Martin Schwidefsky
- Matthew Rosato
- Maxim Shchetynin - Maxim Shchetynin
- Melissa Howland - Melissa Howland
- Michael Ernst - Michael Ernst
@@ -103,6 +105,7 @@ List of all individuals having contributed content to s390-tools
- Stefan Raspl - Stefan Raspl
- Stefan Reimbold - Stefan Reimbold
- Stefan Weinhuber - Stefan Weinhuber
- Steffen Eiden
- Steffen Maier - Steffen Maier
- Steffen Thoss - Steffen Thoss
- Susanne Wintenberger - Susanne Wintenberger
+23
View File
@@ -1,5 +1,28 @@
Release history for s390-tools (MIT version) Release history for s390-tools (MIT version)
-------------------------------------------- --------------------------------------------
* __v2.20.0 (2021-02-04)__
For Linux kernel version: 5.16
Add new tools / libraries:
- Add EditorConfig configuration
Changes of existing tools:
- s390-tools switches to Fuse 3 as Fuse 2 is deprecated.
Affected tools: cmsfs, hmcdrvfs, hsavmcore, zdsfs, zdump
- chreipl-fcp-mpath: don't compress the manpage before installing it
- cpictl: Report extended version information
- genprotimg: Add extended kernel command line support
- zdev: modify the lsblk output parser in lszdev
- zipl: Add support for longer kernel command lines (now supports up to 64k length)
Bug Fixes:
- cpictl: Suppress messages for unwritable sysfs files
- dbginfo.sh: Fix missing syslog for step create_package
- lshwc: Fix CPU list parameter setup for device driver
- zdev: Check for errors when removing a devtype setting
- zdev: Fix path resolution for multi-mount point file systems
* __v2.19.0 (2021-11-10)__ * __v2.19.0 (2021-11-10)__
For Linux kernel version: 5.15 For Linux kernel version: 5.15
+7 -7
View File
@@ -292,7 +292,7 @@ build options:
| __LIBRARY__ | __BUILD OPTION__ | __TOOLS__ | | __LIBRARY__ | __BUILD OPTION__ | __TOOLS__ |
|----------------|:------------------:|:-------------------------------------:| |----------------|:------------------:|:-------------------------------------:|
| fuse | `HAVE_FUSE` | cmsfs-fuse, zdsfs, hmcdrvfs, zgetdump,| | fuse3 | `HAVE_FUSE` | cmsfs-fuse, zdsfs, hmcdrvfs, zgetdump,|
| | | hsavmcore | | | | hsavmcore |
| zlib | `HAVE_ZLIB` | zgetdump, dump2tar | | zlib | `HAVE_ZLIB` | zgetdump, dump2tar |
| ncurses | `HAVE_NCURSES` | hyptop | | ncurses | `HAVE_NCURSES` | hyptop |
@@ -355,12 +355,12 @@ the different tools are provided:
* cmsfs-fuse/zdsfs/hmcdrvfs/zgetdump: * cmsfs-fuse/zdsfs/hmcdrvfs/zgetdump:
The tools cmsfs-fuse, zdsfs, hmcdrvfs, and zgetdump depend on FUSE. The tools cmsfs-fuse, zdsfs, hmcdrvfs, and zgetdump depend on FUSE.
FUSE is provided by installing the fuse and libfuse packages and by a FUSE is provided by installing the fuse3 and libfuse3 packages and by a
kernel compiled with `CONFIG_FUSE_FS`. For compiling the s390-tools package kernel compiled with `CONFIG_FUSE_FS`. For compiling the s390-tools package
the fuse-devel package is required. the fuse3-devel package is required.
The cmsfs-fuse tool requires FUSE version 2.8.1 or newer for full The cmsfs-fuse tool requires FUSE version 3.0 or newer for full
functionality. functionality.
For further information about FUSE see: http://fuse.sourceforge.net For further information about FUSE see: https://github.com/libfuse/libfuse
* hyptop: * hyptop:
The ncurses-devel package is required to build hyptop. The ncurses-devel package is required to build hyptop.
@@ -456,7 +456,7 @@ the different tools are provided:
`HAVE_JSONC=0`, or `HAVE_LIBCURL=0` to the make invocation. `HAVE_JSONC=0`, or `HAVE_LIBCURL=0` to the make invocation.
* hsavmcore: * hsavmcore:
For building the hsavmcore tool you need fuse version 2.6 and optionally For building the hsavmcore tool you need fuse version 3.0 and optionally
systemd which is enabled by default, to disable systemd support, systemd which is enabled by default, to disable systemd support,
add `HAVE_SYSTEMD=0` to the make invocation. add `HAVE_SYSTEMD=0` to the make invocation.
Tip: you may skip the hsavmcore build by adding `HAVE_FUSE=0` Tip: you may skip the hsavmcore build by adding `HAVE_FUSE=0`
@@ -479,4 +479,4 @@ the different tools are provided:
util-linux, udev, and multipath-tools. When using `HAVE_DRACUT=1` with the util-linux, udev, and multipath-tools. When using `HAVE_DRACUT=1` with the
make invocation, it also requires dracut. When using `ENABLE_DOC=1` with the make invocation, it also requires dracut. When using `ENABLE_DOC=1` with the
make invocation to build a man page and render the README.md as HTML, make make invocation to build a man page and render the README.md as HTML, make
further requires pandoc, GNU awk, and GNU Gzip for the build process. further requires pandoc and GNU awk for the build process.
+2 -2
View File
@@ -32,7 +32,7 @@ Usage: $cmd [-t LAST_GIT_TAG]
Add all new authors since last release to the $authors_file file. Without Add all new authors since last release to the $authors_file file. Without
the -t option the tool uses the last available git tag as last release. the -t option the tool uses the last available git tag as last release.
The tool should be called form the s390-tools master branch. The tool runs on the s390-tools master branch.
OPTIONS OPTIONS
-t, --tag LAST_GIT_TAG Use git tag LAST_GIT_TAG as starting point -t, --tag LAST_GIT_TAG Use git tag LAST_GIT_TAG as starting point
@@ -116,7 +116,7 @@ echo "$cmd: Adding new authors since tag: $release_tag_last"
# Print authors list without header # Print authors list without header
tail -n +4 $authors_file_path tail -n +4 $authors_file_path
# Add the new authors # Add the new authors
git log --format="- %an" $release_tag_last.. git log --format="- %an" $release_tag_last..master
# Then sort everything and remove duplicates # Then sort everything and remove duplicates
} | sort | uniq > $authors_file_tmp } | sort | uniq > $authors_file_tmp
# Create new AUTHORS file with header ... # Create new AUTHORS file with header ...
-1
View File
@@ -10,4 +10,3 @@
/README.pdf /README.pdf
/chreipl-fcp-mpath.md /chreipl-fcp-mpath.md
/chreipl-fcp-mpath.7 /chreipl-fcp-mpath.7
/chreipl-fcp-mpath.7.gz
+6 -10
View File
@@ -12,8 +12,6 @@
# bash: # bash:
# - bash # - bash
# If $(ENABLE_DOC) is `1`: # If $(ENABLE_DOC) is `1`:
# GNU Gzip:
# - gzip
# GNU awk: # GNU awk:
# - gawk # - gawk
@@ -133,6 +131,7 @@ install: chreipl-fcp-mpath-install
# install udev rules # install udev rules
INSTDIRS += $(UDEVRULESDIR) INSTDIRS += $(UDEVRULESDIR)
$(DESTDIR)$(UDEVRULESDIR): install_dirs
.PHONY: chreipl-fcp-mpath-install-udev-rules .PHONY: chreipl-fcp-mpath-install-udev-rules
chreipl-fcp-mpath-install-udev-rules: | $(DESTDIR)$(UDEVRULESDIR) chreipl-fcp-mpath-install-udev-rules: | $(DESTDIR)$(UDEVRULESDIR)
@@ -144,6 +143,7 @@ chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-udev-rules
# install udev helper programs # install udev helper programs
INSTDIRS += $(UDEVDIR) INSTDIRS += $(UDEVDIR)
$(DESTDIR)$(UDEVDIR): install_dirs
.PHONY: chreipl-fcp-mpath-install-udev-helper .PHONY: chreipl-fcp-mpath-install-udev-helper
chreipl-fcp-mpath-install-udev-helper: | $(DESTDIR)$(UDEVDIR) chreipl-fcp-mpath-install-udev-helper: | $(DESTDIR)$(UDEVDIR)
@@ -154,6 +154,7 @@ chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-udev-helper
# install common library files # install common library files
INSTDIRS += $(CHREIPLZFCPMPDIR) INSTDIRS += $(CHREIPLZFCPMPDIR)
$(DESTDIR)$(CHREIPLZFCPMPDIR): install_dirs
.PHONY: chreipl-fcp-mpath-install-libfiles .PHONY: chreipl-fcp-mpath-install-libfiles
chreipl-fcp-mpath-install-libfiles: | $(DESTDIR)$(CHREIPLZFCPMPDIR) chreipl-fcp-mpath-install-libfiles: | $(DESTDIR)$(CHREIPLZFCPMPDIR)
@@ -167,6 +168,7 @@ ifeq ($(HAVE_DRACUT),1)
# install dracut config files # install dracut config files
INSTDIRS += $(DRACUTCONFDIR) INSTDIRS += $(DRACUTCONFDIR)
$(DESTDIR)$(DRACUTCONFDIR): install_dirs
.PHONY: chreipl-fcp-mpath-install-dracut-config .PHONY: chreipl-fcp-mpath-install-dracut-config
chreipl-fcp-mpath-install-dracut-config: | $(DESTDIR)$(DRACUTCONFDIR) chreipl-fcp-mpath-install-dracut-config: | $(DESTDIR)$(DRACUTCONFDIR)
@@ -182,22 +184,16 @@ ifeq ($(ENABLE_DOC),1)
# chreipl-fcp-mpath: install man page # chreipl-fcp-mpath: install man page
INSTDIRS += $(MANDIR) INSTDIRS += $(MANDIR)
$(DESTDIR)$(MANDIR)/man7: install_dirs
.PHONY: chreipl-fcp-mpath-install-man-page .PHONY: chreipl-fcp-mpath-install-man-page
chreipl-fcp-mpath-install-man-page: | $(DESTDIR)$(MANDIR)/man7 chreipl-fcp-mpath-install-man-page: | $(DESTDIR)$(MANDIR)/man7
chreipl-fcp-mpath-install-man-page: chreipl-fcp-mpath.7 chreipl-fcp-mpath-install-man-page: chreipl-fcp-mpath.7
$(GZIP) -fk --best chreipl-fcp-mpath.7
$(INSTALL_DATA) -t $(DESTDIR)$(MANDIR)/man7 \ $(INSTALL_DATA) -t $(DESTDIR)$(MANDIR)/man7 \
chreipl-fcp-mpath.7.gz chreipl-fcp-mpath.7
chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-man-page chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-man-page
.PHONY: chreipl-fcp-mpath-install-man-page-clean
chreipl-fcp-mpath-install-man-page-clean:
rm -f chreipl-fcp-mpath.7.gz
chreipl-fcp-mpath-clean: chreipl-fcp-mpath-install-man-page-clean
endif endif
# #
+2 -3
View File
@@ -131,8 +131,7 @@ To build and install the documentation (man page) you need:
- pandoc; - pandoc;
- GNU Core Utilities (date); - GNU Core Utilities (date);
- GNU awk; - GNU awk.
- GNU Gzip.
INSTALLATION INSTALLATION
============ ============
@@ -207,7 +206,7 @@ files to these default locations:
/usr/lib/udev/chreipl-fcp-mpath-record-volume-identifier /usr/lib/udev/chreipl-fcp-mpath-record-volume-identifier
/usr/lib/udev/chreipl-fcp-mpath-try-change-ipl-path /usr/lib/udev/chreipl-fcp-mpath-try-change-ipl-path
/usr/lib/udev/rules.d/70-chreipl-fcp-mpath.rules /usr/lib/udev/rules.d/70-chreipl-fcp-mpath.rules
/usr/share/man/man7/chreipl-fcp-mpath.7.gz /usr/share/man/man7/chreipl-fcp-mpath.7
UNINSTALL UNINSTALL
========= =========
@@ -1,4 +1,3 @@
#!/bin/bash
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
# #
# chreipl-fcp-mpath: use multipath information to change FCP IPL target # chreipl-fcp-mpath: use multipath information to change FCP IPL target
+7 -6
View File
@@ -16,17 +16,18 @@ check_dep:
$(call check_dep, \ $(call check_dep, \
"cmsfs-fuse", \ "cmsfs-fuse", \
"fuse.h", \ "fuse.h", \
"fuse-devel or libfuse-dev", \ "fuse3-devel or libfuse3-dev", \
"HAVE_FUSE=0") "HAVE_FUSE=0", \
"-DFUSE_USE_VERSION=30")
all: check_dep cmsfs-fuse all: check_dep cmsfs-fuse
ifneq ($(shell sh -c 'command -v pkg-config'),) ifneq ($(shell sh -c 'command -v pkg-config'),)
FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse) FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse3)
FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse) FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse3)
else else
FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse3
FUSE_LDLIBS = -lfuse FUSE_LDLIBS = -lfuse3
endif endif
ALL_CFLAGS += -DHAVE_SETXATTR $(FUSE_CFLAGS) ALL_CFLAGS += -DHAVE_SETXATTR $(FUSE_CFLAGS)
LDLIBS += $(FUSE_LDLIBS) -lm LDLIBS += $(FUSE_LDLIBS) -lm
-3
View File
@@ -80,9 +80,6 @@ Allow access by other users
\fB\-o\fR allow_root \fB\-o\fR allow_root
Allow access by root Allow access by root
.TP .TP
\fB\-o\fR nonempty
Allow mounts over non\-empty file/dir
.TP
\fB\-o\fR default_permissions \fB\-o\fR default_permissions
Enable permission checking by kernel Enable permission checking by kernel
.TP .TP
+23 -9
View File
@@ -9,7 +9,7 @@
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#define FUSE_USE_VERSION 26 #define FUSE_USE_VERSION 30
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
@@ -1516,7 +1516,7 @@ static void walk_dir_block(struct fst_entry *fst, struct walk_file *walk,
decode_edf_name(file, fst->name, fst->type); decode_edf_name(file, fst->name, fst->type);
if (!file_unlinked(file)) { if (!file_unlinked(file)) {
cache_fst_addr(walk->addr, file); cache_fst_addr(walk->addr, file);
walk->filler(walk->buf, file, NULL, 0); walk->filler(walk->buf, file, NULL, 0, 0);
} }
} }
} }
@@ -1728,8 +1728,11 @@ static off_t get_file_size_logical(struct fst_entry *fst)
return total; return total;
} }
static int cmsfs_getattr(const char *path, struct stat *stbuf) static int cmsfs_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *fi)
{ {
(void) fi;
int mask = (cmsfs.allow_other) ? 0444 : 0440; int mask = (cmsfs.allow_other) ? 0444 : 0440;
struct fst_entry fst; struct fst_entry fst;
@@ -1783,13 +1786,15 @@ static int cmsfs_getattr(const char *path, struct stat *stbuf)
} }
static int cmsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, static int cmsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi) off_t offset, struct fuse_file_info *fi,
enum fuse_readdir_flags flags)
{ {
struct walk_file walk; struct walk_file walk;
struct fst_entry fst; struct fst_entry fst;
(void) offset; (void) offset;
(void) fi; (void) fi;
(void) flags;
/* /*
* Offset is ignored and 0 passed to the filler fn so the whole * Offset is ignored and 0 passed to the filler fn so the whole
@@ -1800,8 +1805,8 @@ static int cmsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
if (strcmp(path, "/") != 0) if (strcmp(path, "/") != 0)
return -ENOENT; return -ENOENT;
filler(buf, ".", NULL, 0); filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0); filler(buf, "..", NULL, 0, 0);
memset(&walk, 0, sizeof(walk)); memset(&walk, 0, sizeof(walk));
/* readdir is possible without open so fi->fh is not set */ /* readdir is possible without open so fi->fh is not set */
@@ -2683,13 +2688,16 @@ static int cmsfs_statfs(const char *path, struct statvfs *buf)
return 0; return 0;
} }
static int cmsfs_utimens(const char *path, const struct timespec ts[2]) static int cmsfs_utimens(const char *path, const struct timespec ts[2],
struct fuse_file_info *fi)
{ {
struct fst_entry fst; struct fst_entry fst;
off_t fst_addr; off_t fst_addr;
struct tm tm; struct tm tm;
int rc; int rc;
(void) fi;
if (cmsfs.readonly) if (cmsfs.readonly)
return -EACCES; return -EACCES;
@@ -2825,7 +2833,8 @@ error:
return rc; return rc;
} }
static int cmsfs_rename(const char *path, const char *new_path) static int cmsfs_rename(const char *path, const char *new_path,
unsigned int flags)
{ {
struct fst_entry fst, fst_new; struct fst_entry fst, fst_new;
off_t fst_addr, fst_addr_new; off_t fst_addr, fst_addr_new;
@@ -2835,6 +2844,8 @@ static int cmsfs_rename(const char *path, const char *new_path)
struct file *f; struct file *f;
int rc; int rc;
(void) flags;
if (cmsfs.readonly) if (cmsfs.readonly)
return -EACCES; return -EACCES;
@@ -3232,13 +3243,16 @@ static void update_fst(struct file *f, off_t addr)
unhide_null_blocks(f); unhide_null_blocks(f);
} }
static int cmsfs_truncate(const char *path, off_t size) static int cmsfs_truncate(const char *path, off_t size,
struct fuse_file_info *fi)
{ {
struct fst_entry fst; struct fst_entry fst;
off_t fst_addr, len; off_t fst_addr, len;
struct file *f; struct file *f;
int rc = 0; int rc = 0;
(void) fi;
if (cmsfs.readonly) if (cmsfs.readonly)
return -EROFS; return -EROFS;
+1 -1
View File
@@ -5,7 +5,7 @@ COMMON_INCLUDED = true
# The variable "DISTRELEASE" should be overwritten in rpm spec files with: # The variable "DISTRELEASE" should be overwritten in rpm spec files with:
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}" # "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
VERSION = 2 VERSION = 2
RELEASE = 19 RELEASE = 20
PATCHLEVEL = 0 PATCHLEVEL = 0
DISTRELEASE = build-$(shell date +%Y%m%d) DISTRELEASE = build-$(shell date +%Y%m%d)
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE) S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
+2 -8
View File
@@ -298,14 +298,8 @@ static void parse_cpulist(char *parm, struct s390_hwctr_start *start)
words[no_b] |= 1ULL << no_a; words[no_b] |= 1ULL << no_a;
} }
} }
/* no_b is highest used index, swap array */ /* no_b is highest used index */
start->cpumask_len = (no_b + 1) * 8; start->cpumask_len = (no_b + 1) * CHAR_BIT;
for (no_a = 0; no_a < no_b; ++no_a, --no_b) {
uint64_t tmp = words[no_a];
words[no_a] = words[no_b];
words[no_b] = tmp;
}
start->version = S390_HWCTR_START_VERSION; start->version = S390_HWCTR_START_VERSION;
} }
+14 -4
View File
@@ -28,13 +28,23 @@ static inline void __noreturn load_psw(struct psw_t psw)
; ;
} }
static unsigned long get_kernel_cmdline_size(void)
{
unsigned long size = *(volatile unsigned long *)MAX_COMMAND_LINE_SIZE;
if (size != 0)
return size;
return LEGACY_COMMAND_LINE_SIZE;
}
void __noreturn start(void) void __noreturn start(void)
{ {
volatile struct stage3b_args *args = &loader_parms; volatile struct stage3b_args *args = &loader_parms;
volatile struct memblob *kernel = &args->kernel; volatile struct memblob *kernel = &args->kernel;
volatile struct memblob *cmdline = &args->cmdline; volatile struct memblob *cmdline = &args->cmdline;
volatile struct memblob *initrd = &args->initrd; volatile struct memblob *initrd = &args->initrd;
volatile struct psw_t psw = args->psw; struct psw_t psw = args->psw;
/* set up ASCII and line-mode */ /* set up ASCII and line-mode */
sclp_setup(SCLP_LINE_ASCII_INIT); sclp_setup(SCLP_LINE_ASCII_INIT);
@@ -42,14 +52,14 @@ void __noreturn start(void)
if (kernel->size < IMAGE_LOAD_ADDRESS) if (kernel->size < IMAGE_LOAD_ADDRESS)
panic(EINTERNAL, "Invalid kernel\n"); panic(EINTERNAL, "Invalid kernel\n");
if (cmdline->size > COMMAND_LINE_SIZE)
panic(EINTERNAL, "Command line is too large\n");
/* move the kernel and cut the kernel header */ /* move the kernel and cut the kernel header */
memmove((void *)IMAGE_LOAD_ADDRESS, memmove((void *)IMAGE_LOAD_ADDRESS,
(void *)(kernel->src + IMAGE_LOAD_ADDRESS), (void *)(kernel->src + IMAGE_LOAD_ADDRESS),
kernel->size - IMAGE_LOAD_ADDRESS); kernel->size - IMAGE_LOAD_ADDRESS);
if (cmdline->size > get_kernel_cmdline_size())
panic(EINTERNAL, "Command line is too large\n");
/* move the kernel cmdline */ /* move the kernel cmdline */
memmove((void *)COMMAND_LINE, memmove((void *)COMMAND_LINE,
(void *)cmdline->src, (void *)cmdline->src,
+1 -17
View File
@@ -248,19 +248,6 @@ gint pv_component_align(PvComponent *component, const gchar *tmp_path,
g_assert_not_reached(); g_assert_not_reached();
} }
/* Convert uint64_t address to byte array */
static void uint64_to_uint8_buf(uint8_t dst[8], uint64_t addr)
{
uint8_t *p = (uint8_t *)&addr;
g_assert(dst);
for (gint i = 0; i < 8; i++) {
/* cppcheck-suppress objectIndex */
dst[i] = p[i];
}
}
int64_t pv_component_update_ald(const PvComponent *comp, EVP_MD_CTX *ctx, int64_t pv_component_update_ald(const PvComponent *comp, EVP_MD_CTX *ctx,
GError **err) GError **err)
{ {
@@ -273,11 +260,8 @@ int64_t pv_component_update_ald(const PvComponent *comp, EVP_MD_CTX *ctx,
do { do {
uint64_t cur_be = GUINT64_TO_BE(cur); uint64_t cur_be = GUINT64_TO_BE(cur);
uint8_t addr_buf[8];
uint64_to_uint8_buf(addr_buf, cur_be); if (EVP_DigestUpdate(ctx, &cur_be, sizeof(cur_be)) != 1) {
if (EVP_DigestUpdate(ctx, addr_buf, sizeof(addr_buf)) != 1) {
g_set_error(err, PV_CRYPTO_ERROR, g_set_error(err, PV_CRYPTO_ERROR,
PV_CRYPTO_ERROR_INTERNAL, PV_CRYPTO_ERROR_INTERNAL,
_("EVP_DigestUpdate failed")); _("EVP_DigestUpdate failed"));
+1 -1
View File
@@ -440,7 +440,7 @@ static int check_signature_algo_match(const EVP_PKEY *pkey, const X509 *subject,
static X509_CRL *load_crl_from_bio(BIO *bio) static X509_CRL *load_crl_from_bio(BIO *bio)
{ {
g_autoptr(X509_CRL) crl = PEM_read_bio_X509_CRL(bio, NULL, 0, NULL); g_autoptr(X509_CRL) crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
gint rc; gint rc;
if (crl) if (crl)
+6 -6
View File
@@ -16,17 +16,17 @@ check_dep:
$(call check_dep, \ $(call check_dep, \
"hmcdrvfs", \ "hmcdrvfs", \
"fuse.h", \ "fuse.h", \
"fuse-devel or libfuse-dev", \ "fuse3-devel or libfuse3-dev", \
"HAVE_FUSE=0") "HAVE_FUSE=0")
ifneq ($(shell sh -c 'command -v pkg-config'),) ifneq ($(shell sh -c 'command -v pkg-config'),)
FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse) FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse3)
FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse) FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse3)
else else
FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse3
FUSE_LDLIBS = -lfuse FUSE_LDLIBS = -lfuse3
endif endif
ALL_CFLAGS += -DFUSE_USE_VERSION=26 -D_LARGEFILE_SOURCE $(FUSE_CFLAGS) ALL_CFLAGS += -DFUSE_USE_VERSION=30 -D_LARGEFILE_SOURCE $(FUSE_CFLAGS)
LDLIBS += $(FUSE_LDLIBS) -lpthread -lrt -ldl -lm LDLIBS += $(FUSE_LDLIBS) -lpthread -lrt -ldl -lm
OBJECTS = hmcdrvfs.o OBJECTS = hmcdrvfs.o
-3
View File
@@ -111,9 +111,6 @@ allow access by other users
.B -o allow_root .B -o allow_root
allow access by root allow access by root
.TP .TP
.B -o nonempty
allow mounts over non-empty file/dir
.TP
.B -o default_permissions .B -o default_permissions
enable permission checking by kernel enable permission checking by kernel
.TP .TP
+9 -6
View File
@@ -990,7 +990,7 @@ static int hmcdrv_cache_dir(const char *dir, fuse_fill_dir_t filler, void *buf)
hmcdrv_cache_refresh(path, &st, symlink); hmcdrv_cache_refresh(path, &st, symlink);
if ((filler != NULL) && if ((filler != NULL) &&
(filler(buf, fname, &st, 0) != 0)) (filler(buf, fname, &st, 0, 0) != 0))
filler = NULL; /* stop filling */ filler = NULL; /* stop filling */
#ifdef DEBUG #ifdef DEBUG
strftime(symlink, sizeof(symlink), strftime(symlink, sizeof(symlink),
@@ -1109,7 +1109,8 @@ static struct hmcdrv_fuse_file *hmcdrv_file_get(const char *path)
* *
* Note: The most important function which FUSE calls (very often). * Note: The most important function which FUSE calls (very often).
*/ */
static int hmcdrv_fuse_getattr(const char *path, struct stat *stbuf) static int hmcdrv_fuse_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *UNUSED(fi))
{ {
struct hmcdrv_fuse_file *fp; struct hmcdrv_fuse_file *fp;
int rc = 0; int rc = 0;
@@ -1175,12 +1176,13 @@ static int hmcdrv_fuse_opendir(const char *UNUSED(path),
*/ */
static int hmcdrv_fuse_readdir(const char *path, void *buf, static int hmcdrv_fuse_readdir(const char *path, void *buf,
fuse_fill_dir_t filler, off_t UNUSED(offset), fuse_fill_dir_t filler, off_t UNUSED(offset),
struct fuse_file_info *UNUSED(fi)) struct fuse_file_info *UNUSED(fi),
enum fuse_readdir_flags UNUSED(flags))
{ {
int ret; int ret;
filler(buf, ".", NULL, 0); filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0); filler(buf, "..", NULL, 0, 0);
pthread_mutex_lock(&hmcdrv_ctx.mutex); pthread_mutex_lock(&hmcdrv_ctx.mutex);
ret = hmcdrv_cache_dir(path, filler, buf); ret = hmcdrv_cache_dir(path, filler, buf);
@@ -1232,7 +1234,8 @@ static int hmcdrv_fuse_read(const char *path, char *buf, size_t size,
* Return: value to be passed in the private_data field of fuse_context to * Return: value to be passed in the private_data field of fuse_context to
* all file operations and as a parameter to the destroy() method * all file operations and as a parameter to the destroy() method
*/ */
static void *hmcdrv_fuse_init(struct fuse_conn_info *UNUSED(conn)) static void *hmcdrv_fuse_init(struct fuse_conn_info *UNUSED(conn),
struct fuse_config *UNUSED(cfg))
{ {
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
+7 -6
View File
@@ -23,11 +23,11 @@ else # HAVE_FUSE
# FUSE # FUSE
# #
ifneq ($(shell sh -c 'command -v pkg-config'),) ifneq ($(shell sh -c 'command -v pkg-config'),)
FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse) FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse3)
FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse) FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse3)
else else
FUSE_CFLAGS = -I/usr/include/fuse FUSE_CFLAGS = -I/usr/include/fuse3
FUSE_LDLIBS = -lfuse FUSE_LDLIBS = -lfuse3
endif endif
# #
@@ -67,8 +67,9 @@ check-dep-fuse:
$(call check_dep, \ $(call check_dep, \
"hsavmcore", \ "hsavmcore", \
"fuse.h", \ "fuse.h", \
"fuse-devel or libfuse-dev", \ "fuse3-devel or libfuse3-dev", \
"HAVE_FUSE=0") "HAVE_FUSE=0", \
"-DFUSE_USE_VERSION=30")
touch check-dep-fuse touch check-dep-fuse
install: all install: all
+1 -1
View File
@@ -15,7 +15,7 @@ sudo reboot
## Dependencies ## Dependencies
```shell ```shell
sudo dnf install -y fuse fuse-devel systemd-devel sudo dnf install -y fuse3 fuse3-devel systemd-devel
``` ```
## Build hsavmcore ## Build hsavmcore
+1 -1
View File
@@ -18,7 +18,7 @@ sudo reboot
## Dependencies ## Dependencies
```shell ```shell
sudo zypper install -y fuse fuse-devel systemd-devel sudo zypper install -y fuse3 fuse3-devel systemd-devel
``` ```
## Build hsavmcore ## Build hsavmcore
+1 -1
View File
@@ -11,7 +11,7 @@
## Dependencies ## Dependencies
```shell ```shell
sudo apt-get install -y make gcc kdump-tools fuse libfuse-dev libsystemd-dev sudo apt-get install -y make gcc kdump-tools fuse3 libfuse3-dev libsystemd-dev
``` ```
## Build hsavmcore ## Build hsavmcore
+11 -6
View File
@@ -15,7 +15,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#define FUSE_USE_VERSION 26 #define FUSE_USE_VERSION 30
#include <fuse.h> #include <fuse.h>
#include "lib/util_log.h" #include "lib/util_log.h"
@@ -31,8 +31,11 @@ struct vmcore_overlay {
bool fuse_debug; bool fuse_debug;
}; };
static int vmcore_fuse_getattr(const char *path, struct stat *stbuf) static int vmcore_fuse_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *fi)
{ {
(void)fi;
struct vmcore_overlay *overlay = fuse_get_context()->private_data; struct vmcore_overlay *overlay = fuse_get_context()->private_data;
int ret = 0; int ret = 0;
@@ -54,18 +57,20 @@ static int vmcore_fuse_getattr(const char *path, struct stat *stbuf)
static int vmcore_fuse_readdir(const char *path, void *buf, static int vmcore_fuse_readdir(const char *path, void *buf,
fuse_fill_dir_t filler, off_t offset, fuse_fill_dir_t filler, off_t offset,
struct fuse_file_info *fi) struct fuse_file_info *fi,
enum fuse_readdir_flags flags)
{ {
(void)offset; (void)offset;
(void)fi; (void)fi;
(void)flags;
if (strcmp(path, ROOT_DIR) != 0) if (strcmp(path, ROOT_DIR) != 0)
return -ENOENT; return -ENOENT;
/* We have only one file */ /* We have only one file */
filler(buf, ".", NULL, 0); filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0); filler(buf, "..", NULL, 0, 0);
filler(buf, VMCORE_FILE, NULL, 0); filler(buf, VMCORE_FILE, NULL, 0, 0);
return 0; return 0;
} }
+2 -1
View File
@@ -23,10 +23,11 @@
#define INITRD_SIZE _AC(0x10410, UL) #define INITRD_SIZE _AC(0x10410, UL)
#define OLDMEM_BASE _AC(0x10418, UL) #define OLDMEM_BASE _AC(0x10418, UL)
#define OLDMEM_SIZE _AC(0x10420, UL) #define OLDMEM_SIZE _AC(0x10420, UL)
#define MAX_COMMAND_LINE_SIZE _AC(0x10430, UL)
#define COMMAND_LINE _AC(0x10480, UL) #define COMMAND_LINE _AC(0x10480, UL)
/* Parameter sizes */ /* Parameter sizes */
#define COMMAND_LINE_SIZE 896 #define LEGACY_COMMAND_LINE_SIZE 896
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
+1 -1
View File
@@ -96,7 +96,7 @@ int dasd_sys_ese(char *devnode)
return (rc == 1) ? 1 : 0; return (rc == 1) ? 1 : 0;
} }
int dasd_get_pm_from_chpid(char *busid, unsigned int chpid, int *mask) static int dasd_get_pm_from_chpid(char *busid, unsigned int chpid, int *mask)
{ {
unsigned int val; unsigned int val;
int count, i; int count, i;
+1 -1
View File
@@ -20,7 +20,7 @@ install:
sed -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' cpictl > \ sed -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' cpictl > \
$(DESTDIR)$(TOOLS_LIBDIR)/cpictl $(DESTDIR)$(TOOLS_LIBDIR)/cpictl
chown $(OWNER):$(GROUP) $(DESTDIR)$(TOOLS_LIBDIR)/cpictl chown $(OWNER):$(GROUP) $(DESTDIR)$(TOOLS_LIBDIR)/cpictl
chmod 775 $(DESTDIR)$(TOOLS_LIBDIR)/cpictl chmod 755 $(DESTDIR)$(TOOLS_LIBDIR)/cpictl
@for i in $(MAN_PAGES); \ @for i in $(MAN_PAGES); \
do \ do \
+236 -9
View File
@@ -24,6 +24,9 @@ readonly SYSTEM_NAME_PATH="/sys/firmware/cpi/system_name"
readonly SYSPLEX_NAME_PATH="/sys/firmware/cpi/sysplex_name" readonly SYSPLEX_NAME_PATH="/sys/firmware/cpi/sysplex_name"
readonly CPI_SET="/sys/firmware/cpi/set" readonly CPI_SET="/sys/firmware/cpi/set"
# Location of os-release file - can be specified externally for testing purpose
readonly OS_RELEASE=${CPI_OS_RELEASE:-"/etc/os-release"}
declare LEVEL declare LEVEL
declare TYPE declare TYPE
declare NAME declare NAME
@@ -37,6 +40,16 @@ readonly EXIT_FAILURE=1
readonly EXIT_ARG_TOO_LONG=3 readonly EXIT_ARG_TOO_LONG=3
readonly EXIT_INVALID_CHARS=4 readonly EXIT_INVALID_CHARS=4
# Distro-IDs as supported by SE/HMC firmware
readonly DISTRO_GENERIC=0
readonly DISTRO_RHEL=1
readonly DISTRO_SLES=2
readonly DISTRO_UBUNTU=3
readonly DISTRO_FEDORA=4
readonly DISTRO_OPENSUSE=5
readonly DISTRO_DEBIAN=6
readonly DISTRO_RHCOS=7
print_help_and_exit() print_help_and_exit()
{ {
cat <<EndHelp cat <<EndHelp
@@ -49,7 +62,8 @@ Configure the Control-Program-Information (CPI) settings.
sysplex name with values taken from environment sysplex name with values taken from environment
variables variables
-h, --help Print this help, then exit -h, --help Print this help, then exit
-L, --level LEVEL Set and commit OS level to LEVEL (format xx.yy.zzABCD) -L, --level LEVEL Set and commit OS level to LEVEL. Format: 0x<level> or
[[[flags:]distro_id:distro_version:]kernel_version]
-N, --name SYSTEM Set and commit the system name to SYSTEM -N, --name SYSTEM Set and commit the system name to SYSTEM
-S, --sysplex SYSPLEX Set and commit the sysplex name to SYSPLEX -S, --sysplex SYSPLEX Set and commit the sysplex name to SYSPLEX
-T, --type TYPE Set and commit OS type to TYPE -T, --type TYPE Set and commit OS type to TYPE
@@ -109,7 +123,7 @@ fail_with()
cpi_commit() cpi_commit()
{ {
echo 1 > "$CPI_SET" echo 1 > "$CPI_SET" 2> /dev/null
} }
do_length_check() do_length_check()
@@ -129,15 +143,228 @@ cpi_set_bit()
LEVEL=$(printf '0x%x' $((LEVEL | (1 << (63 - $1)) )) ) LEVEL=$(printf '0x%x' $((LEVEL | (1 << (63 - $1)) )) )
} }
#
# split_version - Split generic version string into array of sub-versions
#
# @version: Version string
# @delim: Characters that delimit sub-versions in version string
# @num: Number of sub-versions
#
# Print @num sub-versions of @version where each sub-version is delimited by
# any of the characters in @delim. Print 0 in place of non-decimal or missing
# sub-versions.
#
# Examples:
# version=10 delim=. num=3 => 10 0 0
# version=4.8 delim=. num=2 => 4 8
#
split_version()
{
local version="$1" delim="$2" num="$3"
local list i subver
IFS="$delim" read -r -a list <<< "$version"
for (( i=0; i<num; i++ )) ; do
subver="${list[i]:-0}"
# Handle non-number sub-versions
[[ "$subver" =~ ^[0-9]+$ ]] || subver=0
# Force decimal interpretation in case of leading zeroes
subver=$(( 10#$subver ))
printf "%s " "$subver"
done
}
#
# split_kver - Split Linux kernel version string into array of sub-versions
#
# @version: Linux kernel version string
# @num: Number of sub-versions
#
# Print @num sub-versions of the specified kernel @version. Print 0 in place
# of non-decimal or missing sub-versions.
#
# Examples:
# version=2.4-13 num=4 => 2 4 0 13
# version=3.0.93_3.0.101-0.8.2_0.8.1 num=6 => 3 0 93 3 0 101
# version=4.12.14-lp150.11.4 num=5 => 4 12 14 0 11
#
split_kver()
{
local version="$1" num="$2"
local main extra
# Separate extra version to handle short main version (e.g. 2.4-13)
IFS="-_" read -r main extra <<< "$version"
split_version "$main" "." $(( num > 3 ? 3 : num ))
[[ "$num" -gt 3 ]] && split_version "$extra" ".-_" $(( num - 3 ))
}
#
# bytes_to_word - Convert byte array to hexadecimal word
#
# @bytes: List of numbers representing byte values
#
# Print a big-endian hexadecimal representation of the word that results from
# combining the specified byte values.
#
bytes_to_word()
{
printf "0x"
printf "%02x" "$@"
}
#
# get_system_level - Print system level word for specified distribution version
#
# @distro: Distro ID (ID value from /etc/os-release)
# @ver_str: Distro version string (VERSION_ID from /etc/os-release)
# @kver_str: Kernel version string (output of 'uname -r')
# @flags: Optional statistics flags
#
# Print a 64 bit hexadecimal system level in a format as understood by firmware.
#
# The format is 0xabccddeeeeffgghh, where
# - a=statistics flags
# - b=distro id
# - c=distro major version
# - d=distro minor version(s)
# - e=kernel sublevel 2
# - f=kernel version
# - g=kernel patchlevel
# - h=kernel sublevel 1
#
get_system_level()
{
local distro="$1" ver_str="$2" kver_str="$3" flags="${4:-0}"
local distro_id d_major d_minor d_minor2
local k_ver k_patchlvl k_sublvl k_sublvl2 bytes=()
# Extract list of sub-version numbers from version strings
read -r d_major d_minor d_minor2 <<< "$(split_version "$ver_str" "._-" 3)"
read -r k_ver k_patchlvl k_sublvl k_sublvl2 <<< "$(split_kver "$kver_str" 4)"
# Apply distro-specific logic
case "$distro" in
"rhel")
distro_id=$DISTRO_RHEL
;;
"sles")
distro_id=$DISTRO_SLES
;;
"ubuntu")
distro_id=$DISTRO_UBUNTU
# Encode minor and update version numbers in minor field
(( d_minor=((d_minor & 0xf) * 0x10) + (d_minor2 & 0xf) ))
;;
"fedora")
distro_id=$DISTRO_FEDORA
;;
"opensuse-leap")
distro_id=$DISTRO_OPENSUSE
;;
"debian")
distro_id=$DISTRO_DEBIAN
;;
"rhcos")
distro_id=$DISTRO_RHCOS
;;
*)
distro_id=$DISTRO_GENERIC
# Reset unsupported fields
d_major=0
d_minor=0
k_sublvl2=0
;;
esac
# Assemble byte data
(( bytes[0] = (flags & 0xf) * 0x10 + distro_id ))
(( bytes[1] = d_major ))
(( bytes[2] = d_minor ))
(( bytes[3] = (k_sublvl2 / 256) & 0xff ))
(( bytes[4] = k_sublvl2 & 0xff ))
(( bytes[5] = k_ver ))
(( bytes[6] = k_patchlvl ))
(( bytes[7] = k_sublvl ))
# Print as single hex word
bytes_to_word "${bytes[@]}"
}
get_distro()
{
local line ID="linux" VERSION_ID="0" VERSION="" update
[[ ! -e "$OS_RELEASE" ]] && return
# Only import required variables
while read -r line ; do
if [[ "$line" =~ ^ID= ]] || [[ "$line" =~ ^VERSION_ID= ]] ||
[[ "$line" =~ ^VERSION= ]] ; then
eval "$line"
fi
done <"$OS_RELEASE"
if [[ "$ID" == "ubuntu" ]] ; then
# Extract update version number only found in VERSION, e.g.
# VERSION_ID="18.04" VERSION="18.04.5 LTS"
update="${VERSION/*$VERSION_ID/}"
update="${update%% *}"
VERSION_ID="$VERSION_ID$update"
fi
echo "$ID:$VERSION_ID"
}
cpi_set_oslevel() cpi_set_oslevel()
{ {
local kver=$(echo "${1:-$(uname -r)}" | grep -E -o '^[0-9]+[.][0-9]+[.][0-9]+') local level="${1:-}"
local maj=$((${kver%%.*} % 256)) local flags list distro_id distro_ver kver id ver
local min=${kver#*.}
min=$((${min%.*} % 256)) if [[ "$level" =~ ^0x ]] && ! [[ "$level" =~ : ]] ; then
local rev=$((${kver##*.} % 256)) # Format: level=0x<hex>
local hexlevel=$(printf '0x%02x%02x%02x' $maj $min $rev) printf -v LEVEL "0x%016x" "$level" 2>/dev/null ||
LEVEL=$(printf '0x%016x' $(((LEVEL & 0xFFFFFFFFFF000000) | hexlevel))) fail_with "$PRG: Invalid hexadecimal number in $level" \
$EXIT_INVALID_CHARS
return
fi
# Format: level=[[[flags:]distro_id:distro_ver:]kver]
IFS=":" read -r -a list <<< "$level:"
kver="${list[*]: -1: 1}"
distro_ver="${list[*]: -2: 1}"
distro_id="${list[*]: -3: 1}"
flags="${list[*]: -4: 1}"
if [[ -z "$kver" ]] ; then
# Use version of currently running kernel
kver="$(uname -r)"
fi
if [[ -z "$distro_ver" ]] || [[ -z "$distro_id" ]] ; then
# Use distro ID and version from os-release file
IFS=":" read -r id ver <<< "$(get_distro)"
distro_id=${distro_id:-$id}
distro_ver=${distro_ver:-$ver}
fi
if [[ -z "$flags" ]] ; then
# Keep statistics flags from current system level
flags=$(( (LEVEL >> 60) & 0xf ))
fi
LEVEL=$(get_system_level "$distro_id" "$distro_ver" "$kver" "$flags")
} }
cpi_set_type() cpi_set_type()
+1 -1
View File
@@ -1154,7 +1154,7 @@ environment_setup() {
# create gzip-ped tar file # create gzip-ped tar file
create_package() { create_package() {
local rc_tar local rc_tar
pr_stdout "${step_num} Finalizing: Creating archive with collected data" pr_syslog_stdout "${step_num} Finalizing: Creating archive with collected data"
cd "${WORKDIR_BASE}" cd "${WORKDIR_BASE}"
touch "${WORKARCHIVE}" touch "${WORKARCHIVE}"
+56 -8
View File
@@ -7,6 +7,7 @@
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -16,6 +17,7 @@
#include "misc.h" #include "misc.h"
#define LSBLK_CMDLINE "lsblk -P -o NAME,MAJ:MIN,FSTYPE,UUID,MOUNTPOINT,PKNAME 2>/dev/null" #define LSBLK_CMDLINE "lsblk -P -o NAME,MAJ:MIN,FSTYPE,UUID,MOUNTPOINT,PKNAME 2>/dev/null"
#define LSBLK_CMDLINE2 "lsblk -P -o NAME,MAJ:MIN,FSTYPE,UUID,MOUNTPOINTS,PKNAME 2>/dev/null"
struct blkinfo { struct blkinfo {
struct devnode *devnode; struct devnode *devnode;
@@ -82,6 +84,26 @@ void blkinfo_print(struct blkinfo *blkinfo, int level)
printf("%*sparent=%s\n", level, "", blkinfo->parent); printf("%*sparent=%s\n", level, "", blkinfo->parent);
} }
/* Convert each occurrence of '\xnn' in @str to character with hex code <nn>. */
static void hex_unescape(char *str)
{
unsigned int c;
while ((str = strstr(str, "\\x"))) {
if (isxdigit(str[2]) && isxdigit(str[3]) &&
sscanf(str + 2, "%2x", &c) == 1) {
str[0] = (char)c;
/* Move remainder of str including nul behind <c>. */
memmove(str + /* <c> */ 1,
str + /* '\xnn' */ 4,
strlen(str + 4) + /* <nul> */ 1);
}
str++;
}
}
static char *isolate_keyword(char **line_ptr, const char *keyword) static char *isolate_keyword(char **line_ptr, const char *keyword)
{ {
char *start, *end; char *start, *end;
@@ -102,30 +124,58 @@ static char *isolate_keyword(char **line_ptr, const char *keyword)
return start; return start;
} }
static struct blkinfo *blkinfo_from_line(char *line) static void add_blkinfos_from_line(struct util_list *blkinfos,
char *line)
{ {
char *name, *majmin, *fstype, *uuid, *mountpoint, *parent; char *name, *majmin, *fstype, *uuid, *mountpoint, *mountpoints, *parent;
struct blkinfo *blkinfo;
name = isolate_keyword(&line, "NAME=\""); name = isolate_keyword(&line, "NAME=\"");
majmin = isolate_keyword(&line, "MAJ:MIN=\""); majmin = isolate_keyword(&line, "MAJ:MIN=\"");
if (!majmin)
majmin = isolate_keyword(&line, "MAJ_MIN=\"");
fstype = isolate_keyword(&line, "FSTYPE=\""); fstype = isolate_keyword(&line, "FSTYPE=\"");
uuid = isolate_keyword(&line, "UUID=\""); uuid = isolate_keyword(&line, "UUID=\"");
mountpoint = isolate_keyword(&line, "MOUNTPOINT=\""); mountpoint = isolate_keyword(&line, "MOUNTPOINT=\"");
mountpoints = isolate_keyword(&line, "MOUNTPOINTS=\"");
parent = isolate_keyword(&line, "PKNAME=\""); parent = isolate_keyword(&line, "PKNAME=\"");
return blkinfo_new(name, majmin, fstype, uuid, mountpoint, parent); if (!mountpoints) {
/* Handle old lsblk output format. */
blkinfo = blkinfo_new(name, majmin, fstype, uuid, mountpoint,
parent);
ptrlist_add(blkinfos, blkinfo);
return;
}
/* Restore newline mount point separator encoded as hex. */
hex_unescape(mountpoints);
/* Represent each mount point as a separate blkinfo to support
* resolution of multi-mount point file systems like btrfs
* subvolumes. */
while ((mountpoint = strsep(&mountpoints, "\n"))) {
blkinfo = blkinfo_new(name, majmin, fstype, uuid, mountpoint,
parent);
ptrlist_add(blkinfos, blkinfo);
}
} }
static struct util_list *blkinfos_read(void) static struct util_list *blkinfos_read(void)
{ {
char *output, *curr, *next; char *output, *curr, *next;
struct util_list *blkinfos; struct util_list *blkinfos;
struct blkinfo *blkinfo;
if (cached_blkinfos) if (cached_blkinfos)
return cached_blkinfos; return cached_blkinfos;
output = misc_read_cmd_output(LSBLK_CMDLINE, 0, 1); output = misc_read_cmd_output(LSBLK_CMDLINE2, 0, 1);
if (output && !*output) {
/* No output might indicate no support for new lsblk command-
* line format - fall back to old format. */
free(output);
output = misc_read_cmd_output(LSBLK_CMDLINE, 0, 1);
}
if (!output) if (!output)
return NULL; return NULL;
@@ -134,9 +184,7 @@ static struct util_list *blkinfos_read(void)
/* Iterate over each line. */ /* Iterate over each line. */
next = output; next = output;
while ((curr = strsep(&next, "\n"))) { while ((curr = strsep(&next, "\n"))) {
blkinfo = blkinfo_from_line(curr); add_blkinfos_from_line(blkinfos, curr);
if (blkinfo)
ptrlist_add(blkinfos, blkinfo);
} }
free(output); free(output);
+11 -4
View File
@@ -2088,12 +2088,18 @@ static exit_code_t devtype_remove_settings(struct devtype *dt, config_t config,
found = strlist_new(); found = strlist_new();
notfound = strlist_new(); notfound = strlist_new();
if (SCOPE_ACTIVE(config)) if (SCOPE_ACTIVE(config)) {
remove_settings(dt->active_settings, names, found, notfound, 1); rc = remove_settings(dt->active_settings, names, found,
notfound, 1);
if (rc)
goto out;
}
if (SCOPE_PERSISTENT(config)) { if (SCOPE_PERSISTENT(config)) {
remove_settings(dt->persistent_settings, names, found, rc = remove_settings(dt->persistent_settings, names, found,
notfound, 0); notfound, 0);
if (rc)
goto out;
} }
if (!util_list_is_empty(notfound)) { if (!util_list_is_empty(notfound)) {
@@ -2104,6 +2110,7 @@ static exit_code_t devtype_remove_settings(struct devtype *dt, config_t config,
rc = EXIT_SETTING_NOT_FOUND; rc = EXIT_SETTING_NOT_FOUND;
} }
out:
strlist_free(found); strlist_free(found);
strlist_free(notfound); strlist_free(notfound);
+7 -6
View File
@@ -30,8 +30,9 @@ check_dep:
$(call check_dep, \ $(call check_dep, \
"zdsfs", \ "zdsfs", \
"fuse.h", \ "fuse.h", \
"fuse-devel or libfuse-dev", \ "fuse3-devel or libfuse3-dev", \
"HAVE_FUSE=0") "HAVE_FUSE=0", \
"-DFUSE_USE_VERSION=30")
$(call check_dep, \ $(call check_dep, \
"zdsfs", \ "zdsfs", \
"curl/curl.h", \ "curl/curl.h", \
@@ -39,13 +40,13 @@ check_dep:
"HAVE_CURL=0") "HAVE_CURL=0")
ifneq ($(shell sh -c 'command -v pkg-config'),) ifneq ($(shell sh -c 'command -v pkg-config'),)
FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse) FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse3)
FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse) FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse3)
CURL_CFLAGS = $(shell pkg-config --silence-errors --cflags libcurl) CURL_CFLAGS = $(shell pkg-config --silence-errors --cflags libcurl)
CURL_LDLIBS = $(shell pkg-config --silence-errors --libs libcurl) CURL_LDLIBS = $(shell pkg-config --silence-errors --libs libcurl)
else else
FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse3
FUSE_LDLIBS = -lfuse FUSE_LDLIBS = -lfuse3
CURL_CFLAGS = -I/usr/include/s390x-linux-gnu/curl CURL_CFLAGS = -I/usr/include/s390x-linux-gnu/curl
CURL_LDLIBS = -lcurl CURL_LDLIBS = -lcurl
endif endif
-3
View File
@@ -227,9 +227,6 @@ Allow access by other users
\fB\-o\fR allow_root \fB\-o\fR allow_root
Allow access by root Allow access by root
.TP .TP
\fB\-o\fR nonempty
Allow mounts over non\-empty file/dir
.TP
\fB\-o\fR default_permissions \fB\-o\fR default_permissions
Enable permission checking by kernel Enable permission checking by kernel
.TP .TP
+12 -10
View File
@@ -8,7 +8,7 @@
*/ */
/* The fuse version define tells fuse that we want to use the new API */ /* The fuse version define tells fuse that we want to use the new API */
#define FUSE_USE_VERSION 26 #define FUSE_USE_VERSION 30
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@@ -312,7 +312,8 @@ void keepalive_start(void)
setup_timer(zdsfsinfo.keepalive); setup_timer(zdsfsinfo.keepalive);
} }
static int zdsfs_getattr(const char *path, struct stat *stbuf) static int zdsfs_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *UNUSED(fi))
{ {
char normds[MAXDSNAMELENGTH]; char normds[MAXDSNAMELENGTH];
size_t dssize; size_t dssize;
@@ -524,7 +525,8 @@ static int zdsfs_update_vtoc(void)
} }
static int zdsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, static int zdsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t UNUSED(offset), struct fuse_file_info *UNUSED(fi)) off_t UNUSED(offset), struct fuse_file_info *UNUSED(fi),
enum fuse_readdir_flags UNUSED(flags))
{ {
char normds[MAXDSNAMELENGTH]; char normds[MAXDSNAMELENGTH];
char *mbrname; char *mbrname;
@@ -544,9 +546,9 @@ static int zdsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
* type one: the root directory contains all data sets * type one: the root directory contains all data sets
*/ */
if (strcmp(path, "/") == 0) { if (strcmp(path, "/") == 0) {
filler(buf, ".", NULL, 0); filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0); filler(buf, "..", NULL, 0, 0);
filler(buf, METADATAFILE, NULL, 0); filler(buf, METADATAFILE, NULL, 0, 0);
/* note that we do not need to distinguish between /* note that we do not need to distinguish between
* normal files and directories here, that is done * normal files and directories here, that is done
* in the rdf_getattr function * in the rdf_getattr function
@@ -558,7 +560,7 @@ static int zdsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
lzds_dataset_get_is_supported(ds, &issupported); lzds_dataset_get_is_supported(ds, &issupported);
if (issupported) { if (issupported) {
lzds_dataset_get_name(ds, &dsname); lzds_dataset_get_name(ds, &dsname);
filler(buf, dsname, NULL, 0); filler(buf, dsname, NULL, 0, 0);
} }
} }
lzds_dsiterator_free(dsit); lzds_dsiterator_free(dsit);
@@ -572,14 +574,14 @@ static int zdsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
return -ENOENT; return -ENOENT;
lzds_dataset_get_is_PDS(ds, &ispds); lzds_dataset_get_is_PDS(ds, &ispds);
if (ispds) { if (ispds) {
filler(buf, ".", NULL, 0); filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0); filler(buf, "..", NULL, 0, 0);
rc = lzds_dataset_alloc_memberiterator(ds, &it); rc = lzds_dataset_alloc_memberiterator(ds, &it);
if (rc) if (rc)
return -ENOMEM; return -ENOMEM;
while (!lzds_memberiterator_get_next_member(it, &member)) { while (!lzds_memberiterator_get_next_member(it, &member)) {
lzds_pdsmember_get_name(member, &mbrname); lzds_pdsmember_get_name(member, &mbrname);
filler(buf, mbrname, NULL, 0); filler(buf, mbrname, NULL, 0, 0);
} }
lzds_memberiterator_free(it); lzds_memberiterator_free(it);
} else } else
+11 -10
View File
@@ -15,8 +15,9 @@ check_dep_fuse:
$(call check_dep, \ $(call check_dep, \
"zgetdump mount support", \ "zgetdump mount support", \
"fuse.h", \ "fuse.h", \
"fuse-devel or libfuse-dev", \ "fuse3-devel or libfuse3-dev", \
"HAVE_FUSE=0") "HAVE_FUSE=0", \
"-DFUSE_USE_VERSION=30")
endif endif
# #
@@ -41,28 +42,28 @@ check_dep_zlib:
all: check_dep_fuse check_dep_zlib zgetdump all: check_dep_fuse check_dep_zlib zgetdump
OBJECTS = zgetdump.o opts.o zg.o \ OBJECTS = zgetdump.o opts.o zg.o zg_error.o zg_print.o \
dfi.o dfi_mem_chunk.o dfi_vmcoreinfo.o \ dfi.o dfi_mem_chunk.o dfi_vmcoreinfo.o \
dfi_lkcd.o dfi_elf.o \ dfi_lkcd.o dfi_elf.o \
dfi_s390.o dfi_s390_ext.o\ dfi_s390.o dfi_s390_ext.o\
dfi_s390mv.o dfi_s390mv_ext.o \ dfi_s390mv.o dfi_s390mv_ext.o \
dfi_s390tape.o dfi_kdump.o \ dfi_s390tape.o dfi_kdump.o \
dfi_devmem.o dfo.o \ dfi_devmem.o dfo.o dfo_mem_chunk.o \
dfo_elf.o dfo_s390.o \ dfo_elf.o dfo_s390.o \
df_s390.o \ df_elf.o df_s390.o \
dt.o dt_s390sv.o dt_s390sv_ext.o \ dt.o dt_s390sv.o dt_s390sv_ext.o \
dt_s390mv.o dt_s390mv_ext.o \ dt_s390mv.o dt_s390mv_ext.o \
dt_scsi.o stdout.o \ dt_scsi.o output.o
ifeq ("$(HAVE_FUSE)","0") ifeq ("$(HAVE_FUSE)","0")
FUSE_CFLAGS = -DHAVE_FUSE=0 -D_FILE_OFFSET_BITS=64 FUSE_CFLAGS = -DHAVE_FUSE=0 -D_FILE_OFFSET_BITS=64
FUSE_LDLIBS = FUSE_LDLIBS =
else ifneq ($(shell sh -c 'command -v pkg-config'),) else ifneq ($(shell sh -c 'command -v pkg-config'),)
FUSE_CFLAGS = -DHAVE_FUSE=1 $(shell pkg-config --silence-errors --cflags fuse) FUSE_CFLAGS = -DHAVE_FUSE=1 $(shell pkg-config --silence-errors --cflags fuse3)
FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse) FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse3)
else else
FUSE_CFLAGS = -DHAVE_FUSE=1 -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse FUSE_CFLAGS = -DHAVE_FUSE=1 -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse3
FUSE_LDLIBS = -lfuse FUSE_LDLIBS = -lfuse3
endif endif
LDLIBS += -lz $(FUSE_LDLIBS) LDLIBS += -lz $(FUSE_LDLIBS)
ALL_CFLAGS += $(FUSE_CFLAGS) ALL_CFLAGS += $(FUSE_CFLAGS)
+191
View File
@@ -0,0 +1,191 @@
/*
* Copyright IBM Corp. 2001, 2018, 2021
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <string.h>
#include "df_elf.h"
#define NOTE_NAME_CORE "CORE"
#define NOTE_NAME_LINUX "LINUX"
#define NOTE_NAME_VMCOREINFO "VMCOREINFO"
/*
* Initialize ELF header
*/
void *ehdr_init(Elf64_Ehdr *ehdr, Elf64_Half phnum)
{
memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
ehdr->e_ident[EI_CLASS] = ELFCLASS64;
ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
ehdr->e_ident[EI_VERSION] = EV_CURRENT;
ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
ehdr->e_ident[EI_ABIVERSION] = 0;
memset(ehdr->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
ehdr->e_type = ET_CORE;
ehdr->e_machine = EM_S390;
ehdr->e_version = EV_CURRENT;
ehdr->e_entry = 0;
ehdr->e_phoff = sizeof(Elf64_Ehdr);
ehdr->e_shoff = 0;
ehdr->e_flags = 0;
ehdr->e_ehsize = sizeof(Elf64_Ehdr);
ehdr->e_phentsize = sizeof(Elf64_Phdr);
ehdr->e_phnum = phnum;
ehdr->e_shentsize = 0;
ehdr->e_shnum = 0;
ehdr->e_shstrndx = 0;
return ehdr + 1;
}
/*
* Initialize ELF note
*/
void *nt_init(void *buf, Elf64_Word type, const void *desc, int d_len,
const char *name)
{
Elf64_Nhdr *note;
u64 len;
note = (Elf64_Nhdr *)buf;
note->n_namesz = strlen(name) + 1;
note->n_descsz = d_len;
note->n_type = type;
len = sizeof(Elf64_Nhdr);
memcpy(buf + len, name, note->n_namesz);
len = ROUNDUP(len + note->n_namesz, 4);
memcpy(buf + len, desc, note->n_descsz);
len = ROUNDUP(len + note->n_descsz, 4);
return PTR_ADD(buf, len);
}
/*
* Initialize prstatus note
*/
void *nt_prstatus(void *ptr, const struct dfi_cpu *cpu)
{
struct nt_prstatus_64 nt_prstatus;
static int cpu_nr = 1;
memset(&nt_prstatus, 0, sizeof(nt_prstatus));
memcpy(&nt_prstatus.gprs, cpu->gprs, sizeof(cpu->gprs));
memcpy(&nt_prstatus.psw, cpu->psw, sizeof(cpu->psw));
memcpy(&nt_prstatus.acrs, cpu->acrs, sizeof(cpu->acrs));
nt_prstatus.pr_pid = cpu_nr;
cpu_nr++;
return nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus),
NOTE_NAME_CORE);
}
/*
* Initialize fpregset (floating point) note
*/
void *nt_fpregset(void *ptr, const struct dfi_cpu *cpu)
{
struct nt_fpregset_64 nt_fpregset;
memset(&nt_fpregset, 0, sizeof(nt_fpregset));
memcpy(&nt_fpregset.fpc, &cpu->fpc, sizeof(cpu->fpc));
memcpy(&nt_fpregset.fprs, &cpu->fprs, sizeof(cpu->fprs));
return nt_init(ptr, NT_FPREGSET, &nt_fpregset, sizeof(nt_fpregset),
NOTE_NAME_CORE);
}
/*
* Initialize timer note
*/
void *nt_s390_timer(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_TIMER, &cpu->timer, sizeof(cpu->timer),
NOTE_NAME_LINUX);
}
/*
* Initialize TOD clock comparator note
*/
void *nt_s390_tod_cmp(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_TODCMP, &cpu->todcmp,
sizeof(cpu->todcmp), NOTE_NAME_LINUX);
}
/*
* Initialize TOD programmable register note
*/
void *nt_s390_tod_preg(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_TODPREG, &cpu->todpreg,
sizeof(cpu->todpreg), NOTE_NAME_LINUX);
}
/*
* Initialize control register note
*/
void *nt_s390_ctrs(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_CTRS, &cpu->ctrs, sizeof(cpu->ctrs),
NOTE_NAME_LINUX);
}
/*
* Initialize prefix register note
*/
void *nt_s390_prefix(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_PREFIX, &cpu->prefix,
sizeof(cpu->prefix), NOTE_NAME_LINUX);
}
/*
* Initialize vxrs_low register note
*/
void *nt_s390_vxrs_low(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_VXRS_LOW, &cpu->vxrs_low,
sizeof(cpu->vxrs_low), NOTE_NAME_LINUX);
}
/*
* Initialize vxrs_high register note
*/
void *nt_s390_vxrs_high(void *ptr, const struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_VXRS_HIGH, &cpu->vxrs_high,
sizeof(cpu->vxrs_high), NOTE_NAME_LINUX);
}
/*
* Initialize prpsinfo note
*/
void *nt_prpsinfo(void *ptr)
{
struct nt_prpsinfo_64 prpsinfo;
memset(&prpsinfo, 0, sizeof(prpsinfo));
prpsinfo.pr_state = 0;
prpsinfo.pr_sname = 'R';
prpsinfo.pr_zomb = 0;
strcpy(prpsinfo.pr_fname, "vmlinux");
return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo),
NOTE_NAME_CORE);
}
/*
* Initialize vmcoreinfo note
*/
void *nt_vmcoreinfo(void *ptr, const char *vmcoreinfo)
{
if (!vmcoreinfo)
return ptr;
return nt_init(ptr, 0, vmcoreinfo, strlen(vmcoreinfo),
NOTE_NAME_VMCOREINFO);
}
+17 -1
View File
@@ -17,8 +17,8 @@
#include "lib/zt_common.h" #include "lib/zt_common.h"
#include "dfo.h"
#include "zg.h" #include "zg.h"
#include "dfi.h"
/* /*
* S390 CPU timer note (u64) * S390 CPU timer note (u64)
@@ -116,4 +116,20 @@ static inline void df_elf_ensure_s390x(void)
#endif #endif
} }
void *ehdr_init(Elf64_Ehdr *ehdr, Elf64_Half phnum);
void *nt_init(void *buf, Elf64_Word type, const void *desc, int d_len,
const char *name);
void *nt_prstatus(void *ptr, const struct dfi_cpu *cpu);
void *nt_fpregset(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_timer(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_tod_cmp(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_tod_preg(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_ctrs(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_prefix(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_vxrs_low(void *ptr, const struct dfi_cpu *cpu);
void *nt_s390_vxrs_high(void *ptr, const struct dfi_cpu *cpu);
void *nt_prpsinfo(void *ptr);
void *nt_vmcoreinfo(void *ptr, const char *vmcoreinfo);
#endif /* DF_ELF_H */ #endif /* DF_ELF_H */
+2
View File
@@ -286,6 +286,7 @@ const char *dfi_arch_str(enum dfi_arch arch)
return "unknown"; return "unknown";
} }
ABORT("dfi_arch_str: Invalid dfi arch: %d", arch); ABORT("dfi_arch_str: Invalid dfi arch: %d", arch);
return NULL; /* UNREACHABLE */
} }
/* /*
@@ -784,6 +785,7 @@ int dfi_init(void)
i++; i++;
} }
ERR_EXIT("No valid dump found on \"%s\"", g.opts.device); ERR_EXIT("No valid dump found on \"%s\"", g.opts.device);
return -1; /* UNREACHABLE */
} }
/* /*
+11 -108
View File
@@ -9,16 +9,13 @@
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#include <time.h> #include <string.h>
#include <errno.h>
#include "lib/util_list.h" #include "zg.h"
#include "dfo_mem_chunk.h"
#include "dfi_mem_chunk.h"
#include "dfo.h" #include "dfo.h"
#define dfo_chunk_iterate(dfo_chunk) \
util_list_iterate(&l.dump.chunk_list, dfo_chunk)
/* /*
* DFO vector * DFO vector
*/ */
@@ -28,70 +25,14 @@ static struct dfo *dfo_vec[] = {
NULL, NULL,
}; };
/*
* Dump (output) information
*/
struct dump {
u64 off; /* Current file offset in dump */
u64 size; /* Size of dump in bytes */
unsigned int chunk_cnt; /* Number of dump chunks */
struct util_list chunk_list; /* DFO chunk list */
};
/* /*
* File local static data * File local static data
*/ */
static struct { static struct {
struct dump dump; u64 off; /* Current file offset in dump */
struct dfo *dfo; struct dfo *dfo;
} l; } l;
/*
* Add dump chunk
*/
void dfo_chunk_add(u64 start, u64 size, void *data, dfo_chunk_read_fn read_fn)
{
struct dfo_chunk *dfo_chunk;
dfo_chunk = zg_alloc(sizeof(*dfo_chunk));
dfo_chunk->start = start;
dfo_chunk->end = start + size - 1;
dfo_chunk->data = data;
dfo_chunk->read_fn = read_fn;
util_list_add_head(&l.dump.chunk_list, dfo_chunk);
l.dump.chunk_cnt++;
l.dump.size = MAX(l.dump.size, dfo_chunk->end + 1);
}
/*
* Dump chunk function: Copy zero pages for chunk
*/
void dfo_chunk_zero_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
{
(void) dfo_chunk;
(void) off;
memset(buf, 0, cnt);
}
/*
* Dump chunk function: Copy given buffer for chunk
*/
void dfo_chunk_buf_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
{
memcpy(buf, dfo_chunk->data + off, cnt);
}
/*
* Dump chunk function: Copy given memory range for chunk
*/
void dfo_chunk_mem_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
{
struct dfi_mem_chunk *mem_chunk = dfo_chunk->data;
mem_chunk->read_fn(mem_chunk, off, buf, cnt);
}
/* /*
* Get DFO name * Get DFO name
*/ */
@@ -125,55 +66,17 @@ void dfo_init(void)
{ {
if (!l.dfo) if (!l.dfo)
ABORT("DFO not set"); ABORT("DFO not set");
util_list_init(&l.dump.chunk_list, struct dfo_chunk, list); if (dfo_chunk_init())
ABORT("DFO memory chunk init failed");
l.dfo->init(); l.dfo->init();
} }
/*
* Find dump chunk for offset "off"
*
* This function is a bit hacky. DFO chunks can overlap. If two DFO chunks
* overlap, the last registered chunk wins. The dfo_chunk_find() function
* reflects that by returning the first memory chunk that is found in
* the dfo chunk list.
*
* In addition to that it calculates the "virtual end" of that chunk. An
* overlapping chunk can limit the "virtual end" of an underlying chunk so
* that the "virtual end" of that chunk is lower than the "real end".
*
* Example:
*
* chunk 1.: |------|
* chunk 2.: |---------------------|
* off.....: ^
* virt end: ^
* real end: ^
*
* In this case chunk 2 will be returned and "end" is set to the start of
* chunk 1.
*/
static struct dfo_chunk *dfo_chunk_find(u64 off, u64 *end)
{
struct dfo_chunk *dfo_chunk;
*end = U64_MAX;
dfo_chunk_iterate(dfo_chunk) {
if (dfo_chunk->start <= off && dfo_chunk->end >= off) {
*end = MIN(*end, dfo_chunk->end);
return dfo_chunk;
} else if (dfo_chunk->start > off) {
*end = MIN(*end, dfo_chunk->start - 1);
}
}
return NULL;
}
/* /*
* Seek to output dump offset "off" * Seek to output dump offset "off"
*/ */
void dfo_seek(u64 off) void dfo_seek(u64 off)
{ {
l.dump.off = off; l.off = off;
} }
/* /*
@@ -183,7 +86,7 @@ u64 dfo_read(void *buf, u64 cnt)
{ {
struct dfo_chunk *dfo_chunk; struct dfo_chunk *dfo_chunk;
u64 copied = 0, end, size; u64 copied = 0, end, size;
u64 off = l.dump.off; u64 off = l.off;
while (copied != cnt) { while (copied != cnt) {
dfo_chunk = dfo_chunk_find(off, &end); dfo_chunk = dfo_chunk_find(off, &end);
@@ -196,7 +99,7 @@ u64 dfo_read(void *buf, u64 cnt)
off += size; off += size;
} }
out: out:
l.dump.off = off; l.off = off;
return copied; return copied;
} }
@@ -205,5 +108,5 @@ out:
*/ */
u64 dfo_size(void) u64 dfo_size(void)
{ {
return l.dump.size; return dfo_chunk_dump_size();
} }
+6 -31
View File
@@ -12,37 +12,12 @@
#ifndef DFO_H #ifndef DFO_H
#define DFO_H #define DFO_H
#include "lib/util_list.h" u64 dfo_read(void *buf, u64 cnt);
#include "zg.h" void dfo_seek(u64 addr);
u64 dfo_size(void);
struct dfo_chunk; const char *dfo_name(void);
void dfo_init(void);
typedef void (*dfo_chunk_read_fn)(struct dfo_chunk *chunk, u64 off, int dfo_set(const char *dfo_name);
void *buf, u64 cnt);
struct dfo_chunk {
struct util_list_node list;
u64 start;
u64 end;
dfo_chunk_read_fn read_fn;
void *data;
};
extern void dfo_chunk_zero_fn(struct dfo_chunk *chunk, u64 off, void *buf,
u64 cnt);
extern void dfo_chunk_buf_fn(struct dfo_chunk *chunk, u64 off, void *buf,
u64 cnt);
extern void dfo_chunk_mem_fn(struct dfo_chunk *chunk, u64 off, void *buf,
u64 cnt);
extern void dfo_chunk_add(u64 start, u64 size, void *data,
dfo_chunk_read_fn read_fn);
extern u64 dfo_read(void *buf, u64 cnt);
extern void dfo_seek(u64 addr);
extern u64 dfo_size(void);
extern const char *dfo_name(void);
extern void dfo_init(void);
extern int dfo_set(const char *dfo_name);
/* /*
* DFO operations * DFO operations
+26 -211
View File
@@ -19,6 +19,7 @@
#include "df_elf.h" #include "df_elf.h"
#include "dfi.h" #include "dfi.h"
#include "dfi_mem_chunk.h" #include "dfi_mem_chunk.h"
#include "dfo_mem_chunk.h"
#include "dfi_vmcoreinfo.h" #include "dfi_vmcoreinfo.h"
#include "dfo.h" #include "dfo.h"
@@ -27,55 +28,19 @@
#define HDR_BASE_SIZE 0x2000 #define HDR_BASE_SIZE 0x2000
/* /*
* File local static data * Initialize ELF loads program headers
*/ */
static struct { static u64 load_phdrs_init(Elf64_Phdr *phdr, u64 elf_offset)
void *hdr;
u32 hdr_size;
} l;
/*
* Initialize ELF header
*/
static void *ehdr_init(Elf64_Ehdr *ehdr)
{
memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
ehdr->e_ident[EI_CLASS] = ELFCLASS64;
ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
ehdr->e_ident[EI_VERSION] = EV_CURRENT;
ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
ehdr->e_ident[EI_ABIVERSION] = 0;
memset(ehdr->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
ehdr->e_type = ET_CORE;
ehdr->e_machine = EM_S390;
ehdr->e_version = EV_CURRENT;
ehdr->e_entry = 0;
ehdr->e_phoff = sizeof(Elf64_Ehdr);
ehdr->e_shoff = 0;
ehdr->e_flags = 0;
ehdr->e_ehsize = sizeof(Elf64_Ehdr);
ehdr->e_phentsize = sizeof(Elf64_Phdr);
ehdr->e_phnum = dfi_mem_chunk_cnt() + 1;
ehdr->e_shentsize = 0;
ehdr->e_shnum = 0;
ehdr->e_shstrndx = 0;
return ehdr + 1;
}
/*
* Initialize ELF loads
*/
static u64 loads_init(Elf64_Phdr *phdr, u64 loads_offset)
{ {
struct dfi_mem_chunk *mem_chunk; struct dfi_mem_chunk *mem_chunk;
u64 mem_size = 0; u64 mem_size = 0;
dfi_mem_chunk_iterate(mem_chunk) { dfi_mem_chunk_iterate(mem_chunk) {
phdr->p_type = PT_LOAD; phdr->p_type = PT_LOAD;
phdr->p_offset = loads_offset; phdr->p_offset = elf_offset;
phdr->p_vaddr = mem_chunk->start; phdr->p_vaddr = mem_chunk->start;
phdr->p_paddr = mem_chunk->start; phdr->p_paddr = phdr->p_vaddr;
phdr->p_memsz = mem_chunk->end - mem_chunk->start + 1; phdr->p_memsz = mem_chunk->size;
if (mem_chunk->read_fn == dfi_mem_chunk_read_zero) if (mem_chunk->read_fn == dfi_mem_chunk_read_zero)
/* Zero memory chunk */ /* Zero memory chunk */
phdr->p_filesz = 0; phdr->p_filesz = 0;
@@ -83,7 +48,7 @@ static u64 loads_init(Elf64_Phdr *phdr, u64 loads_offset)
phdr->p_filesz = phdr->p_memsz; phdr->p_filesz = phdr->p_memsz;
phdr->p_flags = PF_R | PF_W | PF_X; phdr->p_flags = PF_R | PF_W | PF_X;
phdr->p_align = PAGE_SIZE; phdr->p_align = PAGE_SIZE;
loads_offset += phdr->p_filesz; elf_offset += phdr->p_filesz;
mem_size += phdr->p_memsz; mem_size += phdr->p_memsz;
phdr++; phdr++;
} }
@@ -91,160 +56,12 @@ static u64 loads_init(Elf64_Phdr *phdr, u64 loads_offset)
} }
/* /*
* Initialize ELF note * Initialize the program header entries for the notes and the related segment
* data.
*/ */
static void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len, static void *notes_init(Elf64_Phdr *phdr, void *segment_start, u64 elf_offset)
const char *name)
{ {
Elf64_Nhdr *note; void *ptr = segment_start;
u64 len;
note = (Elf64_Nhdr *)buf;
note->n_namesz = strlen(name) + 1;
note->n_descsz = d_len;
note->n_type = type;
len = sizeof(Elf64_Nhdr);
memcpy(buf + len, name, note->n_namesz);
len = ROUNDUP(len + note->n_namesz, 4);
memcpy(buf + len, desc, note->n_descsz);
len = ROUNDUP(len + note->n_descsz, 4);
return PTR_ADD(buf, len);
}
/*
* Initialize prstatus note
*/
static void *nt_prstatus(void *ptr, struct dfi_cpu *cpu)
{
struct nt_prstatus_64 nt_prstatus;
static int cpu_nr = 1;
memset(&nt_prstatus, 0, sizeof(nt_prstatus));
memcpy(&nt_prstatus.gprs, cpu->gprs, sizeof(cpu->gprs));
memcpy(&nt_prstatus.psw, cpu->psw, sizeof(cpu->psw));
memcpy(&nt_prstatus.acrs, cpu->acrs, sizeof(cpu->acrs));
nt_prstatus.pr_pid = cpu_nr;
cpu_nr++;
return nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus),
"CORE");
}
/*
* Initialize fpregset (floating point) note
*/
static void *nt_fpregset(void *ptr, struct dfi_cpu *cpu)
{
struct nt_fpregset_64 nt_fpregset;
memset(&nt_fpregset, 0, sizeof(nt_fpregset));
memcpy(&nt_fpregset.fpc, &cpu->fpc, sizeof(cpu->fpc));
memcpy(&nt_fpregset.fprs, &cpu->fprs, sizeof(cpu->fprs));
return nt_init(ptr, NT_FPREGSET, &nt_fpregset, sizeof(nt_fpregset),
"CORE");
}
/*
* Initialize timer note
*/
static void *nt_s390_timer(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_TIMER, &cpu->timer, sizeof(cpu->timer),
"LINUX");
}
/*
* Initialize TOD clock comparator note
*/
static void *nt_s390_tod_cmp(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_TODCMP, &cpu->todcmp,
sizeof(cpu->todcmp), "LINUX");
}
/*
* Initialize TOD programmable register note
*/
static void *nt_s390_tod_preg(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_TODPREG, &cpu->todpreg,
sizeof(cpu->todpreg), "LINUX");
}
/*
* Initialize control register note
*/
static void *nt_s390_ctrs(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_CTRS, &cpu->ctrs, sizeof(cpu->ctrs),
"LINUX");
}
/*
* Initialize prefix register note
*/
static void *nt_s390_prefix(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_PREFIX, &cpu->prefix,
sizeof(cpu->prefix), "LINUX");
}
/*
* Initialize vxrs_low register note
*/
static void *nt_s390_vxrs_low(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_VXRS_LOW, &cpu->vxrs_low,
sizeof(cpu->vxrs_low), "LINUX");
}
/*
* Initialize vxrs_high register note
*/
static void *nt_s390_vxrs_high(void *ptr, struct dfi_cpu *cpu)
{
return nt_init(ptr, NT_S390_VXRS_HIGH, &cpu->vxrs_high,
sizeof(cpu->vxrs_high), "LINUX");
}
/*
* Initialize prpsinfo note
*/
static void *nt_prpsinfo(void *ptr)
{
struct nt_prpsinfo_64 prpsinfo;
memset(&prpsinfo, 0, sizeof(prpsinfo));
prpsinfo.pr_state = 0;
prpsinfo.pr_sname = 'R';
prpsinfo.pr_zomb = 0;
strcpy(prpsinfo.pr_fname, "vmlinux");
return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo), "CORE");
}
/*
* Initialize vmcoreinfo note
*/
static void *nt_vmcoreinfo(void *ptr)
{
char *vmcoreinfo = dfi_vmcoreinfo_get();
if (!vmcoreinfo)
return ptr;
return nt_init(ptr, 0, vmcoreinfo, strlen(vmcoreinfo), "VMCOREINFO");
}
/*
* Initialize notes
*/
static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
{
void *ptr_start = ptr;
struct dfi_cpu *cpu; struct dfi_cpu *cpu;
ptr = nt_prpsinfo(ptr); ptr = nt_prpsinfo(ptr);
@@ -266,24 +83,24 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
} }
} }
out: out:
ptr = nt_vmcoreinfo(ptr); ptr = nt_vmcoreinfo(ptr, dfi_vmcoreinfo_get());
memset(phdr, 0, sizeof(*phdr)); memset(phdr, 0, sizeof(*phdr));
phdr->p_type = PT_NOTE; phdr->p_type = PT_NOTE;
phdr->p_offset = notes_offset; phdr->p_offset = elf_offset;
phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start); phdr->p_filesz = PTR_DIFF(ptr, segment_start);
return ptr; return ptr;
} }
/* /*
* Setup dump chunks * Setup dump chunks
*/ */
static void dump_chunks_init(void) static void dump_chunks_init(void *hdr, u64 hdr_size)
{ {
struct dfi_mem_chunk *mem_chunk; struct dfi_mem_chunk *mem_chunk;
u64 off = 0; u64 off = 0;
dfo_chunk_add(0, l.hdr_size, l.hdr, dfo_chunk_buf_fn); dfo_chunk_add(off, hdr_size, hdr, dfo_chunk_buf_fn);
off = l.hdr_size; off += hdr_size;
dfi_mem_chunk_iterate(mem_chunk) { dfi_mem_chunk_iterate(mem_chunk) {
if (mem_chunk->read_fn == dfi_mem_chunk_read_zero) if (mem_chunk->read_fn == dfi_mem_chunk_read_zero)
/* Zero memory chunk */ /* Zero memory chunk */
@@ -312,31 +129,29 @@ static void dfo_elf_init(void)
{ {
Elf64_Phdr *phdr_notes, *phdr_loads; Elf64_Phdr *phdr_notes, *phdr_loads;
u32 alloc_size; u32 alloc_size;
void *buf, *ptr;
u64 hdr_off; u64 hdr_off;
void *ptr;
ensure_s390x(); ensure_s390x();
alloc_size = HDR_BASE_SIZE + alloc_size = HDR_BASE_SIZE +
dfi_cpu_cnt() * HDR_PER_CPU_SIZE + dfi_cpu_cnt() * HDR_PER_CPU_SIZE +
dfi_mem_chunk_cnt() * HDR_PER_MEMC_SIZE; dfi_mem_chunk_cnt() * HDR_PER_MEMC_SIZE;
l.hdr = zg_alloc(alloc_size); buf = zg_alloc(alloc_size);
/* Init elf header */ /* Init elf header */
ptr = ehdr_init(l.hdr); ptr = ehdr_init(buf, dfi_mem_chunk_cnt() + 1);
/* Init program headers */ /* Init program headers */
phdr_notes = ptr; phdr_notes = ptr;
ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr)); ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr));
phdr_loads = ptr; phdr_loads = ptr;
ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr) * dfi_mem_chunk_cnt()); ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr) * dfi_mem_chunk_cnt());
/* Init notes */ /* Init notes */
hdr_off = PTR_DIFF(ptr, l.hdr); hdr_off = PTR_DIFF(ptr, buf);
ptr = notes_init(phdr_notes, ptr, hdr_off); ptr = notes_init(phdr_notes, ptr, hdr_off);
/* Init loads */ hdr_off = PTR_DIFF(ptr, buf);
hdr_off = PTR_DIFF(ptr, l.hdr); load_phdrs_init(phdr_loads, hdr_off);
loads_init(phdr_loads, hdr_off); if (hdr_off > alloc_size)
l.hdr_size = hdr_off; ABORT("hdr_size=%llu alloc_size=%u", hdr_off, alloc_size);
if (l.hdr_size > alloc_size) dump_chunks_init(buf, hdr_off);
ABORT("hdr_size=%u alloc_size=%u", l.hdr_size, alloc_size);
dump_chunks_init();
} }
/* /*
+128
View File
@@ -0,0 +1,128 @@
/*
* Copyright IBM Corp. 2001, 2017, 2021
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <string.h>
#include "zg.h"
#include "dfi_mem_chunk.h"
#include "dfo_mem_chunk.h"
/*
* File local static data
*/
static struct {
u64 size; /* Size of dump in bytes */
unsigned int chunk_cnt; /* Number of dump chunks */
struct util_list chunk_list; /* DFO chunk list */
} l;
/*
* Add dump chunk
*/
void dfo_chunk_add(u64 start, u64 size, void *data, dfo_chunk_read_fn read_fn)
{
struct dfo_chunk *dfo_chunk;
dfo_chunk = zg_alloc(sizeof(*dfo_chunk));
dfo_chunk->start = start;
dfo_chunk->end = start + size - 1;
dfo_chunk->data = data;
dfo_chunk->read_fn = read_fn;
util_list_add_head(&l.chunk_list, dfo_chunk);
l.chunk_cnt++;
l.size = MAX(l.size, dfo_chunk->end + 1);
}
/*
* Dump chunk function: Copy zero pages for chunk
*/
void dfo_chunk_zero_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
{
(void) dfo_chunk;
(void) off;
memset(buf, 0, cnt);
}
/*
* Dump chunk function: Copy given buffer for chunk
*/
void dfo_chunk_buf_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
{
memcpy(buf, dfo_chunk->data + off, cnt);
}
/*
* Dump chunk function: Copy given memory range for chunk
*/
void dfo_chunk_mem_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt)
{
struct dfi_mem_chunk *mem_chunk = dfo_chunk->data;
mem_chunk->read_fn(mem_chunk, off, buf, cnt);
}
/*
* Find dump chunk for offset "off"
*
* This function is a bit hacky. DFO chunks can overlap. If two DFO chunks
* overlap, the last registered chunk wins. The dfo_chunk_find() function
* reflects that by returning the first memory chunk that is found in
* the dfo chunk list.
*
* In addition to that it calculates the "virtual end" of that chunk. An
* overlapping chunk can limit the "virtual end" of an underlying chunk so
* that the "virtual end" of that chunk is lower than the "real end".
*
* Example:
*
* chunk 1.: |------|
* chunk 2.: |---------------------|
* off.....: ^
* virt end: ^
* real end: ^
*
* In this case chunk 2 will be returned and "end" is set to the start of
* chunk 1.
*/
struct dfo_chunk *dfo_chunk_find(u64 off, u64 *end)
{
struct dfo_chunk *dfo_chunk;
*end = U64_MAX;
dfo_chunk_iterate(dfo_chunk) {
if (dfo_chunk->start <= off && dfo_chunk->end >= off) {
*end = MIN(*end, dfo_chunk->end);
return dfo_chunk;
} else if (dfo_chunk->start > off) {
*end = MIN(*end, dfo_chunk->start - 1);
}
}
return NULL;
}
struct util_list *dfo_chunk_list(void)
{
return &l.chunk_list;
}
u64 dfo_chunk_dump_size(void)
{
return l.size;
}
int dfo_chunk_init(void)
{
util_list_init(&l.chunk_list, struct dfo_chunk, list);
return 0;
}
void dfo_chunk_deinit(void)
{
memset(&l, 0, sizeof(l));
}
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright IBM Corp. 2001, 2017, 2021
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef DFO_MEM_CHUNK_H
#define DFO_MEM_CHUNK_H
#include "lib/zt_common.h"
#include "lib/util_list.h"
struct dfo_chunk;
typedef void (*dfo_chunk_read_fn)(struct dfo_chunk *chunk, u64 off,
void *buf, u64 cnt);
struct dfo_chunk {
struct util_list_node list;
u64 start;
u64 end;
dfo_chunk_read_fn read_fn;
void *data;
};
void dfo_chunk_zero_fn(struct dfo_chunk *chunk, u64 off, void *buf, u64 cnt);
void dfo_chunk_buf_fn(struct dfo_chunk *chunk, u64 off, void *buf, u64 cnt);
void dfo_chunk_mem_fn(struct dfo_chunk *chunk, u64 off, void *buf, u64 cnt);
void dfo_chunk_add(u64 start, u64 size, void *data, dfo_chunk_read_fn read_fn);
struct dfo_chunk *dfo_chunk_find(u64 off, u64 *end);
struct util_list *dfo_chunk_list(void);
#define dfo_chunk_iterate(dfo_chunk) \
util_list_iterate(dfo_chunk_list(), dfo_chunk)
u64 dfo_chunk_dump_size(void);
int dfo_chunk_init(void);
void dfo_chunk_deinit(void);
#endif /* DFO_MEM_CHUNK_H */
+1
View File
@@ -19,6 +19,7 @@
#include "df_s390.h" #include "df_s390.h"
#include "dfi_mem_chunk.h" #include "dfi_mem_chunk.h"
#include "dfo_mem_chunk.h"
#include "dfo.h" #include "dfo.h"
/* /*
+18
View File
@@ -40,6 +40,7 @@ static const char optstr[] = "hvVidmus:f:X";
*/ */
static const char help_text[] = static const char help_text[] =
"Usage: zgetdump DUMP [-s SYS] [-f FMT] > DUMP_FILE\n" "Usage: zgetdump DUMP [-s SYS] [-f FMT] > DUMP_FILE\n"
" DUMP [-s SYS] [-f FMT] DUMP_FILE\n"
" -m DUMP [-s SYS] [-f FMT] DIR\n" " -m DUMP [-s SYS] [-f FMT] DIR\n"
" -i DUMP [-s SYS]\n" " -i DUMP [-s SYS]\n"
" -d DUMPDEV\n" " -d DUMPDEV\n"
@@ -86,6 +87,7 @@ static void init_defaults(struct options *opts)
{ {
opts->prog_name = "zgetdump"; opts->prog_name = "zgetdump";
opts->action = ZG_ACTION_COPY; opts->action = ZG_ACTION_COPY;
opts->output_path = NULL;
#ifdef __s390x__ #ifdef __s390x__
opts->fmt = "elf"; opts->fmt = "elf";
#else #else
@@ -166,6 +168,14 @@ static void device_set(struct options *opts, const char *path)
opts->device = zg_strdup(path); opts->device = zg_strdup(path);
} }
/*
* Set output path
*/
static void output_set(struct options *opts, const char *path)
{
opts->output_path = zg_strdup(path);
}
/* /*
* Set FUSE debug options * Set FUSE debug options
*/ */
@@ -229,6 +239,14 @@ static void parse_pos_args(struct options *opts, char *argv[], int argc)
switch (opts->action) { switch (opts->action) {
case ZG_ACTION_COPY: case ZG_ACTION_COPY:
if (pos_args == 0)
ERR_EXIT("No device or dump specified");
if (pos_args > 2)
ERR_EXIT("Too many positional parameters specified");
device_set(opts, argv[optind]);
if (pos_args > 1)
output_set(opts, argv[optind + 1]);
break;
case ZG_ACTION_DUMP_INFO: case ZG_ACTION_DUMP_INFO:
case ZG_ACTION_DEVICE_INFO: case ZG_ACTION_DEVICE_INFO:
if (pos_args == 0) if (pos_args == 0)
+2
View File
@@ -18,6 +18,8 @@ struct options {
int action_specified; int action_specified;
enum zg_action action; enum zg_action action;
char *device; char *device;
/* If `output_path == NULL` the output is written to `stdout` */
const char *output_path;
char *mount_point; char *mount_point;
int fmt_specified; int fmt_specified;
const char *fmt; const char *fmt;
+7 -9
View File
@@ -1,7 +1,7 @@
/* /*
* zgetdump - Tool for copying and converting System z dumps * zgetdump - Tool for copying and converting System z dumps
* *
* Write dump to standard output (stdout) * Write dump to the file descriptor (fd)
* *
* Copyright IBM Corp. 2001, 2017 * Copyright IBM Corp. 2001, 2017
* *
@@ -12,9 +12,9 @@
#include "zg.h" #include "zg.h"
#include "dfi.h" #include "dfi.h"
#include "dfo.h" #include "dfo.h"
#include "stdout.h" #include "output.h"
int stdout_write_dump(void) int write_dump(FILE *stream)
{ {
const u64 output_size = dfo_size(); const u64 output_size = dfo_size();
char buf[8UL * PAGE_SIZE]; char buf[8UL * PAGE_SIZE];
@@ -28,15 +28,13 @@ int stdout_write_dump(void)
STDERR("\n"); STDERR("\n");
zg_progress_init("Copying dump", output_size); zg_progress_init("Copying dump", output_size);
while (written != output_size) { while (written != output_size) {
ssize_t rc; size_t rc;
u64 cnt; u64 cnt;
cnt = dfo_read(buf, sizeof(buf)); cnt = dfo_read(buf, sizeof(buf));
rc = write(STDOUT_FILENO, buf, cnt); rc = fwrite(buf, cnt, 1, stream);
if (rc == -1) if (rc != 1 && ferror(stream))
ERR_EXIT_ERRNO("Error: Write failed"); ERR_EXIT("Error: Write failed");
if (rc != (ssize_t) cnt)
ERR_EXIT("Error: Could not write full block");
written += cnt; written += cnt;
zg_progress(written); zg_progress(written);
}; };
+6 -4
View File
@@ -5,9 +5,11 @@
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#ifndef STDOUT_H #ifndef OUTPUT_H
#define STDOUT_H #define OUTPUT_H
int stdout_write_dump(void); #include <stdio.h>
#endif /* STDOUT_H */ int write_dump(FILE *stream);
#endif /* OUTPUT_H */
+13 -8
View File
@@ -9,7 +9,7 @@
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#define FUSE_USE_VERSION 25 #define FUSE_USE_VERSION 30
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@@ -84,8 +84,11 @@ static void stat_dump_init(void)
/* /*
* FUSE callback: Getattr * FUSE callback: Getattr
*/ */
static int zfuse_getattr(const char *path, struct stat *stat) static int zfuse_getattr(const char *path, struct stat *stat,
struct fuse_file_info *fi)
{ {
(void) fi;
if (strcmp(path, "/") == 0) { if (strcmp(path, "/") == 0) {
*stat = l.stat_root; *stat = l.stat_root;
return 0; return 0;
@@ -101,17 +104,19 @@ static int zfuse_getattr(const char *path, struct stat *stat)
* FUSE callback: Readdir - Return ".", ".." and dump file * FUSE callback: Readdir - Return ".", ".." and dump file
*/ */
static int zfuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, static int zfuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi) off_t offset, struct fuse_file_info *fi,
enum fuse_readdir_flags flags)
{ {
(void) offset; (void) offset;
(void) fi; (void) fi;
(void) flags;
if (strcmp(path, "/") != 0) if (strcmp(path, "/") != 0)
return -ENOENT; return -ENOENT;
filler(buf, ".", NULL, 0); filler(buf, ".", NULL, 0, 0);
filler(buf, "..", NULL, 0); filler(buf, "..", NULL, 0, 0);
filler(buf, &l.path[1], NULL, 0); filler(buf, &l.path[1], NULL, 0, 0);
return 0; return 0;
} }
@@ -206,7 +211,7 @@ int zfuse_mount_dump(void)
fuse_opt_add_arg(&args, "zgetdump"); fuse_opt_add_arg(&args, "zgetdump");
fuse_opt_add_arg(&args, "-s"); fuse_opt_add_arg(&args, "-s");
snprintf(tmp_str, sizeof(tmp_str), snprintf(tmp_str, sizeof(tmp_str),
"-ofsname=%s,ro,default_permissions,nonempty", "-ofsname=%s,ro,default_permissions",
g.opts.device); g.opts.device);
fuse_opt_add_arg(&args, tmp_str); fuse_opt_add_arg(&args, tmp_str);
fuse_opt_add_arg(&args, g.opts.mount_point); fuse_opt_add_arg(&args, g.opts.mount_point);
@@ -214,7 +219,7 @@ int zfuse_mount_dump(void)
stat_root_init(); stat_root_init();
stat_dump_init(); stat_dump_init();
snprintf(l.path, sizeof(l.path), "/dump.%s", dfo_name()); snprintf(l.path, sizeof(l.path), "/dump.%s", dfo_name());
return fuse_main(args.argc, args.argv, &zfuse_ops); return fuse_main(args.argc, args.argv, &zfuse_ops, NULL);
} }
/* /*
+42 -71
View File
@@ -45,79 +45,50 @@
/* /*
* Memory functions * Memory functions
*/ */
extern void *zg_alloc(unsigned int size); void *zg_alloc(unsigned int size);
extern void *zg_realloc(void *ptr, unsigned int size); void *zg_realloc(void *ptr, unsigned int size);
extern void zg_free(void *ptr); void zg_free(void *ptr);
extern char *zg_strdup(const char *str); char *zg_strdup(const char *str);
/* /*
* At exit functions * At exit functions
*/ */
typedef void (*zg_atexit_fn_t)(void); typedef void (*zg_atexit_fn_t)(void);
extern void zg_atexit(zg_atexit_fn_t fn); void zg_atexit(zg_atexit_fn_t fn);
extern void __noreturn zg_exit(int rc); void __noreturn zg_exit(int rc);
/* /*
* Temporary device node functions * Temporary device node functions
*/ */
extern char *zg_devnode_create(dev_t dev); char *zg_devnode_create(dev_t dev);
/* /*
* Progress bar functions * Progress bar functions
*/ */
extern void zg_progress_init(const char *msg, u64 mem_size); void zg_progress_init(const char *msg, u64 mem_size);
extern void zg_progress(u64 addr); void zg_progress(u64 addr);
/* /*
* Error and print functions * Error and print functions
*/ */
#define ERR(x...) \
do { \
fprintf(stderr, "%s: ", "zgetdump"); \
fprintf(stderr, x); \
fprintf(stderr, "\n"); \
} while (0)
#define ERR_EXIT(x...) \ void zg_err(const char *fmt, ...);
do { \ void zg_err_exit(const char *fmt, ...);
ERR(x); \ void zg_err_exit_errno(const char *fmt, ...);
zg_exit(1); \ void zg_abort(const char *fmt, ...);
} while (0)
#define ABORT(x...) \ #define ERR(fmt, ...) zg_err(fmt, ## __VA_ARGS__)
do { \ #define ERR_EXIT(fmt, ...) zg_err_exit(fmt, ## __VA_ARGS__)
ERR("Internal Error: " x); \ #define ERR_EXIT_ERRNO(fmt, ...) zg_err_exit_errno(fmt, ## __VA_ARGS__)
abort(); \ #define ABORT(fmt, ...) zg_abort(fmt, ## __VA_ARGS__)
} while (0)
#define ERR_EXIT_ERRNO(x...) \ void zg_stderr(const char *fmt, ...);
do { \ void zg_stderr_pr(const char *fmt, ...);
fflush(stdout); \ void zg_stdout(const char *fmt, ...);
fprintf(stderr, "%s: ", "zgetdump"); \
fprintf(stderr, x); \
fprintf(stderr, " (%s)", strerror(errno)); \
fprintf(stderr, "\n"); \
zg_exit(1); \
} while (0)
#define STDERR(x...) \
do { \
fprintf(stderr, x); \
fflush(stderr); \
} while (0)
#define STDERR_PR(x...) \
do { \
fprintf(stderr, "\r%s: ", "zgetdump"); \
fprintf(stderr, x); \
} while (0)
#define STDOUT(x...) \
do { \
fprintf(stdout, x); \
fflush(stdout); \
} while (0)
#define STDERR(fmt, ...) zg_stderr(fmt, ## __VA_ARGS__)
#define STDERR_PR(fmt, ...) zg_stderr_pr(fmt, ## __VA_ARGS__)
#define STDOUT(fmt, ...) zg_stdout(fmt, ## __VA_ARGS__)
/* /*
* Misc * Misc
*/ */
@@ -140,9 +111,9 @@ static inline u32 zg_csum_partial(const void *buf, int len, u32 sum)
/* /*
* Pointer atrithmetic * Pointer atrithmetic
*/ */
#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y))) #define PTR_SUB(x, y) ((void *)(((char *) (x)) - ((unsigned long) (y))))
#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y))) #define PTR_ADD(x, y) ((void *)(((char *) (x)) + ((unsigned long) (y))))
#define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y)))) #define PTR_DIFF(x, y) ((unsigned long)PTR_SUB(x, y))
/* /*
* File functions * File functions
@@ -167,22 +138,22 @@ enum zg_check {
ZG_CHECK_NONE, ZG_CHECK_NONE,
}; };
extern const char *zg_path(struct zg_fh *zg_fh); const char *zg_path(struct zg_fh *zg_fh);
extern const struct stat *zg_stat(struct zg_fh *zg_fh); const struct stat *zg_stat(struct zg_fh *zg_fh);
extern struct zg_fh *zg_open(const char *path, int flags, enum zg_check check); struct zg_fh *zg_open(const char *path, int flags, enum zg_check check);
extern void zg_close(struct zg_fh *zg_fh); void zg_close(struct zg_fh *zg_fh);
extern ssize_t zg_read(struct zg_fh *zg_fh, void *buf, size_t cnt, ssize_t zg_read(struct zg_fh *zg_fh, void *buf, size_t cnt,
enum zg_check check); enum zg_check check);
extern ssize_t zg_gets(struct zg_fh *zg_fh, void *buf, size_t cnt, ssize_t zg_gets(struct zg_fh *zg_fh, void *buf, size_t cnt,
enum zg_check check); enum zg_check check);
extern u64 zg_size(struct zg_fh *zg_fh); u64 zg_size(struct zg_fh *zg_fh);
extern off_t zg_tell(struct zg_fh *zg_fh, enum zg_check check); off_t zg_tell(struct zg_fh *zg_fh, enum zg_check check);
extern off_t zg_seek(struct zg_fh *zg_fh, off_t off, enum zg_check check); off_t zg_seek(struct zg_fh *zg_fh, off_t off, enum zg_check check);
extern off_t zg_seek_end(struct zg_fh *zg_fh, off_t off, enum zg_check check); off_t zg_seek_end(struct zg_fh *zg_fh, off_t off, enum zg_check check);
extern off_t zg_seek_cur(struct zg_fh *zg_fh, off_t off, enum zg_check check); off_t zg_seek_cur(struct zg_fh *zg_fh, off_t off, enum zg_check check);
extern int zg_ioctl(struct zg_fh *zg_fh, int rq, void *data, const char *op, int zg_ioctl(struct zg_fh *zg_fh, int rq, void *data, const char *op,
enum zg_check check); enum zg_check check);
extern enum zg_type zg_type(struct zg_fh *zg_fh); enum zg_type zg_type(struct zg_fh *zg_fh);
/* /*
* zgetdump actions * zgetdump actions
+72
View File
@@ -0,0 +1,72 @@
/*
* Copyright IBM Corp. 2001, 2017, 2021
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <stdarg.h>
#include "lib/util_libc.h"
#include "zg.h"
static inline void _zg_err(const char *fmt, va_list ap)
{
fprintf(stderr, "%s: ", "zgetdump");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
}
static inline void _zg_err_errno(const char *fmt, va_list ap)
{
const int errno_backup = errno;
fflush(stdout);
fprintf(stderr, "%s: ", "zgetdump");
vfprintf(stderr, fmt, ap);
fprintf(stderr, " (%s)", strerror(errno_backup));
fprintf(stderr, "\n");
}
void zg_err(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_zg_err(fmt, ap);
va_end(ap);
}
void zg_err_exit(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_zg_err(fmt, ap);
va_end(ap);
zg_exit(1);
}
void zg_err_exit_errno(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_zg_err_errno(fmt, ap);
va_end(ap);
zg_exit(1);
}
void zg_abort(const char *fmt, ...)
{
char *newfmt;
va_list ap;
newfmt = util_strcat_realloc(util_strdup("Internal Error: "), fmt);
va_start(ap, fmt);
_zg_err(newfmt, ap);
va_end(ap);
free(newfmt);
abort();
}
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright IBM Corp. 2001, 2017, 2021
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <stdarg.h>
#include "zg.h"
static inline void _zg_stderr(const char *fmt, va_list ap)
{
vfprintf(stderr, fmt, ap);
fflush(stderr);
}
static inline void _zg_stderr_pr(const char *fmt, va_list ap)
{
fprintf(stderr, "\r%s: ", "zgetdump");
vfprintf(stderr, fmt, ap);
}
static inline void _zg_stdout(const char *fmt, va_list ap)
{
vfprintf(stdout, fmt, ap);
fflush(stdout);
}
void zg_stderr(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_zg_stderr(fmt, ap);
va_end(ap);
}
void zg_stderr_pr(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_zg_stderr_pr(fmt, ap);
va_end(ap);
}
void zg_stdout(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_zg_stdout(fmt, ap);
va_end(ap);
}
+2
View File
@@ -8,6 +8,8 @@ zgetdump \- Tool for copying and converting System z dumps
.SH SYNOPSIS .SH SYNOPSIS
\fBzgetdump\fR DUMP [-s SYS] [-f FMT] > DUMP_FILE \fBzgetdump\fR DUMP [-s SYS] [-f FMT] > DUMP_FILE
.br
DUMP [-s SYS] [-f FMT] DUMP_FILE
.br .br
-m DUMP [-s SYS] [-f FMT] DIR -m DUMP [-s SYS] [-f FMT] DIR
.br .br
+35 -7
View File
@@ -30,7 +30,7 @@
#include "dt.h" #include "dt.h"
#include "dfi.h" #include "dfi.h"
#include "dfo.h" #include "dfo.h"
#include "stdout.h" #include "output.h"
#include "zfuse.h" #include "zfuse.h"
/* /*
@@ -156,18 +156,46 @@ static int do_mount(void)
return rc; return rc;
} }
/* static FILE *open_file_for_writing(const char *output)
* Run "copy to stdout" action
*/
static int do_copy(void)
{ {
FILE *stream;
int fd;
if (output) {
fd = open(output,
O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC,
0600);
if (fd == -1)
ERR_EXIT_ERRNO("Could not open '%s' exclusively", output);
} else {
fd = dup(STDOUT_FILENO);
if (fd == -1)
ERR_EXIT_ERRNO("Could not dup() stdout");
}
stream = fdopen(fd, "w");
if (!stream)
ERR_EXIT_ERRNO("Could not fdopen()");
fd = -1;
return stream;
}
/*
* Run "copy to output" action
*/
static int do_copy(const char *output)
{
FILE *stream;
int rc; int rc;
if (dfi_init() != 0) if (dfi_init() != 0)
ERR_EXIT("Dump cannot be processed (is not complete)"); ERR_EXIT("Dump cannot be processed (is not complete)");
dfo_init(); dfo_init();
kdump_select_check(); kdump_select_check();
rc = stdout_write_dump(); stream = open_file_for_writing(output);
rc = write_dump(stream);
fclose(stream);
dfi_exit(); dfi_exit();
return rc; return rc;
} }
@@ -185,7 +213,7 @@ int main(int argc, char *argv[])
switch (g.opts.action) { switch (g.opts.action) {
case ZG_ACTION_COPY: case ZG_ACTION_COPY:
return do_copy(); return do_copy(g.opts.output_path);
case ZG_ACTION_DUMP_INFO: case ZG_ACTION_DUMP_INFO:
return do_dump_info(); return do_dump_info();
case ZG_ACTION_DEVICE_INFO: case ZG_ACTION_DEVICE_INFO:
+27
View File
@@ -97,6 +97,33 @@ char *strcpy(char *dest, const char *src)
return dest; return dest;
} }
/**
* Copy \a src to buffer \a dest of size \a size. At most size - 1
* chars will be copied. \a dest will always be NUL terminated.
*
* Note: If the return value is greater than or equal to size truncation
* occurred.
*
* @param[in] dest Destination buffer
* @param[in] src Source string
* @param[in] size Size of destination buffer
*
* @returns strlen Length of \a src string
*/
size_t strlcpy(char *dest, const char *src, size_t size)
{
size_t str_len = strlen(src);
size_t len;
if (size) {
len = MIN(size - 1, str_len);
memcpy(dest, src, len);
dest[len] = '\0';
}
return str_len;
}
/* /*
* Return string length * Return string length
*/ */
+2 -1
View File
@@ -54,13 +54,14 @@ char *strcat(char *, const char *);
int strncmp(const char *, const char *, unsigned long); int strncmp(const char *, const char *, unsigned long);
int strlen(const char *); int strlen(const char *);
char *strcpy(char *, const char *); char *strcpy(char *, const char *);
size_t strlcpy(char *dest, const char *src, size_t size);
char *strchr(const char *str, char c); char *strchr(const char *str, char c);
unsigned int strhash(unsigned char *str, unsigned int hash_size); unsigned int strhash(unsigned char *str, unsigned int hash_size);
unsigned long get_zeroed_page(void); unsigned long get_zeroed_page(void);
void free_page(unsigned long); void free_page(unsigned long);
void initialize(void); void initialize(void);
void libc_stop(unsigned long) __noreturn; void libc_stop(unsigned long) __noreturn;
void start(void); void __noreturn start(void);
void pgm_check_handler(void); void pgm_check_handler(void);
void pgm_check_handler_fn(void); void pgm_check_handler_fn(void);
void panic_notify(unsigned long reason); void panic_notify(unsigned long reason);
+1 -1
View File
@@ -188,7 +188,7 @@ boot:
/* append 'BOOT_IMAGE=<num>' to parmline */ /* append 'BOOT_IMAGE=<num>' to parmline */
snprintf(endstring, sizeof(endstring), " BOOT_IMAGE=%u", value); snprintf(endstring, sizeof(endstring), " BOOT_IMAGE=%u", value);
if ((strlen(cmd_line_extra) + strlen(endstring)) < COMMAND_LINE_SIZE) if ((strlen(cmd_line_extra) + strlen(endstring)) < LEGACY_COMMAND_LINE_SIZE)
strcat(cmd_line_extra, endstring); strcat(cmd_line_extra, endstring);
sclp_setup(SCLP_DISABLE); sclp_setup(SCLP_DISABLE);
+3 -2
View File
@@ -75,15 +75,16 @@ out_free_page:
} }
static void execute(uint64_t psw) static __noreturn void execute(uint64_t psw)
{ {
asm volatile( asm volatile(
" lpsw %[psw]\n" " lpsw %[psw]\n"
: : [psw] "Q" (psw) : "cc" : : [psw] "Q" (psw) : "cc"
); );
__builtin_unreachable();
} }
void start(void) void __noreturn start(void)
{ {
struct stage2_descr stage2_descr; struct stage2_descr stage2_descr;
struct subchannel_id subchannel_id; struct subchannel_id subchannel_id;
+3 -2
View File
@@ -393,7 +393,7 @@ static void store_status(void)
* Block followed by a valid checksum (as defined in lowcore.h and set * Block followed by a valid checksum (as defined in lowcore.h and set
* by ipl.c). In case of match use diag308 to IPL. * by ipl.c). In case of match use diag308 to IPL.
*/ */
static void dump_exit(unsigned long code) static __noreturn void dump_exit(unsigned long code)
{ {
struct ipib_info *ipib_info = (struct ipib_info *)&S390_lowcore.ipib; struct ipib_info *ipib_info = (struct ipib_info *)&S390_lowcore.ipib;
uint32_t ipib_len, csum; uint32_t ipib_len, csum;
@@ -406,6 +406,7 @@ static void dump_exit(unsigned long code)
libc_stop(code); libc_stop(code);
diag308(DIAG308_SET, (void *) ipib_info->ipib); diag308(DIAG308_SET, (void *) ipib_info->ipib);
diag308(DIAG308_IPL, NULL); diag308(DIAG308_IPL, NULL);
__builtin_unreachable();
} }
/* /*
@@ -420,7 +421,7 @@ void panic_notify(unsigned long code)
/* /*
* Create stand-alone dump * Create stand-alone dump
*/ */
void start(void) void __noreturn start(void)
{ {
init_early(); init_early();
dt_device_parm_setup(); dt_device_parm_setup();
+66 -69
View File
@@ -159,8 +159,8 @@ static void hash_table_add(struct env_hash_entry *items,
(*new_idx)++; (*new_idx)++;
} }
struct env_hash_entry *hash_table_find(struct env_hash_entry **buckets, static struct env_hash_entry *hash_table_find(struct env_hash_entry **buckets,
char *name) char *name)
{ {
struct env_hash_entry *item; struct env_hash_entry *item;
@@ -232,7 +232,8 @@ static void parse_envblk(struct env_hash_entry *items,
* CMDL_LEN: length of the command line to be processed * CMDL_LEN: length of the command line to be processed
* BUCKETS: hash table of pairs (NAME, VALUE) * BUCKETS: hash table of pairs (NAME, VALUE)
*/ */
void process_parm_line(struct env_hash_entry **buckets, unsigned int cmdl_len) void process_parm_line(struct env_hash_entry **buckets, unsigned int cmdl_len,
unsigned int max_len)
{ {
struct env_hash_entry *item; struct env_hash_entry *item;
char empty_str = 0; char empty_str = 0;
@@ -282,7 +283,7 @@ void process_parm_line(struct env_hash_entry **buckets, unsigned int cmdl_len)
*/ */
len = strlen(val); len = strlen(val);
if (cmdl_len + len - (end - start + 1) >= COMMAND_LINE_SIZE) if (cmdl_len + len - (end - start + 1) >= max_len)
/* VALUE doesn't fit */ /* VALUE doesn't fit */
break; break;
/* /*
@@ -306,7 +307,7 @@ void process_parm_line(struct env_hash_entry **buckets, unsigned int cmdl_len)
/** /**
* LEN: length of the command line to be processed * LEN: length of the command line to be processed
*/ */
static void handle_environment(unsigned int len) static void handle_environment(unsigned int len, unsigned int max_len)
{ {
struct env_hash_entry *buckets[STR_HASH_SIZE]; struct env_hash_entry *buckets[STR_HASH_SIZE];
struct env_hash_entry *items; struct env_hash_entry *items;
@@ -326,30 +327,76 @@ static void handle_environment(unsigned int len)
* find environment variables in the command line and * find environment variables in the command line and
* replace them with their values as found in the hash table * replace them with their values as found in the hash table
*/ */
process_parm_line(buckets, len); process_parm_line(buckets, len, max_len);
free_page((unsigned long)items); free_page((unsigned long)items);
} }
void start(void) static void verify_secure_boot(void)
{ {
unsigned int subchannel_id;
unsigned char *cextra = (unsigned char *)COMMAND_LINE_EXTRA;
unsigned char *cmdline = (unsigned char *)COMMAND_LINE;
unsigned int cmdline_len = 0, cextra_len = 0;
/* /*
* IPL process is secure we have to use default IPL values and * IPL process is secure we have to use default IPL values and
* check if the psw jump address is within at the start of a * check if the psw jump address is within at the start of a
* verified component. If it is not IPL is aborted. * verified component. If it is not IPL is aborted.
*/ */
if (secure_boot_enabled()) { if (_stage3_parms.image_addr != IMAGE_LOAD_ADDRESS ||
if (_stage3_parms.image_addr != IMAGE_LOAD_ADDRESS || _stage3_parms.load_psw != DEFAULT_PSW_LOAD)
_stage3_parms.load_psw != DEFAULT_PSW_LOAD) panic(ESECUREBOOT, "%s", msg_sipl_inval);
panic(ESECUREBOOT, "%s", msg_sipl_inval);
if (!is_verified_address(_stage3_parms.load_psw & PSW32_ADDR_MASK)) if (!is_verified_address(_stage3_parms.load_psw & PSW32_ADDR_MASK))
panic(ESECUREBOOT, "%s", msg_sipl_unverified); panic(ESECUREBOOT, "%s", msg_sipl_unverified);
}
static void setup_cmdline(void)
{
char *cextra = (char *)COMMAND_LINE_EXTRA;
char *cmdline = (char *)COMMAND_LINE;
unsigned int cmdline_len = 0;
unsigned int max_cmdline_len = *(unsigned long *)MAX_COMMAND_LINE_SIZE;
if (!max_cmdline_len)
max_cmdline_len = LEGACY_COMMAND_LINE_SIZE;
/* if valid command line is given, copy it into new kernel space */
if (_stage3_parms.parm_addr != UNSPECIFIED_ADDRESS) {
strlcpy(cmdline, (void *)(unsigned long *)_stage3_parms.parm_addr,
max_cmdline_len);
} }
/* determine length of original parm line */
cmdline_len = MIN((unsigned int)strlen(cmdline), max_cmdline_len - 1);
/* convert extra parameter to ascii */
if (!_stage3_parms.extra_parm || !*cextra)
goto noextra;
/* Handle extra kernel parameters specified in DASD boot menu. */
ebcdic_to_ascii((unsigned char *)cextra, (unsigned char *)cextra, COMMAND_LINE_EXTRA_SIZE);
while (isspace(*cextra))
cextra++;
/*
* if extra parm string starts with '=' replace original string,
* else append
*/
if (*cextra == 0x3d) {
strlcpy(cmdline, cextra+1, max_cmdline_len);
} else if (*cextra && cmdline_len + 1 <= max_cmdline_len - 1) {
/* add blank */
cmdline[cmdline_len++] = 0x20;
strlcpy(cmdline + cmdline_len, cextra, max_cmdline_len - cmdline_len);
}
noextra:
handle_environment(strlen(cmdline), max_cmdline_len);
}
void start(void)
{
unsigned int subchannel_id;
if (secure_boot_enabled())
verify_secure_boot();
/* /*
* cut the kernel header * cut the kernel header
*/ */
@@ -362,57 +409,7 @@ void start(void)
*(unsigned int *)__LC_IPLDEV = subchannel_id; *(unsigned int *)__LC_IPLDEV = subchannel_id;
*(unsigned long long *)IPL_DEVICE = subchannel_id; *(unsigned long long *)IPL_DEVICE = subchannel_id;
/* if valid command line is given, copy it into new kernel space */ setup_cmdline();
if (_stage3_parms.parm_addr != UNSPECIFIED_ADDRESS) {
memcpy(cmdline,
(void *)(unsigned long *)_stage3_parms.parm_addr,
COMMAND_LINE_SIZE);
/* terminate \0 */
cmdline[COMMAND_LINE_SIZE - 1] = 0;
}
/* determine length of original parm line */
cmdline_len = MIN(strlen((const char *)cmdline),
COMMAND_LINE_SIZE - 1);
/* convert extra parameter to ascii */
if (!_stage3_parms.extra_parm || !*cextra)
goto noextra;
/* Handle extra kernel parameters specified in DASD boot menu. */
ebcdic_to_ascii(cextra, cextra, COMMAND_LINE_SIZE);
/* determine length of extra parameter */
cextra_len = MIN(strlen((const char *)cextra), COMMAND_LINE_SIZE - 1);
/* remove leading whitespace of extra parameter */
while (cextra_len > 0 && *cextra == 0x20) {
cextra++;
cextra_len--;
}
/*
* if extra parm string starts with '=' replace original string,
* else append
*/
if (*cextra == 0x3d && cextra_len >= 1) {
/* skip '=' */
cextra++;
cextra_len--;
memcpy(cmdline, cextra, cextra_len);
cmdline[cextra_len] = 0;
} else if (cmdline_len + 1 <= COMMAND_LINE_SIZE - 1) {
/* add blank */
cmdline[cmdline_len] = 0x20;
cmdline_len++;
/* check if length is within max value */
cextra_len = (cmdline_len + cextra_len <= COMMAND_LINE_SIZE - 1) ?
cextra_len : (COMMAND_LINE_SIZE - 1 - cmdline_len);
/* append string */
memcpy(cmdline + cmdline_len, cextra, cextra_len);
/* terminate 0 */
cmdline[cmdline_len + cextra_len] = 0;
}
noextra:
handle_environment(cmdline_len + cextra_len);
/* copy initrd start address and size intop new kernle space */ /* copy initrd start address and size intop new kernle space */
*(unsigned long long *)INITRD_START = _stage3_parms.initrd_addr; *(unsigned long long *)INITRD_START = _stage3_parms.initrd_addr;
+36 -89
View File
@@ -218,12 +218,25 @@ iplstart:
la %r2,_initrd_addr # store ramdisk address la %r2,_initrd_addr # store ramdisk address
mvc INITRD_START-PARMAREA(8,%r12),0(%r2) mvc INITRD_START-PARMAREA(8,%r12),0(%r2)
# copy kernel to final destination
l %r6,.Lkernsize
sl %r6,.Lkernoff
l %r2,.Lkernoff # 0x10000
lr %r3,%r6
l %r4,.Loffset # 0x4000
a %r4,.Lkernoff
lr %r5,%r6
mvcl %r2,%r4
l %r12,.Lparmarea
# #
# Load parameter file # Load parameter file
# #
l %r4,_parm_addr+4 l %r4,_parm_addr+4
chi %r4,-1
be .Lnopf
.Lagain1: .Lagain1:
lr %r2,%r4 # load parmfile lr %r2,%r4 # load parmfile
bas %r14,.Lloader bas %r14,.Lloader
@@ -236,31 +249,35 @@ iplstart:
clc 0(3,%r4),.L_eof # if it is EOFx clc 0(3,%r4),.L_eof # if it is EOFx
bz .Lagain1 # skip dateset trailer bz .Lagain1 # skip dateset trailer
chi %r2,COMMAND_LINE_SIZE-1 # truncate if line too long lt %r3,MAX_COMMAND_LINE_SIZE-PARMAREA+4(%r12)
jnz 0f
lhi %r3,LEGACY_COMMAND_LINE_SIZE
0: cr %r2,%r3 # truncate if line too long
bnh .Lnotrunc bnh .Lnotrunc
la %r2,COMMAND_LINE_SIZE-1 lr %r2,%r3
.Lnotrunc: .Lnotrunc:
la %r5,0(%r4,%r2) # search for EBCDIC chars la %r5,0(%r4,%r2) # search for EBCDIC chars
lr %r3,%r2 ahi %r5,-1
lr %r6,%r2
.Lidebc: .Lidebc:
tm 0(%r5),0x80 # high order bit set ? tm 0(%r5),0x80 # high order bit set ?
bo .Ldocv # yes -> convert from EBCDIC bo .Ldocv # yes -> convert from EBCDIC
ahi %r5,-1 ahi %r5,-1
bct %r3,.Lidebc bct %r6,.Lidebc
b .Lnocv b .Lnocv
.Ldocv: .Ldocv:
la %r3,_ebcasc lr %r6,%r2
tr 0(256,%r4),0(%r3) # convert parameters to ascii la %r5,_ebcasc
tr 256(256,%r4),0(%r3) 0: tr 0(1,%r4),0(%r5)
tr 512(256,%r4),0(%r3) ahi %r4,1
tr 768(127,%r4),0(%r3) brct %r6,0b
l %r4,_parm_addr+4
.Lnocv: .Lnocv:
la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line lr %r5,%r2
mvc 0(256,%r3),0(%r4) ahi %r5,-1
mvc 256(256,%r3),256(%r4) la %r6,COMMAND_LINE-PARMAREA(%r12)
mvc 512(256,%r3),512(%r4) lr %r7,%r2
mvc 768(127,%r3),768(%r4) mvcl %r6,%r4
slr %r0,%r0 slr %r0,%r0
b .Lcntlp b .Lcntlp
.Ldelspc: .Ldelspc:
@@ -284,6 +301,8 @@ iplstart:
.Lagain2: .Lagain2:
l %r2,INITRD_START-PARMAREA+4(%r12) # load ramdisk l %r2,INITRD_START-PARMAREA+4(%r12) # load ramdisk
chi %r2,-1
be .Lnoinitrd
bas %r14,.Lloader bas %r14,.Lloader
st %r2,INITRD_SIZE-PARMAREA+4(%r12) # store ramdisk size st %r2,INITRD_SIZE-PARMAREA+4(%r12) # store ramdisk size
@@ -298,86 +317,14 @@ iplstart:
clc 0(3,%r2),.L_eof clc 0(3,%r2),.L_eof
bz .Lagain2 bz .Lagain2
# .Lnoinitrd:
# Copy kernel image to final position mvc 0(8,0),_load_psw # copy load psw
#
la %r2,_load_psw # prepare copy code
la %r3,.Lcopypsw
mvc 0(8,%r3),0(%r2) # copy load psw
l %r4,_initrd_addr+4
ahi %r4,-0x100
la %r2,.Lcopystart # get copy code addr (from)
mvc 0(.Lcopyend-.Lcopystart,%r4),0(%r2) # copy code
l %r1,.Loffset # temp kernel address (from)
l %r2,4(%r3) # get kernel addr from psw (to)
n %r2,.Lpswmask
s %r2,.Lkernoff
l %r3,.Lkernsize # (length)
br %r4 # branch to copy routine
#
# Copy kernel, then load PSW
#
# R1 = from
# R2 = to
# R3 = length
#
.align 8
.Lcopystart:
clr %r1,%r2
je .Lcopyfinish # kernel is already at dest
jh .Lcopytolower # need move to lower address
# Copy last to first
ar %r1,%r3 # start from last long
ar %r2,%r3
lhi %r4,-4 # set addr increment to -4
j .Lcopygo
# Copy first to last
.Lcopytolower:
lhi %r4,4 # set addr increment to 4
.Lcopygo:
ahi %r3,3 # get size in longs
srl %r3,2
.Lcopyloop:
l %r0,0(%r1) # copy longs
st %r0,0(%r2)
ar %r1,%r4
ar %r2,%r4
brct %r3,.Lcopyloop
.Lcopyfinish:
bras %r13,.Lcopyload # set up base register
.Lcopyload:
sr %r0,%r0
la %r1,.Lcopypsw-.Lcopyload(%r13)
mvc 0(8,%r0),0(%r1) # copy load psw to 0
lm %r0,%r15,.Lvmparam-.Lcopyload(%r13) # load saved registers
lpsw 0 # start kernel lpsw 0 # start kernel
.align 8 .align 8
.Lcopypsw:
.quad 0
.Lvmparam: .Lvmparam:
.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 # vm parameter space .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 # vm parameter space
.Lcopyend:
.Lpswmask:
.long 0x7fffffff
.Lkernsize: .Lkernsize:
.long 0 .long 0
.Lkernoff: .Lkernoff:
+7 -13
View File
@@ -39,13 +39,17 @@ struct job_target_data {
blocknum_t targetoffset; blocknum_t targetoffset;
}; };
struct job_ipl_data { struct job_common_ipl_data {
char* image; char* image;
char* parmline; char* parmline;
char* ramdisk; char* ramdisk;
address_t image_addr; address_t image_addr;
address_t parm_addr; address_t parm_addr;
address_t ramdisk_addr; address_t ramdisk_addr;
};
struct job_ipl_data {
struct job_common_ipl_data common;
address_t envblk_addr; address_t envblk_addr;
int is_kdump; int is_kdump;
}; };
@@ -61,13 +65,8 @@ struct job_segment_data {
}; };
struct job_dump_data { struct job_dump_data {
struct job_common_ipl_data common;
char* device; char* device;
char* image;
char* parmline;
char* ramdisk;
address_t image_addr;
address_t parm_addr;
address_t ramdisk_addr;
uint64_t mem; uint64_t mem;
}; };
@@ -80,13 +79,8 @@ struct job_mvdump_data {
}; };
struct job_ipl_tape_data { struct job_ipl_tape_data {
struct job_common_ipl_data common;
char* device; char* device;
char* image;
char* parmline;
char* ramdisk;
address_t image_addr;
address_t parm_addr;
address_t ramdisk_addr;
}; };
+2 -1
View File
@@ -23,7 +23,8 @@
#define ADDRESS_LIMIT 0x80000000UL #define ADDRESS_LIMIT 0x80000000UL
#define UNSPECIFIED_ADDRESS -1UL #define UNSPECIFIED_ADDRESS -1UL
#define MAXIMUM_PARMLINE_SIZE 0x380UL #define LEGACY_MAXIMUM_PARMLINE_SIZE 0x380UL
#define MAXIMUM_PARMLINE_SIZE 0x10000UL
#define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000UL #define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000UL
#define BOOTMAP_FILENAME "bootmap" #define BOOTMAP_FILENAME "bootmap"
+37 -40
View File
@@ -34,7 +34,7 @@
#include "misc.h" #include "misc.h"
/* Pointer to dedicated empty block in bootmap. */ /* Pointer to dedicated empty block in bootmap. */
disk_blockptr_t empty_block; static disk_blockptr_t empty_block;
/* Get size of a bootmap block pointer for disk with given INFO. */ /* Get size of a bootmap block pointer for disk with given INFO. */
static int static int
@@ -142,7 +142,7 @@ check_secure_boot_support(void)
* of segment table blocks to the file identified by file descriptor FD. Upon * of segment table blocks to the file identified by file descriptor FD. Upon
* success, return 0 and set SECTION_POINTER to point to the first block in * success, return 0 and set SECTION_POINTER to point to the first block in
* the resulting segment table. Return non-zero otherwise. */ * the resulting segment table. Return non-zero otherwise. */
int static int
add_segment_table(int fd, disk_blockptr_t* list, blocknum_t count, add_segment_table(int fd, disk_blockptr_t* list, blocknum_t count,
disk_blockptr_t* segment_pointer, disk_blockptr_t* segment_pointer,
struct disk_info* info) struct disk_info* info)
@@ -560,16 +560,16 @@ static int add_ipl_program(int fd, char *filename,
*/ */
/* initiate values for ramdisk */ /* initiate values for ramdisk */
stats.st_size = 0; stats.st_size = 0;
if (ipl->ramdisk != NULL) { if (ipl->common.ramdisk != NULL) {
/* Add ramdisk */ /* Add ramdisk */
if (verbose) { if (verbose) {
printf(" initial ramdisk...: %s\n", ipl->ramdisk); printf(" initial ramdisk...: %s\n", ipl->common.ramdisk);
} }
/* Get ramdisk file size */ /* Get ramdisk file size */
if (stat(ipl->ramdisk, &stats)) { if (stat(ipl->common.ramdisk, &stats)) {
error_reason(strerror(errno)); error_reason(strerror(errno));
error_text("Could not get information for file '%s'", error_text("Could not get information for file '%s'",
ipl->ramdisk); ipl->common.ramdisk);
free(table); free(table);
return -1; return -1;
} }
@@ -609,10 +609,10 @@ static int add_ipl_program(int fd, char *filename,
flags |= STAGE3_FLAG_KDUMP; flags |= STAGE3_FLAG_KDUMP;
/* Get kernel file size */ /* Get kernel file size */
if (stat(ipl->image, &stats)) { if (stat(ipl->common.image, &stats)) {
error_reason(strerror(errno)); error_reason(strerror(errno));
error_text("Could not get information for file '%s'", error_text("Could not get information for file '%s'",
ipl->image); ipl->common.image);
free(table); free(table);
return -1; return -1;
} }
@@ -669,12 +669,12 @@ static int add_ipl_program(int fd, char *filename,
/* Add stage 3 parameter to bootmap */ /* Add stage 3 parameter to bootmap */
rc = boot_get_stage3_parms(&stage3_params, &stage3_params_size, rc = boot_get_stage3_parms(&stage3_params, &stage3_params_size,
ipl->parm_addr, ipl->ramdisk_addr, ipl->common.parm_addr, ipl->common.ramdisk_addr,
ramdisk_size, ramdisk_size,
ipl->is_kdump ? IMAGE_ENTRY_KDUMP : ipl->is_kdump ? IMAGE_ENTRY_KDUMP :
IMAGE_ENTRY, IMAGE_ENTRY,
(info->type == disk_type_scsi) ? 0 : 1, (info->type == disk_type_scsi) ? 0 : 1,
flags, ipl->image_addr, image_size, flags, ipl->common.image_addr, image_size,
ipl->envblk_addr, ipl->envblk_addr,
add_envblk ? envblk->size : 0); add_envblk ? envblk->size : 0);
if (rc) { if (rc) {
@@ -698,14 +698,14 @@ static int add_ipl_program(int fd, char *filename,
/* Add kernel image */ /* Add kernel image */
if (verbose) { if (verbose) {
printf(" kernel image......: %s\n", ipl->image); printf(" kernel image......: %s\n", ipl->common.image);
} }
signature_size = extract_signature(ipl->image, &signature, &sig_head); signature_size = extract_signature(ipl->common.image, &signature, &sig_head);
if (signature_size && if (signature_size &&
(is_secure == SECURE_BOOT_ENABLED || (is_secure == SECURE_BOOT_ENABLED ||
(is_secure == SECURE_BOOT_AUTO && secure_boot_supported))) { (is_secure == SECURE_BOOT_AUTO && secure_boot_supported))) {
if (verbose) if (verbose)
printf(" signature for.....: %s\n", ipl->image); printf(" signature for.....: %s\n", ipl->common.image);
rc = add_component_buffer(fd, signature, sig_head.length, rc = add_component_buffer(fd, signature, sig_head.length,
(component_data)sig_head, (component_data)sig_head,
@@ -722,7 +722,7 @@ static int add_ipl_program(int fd, char *filename,
comp_nr++; comp_nr++;
free(signature); free(signature);
check_remaining_filesize(image_size, signature_size, info, check_remaining_filesize(image_size, signature_size, info,
ipl->image); ipl->common.image);
} else if (is_secure == SECURE_BOOT_ENABLED) { } else if (is_secure == SECURE_BOOT_ENABLED) {
/* /*
* If secure boot is forced and we have failed to extract a * If secure boot is forced and we have failed to extract a
@@ -731,16 +731,16 @@ static int add_ipl_program(int fd, char *filename,
*/ */
error_text("Could not install Secure Boot IPL records"); error_text("Could not install Secure Boot IPL records");
error_reason("Missing signature in image file %s", error_reason("Missing signature in image file %s",
ipl->image); ipl->common.image);
free(table); free(table);
return -1; return -1;
} }
rc = add_component_file(fd, ipl->image, ipl->image_addr, rc = add_component_file(fd, ipl->common.image, ipl->common.image_addr,
signature_size, VOID_ADD(table, offset), signature_size, VOID_ADD(table, offset),
add_files, info, target, &comp_loc[comp_nr]); add_files, info, target, &comp_loc[comp_nr]);
if (rc) { if (rc) {
error_text("Could not add image file '%s'", ipl->image); error_text("Could not add image file '%s'", ipl->common.image);
free(table); free(table);
return rc; return rc;
} }
@@ -749,19 +749,19 @@ static int add_ipl_program(int fd, char *filename,
comp_nr++; comp_nr++;
/* Add kernel parmline */ /* Add kernel parmline */
if (ipl->parmline != NULL) { if (ipl->common.parmline != NULL) {
if (verbose) { if (verbose) {
printf(" kernel parmline...: '%s'\n", ipl->parmline); printf(" kernel parmline...: '%s'\n", ipl->common.parmline);
} }
rc = add_component_buffer(fd, ipl->parmline, rc = add_component_buffer(fd, ipl->common.parmline,
strlen(ipl->parmline) + 1, strlen(ipl->common.parmline) + 1,
(component_data) ipl->parm_addr, (component_data) ipl->common.parm_addr,
VOID_ADD(table, offset), VOID_ADD(table, offset),
info, &comp_loc[comp_nr], info, &comp_loc[comp_nr],
component_load); component_load);
if (rc) { if (rc) {
error_text("Could not add parmline '%s'", error_text("Could not add parmline '%s'",
ipl->parmline); ipl->common.parmline);
free(table); free(table);
return -1; return -1;
} }
@@ -770,8 +770,8 @@ static int add_ipl_program(int fd, char *filename,
comp_nr++; comp_nr++;
} }
/* add ramdisk */ /* add ramdisk */
if (ipl->ramdisk != NULL) { if (ipl->common.ramdisk != NULL) {
signature_size = extract_signature(ipl->ramdisk, &signature, signature_size = extract_signature(ipl->common.ramdisk, &signature,
&sig_head); &sig_head);
if (signature_size && if (signature_size &&
(is_secure == SECURE_BOOT_ENABLED || (is_secure == SECURE_BOOT_ENABLED ||
@@ -779,7 +779,7 @@ static int add_ipl_program(int fd, char *filename,
secure_boot_supported))) { secure_boot_supported))) {
if (verbose) { if (verbose) {
printf(" signature for.....: %s\n", printf(" signature for.....: %s\n",
ipl->ramdisk); ipl->common.ramdisk);
} }
rc = add_component_buffer(fd, signature, rc = add_component_buffer(fd, signature,
sig_head.length, sig_head.length,
@@ -797,16 +797,16 @@ static int add_ipl_program(int fd, char *filename,
comp_nr++; comp_nr++;
free(signature); free(signature);
check_remaining_filesize(ramdisk_size, signature_size, check_remaining_filesize(ramdisk_size, signature_size,
info, ipl->ramdisk); info, ipl->common.ramdisk);
} }
rc = add_component_file(fd, ipl->ramdisk, rc = add_component_file(fd, ipl->common.ramdisk,
ipl->ramdisk_addr, signature_size, ipl->common.ramdisk_addr, signature_size,
VOID_ADD(table, offset), VOID_ADD(table, offset),
add_files, info, target, add_files, info, target,
&comp_loc[comp_nr]); &comp_loc[comp_nr]);
if (rc) { if (rc) {
error_text("Could not add ramdisk '%s'", error_text("Could not add ramdisk '%s'",
ipl->ramdisk); ipl->common.ramdisk);
free(table); free(table);
return -1; return -1;
} }
@@ -1009,17 +1009,14 @@ add_dump_program(int fd, struct job_dump_data* dump,
/* Convert fs dump job to IPL job */ /* Convert fs dump job to IPL job */
memset(&ipl, 0, sizeof(ipl)); memset(&ipl, 0, sizeof(ipl));
ipl.image = dump->image; ipl.common = dump->common;
ipl.image_addr = dump->image_addr;
ipl.ramdisk = dump->ramdisk;
ipl.ramdisk_addr = dump->ramdisk_addr;
/* Get file system dump parmline */ /* Get file system dump parmline */
rc = get_dump_parmline(dump->device, dump->parmline, rc = get_dump_parmline(dump->device, dump->common.parmline,
info, target, &ipl.parmline); info, target, &ipl.common.parmline);
if (rc) if (rc)
return rc; return rc;
ipl.parm_addr = dump->parm_addr; ipl.common.parm_addr = dump->common.parm_addr;
return add_ipl_program(fd, NULL, false, NULL, &ipl, program, verbose, 1, return add_ipl_program(fd, NULL, false, NULL, &ipl, program, verbose, 1,
type, info, target, SECURE_BOOT_DISABLED); type, info, target, SECURE_BOOT_DISABLED);
} }
@@ -1283,14 +1280,14 @@ bootmap_create(struct job_data *job, disk_blockptr_t *program_table,
size = IMAGE_LOAD_ADDRESS; size = IMAGE_LOAD_ADDRESS;
/* Ramdisk */ /* Ramdisk */
if (job->data.dump.ramdisk != NULL) { if (job->data.dump.common.ramdisk != NULL) {
if (stat(job->data.dump.ramdisk, &st)) if (stat(job->data.dump.common.ramdisk, &st))
goto out_misc_free_temp_dev; goto out_misc_free_temp_dev;
size += DIV_ROUND_UP(st.st_size, info->phy_block_size); size += DIV_ROUND_UP(st.st_size, info->phy_block_size);
size += 1; /* For ramdisk section entry */ size += 1; /* For ramdisk section entry */
} }
/* Kernel */ /* Kernel */
if (stat(job->data.dump.image, &st)) if (stat(job->data.dump.common.image, &st))
goto out_misc_free_temp_dev; goto out_misc_free_temp_dev;
size += DIV_ROUND_UP(st.st_size - IMAGE_LOAD_ADDRESS, size += DIV_ROUND_UP(st.st_size - IMAGE_LOAD_ADDRESS,
info->phy_block_size); info->phy_block_size);
+3 -3
View File
@@ -91,7 +91,7 @@ disk_determine_dasd_type(struct disk_info *data,
} }
/* Return non-zero for ECKD type. */ /* Return non-zero for ECKD type. */
int static int
disk_is_eckd(disk_type_t type) disk_is_eckd(disk_type_t type)
{ {
return (type == disk_type_eckd_ldl || return (type == disk_type_eckd_ldl ||
@@ -114,7 +114,7 @@ read_block_by_offset(int fd, int blksize, uint64_t offset, char *buffer)
return 0; return 0;
} }
int static int
determine_virtblk_type(struct disk_info *data, struct stat *stats) determine_virtblk_type(struct disk_info *data, struct stat *stats)
{ {
char *device; char *device;
@@ -559,7 +559,7 @@ disk_free_info(struct disk_info* info)
* logical block number. Upon success, return 0 and store the physical * logical block number. Upon success, return 0 and store the physical
* blocknumber in the variable pointed to by PHYSICAL. Return non-zero * blocknumber in the variable pointed to by PHYSICAL. Return non-zero
* otherwise. */ * otherwise. */
int static int
disk_get_blocknum(int fd, int fd_is_basedisk, blocknum_t logical, disk_get_blocknum(int fd, int fd_is_basedisk, blocknum_t logical,
blocknum_t* physical, struct disk_info* info) blocknum_t* physical, struct disk_info* info)
{ {
+2 -2
View File
@@ -167,8 +167,8 @@ static int hash_table_add(struct line_hash_entry **table, char *line, int len)
* LINE: string contailing NAME=VALUE * LINE: string contailing NAME=VALUE
* LEN: length of the NAME with trailing delimiter "=" * LEN: length of the NAME with trailing delimiter "="
*/ */
struct line_hash_entry *hash_table_find(struct line_hash_entry **table, static struct line_hash_entry *hash_table_find(struct line_hash_entry **table,
char *name, size_t len) char *name, size_t len)
{ {
struct line_hash_entry *item; struct line_hash_entry *item;
+169 -305
View File
@@ -19,6 +19,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h>
#include "lib/util_arch.h" #include "lib/util_arch.h"
@@ -357,8 +358,7 @@ get_command_line(int argc, char* argv[], struct command_line* line)
static void static void
free_target_data(struct job_target_data* data) free_target_data(struct job_target_data* data)
{ {
if (data->targetbase != NULL) free(data->targetbase);
free(data->targetbase);
} }
static void static void
@@ -367,51 +367,41 @@ free_envblk_data(struct job_envblk_data *data)
free(data->buf); free(data->buf);
} }
static void
free_common_ipl_data(struct job_common_ipl_data *common)
{
free(common->image);
free(common->parmline);
free(common->ramdisk);
}
static void static void
free_ipl_data(struct job_ipl_data* data) free_ipl_data(struct job_ipl_data* data)
{ {
if (data->image != NULL) free_common_ipl_data(&data->common);
free(data->image);
if (data->parmline != NULL)
free(data->parmline);
if (data->ramdisk != NULL)
free(data->ramdisk);
} }
static void static void
free_ipl_tape_data(struct job_ipl_tape_data* data) free_ipl_tape_data(struct job_ipl_tape_data* data)
{ {
if (data->device != NULL) free(data->device);
free(data->device); free_common_ipl_data(&data->common);
if (data->image != NULL)
free(data->image);
if (data->parmline != NULL)
free(data->parmline);
if (data->ramdisk != NULL)
free(data->ramdisk);
} }
static void static void
free_segment_data(struct job_segment_data* data) free_segment_data(struct job_segment_data* data)
{ {
if (data->segment != NULL) free(data->segment);
free(data->segment);
} }
static void static void
free_dump_data(struct job_dump_data* data) free_dump_data(struct job_dump_data* data)
{ {
if (data->device != NULL) free(data->device);
free(data->device); free_common_ipl_data(&data->common);
if (data->image != NULL)
free(data->image);
if (data->parmline != NULL)
free(data->parmline);
if (data->ramdisk != NULL)
free(data->ramdisk);
} }
@@ -422,8 +412,7 @@ free_menu_data(struct job_menu_data* data)
if (data->entry != NULL) { if (data->entry != NULL) {
for (i=0; i < data->num; i++) { for (i=0; i < data->num; i++) {
if (data->entry[i].name != NULL) free(data->entry[i].name);
free(data->entry[i].name);
switch (data->entry[i].id) { switch (data->entry[i].id) {
case job_ipl: case job_ipl:
free_ipl_data(&data->entry[i].data.ipl); free_ipl_data(&data->entry[i].data.ipl);
@@ -441,28 +430,25 @@ free_menu_data(struct job_menu_data* data)
} }
void static void
free_mvdump_data(struct job_mvdump_data* data) free_mvdump_data(struct job_mvdump_data* data)
{ {
int i; int i;
if (data->device_list != NULL) free(data->device_list);
free(data->device_list);
for (i = 0; i < data->device_count; i++) for (i = 0; i < data->device_count; i++)
if (data->device[i] != NULL) free(data->device[i]);
free(data->device[i]);
} }
void void
job_free(struct job_data* job) job_free(struct job_data* job)
{ {
if (job->target.bootmap_dir != NULL)
free(job->target.bootmap_dir); free(job->target.bootmap_dir);
free_target_data(&job->target); free_target_data(&job->target);
free_envblk_data(&job->envblk); free_envblk_data(&job->envblk);
if (job->name != NULL) free(job->name);
free(job->name);
switch (job->id) { switch (job->id) {
case job_ipl: case job_ipl:
free_ipl_data(&job->data.ipl); free_ipl_data(&job->data.ipl);
@@ -510,6 +496,7 @@ set_cl_element(struct component_loc *cl, char *name, const char *filename,
cl->size = ALIGN(size, MAXIMUM_PHYSICAL_BLOCKSIZE); cl->size = ALIGN(size, MAXIMUM_PHYSICAL_BLOCKSIZE);
return 0; return 0;
} }
assert(filename != NULL);
/* Get size */ /* Get size */
if (stat(filename, &stats)) { if (stat(filename, &stats)) {
error_reason(strerror(errno)); error_reason(strerror(errno));
@@ -545,6 +532,53 @@ sort_cl_array(struct component_loc* cl, int elements)
} }
} }
} }
static int
get_common_components(struct job_common_ipl_data *common,
struct component_loc **clp, int *nump,
int extra)
{
struct component_loc *cl;
int num;
int rc;
/*
* Get memory for image, parmline, ramdisk, loader and
* possible extra components
*/
cl = misc_calloc(3 + extra, sizeof(struct component_loc));
if (cl == NULL)
return -1;
/* Fill in component data */
num = 0;
rc = set_cl_element(&cl[num++], "kernel image", common->image,
&common->image_addr, 0, 0,
MAXIMUM_PHYSICAL_BLOCKSIZE);
if (rc)
goto error;
rc = set_cl_element(&cl[num++], "parmline", NULL, &common->parm_addr,
MAXIMUM_PARMLINE_SIZE, 0,
MAXIMUM_PHYSICAL_BLOCKSIZE);
if (rc)
goto error;
if (common->ramdisk) {
rc = set_cl_element(&cl[num++], "initial ramdisk",
common->ramdisk, &common->ramdisk_addr,
0, 0, 0x10000);
if (rc)
goto error;
}
*clp = cl;
*nump = num;
return 0;
error:
free(cl);
return rc;
}
static int static int
get_ipl_components(struct job_ipl_data *ipl, struct component_loc **clp, get_ipl_components(struct job_ipl_data *ipl, struct component_loc **clp,
int *nump, struct job_envblk_data *envblk) int *nump, struct job_envblk_data *envblk)
@@ -553,30 +587,9 @@ get_ipl_components(struct job_ipl_data *ipl, struct component_loc **clp,
int num; int num;
int rc; int rc;
/* Get memory for image, parmline, ramdisk and environment block */ rc = get_common_components(&ipl->common, &cl, &num, 1);
cl = misc_calloc(4, sizeof(struct component_loc));
if (cl == NULL)
return -1;
/* Fill in component data */
num = 0;
rc = set_cl_element(&cl[num++], "kernel image", ipl->image,
&ipl->image_addr, 0, 0,
MAXIMUM_PHYSICAL_BLOCKSIZE);
if (rc) if (rc)
goto error; return rc;
if (ipl->parmline) {
rc = set_cl_element(&cl[num++], "parmline", NULL,
&ipl->parm_addr, MAXIMUM_PARMLINE_SIZE, 0,
MAXIMUM_PHYSICAL_BLOCKSIZE);
if (rc)
goto error;
}
if (ipl->ramdisk) {
rc = set_cl_element(&cl[num++], "initial ramdisk", ipl->ramdisk,
&ipl->ramdisk_addr, 0, 0, 0x10000);
if (rc)
goto error;
}
rc = set_cl_element(&cl[num++], "environment block", rc = set_cl_element(&cl[num++], "environment block",
NULL, NULL,
&ipl->envblk_addr, envblk->size, 0, &ipl->envblk_addr, envblk->size, 0,
@@ -593,91 +606,6 @@ error:
} }
static int
get_dump_components(struct job_dump_data *dump,
struct component_loc **clp, int *nump)
{
struct component_loc *cl;
int num;
int rc;
/* Get memory for image, parmline, ramdisk, loader */
cl = misc_calloc(3, sizeof(struct component_loc));
if (cl == NULL)
return -1;
/* Fill in component data */
num = 0;
rc = set_cl_element(&cl[num++], "kernel image", dump->image,
&dump->image_addr, 0, 0x0,
MAXIMUM_PHYSICAL_BLOCKSIZE);
if (rc)
goto error;
rc = set_cl_element(&cl[num++], "parmline", NULL, &dump->parm_addr,
MAXIMUM_PARMLINE_SIZE, 0,
MAXIMUM_PHYSICAL_BLOCKSIZE);
if (rc)
goto error;
if (dump->ramdisk) {
rc = set_cl_element(&cl[num++], "initial ramdisk",
dump->ramdisk, &dump->ramdisk_addr,
0, 0, 0x10000);
if (rc)
goto error;
}
*clp = cl;
*nump = num;
return 0;
error:
free(cl);
return rc;
}
static int
get_ipl_tape_components(struct job_ipl_tape_data *ipl_tape,
struct component_loc **clp, int *nump)
{
struct component_loc *cl;
int num;
int rc;
/* Get memory for image, parmline, ramdisk */
cl = misc_calloc(3, sizeof(struct component_loc));
if (cl == NULL)
return -1;
/* Fill in component data */
num = 0;
rc = set_cl_element(&cl[num++], "kernel image", ipl_tape->image,
&ipl_tape->image_addr, 0, 0x10000,
MAXIMUM_PHYSICAL_BLOCKSIZE);
if (rc)
goto error;
/* Enhance the image size value for tape loader specific logic */
cl[0].size = ALIGN(cl[0].size + 0x100, MAXIMUM_PHYSICAL_BLOCKSIZE);
if (ipl_tape->parmline) {
rc = set_cl_element(&cl[num++], "parmline", NULL,
&ipl_tape->parm_addr, MAXIMUM_PARMLINE_SIZE,
0, MAXIMUM_PHYSICAL_BLOCKSIZE);
if (rc)
goto error;
}
if (ipl_tape->ramdisk) {
rc = set_cl_element(&cl[num++], "initial ramdisk",
ipl_tape->ramdisk, &ipl_tape->ramdisk_addr,
0, 0, 0x10000);
if (rc)
goto error;
}
*clp = cl;
*nump = num;
return 0;
error:
free(cl);
return rc;
}
static int static int
check_component_address_data(struct component_loc *cl, int num, char *name, check_component_address_data(struct component_loc *cl, int num, char *name,
unsigned long address_limit) unsigned long address_limit)
@@ -800,13 +728,13 @@ out_free:
static int static int
finalize_dump_address_data(struct job_dump_data* dump, char *name) finalize_common_address_data(struct job_common_ipl_data *common, char *name)
{ {
struct component_loc *cl; struct component_loc *cl;
int num; int num;
int rc; int rc;
rc = get_dump_components(dump, &cl, &num); rc = get_common_components(common, &cl, &num, 0);
if (rc) if (rc)
return rc; return rc;
sort_cl_array(cl, num); sort_cl_array(cl, num);
@@ -819,36 +747,58 @@ out_free:
return rc; return rc;
} }
static void error_text_section(const char *text, const char *section, const char *file)
{
if (section == NULL) {
error_text("%s '%s'", text, file);
} else {
error_text("%s '%s' in section '%s'", text, file, section);
}
}
static int static int
finalize_ipl_tape_address_data(struct job_ipl_tape_data* ipl_tape, char *name) check_common_ipl_data(struct job_common_ipl_data *common, const char *section)
{ {
struct component_loc *cl; uint64_t max_parm_size, len;
int num; char *buffer = NULL;
size_t size;
int rc; int rc;
int i;
rc = get_ipl_tape_components(ipl_tape, &cl, &num); if (common->image != NULL) {
if (rc) rc = misc_read_file(common->image, &buffer, &size, 0);
return rc; if (rc) {
sort_cl_array(cl, num); error_text_section("Image file", section, common->image);
rc = check_component_address_data(cl, num, name, ADDRESS_LIMIT); return rc;
if (rc) }
goto out_free;
rc = finalize_component_address_data(cl, num, ADDRESS_LIMIT); if (size < MAX_COMMAND_LINE_SIZE + sizeof(uint64_t)) {
/* The loader needs a ramdisk_addr anyway */ error_text_section("Image file", section, common->image);
if (ipl_tape->ramdisk_addr == 0) { return -1;
for (i = 0; i < num; i++) { }
if (*cl[i].addrp == ipl_tape->image_addr)
ipl_tape->ramdisk_addr = max_parm_size = *(uint64_t *)(buffer + MAX_COMMAND_LINE_SIZE);
*cl[i].addrp + cl[i].size; if (!max_parm_size)
max_parm_size = LEGACY_MAXIMUM_PARMLINE_SIZE;
len = strlen(common->parmline);
if (len > max_parm_size) {
error_text("The length of the parameters line "
"(%d bytes) exceeds the allowed maximum "
"(%d bytes) in section '%s'", len, max_parm_size, section);
return -1;
} }
} }
out_free:
free(cl);
return rc;
}
if (common->ramdisk != NULL) {
rc = misc_check_readable_file(common->ramdisk);
if (rc) {
error_text_section("Ramdisk file", section, common->ramdisk);
return rc;
}
}
return 0;
}
static int static int
check_job_ipl_data(struct job_ipl_data *ipl, char *name, check_job_ipl_data(struct job_ipl_data *ipl, char *name,
@@ -856,30 +806,9 @@ check_job_ipl_data(struct job_ipl_data *ipl, char *name,
{ {
int rc; int rc;
if (ipl->image != NULL) { rc = check_common_ipl_data(&ipl->common, name);
rc = misc_check_readable_file(ipl->image); if (rc)
if (rc) { return rc;
if (name == NULL) {
error_text("Image file '%s'", ipl->image);
} else {
error_text("Image file '%s' in section '%s'",
ipl->image, name);
}
return rc;
}
}
if (ipl->ramdisk != NULL) {
rc = misc_check_readable_file(ipl->ramdisk);
if (rc) {
if (name == NULL) {
error_text("Ramdisk file '%s'", ipl->ramdisk);
} else {
error_text("Ramdisk file '%s' in section '%s'",
ipl->ramdisk, name);
}
return rc;
}
}
return finalize_ipl_address_data(ipl, name, envblk); return finalize_ipl_address_data(ipl, name, envblk);
} }
@@ -892,13 +821,7 @@ check_job_segment_data(struct job_segment_data* segment, char* name)
if (segment->segment != NULL) { if (segment->segment != NULL) {
rc = misc_check_readable_file(segment->segment); rc = misc_check_readable_file(segment->segment);
if (rc) { if (rc) {
if (name == NULL) { error_text_section("Segment file", name, segment->segment);
error_text("Segment file '%s'",
segment->segment);
} else {
error_text("Segment file '%s' in section '%s'",
segment->segment, name);
}
return rc; return rc;
} }
} }
@@ -914,12 +837,7 @@ check_job_dump_data(struct job_dump_data* dump, char* name)
if (dump->device != NULL) { if (dump->device != NULL) {
rc = misc_check_writable_device(dump->device, 1, 1); rc = misc_check_writable_device(dump->device, 1, 1);
if (rc) { if (rc) {
if (name == NULL) { error_text_section("Dump device", name, dump->device);
error_text("Dump device '%s'", dump->device);
} else {
error_text("Dump device '%s' in section '%s'",
dump->device, name);
}
return rc; return rc;
} }
} }
@@ -938,23 +856,23 @@ check_job_dump_images(struct job_dump_data* dump, char* name)
ZFCPDUMP_IMAGE); ZFCPDUMP_IMAGE);
return rc; return rc;
} }
dump->image = misc_strdup(ZFCPDUMP_IMAGE); dump->common.image = misc_strdup(ZFCPDUMP_IMAGE);
if (dump->image == NULL) if (dump->common.image == NULL)
return -1; return -1;
dump->image_addr = IMAGE_LOAD_ADDRESS; dump->common.image_addr = IMAGE_LOAD_ADDRESS;
/* Ramdisk is no longer required with new initramfs dump system */ /* Ramdisk is no longer required with new initramfs dump system */
if (misc_check_readable_file(ZFCPDUMP_INITRD)) if (misc_check_readable_file(ZFCPDUMP_INITRD))
dump->ramdisk = NULL; dump->common.ramdisk = NULL;
else { else {
dump->ramdisk = misc_strdup(ZFCPDUMP_INITRD); dump->common.ramdisk = misc_strdup(ZFCPDUMP_INITRD);
if (dump->ramdisk == NULL) if (dump->common.ramdisk == NULL)
return -1; return -1;
dump->ramdisk_addr = UNSPECIFIED_ADDRESS; dump->common.ramdisk_addr = UNSPECIFIED_ADDRESS;
} }
dump->parm_addr = UNSPECIFIED_ADDRESS; dump->common.parm_addr = UNSPECIFIED_ADDRESS;
return finalize_dump_address_data(dump, name); return finalize_common_address_data(&dump->common, name);
} }
@@ -995,40 +913,14 @@ check_job_ipl_tape_data(struct job_ipl_tape_data *ipl, char* name)
if (ipl->device != NULL) { if (ipl->device != NULL) {
rc = misc_check_writable_device(ipl->device, 1, 1); rc = misc_check_writable_device(ipl->device, 1, 1);
if (rc) { if (rc) {
if (name == NULL) { error_text_section("Tape device", name, ipl->device);
error_text("Tape device '%s'", ipl->device);
} else {
error_text("Tape device '%s' in section '%s'",
ipl->device, name);
}
return rc; return rc;
} }
} }
if (ipl->image != NULL) { rc = check_common_ipl_data(&ipl->common, name);
rc = misc_check_readable_file(ipl->image); if (rc)
if (rc) { return rc;
if (name == NULL) { return finalize_common_address_data(&ipl->common, name);
error_text("Image file '%s'", ipl->image);
} else {
error_text("Image file '%s' in section '%s'",
ipl->image, name);
}
return rc;
}
}
if (ipl->ramdisk != NULL) {
rc = misc_check_readable_file(ipl->ramdisk);
if (rc) {
if (name == NULL) {
error_text("Ramdisk file '%s'", ipl->ramdisk);
} else {
error_text("Ramdisk file '%s' in section '%s'",
ipl->ramdisk, name);
}
return rc;
}
}
return finalize_ipl_tape_address_data(ipl, name);
} }
static int static int
@@ -1040,12 +932,7 @@ check_job_mvdump_data(struct job_mvdump_data* dump, char* name)
rc = misc_read_file(dump->device_list, &buffer, &size, 0); rc = misc_read_file(dump->device_list, &buffer, &size, 0);
if (rc) { if (rc) {
if (name == NULL) { error_text_section("Dump target list", name, dump->device_list);
error_text("Dump target list '%s'", dump->device_list);
} else {
error_text("Dump target list '%s' in section '%s'",
dump->device_list, name);
}
return rc; return rc;
} }
if (size == 0) { if (size == 0) {
@@ -1118,14 +1005,7 @@ check_job_data(struct job_data* job)
if (job->target.bootmap_dir != NULL) { if (job->target.bootmap_dir != NULL) {
rc = misc_check_writable_directory(job->target.bootmap_dir); rc = misc_check_writable_directory(job->target.bootmap_dir);
if (rc) { if (rc) {
if (job->name == NULL) { error_text_section("Target directory", job->name, job->target.bootmap_dir);
error_text("Target directory '%s'",
job->target.bootmap_dir);
} else {
error_text("Target directory '%s' in section "
"'%s'",
job->target.bootmap_dir, job->name);
}
return rc; return rc;
} }
} }
@@ -1262,12 +1142,7 @@ get_parmline(char* filename, char* line, char** parmline, address_t* address,
extract_address(filename, &addr); extract_address(filename, &addr);
rc = misc_read_file(filename, &buffer, &len, 1); rc = misc_read_file(filename, &buffer, &len, 1);
if (rc) { if (rc) {
if (section == NULL) error_text_section("Parmfile", section, filename);
error_text("Parmfile '%s'", filename);
else {
error_text("Parmfile '%s' in section '%s'",
filename, section);
}
free(filename); free(filename);
return rc; return rc;
} }
@@ -1300,17 +1175,6 @@ get_parmline(char* filename, char* line, char** parmline, address_t* address,
return -1; return -1;
} else result = NULL; } else result = NULL;
/* Check for maximum length */
if (result) {
len = strlen(result);
if (len > MAXIMUM_PARMLINE_SIZE) {
error_text("The length of the parameters line "
"(%d bytes) exceeds the allowed maximum "
"(%d bytes)", len, MAXIMUM_PARMLINE_SIZE);
free(result);
return -1;
}
}
*parmline = result; *parmline = result;
*address = addr; *address = addr;
return 0; return 0;
@@ -1383,19 +1247,19 @@ get_job_from_section_data(char* data[], struct job_data* job, char* section)
atol(data[(int) scan_keyword_targetoffset]); atol(data[(int) scan_keyword_targetoffset]);
/* Fill in name and address of image file */ /* Fill in name and address of image file */
job->data.ipl.image = misc_strdup( job->data.ipl.common.image = misc_strdup(
data[(int) scan_keyword_image]); data[(int) scan_keyword_image]);
if (job->data.ipl.image == NULL) if (job->data.ipl.common.image == NULL)
return -1; return -1;
if (extract_address(job->data.ipl.image, if (extract_address(job->data.ipl.common.image,
&job->data.ipl.image_addr)) { &job->data.ipl.common.image_addr)) {
job->data.ipl.image_addr = IMAGE_LOAD_ADDRESS; job->data.ipl.common.image_addr = IMAGE_LOAD_ADDRESS;
} }
/* Fill in parmline */ /* Fill in parmline */
rc = get_parmline(data[(int) scan_keyword_parmfile], rc = get_parmline(data[(int) scan_keyword_parmfile],
data[(int) scan_keyword_parameters], data[(int) scan_keyword_parameters],
&job->data.ipl.parmline, &job->data.ipl.common.parmline,
&job->data.ipl.parm_addr, section); &job->data.ipl.common.parm_addr, section);
if (rc) if (rc)
return rc; return rc;
/* Fill in environment block */ /* Fill in environment block */
@@ -1403,13 +1267,13 @@ get_job_from_section_data(char* data[], struct job_data* job, char* section)
/* Fill in name and address of ramdisk file */ /* Fill in name and address of ramdisk file */
if (data[(int) scan_keyword_ramdisk] != NULL) { if (data[(int) scan_keyword_ramdisk] != NULL) {
job->data.ipl.ramdisk = job->data.ipl.common.ramdisk =
misc_strdup(data[(int) scan_keyword_ramdisk]); misc_strdup(data[(int) scan_keyword_ramdisk]);
if (job->data.ipl.ramdisk == NULL) if (job->data.ipl.common.ramdisk == NULL)
return -1; return -1;
if (extract_address(job->data.ipl.ramdisk, if (extract_address(job->data.ipl.common.ramdisk,
&job->data.ipl.ramdisk_addr)) { &job->data.ipl.common.ramdisk_addr)) {
job->data.ipl.ramdisk_addr = job->data.ipl.common.ramdisk_addr =
UNSPECIFIED_ADDRESS; UNSPECIFIED_ADDRESS;
} }
} }
@@ -1441,30 +1305,30 @@ get_job_from_section_data(char* data[], struct job_data* job, char* section)
if (job->data.ipl_tape.device == NULL) if (job->data.ipl_tape.device == NULL)
return -1; return -1;
/* Fill in name and address of image file */ /* Fill in name and address of image file */
job->data.ipl_tape.image = misc_strdup( job->data.ipl_tape.common.image = misc_strdup(
data[(int) scan_keyword_image]); data[(int) scan_keyword_image]);
if (job->data.ipl_tape.image == NULL) if (job->data.ipl_tape.common.image == NULL)
return -1; return -1;
if (extract_address(job->data.ipl_tape.image, if (extract_address(job->data.ipl_tape.common.image,
&job->data.ipl_tape.image_addr)) { &job->data.ipl_tape.common.image_addr)) {
job->data.ipl_tape.image_addr = IMAGE_LOAD_ADDRESS; job->data.ipl_tape.common.image_addr = IMAGE_LOAD_ADDRESS;
} }
/* Fill in parmline */ /* Fill in parmline */
rc = get_parmline(data[(int) scan_keyword_parmfile], rc = get_parmline(data[(int) scan_keyword_parmfile],
data[(int) scan_keyword_parameters], data[(int) scan_keyword_parameters],
&job->data.ipl_tape.parmline, &job->data.ipl_tape.common.parmline,
&job->data.ipl_tape.parm_addr, section); &job->data.ipl_tape.common.parm_addr, section);
if (rc) if (rc)
return rc; return rc;
/* Fill in name and address of ramdisk file */ /* Fill in name and address of ramdisk file */
if (data[(int) scan_keyword_ramdisk] != NULL) { if (data[(int) scan_keyword_ramdisk] != NULL) {
job->data.ipl_tape.ramdisk = job->data.ipl_tape.common.ramdisk =
misc_strdup(data[(int) scan_keyword_ramdisk]); misc_strdup(data[(int) scan_keyword_ramdisk]);
if (job->data.ipl_tape.ramdisk == NULL) if (job->data.ipl_tape.common.ramdisk == NULL)
return -1; return -1;
if (extract_address(job->data.ipl_tape.ramdisk, if (extract_address(job->data.ipl_tape.common.ramdisk,
&job->data.ipl_tape.ramdisk_addr)) { &job->data.ipl_tape.common.ramdisk_addr)) {
job->data.ipl_tape.ramdisk_addr = job->data.ipl_tape.common.ramdisk_addr =
UNSPECIFIED_ADDRESS; UNSPECIFIED_ADDRESS;
} }
} }
@@ -1801,15 +1665,15 @@ get_section_job(struct scan_token* scan, char* section, struct job_data* job,
if (extra_parmline != NULL) { if (extra_parmline != NULL) {
switch (job->id) { switch (job->id) {
case job_ipl: case job_ipl:
if (job->data.ipl.parmline == NULL) if (job->data.ipl.common.parmline == NULL)
buffer = misc_strdup(extra_parmline); buffer = misc_strdup(extra_parmline);
else { else {
buffer = append_parmline( buffer = append_parmline(
job->data.ipl.parmline, job->data.ipl.common.parmline,
extra_parmline); extra_parmline);
free(job->data.ipl.parmline); free(job->data.ipl.common.parmline);
} }
job->data.ipl.parmline = buffer; job->data.ipl.common.parmline = buffer;
if (buffer == NULL) if (buffer == NULL)
return -1; return -1;
break; break;
+2 -2
View File
@@ -497,7 +497,7 @@ misc_check_writable_device(const char* devno, int blockdev, int chardev)
/* ASCII to EBCDIC conversion table. */ /* ASCII to EBCDIC conversion table. */
unsigned char ascebc[256] = static unsigned char ascebc[256] =
{ {
0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
@@ -534,7 +534,7 @@ unsigned char ascebc[256] =
}; };
/* EBCDIC to ASCII conversion table. */ /* EBCDIC to ASCII conversion table. */
unsigned char ebcasc[256] = static unsigned char ebcasc[256] =
{ {
/* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */ /* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */
0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F, 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+1 -1
View File
@@ -82,7 +82,7 @@ enum scan_key_state scan_key_table[SCAN_SECTION_NUM][SCAN_KEYWORD_NUM] = {
}; };
/* Determines which keyword may be present in a menu section */ /* Determines which keyword may be present in a menu section */
enum scan_key_state scan_menu_key_table[SCAN_KEYWORD_NUM] = { static enum scan_key_state scan_menu_key_table[SCAN_KEYWORD_NUM] = {
/* menu section */ /* menu section */
opt, inv, inv, inv, inv, inv, inv, inv, req, opt, opt, inv, inv, inv, opt, inv, inv, inv, inv, inv, inv, inv, req, opt, opt, inv, inv, inv,
opt, opt, opt, opt, opt, inv, inv, opt opt, opt, opt, opt, opt, inv, inv, opt
+6 -6
View File
@@ -212,12 +212,12 @@ main(int argc, char* argv[])
break; break;
case job_ipl_tape: case job_ipl_tape:
rc = install_tapeloader(job->data.ipl_tape.device, rc = install_tapeloader(job->data.ipl_tape.device,
job->data.ipl_tape.image, job->data.ipl_tape.common.image,
job->data.ipl_tape.parmline, job->data.ipl_tape.common.parmline,
job->data.ipl_tape.ramdisk, job->data.ipl_tape.common.ramdisk,
job->data.ipl_tape.image_addr, job->data.ipl_tape.common.image_addr,
job->data.ipl_tape.parm_addr, job->data.ipl_tape.common.parm_addr,
job->data.ipl_tape.ramdisk_addr); job->data.ipl_tape.common.ramdisk_addr);
break; break;
case job_mvdump: case job_mvdump:
rc = install_mvdump(job->data.mvdump.device, rc = install_mvdump(job->data.mvdump.device,