Compare commits

...

29 Commits

Author SHA1 Message Date
Jan Höppner f75c923627 New release s390-tools-2.25.0
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-12-08 13:40:15 +01:00
Fedor Loshakov bca8fa3f9c ziomon: fix Makefile install step chown warnings
Since coreutils v9.1 commit 8f31074cb ("chown: warn about USER.GROUP")
chown utility now warns about using of wrong separator for USER and
GROUP options. This leads to warnings during intall step in ziomon:

$ make install
  INSTALL ziomon
  SED     ziomon/install
chown: warning: '.' should be ':': ‘root.root’
  SED     ziomon/install
chown: warning: '.' should be ':': ‘root.root’
  SED     ziomon/install
chown: warning: '.' should be ':': ‘root.root’

To fix those warnings use ':' as separator instead of '.'. With this
patch applied those warnings are no longer present.

Signed-off-by: Fedor Loshakov <loshakov@linux.ibm.com>
Reviewed-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:54:09 +01:00
Joern Siglen d713ea6389 dbginfo.sh: log the work dir state in dbginfo.log
As on space problems the packing may fail, incomplete tgz are send.
Today no evidence for this is in dbginfo.log, packed upfront into the tgz.
This update helps to identify space related corruption of tgz files.

Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:54:09 +01:00
Niklas Schnelle f9fbe79e4f ipl_tools: Fix chreipl node for NVMes with CONFIG_NVME_MULTIPATH
When the kernel is build with CONFIG_NVME_MULTIPATH enabled and an NVMe
where the driver exposes its controller separately is used, chreipl node
on a mount point of the NVMe fails. The failure occurs because chreipl
tries to get the function_id from the NVMe's nvmeXnY block device via
the path '/sys/block/nvmeXnY/device/device/function_id' which does not
exist.

The underlying problem is that with NVMe multipath support the PCI
function is not associated directly with a particular NVMe namespace but
instead with the entire NVMe device which may host multiple NVMe
namespaces. The correct way to get from the block device to the
underlying PCI device and its function ID is then to extract the device
name i.e. the 'nvmeX' part from 'nvmeXnY' and use that to get the
function ID via '/sys/class/nvme/nvme<X>/device/function_id'.

Fixes: 0472b5ea5c ("ipl-tools: Add nvme device support to lsreipl/chreipl")
Reviewed-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:54:09 +01:00
Steffen Eiden 3cc0b4cdea pvattest/tools: remove xxd dependency from scripts
xxd has vim-common as a dependency. We can avoid that by using od
instead which is from coreutils.

While at it, add the require_command function from the
pvattest-info script to the pvextract-hdr script and use it.

Suggested-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:53:37 +01:00
Steffen Eiden eef9f622c0 pvattest/man: fix wording
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:50:16 +01:00
Daniel S. Haischt 889293e557 zdev: implement --shell command line switch
Fix issue in the lszdev command where column names if using the --pairs
command line switch can contain characters that are not allowed to be
used as variable names in a shell environment.

Replace bad characters in column names by an underscore if the --shell
command line switch is specified along with the --pairs switch.

The additional --shell switch mimics what is already available in the
lsblk command and thus it shall be used along with the --pairs switch.

Signed-off-by: Daniel S. Haischt <modean@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:50:16 +01:00
Jan Höppner 0c5b9f5d11 mon_tools: Silence address-of-packed-member compile warning
The proc_sum_t struct is defined with the packed attribute and
produces the following compile warning:

mon_procd.c: In function ‘read_cpu’:
mon_procd.c:351:27: warning: taking address of packed member of ‘struct proc_sum_t’ may result in an unaligned pointer value [-Waddress-of-packed-member]
  351 |         cal_cpu(&cpudata, &proc_sum.cpu);
      |                           ^~~~~~~~~~~~~

Silence the warning with -Wno-address-of-packed-member compile flag
since the struct is required to be as is.

Reviewed-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:50:09 +01:00
Jan Höppner 02af069d48 boot_defs.h: Fix compile warning in zfcpdump
The struct scsi_dump_sb is defined with the __packed attribute and
produces the following compile warning in zfcpdump:

zfcpdump_part.c: In function ‘csum_update’:
zfcpdump_part.c:125:41: warning: taking address of packed member of ‘struct scsi_dump_sb’ may result in an unaligned pointer value [-Waddress-of-packed-member]
  125 |                      dump_sb.csum_size, &dump_sb.csum)) {
      |                                         ^~~~~~~~~~~~~

However, all members are of the same size and the __packed attribute is
unnecessary. Remove the attribute to get rid of the warning.
Add assertion to ensure correct size of the struct during compile time.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:49:04 +01:00
Steffen Eiden 5e0056db8d util_lockfile: fix includes
The 'unistd.h' header was missing. Under some circumstances the
-D_GNU_SOURCE gcc flag does not trigger including that file.
Therefore, explicitly include this file here.

Fixes: e1aec24e84 ("libutil: introduce util_lockfile")
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-30 15:51:15 +01:00
Matthew Rosato 4b5937f142 ap_tools/ap-check: use new mdevctl install location
mdevctl has been updated to use /usr/lib/mdevctl/scripts.d/callouts/
instead of /etc/mdevctl.d/scripts.d/callouts/.  The /etc location
is considered deprecated, meaning mdevctl will also look at that
location for now but might eventually stop looking in /etc for
callout scripts.
Based on that, update the installation location for the ap-check
callout.  However, because older versions of mdevctl will still
only look in /etc, let's also put a wrapper script in /etc for now
to provide backward compatibility, and plan to remove it at a
later time.

Link: https://github.com/mdevctl/mdevctl/commit/df6bb57429ba7425e8b7901b0580ed7e616b6c4f
Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/139
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-30 15:50:33 +01:00
Marc Hartmayer 8d8d5e9746 zdump: Fix Makefile dependencies
The Makefile target `check_dep_fuse` was declared as .PHONY and
therefore it was always rebuilt. This caused zgetdump to always be
relinked. While at it, remove the non-existent Makefile target
`check_dep_zlib` and add the cache files to `.gitignore`.

Closes: https://github.com/ibm-s390-linux/s390-tools/issues/144
Fixes: e537ab902e ("zdump: Makefile: add basic libpv support")
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00
Jan Höppner 5bdabe3e06 common.mak: Fix pretty print for linking
Commit ae7217806b ("common.mak: remove `LINK` and `LINKXX`") changed
the LINK and LINKXX definition to ensure that the same compiler is used
for compilation and linking when specified with CC= (or CXX=
respectively) on the commandline.

However, the commit also removed the pretty print for both commands. Add
the pretty print back in and use the already defined $(CC) and $(CXX)
variables to preserve the original change.

Fixes: ae7217806b ("common.mak: remove `LINK` and `LINKXX`")
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00
Marc Hartmayer 8a1db94d37 zdump: add missing newlines for log messages
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-11-29 17:03:57 +01:00
Marc Hartmayer 1911cba130 zdump: check provided sizes for reasonableness
Check the dump provided sizes for reasonableness. This avoids that a
corrupted dump leads to allocation of large buffers on the heap.

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-11-29 17:03:57 +01:00
Marc Hartmayer f4ed0b0ec6 zdump: check size before mmap'ing
Verify that the size is large enough before doing the mmap. Otherwise
this can result in a SIGBUS signal if there is an attempt to access a
page that lies beyond the end of the mapped file (see `man 2 mmap`).

Fixes: 8fa1b5a00b ("zdump: dfi: add support to read Protected Virtualization dumps")
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-11-29 17:03:57 +01:00
Marc Hartmayer 6e42c527d7 zdump: pv_process_pglist: convert assertions into errors
Corrupted dumps might have invalid page states. Therefore, let's convert
the assertions into errors.

Fixes: 8fa1b5a00b ("zdump: dfi: add support to read Protected Virtualization dumps")
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-11-29 17:03:57 +01:00
Eduard Shishkin f7d2339c6a zipl: List-Directed IPL from ECKD DASD
Make zipl tool prepare ECKD DASD for booting by different IPL
programs (with the same boot record installed).

Besides standard CCW-type IPL, user gets an ability to trigger
(with the same boot record installed!) List-Directed IPL. This
allows to use the feature of secure boot from ECKD DASD (which
is not available for CCW-type IPL).

When using the old boot interfaces, the usual CCW-type IPL is
triggered for DASD. Also for compatibility reasons zipl(8) tool
is modified to create and install one, or two "similar" program
tables per boot partition, depending on job and disk type. The
"similar" program tables differ only in block pointers format.
The old IPL programs (CCW-type IPL) use program table based on the
old format.

All program tables are packed to the same bootmap file. Their
order and logical offsets in the file are not significant (not
used by anyone).

The picture below shows which program table is used for IPL of
specified type from disk of specified type. Here "0" and "1" are
identifiers of program tables based on the old and new block
pointers format respectively. E.g. program table "0" is used for
CCW-type IPL from ECKD DASD. LD-IPL from DASD FBA is unsupported
(respectively, only one program table "0" is used), etc.

                            CCW-IPL   LD-IPL

 SCSI                          X        0
 DASD FBA                      0        X
 ECKD DASD LDL                 0        X
 ECKD DASD CDL                 0        1

Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00
Eduard Shishkin cf5f373142 zipl: Rename component_type enum
Rename component_type enum from COMPONENT_* to COMPONENT_TYPE_*

Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00
Eduard Shishkin e09c675b70 libvtoc: Introduce is_vol1() check
Introduce is_vol1() in vtoc.h and update the user in libzds.c

Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00
Eduard Shishkin 6bd93f475c Clean up of libdasd
Remove standalone IOCTLs definitions and use sys/mount.h instead

Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00
Stefan Haberland 3f12bdf4c7 tunedasd: add copy_pair swap capability
Add an option to tunedasd to trigger a copy pair swap using the appropriate
ioctl for DASD devices.

      -s, --copy-pair-swap COPY_PAIR

This command requires a comma separated pair of primary,secondary to be
specified. In case of success the old secondary will become the new primary
device and the old primary will become a secondary device.

Example:

tunedasd /dev/dasda -s 0.0.9700,0.0.9740

This will set the old secondary device 0.0.9740 as the new primary.
The old primary device 0.0.9700 will automatically become a secondary
device.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Stefan Haberland 3aa7f6e298 libdasd: fix ioctl macro to return also positive return codes
In case of an error the ioctl macro only returns errno to the calling
function.
This misses positive returncodes from ioctls.
Change the macro to also return positive return codes.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Stefan Haberland 4e28047eb4 tunedasd: move tunedasd ioctls to libdasd
Move all DASD IOCTLs to libdasd and adapt all affected
users accordingly.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Stefan Haberland f654b971d0 zdev: add copy_pair attribute for DASD devices
The DASD device driver has a new attribute copy_pair to make storage
server copy pairs known to the driver.
Add this attribute to zdev.

Usage example:

Add two copy pairs 1000,2000 and 1000,3000 to a DASD device 1000
$ chzdev dasd 1000 copy_pairs=1000,2000 copy_pairs=1000,3000

or

$ chzdev dasd 1000 copy_pairs="1000,2000 1000,3000"

To add a third copy pair later on:
$ chzdev dasd 1000 copy_pairs=1000,4000

To remove all copy pairs from the device 1000:
$ chzdev dasd 1000 -r copy_pairs

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Stefan Haberland e742d1c9ae zdev: correctly handle multiple values for CCW devices
Correctly create multiple lines in the udev rule for CCW device attributes
with multi bit set that contain multiple values.

Suggested-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Stefan Haberland 803b87e324 zconf/lsdasd: add Copy Pair output option
Add an option -P|--copy-pairs to show all DASD devices with copy
relations set up in the system and their roles.

The output looks like:

    # ./s390-tools/zconf/lsdasd -h
    [...]
            -P|--copy-pairs
	             Print information about copy pairs.

     # ./s390-tools/zconf/lsdasd -P
     Bus-ID    Role       Name      Paired devices
     ================================================================================
     0.0.9700  primary    dasdd     0.0.9740,0.0.9743,0.0.9744,0.0.9745
     0.0.9740  secondary            0.0.9700
     0.0.9701  primary    dasdf     0.0.9741
     0.0.9741  secondary            0.0.9701
     0.0.9702  primary    dasdh     0.0.9742
     0.0.9742  secondary            0.0.9702

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Stefan Haberland 5107a7be16 zconf/lsdasd: fix Copy Pair related output
Fix the default output for copy pair secondary devices to not show
a faulty blockdevice entry and major:minor combination.

The new output looks like:

    # lsdasd
    Bus-ID    Status    Name      Device  Type         BlkSz  Size      Blocks
    ================================================================================
    0.0.9740  secondary                   ECKD
    0.0.9741  secondary                   ECKD
    0.0.9742  secondary                   ECKD
    0.0.e964  active    dasda     94:0    ECKD         4096   21129MB   5409180
    0.0.e967  active    dasdb     94:4    ECKD         4096   21129MB   5409180
    0.0.9330  active    dasdc     94:8    ECKD         4096   782MB     200340
    0.0.9700  active    dasdd     94:12   ECKD         4096   782MB     200340
    0.0.9701  active    dasdf     94:20   ECKD         4096   782MB     200340
    0.0.9702  active    dasdh     94:28   ECKD         4096   782MB     200340

Also add copy_pairs to extended output:

     # lsdasd -l 9700
     0.0.9700/dasdd/94:12
       status:                               active
       type:                                 ECKD
       blksz:                                4096
       size:                                 782MB
       blocks:                               200340
       extent_size:                          1113
       logical_capacity:                     1113
       space_allocated:                      1113
       use_diag:                             0
       readonly:                             0
       eer_enabled:                          0
       erplog:                               0
       hpf:                                  1
       uid:                                  IBM.750000000ABT31.9700.00
       fc_security:                          Unsupported
       paths_installed:                      38 39 3a 3b
       paths_in_use:                         38 39 3a 3b
       paths_non_preferred:
       paths_invalid_cabling:
       paths_cuir_quiesced:
       paths_invalid_hpf_characteristics:
       paths_error_threshold_exceeded:
       copy_pairs:                           0.0.9700,0.0.9740 0.0.9700,0.0.9743 0.0.9700,0.0.9744 0.0.9700,0.0.9745

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Jan Höppner 1178291686 Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-09 17:11:48 +01:00
57 changed files with 2067 additions and 1012 deletions
+3
View File
@@ -95,6 +95,9 @@ zdev/src/chzdev_usage.c
zdev/src/lszdev zdev/src/lszdev
zdev/src/lszdev_usage.c zdev/src/lszdev_usage.c
zdsfs/zdsfs zdsfs/zdsfs
zdump/.check_dep_fuse
zdump/.check_dep_zgetdump
zdump/.detect_openssl.dep.c
zdump/zgetdump zdump/zgetdump
zfcpdump/10-zfcpdump.install zfcpdump/10-zfcpdump.install
zfcpdump/cpioinit zfcpdump/cpioinit
+1
View File
@@ -21,6 +21,7 @@ List of all individuals having contributed content to s390-tools
- Colin Walters - Colin Walters
- Dan Horak - Dan Horak
- Dan Horák - Dan Horák
- Daniel S. Haischt
- Despina Papadopoulou - Despina Papadopoulou
- Dimitri John Ledkov - Dimitri John Ledkov
- Eberhard Pasch - Eberhard Pasch
+14
View File
@@ -1,6 +1,20 @@
Release history for s390-tools (MIT version) Release history for s390-tools (MIT version)
-------------------------------------------- --------------------------------------------
* __v2.25.0 (2022-12-08)__
For Linux kernel version: 6.1
Changes of existing tools:
- ap_tools: Use new mdevctl installation location
- lsdasd/tunedasd/zdev: Add support to handle copy pair relations presented by the DASD driver
- zdev: Add --shell command line switch to generate output suitable for shell environments
- zipl: Add List-Directed IPL from ECKD DASD to support secure boot
Bug Fixes:
- ipl_tools: Fix chreipl node for NVMes with CONFIG_NVME_MULTIPATH
- libdasd: Fix bug that prevented positive ioctl return codes
* __v2.24.0 (2022-11-09)__ * __v2.24.0 (2022-11-09)__
For Linux kernel version: 6.0 For Linux kernel version: 6.0
+17 -3
View File
@@ -1,8 +1,11 @@
include ../common.mak include ../common.mak
MDEVCTL_DIR = /etc/mdevctl.d/ MDEVCTL_DIR = /usr/lib/mdevctl/
MDEVCTL_SCRIPTS = /etc/mdevctl.d/scripts.d/ MDEVCTL_SCRIPTS = /usr/lib/mdevctl/scripts.d/
MDEVCTL_CALLOUTS = /etc/mdevctl.d/scripts.d/callouts/ MDEVCTL_CALLOUTS = /usr/lib/mdevctl/scripts.d/callouts/
MDEVCTL_DEP_DIR = /etc/mdevctl.d/
MDEVCTL_DEP_SCRIPTS = /etc/mdevctl.d/scripts.d/
MDEVCTL_DEP_CALLOUTS = /etc/mdevctl.d/scripts.d/callouts/
libs = $(rootdir)/libap/libap.a \ libs = $(rootdir)/libap/libap.a \
$(rootdir)/libutil/libutil.a $(rootdir)/libutil/libutil.a
@@ -32,6 +35,17 @@ install: all
fi; \ fi; \
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 ap-check \ $(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 ap-check \
$(DESTDIR)$(MDEVCTL_CALLOUTS) $(DESTDIR)$(MDEVCTL_CALLOUTS)
@if [ ! -d $(DESTDIR)$(MDEVCTL_DEP_CALLOUTS) ]; then \
mkdir -p $(DESTDIR)$(MDEVCTL_DEP_CALLOUTS); \
chown $(OWNER).$(GROUP) $(DESTDIR)$(MDEVCTL_DEP_DIR); \
chown $(OWNER).$(GROUP) $(DESTDIR)$(MDEVCTL_DEP_SCRIPTS); \
chown $(OWNER).$(GROUP) $(DESTDIR)$(MDEVCTL_DEP_CALLOUTS); \
chmod 755 $(DESTDIR)$(MDEVCTL_DEP_DIR); \
chmod 755 $(DESTDIR)$(MDEVCTL_DEP_SCRIPTS); \
chmod 755 $(DESTDIR)$(MDEVCTL_DEP_CALLOUTS); \
fi; \
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 ap-check.sh \
$(DESTDIR)$(MDEVCTL_DEP_CALLOUTS)
endif endif
clean: clean:
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh
#
# ap-check.sh - Wrapper script for 'ap-check' binary
#
# mdevctl has deprecated the /etc/mdevctl.d/scripts.d/callouts/ location in
# newer releases. This wrapper ensures that mdevctl 1.2.0 and older can
# still access 'ap-check' for now, and will be removed at a later time.
#
# Copyright 2022 IBM Corp.
#
# s390-tools is free software; you can redistribute it and/or modify
# it under the terms of the MIT license. See LICENSE for details.
#
[ -e /usr/lib/mdevctl/scripts.d/callouts/ap-check ] && /usr/lib/mdevctl/scripts.d/callouts/ap-check "$@"
+3 -3
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 = 24 RELEASE = 25
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)
@@ -60,8 +60,10 @@ endef
$(eval $(call cmd_define, AS," AS ",$(CROSS_COMPILE)as)) $(eval $(call cmd_define, AS," AS ",$(CROSS_COMPILE)as))
$(eval $(call cmd_define, CC," CC ",$(CROSS_COMPILE)gcc)) $(eval $(call cmd_define, CC," CC ",$(CROSS_COMPILE)gcc))
$(eval $(call cmd_define, LINK," LINK ",$(CC)))
$(eval $(call cmd_define, HOSTCC," HOSTCC ",gcc)) $(eval $(call cmd_define, HOSTCC," HOSTCC ",gcc))
$(eval $(call cmd_define, CXX," CXX ",$(CROSS_COMPILE)g++)) $(eval $(call cmd_define, CXX," CXX ",$(CROSS_COMPILE)g++))
$(eval $(call cmd_define, LINKXX," LINKXX ",$(CXX)))
$(eval $(call cmd_define, CPP," CPP ",$(CROSS_COMPILE)gcc -E)) $(eval $(call cmd_define, CPP," CPP ",$(CROSS_COMPILE)gcc -E))
$(eval $(call cmd_define, AR," AR ",$(CROSS_COMPILE)ar)) $(eval $(call cmd_define, AR," AR ",$(CROSS_COMPILE)ar))
$(eval $(call cmd_define, NM," NM ",$(CROSS_COMPILE)nm)) $(eval $(call cmd_define, NM," NM ",$(CROSS_COMPILE)nm))
@@ -81,8 +83,6 @@ CHECKTOOL = $(call echocmd," CHECK ",/$@)$(CHECK_SILENT)
SKIP = echo " SKIP $(call reldir) due to" SKIP = echo " SKIP $(call reldir) due to"
INSTALL = install INSTALL = install
LINK = $(CC)
LINKXX = $(CXX)
CP = cp CP = cp
ifneq ("${V}","1") ifneq ("${V}","1")
MAKEFLAGS += --quiet MAKEFLAGS += --quiet
+49 -5
View File
@@ -57,11 +57,41 @@ struct linear_blockptr {
uint8_t reserved[4]; uint8_t reserved[4];
} __packed; } __packed;
/*
* Format of a boot record on ECKD DASD for List-Directed IPL
*/
struct eckd_boot_record {
uint8_t magic[4];
uint32_t version_id;
uint8_t unused[8];
uint8_t program_table_pointer[16];
uint8_t reserved[478];
uint16_t os_id;
} __packed;
/* /*
* Layout of block pointer for cylinder/head/sector devices * Layout of block pointer for cylinder/head/sector devices
* e.g. ECKD * e.g. ECKD
*/ */
struct eckd_blockptr {
enum blkptr_format_id {
/*
* this is the old format which serves only CCW-type IPL,
* and doesn't fit List-Directed IPL. Still supported for
* compatibility reasons.
*/
LEGACY_BLKPTR_FORMAT_ID,
/*
* this is the "new" format which serves only List-Directed IPL,
* but is also suitable for CCW-type IPL.
*/
BLKPTR_FORMAT_ID
};
/*
* Block pointers format identified as LEGACY_BLKPTR_FORMAT_ID.
*/
struct eckd_blockptr_legacy {
uint16_t cyl; uint16_t cyl;
uint16_t head; uint16_t head;
uint8_t sec; uint8_t sec;
@@ -70,10 +100,22 @@ struct eckd_blockptr {
uint8_t reserved[8]; uint8_t reserved[8];
} __packed; } __packed;
/*
* Block pointers format identified as BLKPTR_FORMAT_ID.
*/
struct eckd_blockptr {
uint32_t cyl;
uint8_t head;
uint8_t sec;
uint8_t reserved1[4];
uint16_t blockct;
uint8_t reserved2[4];
} __packed;
typedef enum { typedef enum {
COMPONENT_EXECUTE = 0x01, COMPONENT_TYPE_EXECUTE = 0x01,
COMPONENT_LOAD = 0x02, COMPONENT_TYPE_LOAD = 0x02,
COMPONENT_SIGNATURE = 0x03 COMPONENT_TYPE_SIGNATURE = 0x03
} component_type; } component_type;
typedef enum { typedef enum {
@@ -117,7 +159,8 @@ struct scsi_dump_sb {
uint64_t csum_offset; uint64_t csum_offset;
uint64_t csum_size; uint64_t csum_size;
uint64_t csum; uint64_t csum;
} __packed; };
STATIC_ASSERT(sizeof(struct scsi_dump_sb) == 72);
#define SCSI_DUMP_SB_MAGIC 0x5a46435044554d50ULL /* ZFCPDUMP */ #define SCSI_DUMP_SB_MAGIC 0x5a46435044554d50ULL /* ZFCPDUMP */
/* To avoid a csum entry of 0 a seed is used */ /* To avoid a csum entry of 0 a seed is used */
@@ -153,6 +196,7 @@ struct boot_info_bp_dump {
struct boot_info_bp_ipl { struct boot_info_bp_ipl {
union { union {
struct eckd_blockptr_legacy eckd_legacy;
struct eckd_blockptr eckd; struct eckd_blockptr eckd;
struct linear_blockptr lin; struct linear_blockptr lin;
} bm_ptr; } bm_ptr;
+85 -14
View File
@@ -20,8 +20,8 @@
#include <stdio.h> #include <stdio.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
/* A bus id of a DASD is 8 characters long. E.g. 0.0.4711 */ /* the definition of a BUSID in the DASD driver is 20 */
#define DASD_BUS_ID_SIZE 9 #define DASD_BUS_ID_SIZE 20
typedef struct dasd_information2_t { typedef struct dasd_information2_t {
unsigned int devno; /* S/390 devno */ unsigned int devno; /* S/390 devno */
@@ -187,6 +187,68 @@ typedef struct format_check_t {
#define DASD_FMT_ERR_RECORD_ID 4 #define DASD_FMT_ERR_RECORD_ID 4
#define DASD_FMT_ERR_KEY_LENGTH 5 #define DASD_FMT_ERR_KEY_LENGTH 5
/*
* struct profile_info_t
* holds the profiling information
*/
typedef struct dasd_profile_info_t {
unsigned int dasd_io_reqs; /* # of requests processed at all */
unsigned int dasd_io_sects; /* # of sectors processed at all */
unsigned int dasd_io_secs[32]; /* request's sizes */
unsigned int dasd_io_times[32]; /* requests's times */
unsigned int dasd_io_timps[32]; /* requests's times per sector */
unsigned int dasd_io_time1[32]; /* time from build to start */
unsigned int dasd_io_time2[32]; /* time from start to irq */
unsigned int dasd_io_time2ps[32]; /* time from start to irq */
unsigned int dasd_io_time3[32]; /* time from irq to end */
unsigned int dasd_io_nr_req[32]; /* # of requests in chanq */
} dasd_profile_info_t;
/*
* struct attrib_data_t
* represents the operation (cache) bits for the device.
* Used in DE to influence caching of the DASD.
*/
typedef struct attrib_data_t {
unsigned char operation : 3; /* cache operation mode */
unsigned char reserved : 5;
unsigned short nr_cyl; /* no of cyliners for read ahaed */
unsigned char reserved2[29]; /* for future use */
} __attribute__((packed)) attrib_data_t;
/* definition of operation (cache) bits within attributes of DE */
#define DASD_NORMAL_CACHE 0x0
#define DASD_BYPASS_CACHE 0x1
#define DASD_INHIBIT_LOAD 0x2
#define DASD_SEQ_ACCESS 0x3
#define DASD_SEQ_PRESTAGE 0x4
#define DASD_REC_ACCESS 0x5
/*
* Data returned by Sense Path Group ID (SNID)
*/
struct dasd_snid_data {
struct {
__u8 group : 2;
__u8 reserve : 2;
__u8 mode : 1;
__u8 res : 3;
} __attribute__((packed)) path_state;
__u8 pgid[11];
} __attribute__((packed));
struct dasd_snid_ioctl_data {
struct dasd_snid_data data;
__u8 path_mask;
} __attribute__((packed));
struct dasd_copypair_swap_data {
char primary[DASD_BUS_ID_SIZE]; /* BUSID of primary */
char secondary[DASD_BUS_ID_SIZE]; /* BUSID of secondary */
/* Reserved for future updates. */
char reserved[64];
};
#ifndef __linux__ #ifndef __linux__
/* definition from hdreg.h */ /* definition from hdreg.h */
struct hd_geometry { struct hd_geometry {
@@ -207,27 +269,29 @@ struct hd_geometry {
#define BIODASDRSRV _IO(DASD_IOCTL_LETTER, 2) #define BIODASDRSRV _IO(DASD_IOCTL_LETTER, 2)
/* Release the device for the current LPAR */ /* Release the device for the current LPAR */
#define BIODASDRLSE _IO(DASD_IOCTL_LETTER, 3) #define BIODASDRLSE _IO(DASD_IOCTL_LETTER, 3)
/* Unconditional reserve the device for the current LPAR */
#define BIODASDSLCK _IO(DASD_IOCTL_LETTER, 4)
/* reset profiling information of a device */
#define BIODASDPRRST _IO(DASD_IOCTL_LETTER, 5)
/* retrieve profiling information of a device */
#define BIODASDPRRD _IOR(DASD_IOCTL_LETTER, 2, dasd_profile_info_t)
/* Get information on a dasd device (enhanced) */ /* Get information on a dasd device (enhanced) */
#define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER, 3, dasd_information2_t) #define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER, 3, dasd_information2_t)
/* Get Attributes (cache operations) */
#define BIODASDGATTR _IOR(DASD_IOCTL_LETTER, 5, attrib_data_t)
/* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */ /* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */
#define BIODASDFMT _IOW(DASD_IOCTL_LETTER, 1, format_data_t) #define BIODASDFMT _IOW(DASD_IOCTL_LETTER, 1, format_data_t)
/* Set Attributes (cache operations) */
#define BIODASDSATTR _IOW(DASD_IOCTL_LETTER, 2, attrib_data_t)
/* Release Allocated Space */ /* Release Allocated Space */
#define BIODASDRAS _IOW(DASD_IOCTL_LETTER, 3, format_data_t) #define BIODASDRAS _IOW(DASD_IOCTL_LETTER, 3, format_data_t)
/* Swap copy pair */
#define BIODASDPPRCSWAP _IOW(DASD_IOCTL_LETTER, 4, struct dasd_copypair_swap_data)
/* Get Sense Path Group ID (SNID) data */
#define BIODASDSNID _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data)
/* Check device format according to format_data_t */ /* Check device format according to format_data_t */
#define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t) #define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t)
/********************************************************************************
* SECTION: Further IOCTL Definitions (see fs.h and hdreq.h)
*******************************************************************************/
/* get read-only status (0 = read_write) */
#define BLKROGET _IO(0x12, 94)
/* re-read partition table */
#define BLKRRPART _IO(0x12, 95)
/* get block device sector size */
#define BLKSSZGET _IO(0x12, 104)
/* return device size in bytes (u64 *arg) */
#define BLKGETSIZE64 _IOR(0x12, 114, size_t)
#ifndef __linux__ /* from <linux/hdreg.h> */ #ifndef __linux__ /* from <linux/hdreg.h> */
#define HDIO_GETGEO 0x0301 #define HDIO_GETGEO 0x0301
#endif #endif
@@ -245,5 +309,12 @@ int dasd_is_ro(const char *device, bool *ro);
int dasd_reread_partition_table(const char *device, int ntries); int dasd_reread_partition_table(const char *device, int ntries);
int dasd_disk_reserve(const char *device); int dasd_disk_reserve(const char *device);
int dasd_disk_release(const char *device); int dasd_disk_release(const char *device);
int dasd_slock(const char *device);
int dasd_get_cache(const char *device, attrib_data_t *attrib_data);
int dasd_set_cache(const char *device, attrib_data_t *attrib_data);
int dasd_query_reserve(const char *device);
int dasd_profile(const char *device, dasd_profile_info_t *dasd_profile_info);
int dasd_reset_profile(const char *device);
int dasd_copy_swap(const char *device, struct dasd_copypair_swap_data *data);
#endif /* LIB_DASD_BASE_H */ #endif /* LIB_DASD_BASE_H */
+18
View File
@@ -97,6 +97,24 @@ typedef struct volume_label
unsigned long long formatted_blocks; /* valid when ldl_version >= f2 */ unsigned long long formatted_blocks; /* valid when ldl_version >= f2 */
} __attribute__ ((packed)) volume_label_t; } __attribute__ ((packed)) volume_label_t;
/**
* This represents a volume label specific for OS/390 compatible disk layout
*/
struct vol_label_cdl {
char volkey[4];
char vollbl[4];
char opaq[70];
cchhb_t br; /* boot record address */
char stdv[1]; /* standard version ID */
} __attribute__ ((packed));
static inline int is_vol1(char *this)
{
char vol1[] = {0xe5, 0xd6, 0xd3, 0xf1, 0x00} /* "VOL1" in EBCDIC */;
return !strncmp(this, vol1, 4);
}
typedef struct extent typedef struct extent
{ {
u_int8_t typeind; /* extent type indicator */ u_int8_t typeind; /* extent type indicator */
+1
View File
@@ -75,6 +75,7 @@ extern void fcp_busid_get(const char *device, char *devno);
* NVME * NVME
*/ */
#define FID_MAX_LEN 11 /* 8 characters + 0x + null */ #define FID_MAX_LEN 11 /* 8 characters + 0x + null */
#define NVME_DEV_MAX_LEN 15 /* "nvme" + u32 in decimal + null */
#define NVME_PATH_MAX (PATH_MAX + NAME_MAX + 1) #define NVME_PATH_MAX (PATH_MAX + NAME_MAX + 1)
extern void nvme_fid_get(const char *device, char *fid); extern void nvme_fid_get(const char *device, char *fid);
+18 -2
View File
@@ -18,15 +18,31 @@
#include "lib/util_file.h" #include "lib/util_file.h"
#include "ipl_tools.h" #include "ipl_tools.h"
static void nvme_dev_from_bdev(char *dev_name)
{
char *delim = strrchr(dev_name, 'n');
if (delim)
*delim = 0;
}
/* /*
* Return the fid of a device * Return the fid of a device
*/ */
void nvme_fid_get(const char *device, char *fid) void nvme_fid_get(const char *device, char *fid)
{ {
char path[PATH_MAX], buf[FID_MAX_LEN]; char path[PATH_MAX], buf[FID_MAX_LEN];
char nvme_dev[NVME_DEV_MAX_LEN];
snprintf(path, PATH_MAX, "/sys/block/%s/device/device/function_id", /*
device); * An NVMe may present multiple namespaces and thus block devices, even
* before partitioning, so we need the nvme<NUM> part of the block
* device name to get to the PCI function ID.
*/
util_strlcpy(nvme_dev, device, sizeof(nvme_dev));
nvme_dev_from_bdev(nvme_dev);
snprintf(path, PATH_MAX, "/sys/class/nvme/%s/device/function_id", nvme_dev);
if (util_file_read_line(buf, FID_MAX_LEN, path)) if (util_file_read_line(buf, FID_MAX_LEN, path))
ERR_EXIT_ERRNO("Could not read from \"%s\"", path); ERR_EXIT_ERRNO("Could not read from \"%s\"", path);
+164 -4
View File
@@ -15,7 +15,9 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/mount.h>
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include "lib/dasd_base.h" #include "lib/dasd_base.h"
@@ -27,11 +29,13 @@
#define RUN_IOCTL(fd, req, argp) \ #define RUN_IOCTL(fd, req, argp) \
do { \ do { \
if (ioctl(fd, req, argp) != 0) { \ int rc = ioctl(fd, req, argp); \
int err = errno; \ if (rc != 0) { \
if (err != EBADF) \ if (rc == -1) \
rc = errno; \
if (rc != EBADF) \
dasd_close_device(fd); \ dasd_close_device(fd); \
return err; \ return rc; \
} \ } \
} while (0) } while (0)
@@ -321,3 +325,159 @@ int dasd_disk_release(const char *device)
return 0; return 0;
} }
/*
* Unconditionally reserve DASD disk
*
* An existing reserve lock is lifted (steal lock) and the device
* is reserved.
*
* @param[in] device node device node's name
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_slock(const char *device)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDSLCK, NULL);
dasd_close_device(fd);
return 0;
}
/*
* Get the caching algorithm used for the channel programs of this device.
*
* @param[in] device node device node's name
* @param[out] attrib_data pointer to dasd attrib data with:
* 'cache' is the caching mode
* 'no_cyl' the number of cylinders to be cached.
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_get_cache(const char *device, attrib_data_t *attrib_data)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDGATTR, attrib_data);
dasd_close_device(fd);
return 0;
}
/*
* Set the caching algorithm used for the channel programs of this device.
*
* @param[in] device node device node's name
* @param[in] attrib_data pointer to dasd attrib data with:
* 'cache' is the caching mode
* 'no_cyl' the number of cylinders to be cached.
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_set_cache(const char *device, attrib_data_t *attrib_data)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDSATTR, attrib_data);
dasd_close_device(fd);
return 0;
}
/*
* Get reserve status of device.
*
* @param[in] device node device node's name
*
* @retval errno in case of failure
* @retval 0 unreserved
* @retval 1 implicit reserved
* @retval 2 other reservation
* @retval 3 reserved
*/
int dasd_query_reserve(const char *device)
{
struct dasd_snid_ioctl_data snid = { 0 };
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDSNID, &snid);
dasd_close_device(fd);
return snid.data.path_state.reserve;
}
/*
* Get and print the profiling info of the device.
*
* @param[in] device node device node's name
* @param[in] dasd_profile_info pointer to dasd profile info
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_profile(const char *device, dasd_profile_info_t *dasd_profile_info)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDPRRD, dasd_profile_info);
dasd_close_device(fd);
return 0;
}
/*
* Reset the profiling counters of the device.
*
* @param[in] device node device node's name
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_reset_profile(const char *device)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDPRRST, NULL);
dasd_close_device(fd);
return 0;
}
/*
* Initiate the swap of a copy pairs primary,secondary relation.
* The old secondary will become the new primary and vice versa.
*
* @param[in] device node device node's name
* @param[in] copy_pair data pointer to dasd copypair data with:
* 'primary' old primary, becoming secondary
* 'secondary' old secondary, becoming primary.
*
* @retval errno in case of failure
* @retval 0 in case of success
* @retval 1 swap data invalid
* @retval 2 no active device found
* @retval 3 wrong primary specified
* @retval 4 secondary device not found
* @retval 5 swap already running
*/
int dasd_copy_swap(const char *device, struct dasd_copypair_swap_data *data)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDPPRCSWAP, data);
dasd_close_device(fd);
return 0;
}
+1
View File
@@ -18,6 +18,7 @@
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include "lib/util_libc.h" #include "lib/util_libc.h"
#include "lib/util_lockfile.h" #include "lib/util_lockfile.h"
+1 -3
View File
@@ -1419,7 +1419,6 @@ int lzds_dasd_read_rawvtoc(struct dasd *dasd, struct raw_vtoc *rawvtoc)
volume_label_t *vlabel = NULL; volume_label_t *vlabel = NULL;
char *trackdata = NULL; char *trackdata = NULL;
char vol1[] = {0xe5, 0xd6, 0xd3, 0xf1, 0x00}; /* "VOL1" in EBCDIC */
errorlog_clear(dasd->log); errorlog_clear(dasd->log);
@@ -1431,8 +1430,7 @@ int lzds_dasd_read_rawvtoc(struct dasd *dasd, struct raw_vtoc *rawvtoc)
goto cleanup; goto cleanup;
} }
/* verify that we have a proper VOL1 label */ /* verify that we have a proper VOL1 label */
if (strncmp(vlabel->volkey, vol1, 4) || if (!is_vol1(vlabel->volkey) || !is_vol1(vlabel->vollbl)) {
strncmp(vlabel->vollbl, vol1, 4)) {
rc = EINVAL; rc = EINVAL;
errorlog_add_message( errorlog_add_message(
&dasd->log, NULL, rc, &dasd->log, NULL, rc,
+2
View File
@@ -1,5 +1,7 @@
include ../common.mak include ../common.mak
ALL_CFLAGS += -Wno-address-of-packed-member
all: mon_fsstatd mon_procd all: mon_fsstatd mon_procd
mon_fsstatd: mon_fsstatd.o mon_fsstatd: mon_fsstatd.o
+1 -1
View File
@@ -24,7 +24,7 @@ Prints usage information, then exits.
.B .B
\fB-k\fP, \fB--host-key-document\fP=\fBFILE\fP \fB-k\fP, \fB--host-key-document\fP=\fBFILE\fP
Specify one or more host key documents. At least one is required. Specify one or more host key documents. At least one is required.
Specify this option multiple times to enable the image to run on more than one host. Specify this option multiple times to create an attestation request control block that is usable on multiple hosts.
.TP .TP
.B .B
\fB-C\fP, \fB--cert\fP=\fBFILE\fP \fB-C\fP, \fB--cert\fP=\fBFILE\fP
+14 -8
View File
@@ -14,6 +14,8 @@ set -o pipefail
set -o nounset set -o nounset
set -e set -e
XDUMP='od -A x -t x2z -v'
usage() { usage() {
cat <<-EOF cat <<-EOF
Usage: $(basename "$0") FILE Usage: $(basename "$0") FILE
@@ -33,16 +35,16 @@ function check_is_pvattest_binary() {
exit 1 exit 1
fi fi
xxd -l 16 "${input}" | grep -q pvattest || ${XDUMP} --read-bytes 16 -- "${input}" 2>/dev/null | grep -q pvattest ||
{ echo "ERROR: ${input} does not contain a pvattest binary output." >&2 && exit 1; } { echo "ERROR: ${input} does not contain a pvattest binary output." >&2 && exit 1; }
size=$(xxd -s 12 -l 4 "${input}" | awk 'NR==1 {print "0x" $2 $3}') size=$(${XDUMP} --skip-bytes 12 --read-bytes 4 -- "${input}" 2>/dev/null | awk 'NR==1 {print "0x" $2 $3}')
if [ $((size)) -lt 64 ]; then if [ $((size)) -lt 64 ]; then
echo "ERROR: ${input} does not contain a pvattest binary output." >&2 echo "ERROR: ${input} does not contain a pvattest binary output." >&2
exit 1 exit 1
fi fi
version=$(xxd -s 8 -l 4 "$input") version=$(${XDUMP} --skip-bytes 8 --read-bytes 4 -- "$input" 2>/dev/null)
echo "$version" | grep -q "0000 0100" || echo "$version" | grep -q "0000 0100" ||
{ echo -n "WARNING: unknown hdr version " >&2 && { echo -n "WARNING: unknown hdr version " >&2 &&
echo "$version" | awk '{print "0x" $2 $3}'>&2 ; } echo "$version" | awk '{print "0x" $2 $3}'>&2 ; }
@@ -55,24 +57,28 @@ function print_entry() {
local size local size
local off local off
size=$(xxd -s $((file_off)) -l 4 "${input}" | awk 'NR==1 {print "0x" $2 $3}') size=$(${XDUMP} --skip-bytes $((file_off)) --read-bytes 4 -- "${input}" 2>/dev/null |
off=$(xxd -s $((file_off + 4)) -l 4 "${input}" | awk 'NR==1 {print "0x" $2 $3}') awk 'NR==1 {print "0x" $2 $3}')
off=$(${XDUMP} --skip-bytes $((file_off + 4)) --read-bytes 4 -- "${input}" 2>/dev/null |
awk 'NR==1 {print "0x" $2 $3}')
if [[ $size != "0x00000000" ]] || [[ $off != "0x00000000" ]]; then if [[ $size != "0x00000000" ]] || [[ $off != "0x00000000" ]]; then
echo "${text}:" echo "${text}:"
xxd -s $((off)) -l $((size)) -p "${input}" od -A n -w$((size)) -t x8 --skip-bytes $((off)) --read-bytes $((size)) -- "${input}" 2>/dev/null |\
sed -e 's/\s//g'
fi fi
} }
function require_command() { function require_command() {
local cmd="$1" local cmd="$1"
command -v "$cmd" >/dev/null 2>&1 || { echo >&2 "ERROR: $cmd required but not installed."; exit 1; } command -v "$cmd" >/dev/null 2>&1 || \
{ echo >&2 "ERROR: $cmd required but not installed."; exit 1; }
} }
require_command xxd
require_command awk require_command awk
require_command wc require_command wc
require_command od
if [ $# -eq 0 ]; then if [ $# -eq 0 ]; then
echo "ERROR: Input not set. Use '$(basename "$0") [FILE]' to specify the Input file" >&2 echo "ERROR: Input not set. Use '$(basename "$0") [FILE]' to specify the Input file" >&2
+20 -5
View File
@@ -14,7 +14,9 @@ set -o pipefail
set -o nounset set -o nounset
set -e set -e
def_output="sehdr.bin" XDUMP='od -A x -t x2z -v'
def_output='sehdr.bin'
def_skip=0x14 def_skip=0x14
def_len=0x4 def_len=0x4
@@ -37,11 +39,22 @@ function check_file() {
function check_hdr_ver() { function check_hdr_ver() {
local hdr_start="$1" local hdr_start="$1"
local input="$2" local input="$2"
xxd -s $((hdr_start + 8)) -l 4 "$input" | grep -q "000 0100" || ${XDUMP} --skip-bytes $((hdr_start + 8)) --read-bytes 4 -- "$input" 2>/dev/null | grep -q "000 0100" ||
{ echo -n "WARNING: unknown hdr version " && { echo -n "WARNING: unknown hdr version " &&
xxd -s $((hdr_start + 8)) -l 4 "$input" | awk '{print "0x" $2 $3}'; } ${XDUMP} --skip-bytes $((hdr_start + 8)) --read_bytes 4 -- "$input" 2>/dev/null | awk '{print "0x" $2 $3}'; }
} }
function require_command() {
local cmd="$1"
command -v "$cmd" >/dev/null 2>&1 || \
{ echo >&2 "ERROR: $cmd required but not installed."; exit 1; }
}
require_command od
require_command awk
require_command grep
output=${def_output} output=${def_output}
parsed_skip=${def_skip} parsed_skip=${def_skip}
parsed_len=${def_len} parsed_len=${def_len}
@@ -77,13 +90,15 @@ if [ $# -eq 0 ]; then
fi fi
check_file "$input" check_file "$input"
hdr_start=$(xxd -s $((skip)) -l $((len)) "${input}" | grep IBMSecEx || { echo ERROR: "${input} does not contain an SE header." >&2 && exit 1; }) hdr_start=$(${XDUMP} --skip-bytes $((skip)) --read-bytes $((len)) -- "${input}" 2>/dev/null | grep IBMSecEx ||
{ echo ERROR: "${input} does not contain an SE header." >&2 && exit 1; })
hdr_start=$(echo "${hdr_start}" | awk '{print "0x" $1}' | cut -c 1-10) hdr_start=$(echo "${hdr_start}" | awk '{print "0x" $1}' | cut -c 1-10)
echo "SE header found at offset ${hdr_start}" echo "SE header found at offset ${hdr_start}"
check_hdr_ver "$hdr_start" "$input" check_hdr_ver "$hdr_start" "$input"
size=$(xxd -s $((hdr_start + 12)) -l 4 "${input}" | awk 'NR==1 {print "0x" $2 $3}') size=$(${XDUMP} --skip-bytes $((hdr_start + 12)) --read-bytes 4 -- "${input}" 2>/dev/null |
awk 'NR==1 {print "0x" $2 $3}')
dd if="${input}" of="${output}" bs=1 count=$((size)) skip=$((hdr_start)) status=none dd if="${input}" of="${output}" bs=1 count=$((size)) skip=$((hdr_start)) status=none
echo "SE header written to '${output}' ($((size)) bytes)" echo "SE header written to '${output}' ($((size)) bytes)"
+4
View File
@@ -1192,6 +1192,10 @@ post_processing() {
rm -f "${file_name}" rm -f "${file_name}"
fi fi
done done
echo "log work directory state after post processing:"
echo "du summary: $(du -ks ${WORKPATH})"
df -k ${WORKPATH}
} }
######################################## ########################################
+1
View File
@@ -31,6 +31,7 @@ int disk_query_reserve_status(char* device);
int disk_profile (char* device, char* prof_item); int disk_profile (char* device, char* prof_item);
int disk_reset_prof(char *device); int disk_reset_prof(char *device);
int disk_reset_chpid(char *device, char *chpid); int disk_reset_chpid(char *device, char *chpid);
int disk_copy_swap(char *device, char *copy_pair);
#endif /* not DISK_H */ #endif /* not DISK_H */
+14
View File
@@ -174,6 +174,14 @@ Reset all channel paths of the selected device. The channel paths
might be suspended due to high IFCC error rates or a High Performance might be suspended due to high IFCC error rates or a High Performance
FICON failure. Use this option to resume considering all defined FICON failure. Use this option to resume considering all defined
channel paths for I/O. channel paths for I/O.
.TP
.BR "\-s" " or " "\-\-copy\-pair\-swap <copy_pair>"
Swap the copy roles of the specified copy pair. The <copy_pair> has to
be a comma separated pair of \fBPRIMARY,SECONDARY\fR where
\fBPRIMARY\fR is the old primary device that will become a secondary
automatically. The old \fBSECONDARY\fR device will become the new
primary device. Both devices have to be online for this operation to
succeed.
.\" .\"
.\".TP .\".TP
.\".BR "\-o" " or " "\-\-online" .\".BR "\-o" " or " "\-\-online"
@@ -197,6 +205,12 @@ channel paths for I/O.
.br .br
tunedasd -p 45 /dev/dasdc tunedasd -p 45 /dev/dasdc
.br
4. Scenario: Swap copy pair 0.0.9700 and 0.0.9740
.br
tunedasd -s 0.0.9700,0.0.9740 /dev/dasdc
.br .br
.SH "SEE ALSO" .SH "SEE ALSO"
.BR dasdview (8), .BR dasdview (8),
+96 -218
View File
@@ -19,98 +19,13 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "lib/dasd_base.h"
#include "lib/dasd_sys.h" #include "lib/dasd_sys.h"
#include "lib/util_libc.h"
#include "disk.h" #include "disk.h"
#include "tunedasd.h" #include "tunedasd.h"
#define BUS_ID_SIZE 30
/*
* DASD DEFINITIONS (copied from dasd.h)
*/
#define DASD_IOCTL_LETTER 'D'
/*
* struct profile_info_t
* holds the profiling information
*/
typedef struct dasd_profile_info_t {
unsigned int dasd_io_reqs; /* # of requests processed at all */
unsigned int dasd_io_sects; /* # of sectors processed at all */
unsigned int dasd_io_secs[32]; /* request's sizes */
unsigned int dasd_io_times[32]; /* requests's times */
unsigned int dasd_io_timps[32]; /* requests's times per sector */
unsigned int dasd_io_time1[32]; /* time from build to start */
unsigned int dasd_io_time2[32]; /* time from start to irq */
unsigned int dasd_io_time2ps[32]; /*time from start to irq */
unsigned int dasd_io_time3[32]; /* time from irq to end */
unsigned int dasd_io_nr_req[32]; /* # of requests in chanq */
} dasd_profile_info_t;
/*
* struct attrib_data_t
* represents the operation (cache) bits for the device.
* Used in DE to influence caching of the DASD.
*/
typedef struct attrib_data_t {
unsigned char operation:3; /* cache operation mode */
unsigned char reserved:5;
unsigned short nr_cyl; /* no of cyliners for read ahaed */
unsigned char reserved2[29]; /* for future use */
} __attribute__ ((packed)) attrib_data_t;
/* definition of operation (cache) bits within attributes of DE */
#define DASD_NORMAL_CACHE 0x0
#define DASD_BYPASS_CACHE 0x1
#define DASD_INHIBIT_LOAD 0x2
#define DASD_SEQ_ACCESS 0x3
#define DASD_SEQ_PRESTAGE 0x4
#define DASD_REC_ACCESS 0x5
/*
* Data returned by Sense Path Group ID (SNID)
*/
struct dasd_snid_data {
struct {
__u8 group:2;
__u8 reserve:2;
__u8 mode:1;
__u8 res:3;
} __attribute__ ((packed)) path_state;
__u8 pgid[11];
} __attribute__ ((packed));
struct dasd_snid_ioctl_data {
struct dasd_snid_data data;
__u8 path_mask;
} __attribute__ ((packed));
/*
* DASD-IOCTLs (copied from dasd.h)
*/
/* Issue a reserve/release command, rsp. */
#define BIODASDRSRV _IO (DASD_IOCTL_LETTER,2) /* reserve */
#define BIODASDRLSE _IO (DASD_IOCTL_LETTER,3) /* release */
#define BIODASDSLCK _IO (DASD_IOCTL_LETTER,4) /* steal lock */
/* reset profiling information of a device */
#define BIODASDPRRST _IO (DASD_IOCTL_LETTER,5)
/* retrieve profiling information of a device */
#define BIODASDPRRD _IOR (DASD_IOCTL_LETTER,2,dasd_profile_info_t)
/* Get Attributes (cache operations) */
#define BIODASDGATTR _IOR(DASD_IOCTL_LETTER,5,attrib_data_t)
/* Set Attributes (cache operations) */
#define BIODASDSATTR _IOW (DASD_IOCTL_LETTER,2,attrib_data_t)
/* Get Sense Path Group ID (SNID) data */
#define BIODASDSNID _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data)
/* id definition for profile items */ /* id definition for profile items */
enum prof_id { enum prof_id {
prof_reqs = 0, prof_reqs = 0,
@@ -241,48 +156,33 @@ check_prof_item (char* prof_item)
* 'cache' is the caching mode (see ESS docu for more info) and 'no_cyl' * 'cache' is the caching mode (see ESS docu for more info) and 'no_cyl'
* the number of cylinders to be cached. * the number of cylinders to be cached.
*/ */
int int disk_get_cache(char *device)
disk_get_cache (char* device)
{ {
int fd;
attrib_data_t attrib_data; attrib_data_t attrib_data;
int rc;
/* Open device file */ rc = dasd_get_cache(device, &attrib_data);
fd = open (device, O_RDONLY); if (rc)
if (fd == -1) { return rc;
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
/* Get the given caching attributes */
if (ioctl (fd, BIODASDGATTR, &attrib_data)) {
error_print ("Could not get cache attributes for device <%s>",
device);
close (fd);
return -1;
}
printf ("%s (%i cyl)\n", printf ("%s (%i cyl)\n",
get_cache_name(attrib_data.operation), get_cache_name(attrib_data.operation),
attrib_data.nr_cyl); attrib_data.nr_cyl);
close (fd);
return 0; return 0;
} }
/* /*
* Set the caching algorithm used for the channel programs of this device. * Set the caching algorithm used for the channel programs of this device.
* 'cache' is the caching mode (see ESS docu for more info) and 'no_cyl' * 'cache' is the caching mode (see ESS docu for more info) and 'no_cyl'
* the number of cylinders to be cached. * the number of cylinders to be cached.
*/ */
int int disk_set_cache(char *device, char *cache, char *no_cyl)
disk_set_cache (char* device, char* cache, char* no_cyl)
{ {
int fd;
attrib_data_t attrib_data; attrib_data_t attrib_data;
int rc;
/* get caching mode and # cylinders */ /* get caching mode and # cylinders */
attrib_data.operation = check_cache (cache); attrib_data.operation = check_cache (cache);
attrib_data.nr_cyl = check_no_cyl (no_cyl); attrib_data.nr_cyl = check_no_cyl (no_cyl);
@@ -292,52 +192,34 @@ disk_set_cache (char* device, char* cache, char* no_cyl)
attrib_data.nr_cyl); attrib_data.nr_cyl);
} }
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
/* Set the given caching attributes */ /* Set the given caching attributes */
printf ("Setting cache mode for device <%s>...\n", device); printf ("Setting cache mode for device <%s>...\n", device);
if (ioctl (fd, BIODASDSATTR, &attrib_data)) { rc = dasd_set_cache(device, &attrib_data);
error_print ("Could not set caching for device <%s>", device); if (rc) {
close (fd); error_print("Could not set caching for device <%s>", device);
return -1; return -1;
} }
printf ("Done.\n"); printf ("Done.\n");
close (fd);
return 0; return 0;
} }
/* /*
* Reserve the device. * Reserve the device.
*/ */
int int disk_reserve(char *device)
disk_reserve (char* device)
{ {
int fd; int rc;
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
/* Reserve device */ /* Reserve device */
printf ("Reserving device <%s>...\n", device); printf ("Reserving device <%s>...\n", device);
if (ioctl (fd, BIODASDRSRV)) { rc = dasd_disk_reserve(device);
error_print ("Could not reserve device <%s>", device); if (rc) {
close (fd); error_print("Could not reserve device <%s>", device);
return -1; return -1;
} }
printf ("Done.\n"); printf("Done.\n");
close (fd);
return 0; return 0;
} }
@@ -345,28 +227,18 @@ disk_reserve (char* device)
/* /*
* Release the device. * Release the device.
*/ */
int int disk_release(char *device)
disk_release (char* device)
{ {
int fd; int rc;
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
/* Release device */
printf ("Releasing device <%s>...\n", device); printf ("Releasing device <%s>...\n", device);
if (ioctl (fd, BIODASDRLSE)) { rc = dasd_disk_release(device);
error_print ("Could not release device <%s>", device); if (rc) {
close (fd); error_print("Could not release device <%s>", device);
return -1; return -1;
} }
printf ("Done.\n"); printf("Done.\n");
close (fd);
return 0; return 0;
} }
@@ -376,29 +248,19 @@ disk_release (char* device)
* This means to reserve the device even if it was already reserved. * This means to reserve the device even if it was already reserved.
* The current reserve is broken (steal lock). * The current reserve is broken (steal lock).
*/ */
int int disk_slock(char *device)
disk_slock (char* device)
{ {
int fd; int rc;
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
/* Unconditional reserve device */ /* Unconditional reserve device */
printf ("Unconditional reserving device <%s>...\n", device); printf ("Unconditional reserving device <%s>...\n", device);
if (ioctl (fd, BIODASDSLCK)) { rc = dasd_slock(device);
error_print ("Could not unconditional reserve device <%s>", if (rc) {
device); error_print("Could not unconditional reserve device <%s>", device);
close (fd);
return -1; return -1;
} }
printf ("Done.\n"); printf ("Done.\n");
close (fd);
return 0; return 0;
} }
@@ -407,27 +269,16 @@ disk_slock (char* device)
* Uses the Sense Path Group ID (SNID) ioctl to find out if * Uses the Sense Path Group ID (SNID) ioctl to find out if
* a device is reserved to it's path group. * a device is reserved to it's path group.
*/ */
int int disk_query_reserve_status(char *device)
disk_query_reserve_status(char* device)
{ {
int fd; int rc;
struct dasd_snid_ioctl_data snid;
/* Open device file */ rc = dasd_query_reserve(device);
fd = open (device, O_RDONLY); if (rc < 0) {
if (fd == -1) { error_print("Could not read reserve status for device <%s>", device);
error_print ("<%s> - %s", device, strerror (errno));
return -1; return -1;
} }
snid.path_mask = 0; switch (rc) {
/* Release device */
if (ioctl(fd, BIODASDSNID, &snid)) {
error_print("Could not read reserve status"
" for device <%s>", device);
close (fd);
return -1;
}
switch (snid.data.path_state.reserve) {
case 0: case 0:
printf("none\n"); printf("none\n");
break; break;
@@ -441,7 +292,7 @@ disk_query_reserve_status(char* device)
printf("reserved\n"); printf("reserved\n");
break; break;
} }
close (fd);
return 0; return 0;
} }
@@ -615,21 +466,14 @@ static int disk_profile_item(dasd_profile_info_t dasd_profile_info,
/* /*
* Get and print the profiling info of the device. * Get and print the profiling info of the device.
*/ */
int int disk_profile(char *device, char *prof_item)
disk_profile (char* device, char* prof_item)
{ {
int fd, rc;
dasd_profile_info_t dasd_profile_info; dasd_profile_info_t dasd_profile_info;
int rc;
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
/* Get the profile info */ /* Get the profile info */
if (ioctl (fd, BIODASDPRRD, &dasd_profile_info)) { rc = dasd_profile(device, &dasd_profile_info);
if (rc) {
switch (errno) { switch (errno) {
case EIO: /* profiling is not active */ case EIO: /* profiling is not active */
error_print ("Profiling (on device <%s>) is not " error_print ("Profiling (on device <%s>) is not "
@@ -639,7 +483,6 @@ disk_profile (char* device, char* prof_item)
error_print ("Could not get profile info for device " error_print ("Could not get profile info for device "
"<%s>.", device); "<%s>.", device);
} }
close (fd);
return -1; return -1;
} }
/* Check for profile item or summary */ /* Check for profile item or summary */
@@ -649,37 +492,25 @@ disk_profile (char* device, char* prof_item)
rc = disk_profile_item (dasd_profile_info, prof_item); rc = disk_profile_item (dasd_profile_info, prof_item);
} }
close (fd);
return rc; return rc;
} }
/* /*
* Reset the profiling counters of the device. * Reset the profiling counters of the device.
*/ */
int int disk_reset_prof(char *device)
disk_reset_prof (char* device)
{ {
int fd; int rc;
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
/* reset profile info */ /* reset profile info */
printf ("Resetting profile info for device <%s>...\n", device); printf ("Resetting profile info for device <%s>...\n", device);
if (ioctl (fd, BIODASDPRRST)) { rc = dasd_reset_profile(device);
error_print ("Could not reset profile info for device <%s>", if (rc) {
device); error_print("Could not reset profile info for device <%s>", device);
close (fd);
return -1; return -1;
} }
printf ("Done.\n"); printf ("Done.\n");
close (fd);
return 0; return 0;
} }
@@ -717,3 +548,50 @@ int disk_reset_chpid(char *device, char *chpid)
return -1; return -1;
} }
int disk_copy_swap(char *device, char *copy_pair)
{
struct dasd_copypair_swap_data data = { 0 };
char *primary, *secondary;
int rc = 0;
primary = strtok(copy_pair, ",");
secondary = strtok(NULL, ",");
if (!primary || !secondary) {
error_print("%s: Error parsing Copy Pair %s", device, copy_pair);
return -1;
}
util_strlcpy(data.primary, primary, DASD_BUS_ID_SIZE);
util_strlcpy(data.secondary, secondary, DASD_BUS_ID_SIZE);
printf("Swapping copy pair %s %s on device <%s>...\n", primary, secondary, device);
rc = dasd_copy_swap(device, &data);
switch (rc) {
case 0:
printf("Done.\n");
return 0;
case 1:
error_print("Swap data invalid");
break;
case 2:
error_print("No active device found");
break;
case 3:
error_print("Wrong primary device specified");
break;
case 4:
error_print("Secondary device not found");
break;
case 5:
error_print("Swap already running");
break;
default:
error_print("Swap not successful rc %d", rc);
break;
}
return -1;
}
+35 -22
View File
@@ -119,12 +119,17 @@ static struct util_opt opt_vec[] = {
.desc = "Reset all channel paths of a device", .desc = "Reset all channel paths of a device",
.flags = UTIL_OPT_FLAG_NOSHORT, .flags = UTIL_OPT_FLAG_NOSHORT,
}, },
{
.option = { "copy-pair-swap", required_argument, NULL, 's' },
.argument = "COPY_PAIR",
.desc = "Swap a specified, comma separated copy pair.",
},
UTIL_OPT_HELP, UTIL_OPT_HELP,
UTIL_OPT_VERSION, UTIL_OPT_VERSION,
UTIL_OPT_END UTIL_OPT_END
}; };
#define CMD_KEYWORD_NUM 16 #define CMD_KEYWORD_NUM 17
#define DEVICES_NUM 256 #define DEVICES_NUM 256
enum cmd_keyword_id { enum cmd_keyword_id {
@@ -144,6 +149,7 @@ enum cmd_keyword_id {
cmd_keyword_path_all, cmd_keyword_path_all,
cmd_keyword_enable_stats, cmd_keyword_enable_stats,
cmd_keyword_disable_stats, cmd_keyword_disable_stats,
cmd_keyword_copy_swap,
}; };
@@ -167,7 +173,8 @@ static const struct {
{ "path_reset", cmd_keyword_path }, { "path_reset", cmd_keyword_path },
{ "path_reset_all", cmd_keyword_path_all }, { "path_reset_all", cmd_keyword_path_all },
{ "enable-stats", cmd_keyword_enable_stats }, { "enable-stats", cmd_keyword_enable_stats },
{ "disable-stats", cmd_keyword_disable_stats } { "disable-stats", cmd_keyword_disable_stats },
{ "copy-swap", cmd_keyword_copy_swap },
}; };
@@ -180,26 +187,27 @@ enum cmd_key_state {
/* Determines which combination of keywords are valid */ /* Determines which combination of keywords are valid */
static enum cmd_key_state cmd_key_table[CMD_KEYWORD_NUM][CMD_KEYWORD_NUM] = { static enum cmd_key_state cmd_key_table[CMD_KEYWORD_NUM][CMD_KEYWORD_NUM] = {
/* help vers get_ cach no_c rese rele sloc prof prof rese quer path path /* help vers get_ cach no_c rese rele sloc prof prof rese quer path path enab disa copy
* ion cach e yl rve ase k ile _ite t_pr y_re _all * ion cach e yl rve ase k ile _ite t_pr y_re _all le-s ble- -swa
* e m of serv * e m of serv tats stat p
*/ */
/* help */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt, inv, inv, inv, inv, inv }, /* help */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt, inv, inv, inv, inv, inv, inv },
/* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, /* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, /* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, /* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, /* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv }, /* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv }, /* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv }, /* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv, inv, inv, inv, inv }, /* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv, inv, inv, inv, inv, inv },
/* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv, inv, inv, inv, inv }, /* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv, inv, inv, inv, inv, inv },
/* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv }, /* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv },
/* query_reserve */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv }, /* query_reserve */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv },
/* path */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv }, /* path */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv },
/* path_all */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv }, /* path_all */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv },
/* enable-stats */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv }, /* enable-stats */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv },
/* disable-stats */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req }, /* disable-stats */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv },
/* copy-swap */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req },
}; };
struct parameter { struct parameter {
@@ -439,7 +447,9 @@ static int get_command_line(int argc, char *argv[], struct command_line *line)
rc = store_option (&cmdline, cmd_keyword_query_reserve, rc = store_option (&cmdline, cmd_keyword_query_reserve,
optarg); optarg);
break; break;
case 's':
rc = store_option(&cmdline, cmd_keyword_copy_swap, optarg);
break;
case -1: case -1:
/* End of options string - start of devices list */ /* End of options string - start of devices list */
cmdline.device_id = optind; cmdline.device_id = optind;
@@ -508,6 +518,9 @@ static int do_command(char *device, struct command_line cmdline)
case cmd_keyword_path_all: case cmd_keyword_path_all:
rc = disk_reset_chpid(device, NULL); rc = disk_reset_chpid(device, NULL);
break; break;
case cmd_keyword_copy_swap:
rc = disk_copy_swap(device, cmdline.parm[cmd_keyword_copy_swap].data);
break;
default: default:
error_print ("Unknown command '%s' specified", error_print ("Unknown command '%s' specified",
get_keyword_name (i)); get_keyword_name (i));
+141 -17
View File
@@ -35,6 +35,8 @@ function PrintUsage() {
Print extended information about DASDs. Print extended information about DASDs.
-H|--host-access-list -H|--host-access-list
Print information about hosts accessing DASDs. Print information about hosts accessing DASDs.
-P|--copy-pairs
Print information about copy pairs.
-v|--verbose -v|--verbose
For compatibility/future use. Currently ignored. For compatibility/future use. Currently ignored.
--version --version
@@ -146,6 +148,62 @@ function findDASDDebugfsDirectorie() {
fi fi
} }
#------------------------------------------------------------------------------
# The blockpath can usually be found over the DEVPATH
# In case of a swapped Copy Pair device the blockdev is likely associated
# with one of the secondary devices
# this function checks if the blockdev is associated with the primary device
# and if not search for it in the secondary device list
#------------------------------------------------------------------------------
function setCorrectBlockPath() {
local DRIVERECKD="$SYSFSDIR/bus/ccw/drivers/dasd-eckd/"
local DRIVERFBA="$SYSFSDIR/bus/ccw/drivers/dasd-fba/"
local SEARCHDIRS=
local SEARCHLIST=
if [[ "$COPYROLE" == "none" ]] || [[ -d "$DEVPATH/block" ]]; then
BLOCKPATH="$DEVPATH"/block/dasd*
return
fi
if [[ -d "$DRIVERECKD" ]]; then
SEARCHDIRS="$DRIVERECKD"
fi
if [[ -d "$DRIVERFBA" ]]; then
SEARCHDIRS="$SEARCHDIRS $DRIVERFBA"
fi
SEARCHLIST=$(echo $SECONDARY_LIST | sed 's/,/ /g')
for SEARCHDEV in $SEARCHLIST
do
if [[ -n "$SEARCHDIRS" ]]; then
PRIM_DEVPATH=$(find $SEARCHDIRS -type l -name $SEARCHDEV \
-printf "%h/%l\n" 2> /dev/null)
if [[ -d "$PRIM_DEVPATH/block" ]]; then
break
fi
else
# The above paths may become invalid in the future, so we keep the
# following query as backup:
PRIM_DEVPATH=$(find "$SYSFSDIR/devices" -type l -name $SEARCHDEV \
"driver" -lname "*/dasd*" -printf "%h\n" \
2> /dev/null)
fi
done
BLOCKPATH="$PRIM_DEVPATH"/block/dasd*
}
#------------------------------------------------------------------------------
# gather Copy Pair related data
#------------------------------------------------------------------------------
function gatherCopyPairData() {
read COPYPAIR 2> /dev/null < $DEVPATH/copy_pair
PRIMARY_UID=`echo $COPYPAIR | cut -d " " -f1 | cut -d "," -f1`
COPYPAIR=`echo "$COPYPAIR" | sed 's/ /,/g' | sed 's/^,//' `
SECONDARY_LIST=`echo ${COPYPAIR//$PRIMARY_UID","/} `
}
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# gather device data and call appropriate output function # gather device data and call appropriate output function
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
@@ -165,16 +223,18 @@ function gatherDeviceData() {
read READONLY 2> /dev/null < $DEVPATH/readonly || continue read READONLY 2> /dev/null < $DEVPATH/readonly || continue
read DISCIPLINE 2> /dev/null < $DEVPATH/discipline || continue read DISCIPLINE 2> /dev/null < $DEVPATH/discipline || continue
read ESE 2> /dev/null < $DEVPATH/ese read ESE 2> /dev/null < $DEVPATH/ese
read COPYROLE 2> /dev/null < $DEVPATH/copy_role
if [[ "$COPYROLE" != "none" ]]; then
gatherCopyPairData
fi
# Block device specific information is only available for # Block device specific information is only available for
# devices that are online and not a PAV alias # devices that are online and not a PAV alias
if [[ ! "$ONLINE" == 0 ]] && [[ ! "$ALIAS" == 1 ]]; then if [[ ! "$ONLINE" == 0 ]] && [[ ! "$ALIAS" == 1 ]] &&
#find device Path to the block device [[ ! "$COPYROLE" == "secondary" ]]; then
if [[ -d "$DEVPATH/block" ]]; then #find device Path to the block device
set - "$DEVPATH"/block/dasd* setCorrectBlockPath
else set - $BLOCKPATH
set - "$DEVPATH"/block:dasd*
fi
MAJMIN= MAJMIN=
MAJOR= MAJOR=
MINOR= MINOR=
@@ -194,10 +254,12 @@ function gatherDeviceData() {
fi fi
fi fi
else else
# BLOCKNAME for offline and alias devices will not be # BLOCKNAME for offline, alias and secondary devices
# printed, it's just a key for sorting # will not be printed, it's just a key for sorting
if [[ "$ONLINE" == 0 ]]; then if [[ "$ONLINE" == 0 ]]; then
BLOCKNAME="" BLOCKNAME=""
elif [[ "$COPYROLE" == "secondary" ]]; then
BLOCKNAME="b"
else else
BLOCKNAME="a" BLOCKNAME="a"
fi fi
@@ -232,6 +294,8 @@ function gatherDeviceData() {
uid uid
elif [[ "$OUTPUT" == "host" ]]; then elif [[ "$OUTPUT" == "host" ]]; then
host host
elif [[ "$OUTPUT" == "copy" ]]; then
copy
else else
newoutput newoutput
fi fi
@@ -261,6 +325,15 @@ function newoutput()
return return
fi fi
if [[ "$COPYROLE" == "secondary" ]]; then
printf "%s:%s:%-8s secondary %-8s %13s\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$PRIMARY_BLOCKNAME" \
"$DISCIPLINE"
return
fi
if [[ "$READONLY" == 0 ]]; then if [[ "$READONLY" == 0 ]]; then
ROSTRING="" ROSTRING=""
else else
@@ -519,10 +592,14 @@ function extended()
"${HPF_PATHS[@]}" \ "${HPF_PATHS[@]}" \
"${IFCC_PATHS[@]}" ; "${IFCC_PATHS[@]}" ;
return return
elif [[ "$ALIAS" == 1 ]]; then elif [[ "$ALIAS" == 1 ]] || [[ "$COPYROLE" == "secondary" ]]; then
if [[ "$BASEONLY" == "false" ]]; then if [[ "$BASEONLY" == "false" ]] || [[ "$COPYROLE" == "secondary" ]]; then
ACTIVE="alias" if [[ "$COPYROLE" == "secondary" ]]; then
printf "%s:%s:%s# status:\t\t\t\t%s# type: \t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s # uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \ ACTIVE="secondary"
else
ACTIVE="alias"
fi
printf "%s:%s:%s# status:\t\t\t\t%s# type: \t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s # uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s# copy_pairs:\t\t\t\t%s#\n" \
"$SORTKEYLEN" "$SORTKEY" \ "$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \ "$BUSID" \
"$ACTIVE" \ "$ACTIVE" \
@@ -540,7 +617,8 @@ function extended()
"${CABLE_PATHS[@]}" \ "${CABLE_PATHS[@]}" \
"${CUIR_PATHS[@]}" \ "${CUIR_PATHS[@]}" \
"${HPF_PATHS[@]}" \ "${HPF_PATHS[@]}" \
"${IFCC_PATHS[@]}" ; "${IFCC_PATHS[@]}" \
"${COPYPAIR}" ;
fi fi
return return
elif [[ -z "$BLOCKNAME" ]] || [[ -z "$SIZE" ]]; then elif [[ -z "$BLOCKNAME" ]] || [[ -z "$SIZE" ]]; then
@@ -565,7 +643,7 @@ function extended()
DISCIPLINE="${DISCIPLINE} (ESE)" DISCIPLINE="${DISCIPLINE} (ESE)"
fi fi
printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# extent_size:\t\t\t\t%s# logical_capacity:\t\t\t%s# space_allocated:\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \ printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# extent_size:\t\t\t\t%s# logical_capacity:\t\t\t%s# space_allocated:\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s# copy_pairs:\t\t\t\t%s#\n" \
"$SORTKEYLEN" "$SORTKEY" \ "$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \ "$BUSID" \
"$BLOCKNAME" \ "$BLOCKNAME" \
@@ -593,7 +671,8 @@ function extended()
"${CABLE_PATHS[@]}" \ "${CABLE_PATHS[@]}" \
"${CUIR_PATHS[@]}" \ "${CUIR_PATHS[@]}" \
"${HPF_PATHS[@]}" \ "${HPF_PATHS[@]}" \
"${IFCC_PATHS[@]}" ; "${IFCC_PATHS[@]}" \
"${COPYPAIR}" ;
} }
function host() function host()
@@ -694,6 +773,41 @@ printf "\n";
rm -f $temp rm -f $temp
} }
# pad sortkey with given number zeroes
function padSortKey()
{
local LEN=$1
for (( i=0; i<$LEN; i++ ))
do
printf -v SORTKEY "%s0" $SORTKEY
done
}
function copy()
{
if [[ "$COPYROLE" == "none" ]]; then
return
fi
SORTKEYLEN=$((${#PRIMARY_UID}+${#DEV_UID}))
if [[ "$COPYROLE" == "secondary" ]]; then
SORTKEY=$PRIMARY_UID$DEV_UID
PAIREDDEVICES=$PRIMARY_UID
BLOCKNAME=""
else
SORTKEY=$PRIMARY_UID
padSortKey ${#DEV_UID}
PAIREDDEVICES=$SECONDARY_LIST
fi
printf "%s:%s:%-8s %-10s %-8s %-8s %s \n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$COPYROLE" \
"$BLOCKNAME" \
"$PAIREDDEVICES";
}
function uid() function uid()
{ {
#-------------------------------------------# #-------------------------------------------#
@@ -710,7 +824,11 @@ function uid()
fi fi
fi fi
printf "%s:%s:%-8s %-8s %s\n" \ if [[ "$COPYROLE" == "secondary" ]]; then
BLOCKNAME="secondary"
fi
printf "%s:%s:%-8s %-10s %s\n" \
"$SORTKEYLEN" "$SORTKEY" \ "$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \ "$BUSID" \
"$BLOCKNAME" \ "$BLOCKNAME" \
@@ -756,6 +874,9 @@ while [ $# -gt 0 ]; do
--host-access-list|-H) --host-access-list|-H)
OUTPUT="host" OUTPUT="host"
;; ;;
--copy-pairs|-P)
OUTPUT="copy"
;;
--version) --version)
PrintVersion PrintVersion
exit 0 exit 0
@@ -810,6 +931,9 @@ if [[ "$PRINTUID" == "true" ]] && [[ "$OUTPUT" != "old" ]]; then
elif [[ "$OUTPUT" == "new" ]]; then elif [[ "$OUTPUT" == "new" ]]; then
printf "Bus-ID Status Name Device Type BlkSz Size Blocks\n" printf "Bus-ID Status Name Device Type BlkSz Size Blocks\n"
printf "================================================================================\n" printf "================================================================================\n"
elif [[ "$OUTPUT" == "copy" ]]; then
printf "Bus-ID Role Name Paired devices\n";
printf "================================================================================\n";
elif [[ "$OUTPUT" == "extended" ]]; then elif [[ "$OUTPUT" == "extended" ]]; then
PROCESSING=" $PROCESSING | sed 's/#/\n/g' " PROCESSING=" $PROCESSING | sed 's/#/\n/g' "
fi fi
+1 -1
View File
@@ -66,7 +66,7 @@ typedef char *(*table_value_cb_t)(void *item, int id, const char *heading,
struct column *table_get_column(struct column *, const char *); struct column *table_get_column(struct column *, const char *);
exit_code_t table_print(struct column *, table_value_cb_t, void *, exit_code_t table_print(struct column *, table_value_cb_t, void *,
struct util_list *, struct util_list *, int, int, int, struct util_list *, struct util_list *, int, int, int,
int); int, int);
exit_code_t table_check_columns(struct column *, struct util_list *); exit_code_t table_check_columns(struct column *, struct util_list *);
void table_print_columns(struct column *, struct util_list *, int, int); void table_print_columns(struct column *, struct util_list *, int, int);
void table_set_default(struct column *, int, int); void table_set_default(struct column *, int, int);
+1 -1
View File
@@ -23,7 +23,7 @@ struct table_attrib {
}; };
struct table_attrib *table_attrib_new(struct subtype *, struct attrib *); struct table_attrib *table_attrib_new(struct subtype *, struct attrib *);
void table_attribs_show(struct util_list *, int, int, struct devtype *); void table_attribs_show(struct util_list *, int, int, int, struct devtype *);
void table_attribs_show_details(struct util_list *, struct devtype *); void table_attribs_show_details(struct util_list *, struct devtype *);
#endif /* TABLE_ATTRIBS_H */ #endif /* TABLE_ATTRIBS_H */
+11
View File
@@ -423,6 +423,17 @@ with the name of the corresponding column. Values are enclosed in double
quotation marks. Any quotation marks or slashes in the value string are quotation marks. Any quotation marks or slashes in the value string are
escaped by placing a slash in front of it. escaped by placing a slash in front of it.
.PP .PP
.OD shell "" ""
Produces KEY="VALUE" format usable as shell variables.
You can use this option together with the --pairs option to generate
output that is suitable to be sourced in a shell environment. This
option generates similar output as it would be provided by the --pairs
option but it would take care of replacing any character of a column
name that would not be appropriate to be used as part of a shell
variable name by an underscore.
.PP
. .
.OD persistent "p" "" .OD persistent "p" ""
List information from the persistent configuration only. List information from the persistent configuration only.
+1 -1
View File
@@ -2532,7 +2532,7 @@ static exit_code_t do_list_attribs(struct options *opts)
remove_duplicate_attribs(attribs, devtype_count_subtypes(dt)); remove_duplicate_attribs(attribs, devtype_count_subtypes(dt));
if (attribs) { if (attribs) {
table_attribs_show(attribs, 1, 0, dt); table_attribs_show(attribs, 1, 0, 0, dt);
ptrlist_free(attribs, 1); ptrlist_free(attribs, 1);
} else } else
rc = EXIT_ATTRIB_NOT_FOUND; rc = EXIT_ATTRIB_NOT_FOUND;
+93
View File
@@ -137,6 +137,21 @@ static struct attrib dasd_attr_readonly = {
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)), .accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
}; };
static struct attrib dasd_attr_copy_pair = {
.name = "copy_pair",
.title = "Modify copy-pair relations",
.desc = "Make a copy-pair relation for this device known to the DASD "
"driver.\n"
"A copy-pair is a comma-separated pair of device bus-IDs\n"
"<primary>,<secondary>.\n"
"Example: 0.0.1000,0.0.2000\n"
"Up to 4 copy-pairs are accepted by the DASD driver for each "
"device.\n",
.unstable = 1,
.multi = 1,
.activerem = 1,
};
static struct attrib dasd_attr_erplog = { static struct attrib dasd_attr_erplog = {
.name = "erplog", .name = "erplog",
.title = "Enable logging of Error Recovery Processing", .title = "Enable logging of Error Recovery Processing",
@@ -600,6 +615,81 @@ persistent:
return rc; return rc;
} }
/* Remove all entries from the copy_pair attribute by writing 'clear' to it. */
static void dasd_clear_copy_pair(struct setting *s)
{
free(s->value);
s->value = misc_strdup("clear");
strlist_free(s->values);
s->values = strlist_new();
strlist_add(s->values, "clear");
s->removed = 0;
s->modified = 1;
}
/*
* Copy-pair values may contain multiple values in one line
* those need to be split up and put in multiple values entries
* delimiter is " " and "\n" depending on the source
* values read from sysfs have " " as delimiter and values from
* zdev have "\n"
*/
static void dasd_split_copy_pair(struct setting *s)
{
struct util_list *new = NULL;
struct strlist_node *node;
new = strlist_new();
util_list_iterate(s->values, node)
strlist_add_multi(new, node->str, "\n ", 0);
strlist_free(s->values);
s->values = new;
}
/*
* For persistent configurations one value per values[] entry is required
* to achieve a correct multi-line copy-pair statement in the resulting
* udev-rule.
*/
static exit_code_t dasd_st_configure_persistent(struct subtype *st,
struct device *dev)
{
struct setting *s;
util_list_iterate(&dev->persistent.settings->list, s) {
if (strcmp(s->name, "copy_pair") == 0)
dasd_split_copy_pair(s);
}
return st->super->configure_persistent(st, dev);
}
/*
* For active configurations one value per values[] entry is required to
* correctly operate the sysfs attribute.
*
* In case of removal the string "clear" has to be written to the
* value and values[] entry.
*/
static exit_code_t dasd_st_configure_active(struct subtype *st,
struct device *dev)
{
struct setting *s;
util_list_iterate(&dev->active.settings->list, s) {
if (strcmp(s->name, "copy_pair") != 0)
continue;
if (s->removed)
dasd_clear_copy_pair(s);
else
dasd_split_copy_pair(s);
}
return st->super->configure_active(st, dev);
}
/* /*
* DASD device sub-types. * DASD device sub-types.
*/ */
@@ -634,10 +724,13 @@ struct subtype dasd_subtype_eckd = {
&dasd_attr_last_known_reservation_state, &dasd_attr_last_known_reservation_state,
&dasd_attr_safe_offline, &dasd_attr_safe_offline,
&dasd_attr_fc_security, &dasd_attr_fc_security,
&dasd_attr_copy_pair,
&internal_attr_early, &internal_attr_early,
), ),
.unknown_dev_attribs = 1, .unknown_dev_attribs = 1,
.configure_active = &dasd_st_configure_active,
.configure_persistent = &dasd_st_configure_persistent,
.check_pre_configure = &dasd_st_check_pre_configure, .check_pre_configure = &dasd_st_check_pre_configure,
.add_modules = &dasd_st_add_modules, .add_modules = &dasd_st_add_modules,
}; };
+17 -2
View File
@@ -70,6 +70,7 @@ struct options {
unsigned int no_headings:1; unsigned int no_headings:1;
struct util_list *base; /* List of struct strlist_node */ struct util_list *base; /* List of struct strlist_node */
unsigned int pairs:1; unsigned int pairs:1;
unsigned int shell:1;
unsigned int verbose:1; unsigned int verbose:1;
unsigned int quiet:1; unsigned int quiet:1;
unsigned int site_id; unsigned int site_id;
@@ -106,6 +107,7 @@ enum {
OPT_VERBOSE = 'V', OPT_VERBOSE = 'V',
OPT_QUIET = 'q', OPT_QUIET = 'q',
OPT_PAIRS = 'P', OPT_PAIRS = 'P',
OPT_SHELL = (OPT_ANONYMOUS_BASE+__COUNTER__),
OPT_AUTO_CONF = (OPT_ANONYMOUS_BASE+__COUNTER__), OPT_AUTO_CONF = (OPT_ANONYMOUS_BASE+__COUNTER__),
OPT_SITE = 's', OPT_SITE = 's',
}; };
@@ -167,6 +169,7 @@ static const struct option opt_list[] = {
{ "no-headings", no_argument, NULL, OPT_NO_HEADINGS }, { "no-headings", no_argument, NULL, OPT_NO_HEADINGS },
{ "base", required_argument, NULL, OPT_BASE }, { "base", required_argument, NULL, OPT_BASE },
{ "pairs", no_argument, NULL, OPT_PAIRS }, { "pairs", no_argument, NULL, OPT_PAIRS },
{ "shell", no_argument, NULL, OPT_SHELL },
{ "verbose", no_argument, NULL, OPT_VERBOSE }, { "verbose", no_argument, NULL, OPT_VERBOSE },
{ "quiet", no_argument, NULL, OPT_QUIET }, { "quiet", no_argument, NULL, OPT_QUIET },
{ "site", required_argument, NULL, OPT_SITE }, { "site", required_argument, NULL, OPT_SITE },
@@ -699,6 +702,11 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[])
opts->pairs = 1; opts->pairs = 1;
break; break;
case OPT_SHELL:
/* --shell */
opts->shell = 1;
break;
case OPT_VERBOSE: case OPT_VERBOSE:
/* --verbose */ /* --verbose */
opts->verbose = 1; opts->verbose = 1;
@@ -761,6 +769,13 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[])
if (rc) if (rc)
goto out; goto out;
/* check whether --pairs and --columns is used */
if (opts->shell == 1 && (opts->pairs != 1 || util_list_is_empty(opts->columns))) {
syntax("'--shell' must be used together with "
"'--pairs' and '--columns'\n");
return EXIT_USAGE_ERROR;
}
/* Determine configuration set. */ /* Determine configuration set. */
if (!opts->active && !opts->persistent && !opts->auto_conf) { if (!opts->active && !opts->persistent && !opts->auto_conf) {
/* Default display targets are active + persistent - note that /* Default display targets are active + persistent - note that
@@ -1209,7 +1224,7 @@ static exit_code_t do_list_devices(struct options *opts)
/* Display table. */ /* Display table. */
rc = table_print(dev_table, dev_table_get_value, opts, items, rc = table_print(dev_table, dev_table_get_value, opts, items,
opts->columns, !opts->no_headings, opts->pairs, 0, opts->columns, !opts->no_headings, opts->pairs, 0,
util_list_is_empty(opts->columns)); util_list_is_empty(opts->columns), opts->shell);
ptrlist_free(items, 0); ptrlist_free(items, 0);
return rc; return rc;
@@ -1443,7 +1458,7 @@ static void settings_table_print(struct setting_list *active,
data.pairs = opts->pairs; data.pairs = opts->pairs;
table_print(settings_table, settings_table_get_value, &data, items, table_print(settings_table, settings_table_get_value, &data, items,
NULL, 1, opts->pairs, ind, 0); NULL, 1, opts->pairs, ind, 0, opts->shell);
out: out:
ptrlist_free(items, 1); ptrlist_free(items, 1);
+1
View File
@@ -41,6 +41,7 @@ OPTIONS
-n, --no-headings Do not print column headings -n, --no-headings Do not print column headings
--base PATH Use PATH as base for accessing files --base PATH Use PATH as base for accessing files
--pairs Produce output in KEY="VALUE" format --pairs Produce output in KEY="VALUE" format
--shell Produces KEY="VALUE" format usable as shell variables
--auto-conf Only show auto-configuration data --auto-conf Only show auto-configuration data
-s, --site ID Only show data configured for the specified site -s, --site ID Only show data configured for the specified site
-V, --verbose Print additional run-time information -V, --verbose Print additional run-time information
+46 -5
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 <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -116,6 +117,40 @@ static struct cell *cells_get_default(struct column *columns)
return cells; return cells;
} }
bool is_shell_char(const char c)
{
/* check whether character is alphabetic */
if (tolower(c) >= 'a' && tolower(c) <= 'z')
return true;
if (isdigit(c) || c == '_')
return true;
return false;
}
/* replaces bad characters that won't work if using them
* as part of variable names in a shell environment
*/
char *replace_bad_chars(const char *value)
{
int i;
char *copy, c;
/* remove bad characters and replace them by an underscore */
copy = misc_strdup(value);
for (i = 0; (c = value[i]); i++) {
/*
* check whether character is alphabetic,
* first character of an env var can't be a digit
*/
if (!is_shell_char(c) || (i == 0 && isdigit(c)))
c = '_';
/* copy character into string copy */
copy[i] = c;
}
return copy;
}
/* Return a newly allocated array of struct cells containing a struct cell for /* Return a newly allocated array of struct cells containing a struct cell for
* each column definition whose name was specified in strlist @names. */ * each column definition whose name was specified in strlist @names. */
static struct cell *cells_get(struct column *columns, struct util_list *names) static struct cell *cells_get(struct column *columns, struct util_list *names)
@@ -320,17 +355,23 @@ do_print:
} }
/* Print all cells in a row in pairs format. */ /* Print all cells in a row in pairs format. */
static void print_row_pairs(struct cell *cells) static void print_row_pairs(struct cell *cells, int shell)
{ {
int i; int i;
struct cell *c; struct cell *c;
char *val; char *val;
char *heading;
for (i = 0; cells[i].heading; i++) { for (i = 0; cells[i].heading; i++) {
c = &cells[i]; c = &cells[i];
val = quote_str(c->value ? c->value : "", 1); val = quote_str(c->value ? c->value : "", 1);
printf("%s%s=%s", i > 0 ? " " : "", c->heading, val); if (shell)
heading = replace_bad_chars(c->heading);
else
heading = misc_strdup(c->heading);
printf("%s%s=%s", i > 0 ? " " : "", heading, val);
free(val); free(val);
free(heading);
} }
printf("\n"); printf("\n");
} }
@@ -342,7 +383,7 @@ static void print_row_pairs(struct cell *cells)
exit_code_t table_print(struct column *columns, table_value_cb_t get_value_cb, exit_code_t table_print(struct column *columns, table_value_cb_t get_value_cb,
void *data, struct util_list *items, void *data, struct util_list *items,
struct util_list *names, int heading, int pairs, struct util_list *names, int heading, int pairs,
int indent, int wrap) int indent, int wrap, int shell)
{ {
struct cell *cells; struct cell *cells;
struct ptrlist_node *p; struct ptrlist_node *p;
@@ -372,7 +413,7 @@ exit_code_t table_print(struct column *columns, table_value_cb_t get_value_cb,
util_list_iterate(items, p) { util_list_iterate(items, p) {
cells_get_values(cells, p->ptr, get_value_cb, data); cells_get_values(cells, p->ptr, get_value_cb, data);
if (pairs) if (pairs)
print_row_pairs(cells); print_row_pairs(cells, shell);
else else
print_row(cells, space, indent, wrap); print_row(cells, space, indent, wrap);
} }
@@ -434,7 +475,7 @@ void table_print_columns(struct column *columns, struct util_list *names,
for (i = 0; columns[i].name; i++) for (i = 0; columns[i].name; i++)
ptrlist_add(items, &columns[i]); ptrlist_add(items, &columns[i]);
table_print(columns_table, columns_table_get_value, NULL, items, names, table_print(columns_table, columns_table_get_value, NULL, items, names,
heading, pairs, 0, 0); heading, pairs, 0, 0, 0);
ptrlist_free(items, 0); ptrlist_free(items, 0);
} }
+2 -2
View File
@@ -115,7 +115,7 @@ void print_type(struct devtype *dt, struct subtype *st, bool multiple)
/* Display table of attributes. */ /* Display table of attributes. */
void table_attribs_show(struct util_list *attribs, int headings, int pairs, void table_attribs_show(struct util_list *attribs, int headings, int pairs,
struct devtype *dt) int shell, struct devtype *dt)
{ {
struct util_list *subtypes, *subattribs; struct util_list *subtypes, *subattribs;
struct ptrlist_node *p; struct ptrlist_node *p;
@@ -145,7 +145,7 @@ void table_attribs_show(struct util_list *attribs, int headings, int pairs,
print_type(dt, st, multiple); print_type(dt, st, multiple);
table_print(table_attribs, table_attribs_get_value, st, table_print(table_attribs, table_attribs_get_value, st,
subattribs, NULL, headings, pairs, indent, 0); subattribs, NULL, headings, pairs, shell, indent, 0);
ptrlist_free(subattribs, 0); ptrlist_free(subattribs, 0);
} }
+1 -1
View File
@@ -83,7 +83,7 @@ exit_code_t table_types_show(struct util_list *columns, int headings, int pairs)
items = table_types_build(); items = table_types_build();
rc = table_print(table_types, table_types_get_value, NULL, rc = table_print(table_types, table_types_get_value, NULL,
items, columns, headings, pairs, 0, 0); items, columns, headings, pairs, 0, 0, 0);
ptrlist_free(items, 1); ptrlist_free(items, 1);
return rc; return rc;
+8 -2
View File
@@ -221,6 +221,7 @@ static void write_attr_to_file(FILE *fd, struct device_state *state, const char
struct ptrlist_node *p; struct ptrlist_node *p;
struct setting *s; struct setting *s;
struct util_list *list = NULL; struct util_list *list = NULL;
struct strlist_node *str;
/* Apply attributes in correct order. */ /* Apply attributes in correct order. */
list = setting_list_get_sorted(state->settings); list = setting_list_get_sorted(state->settings);
@@ -229,8 +230,13 @@ static void write_attr_to_file(FILE *fd, struct device_state *state, const char
s = p->ptr; s = p->ptr;
if (s->removed) if (s->removed)
continue; continue;
if ((s->attrib && s->attrib->internal) || if (s->values) {
internal_by_name(s->name)) { util_list_iterate(s->values, str) {
fprintf(fd, "ATTR{[ccw/%s]%s}=\"%s\"\n",
id, s->name, str->str);
}
} else if ((s->attrib && s->attrib->internal) ||
internal_by_name(s->name)) {
fprintf(fd, "ENV{zdev_%s}=\"%s\"\n", fprintf(fd, "ENV{zdev_%s}=\"%s\"\n",
internal_get_name(s->name), s->value); internal_get_name(s->name), s->value);
} else { } else {
+7 -6
View File
@@ -7,17 +7,18 @@ ALL_CFLAGS += -Wno-address-of-packed-member
# #
ifeq (${HAVE_FUSE},0) ifeq (${HAVE_FUSE},0)
check_dep_fuse: .check_dep_fuse:
touch $@
else else
check_dep_fuse: .check_dep_fuse:
$(call check_dep, \ $(call check_dep, \
"zgetdump mount support", \ "zgetdump mount support", \
"fuse.h", \ "fuse.h", \
"fuse3-devel or libfuse3-dev", \ "fuse3-devel or libfuse3-dev", \
"HAVE_FUSE=0", \ "HAVE_FUSE=0", \
"-DFUSE_USE_VERSION=30") "-DFUSE_USE_VERSION=30")
touch $@
endif endif
.detect_openssl.dep.c: .detect_openssl.dep.c:
@@ -30,7 +31,7 @@ endif
echo " EVP_MD_CTX_free(ctx);" >> $@ echo " EVP_MD_CTX_free(ctx);" >> $@
echo "}" >> $@ echo "}" >> $@
.check_dep_zgetdump: .detect_openssl.dep.c check_dep_fuse .check_dep_zgetdump: .detect_openssl.dep.c .check_dep_fuse
$(call check_dep, \ $(call check_dep, \
"zgetdump", \ "zgetdump", \
"zlib.h", \ "zlib.h", \
@@ -131,6 +132,6 @@ install-zgetdump: zgetdump
install: $(INSTALL_TARGETS) install: $(INSTALL_TARGETS)
clean: clean:
rm -f -- *.o *~ zgetdump core.* .detect_openssl.dep.c .check_dep_zgetdump rm -f -- *.o *~ zgetdump core.* .detect_openssl.dep.c .check_dep_zgetdump .check_dep_fuse
.PHONY: all install clean check_dep_fuse check_dep_zlib skip-zgetdump install-zgetdump .PHONY: all install clean skip-zgetdump install-zgetdump
+11 -2
View File
@@ -121,7 +121,8 @@ Elf64_Shdr *read_elf_shdrs(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, unsig
return shdrs; return shdrs;
} }
unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *shdr, size_t *size) unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *shdr, size_t *size,
const size_t max_size)
{ {
const size_t sh_size = shdr->sh_size; const size_t sh_size = shdr->sh_size;
unsigned char *ret; unsigned char *ret;
@@ -133,6 +134,9 @@ unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *s
if (shdr->sh_offset > OFF_T_MAX) if (shdr->sh_offset > OFF_T_MAX)
ERR_EXIT("Unsupported offset"); ERR_EXIT("Unsupported offset");
if (sh_size > max_size)
ERR_EXIT("Unsupported section size: %#lx > %#lx", sh_size, max_size);
ret = util_malloc(sh_size); ret = util_malloc(sh_size);
zg_seek(fh, (off_t)shdr->sh_offset, ZG_CHECK); zg_seek(fh, (off_t)shdr->sh_offset, ZG_CHECK);
zg_read(fh, ret, sh_size, ZG_CHECK); zg_read(fh, ret, sh_size, ZG_CHECK);
@@ -141,7 +145,8 @@ unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *s
} }
char *read_elf_shstrtab(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, const Elf64_Shdr *shdrs, char *read_elf_shstrtab(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, const Elf64_Shdr *shdrs,
const unsigned int shnum, size_t *shstrtab_size) const unsigned int shnum, size_t *shstrtab_size,
const size_t max_shstrtab_size)
{ {
const size_t shstrndx = ehdr->e_shstrndx; const size_t shstrndx = ehdr->e_shstrndx;
Elf64_Xword tmp_shstrtab_size; Elf64_Xword tmp_shstrtab_size;
@@ -166,6 +171,10 @@ char *read_elf_shstrtab(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, const El
ERR_EXIT("Unsupported offset"); ERR_EXIT("Unsupported offset");
tmp_shstrtab_size = shdrs[shstrndx].sh_size; tmp_shstrtab_size = shdrs[shstrndx].sh_size;
if (tmp_shstrtab_size > max_shstrtab_size)
ERR_EXIT("Unsupported shstrtab size: %#lx > %#lx", tmp_shstrtab_size,
max_shstrtab_size);
shstrtab = util_malloc(tmp_shstrtab_size); shstrtab = util_malloc(tmp_shstrtab_size);
zg_seek(fh, (off_t)shstrndx_off, ZG_CHECK); zg_seek(fh, (off_t)shstrndx_off, ZG_CHECK);
zg_read(fh, shstrtab, tmp_shstrtab_size, ZG_CHECK); zg_read(fh, shstrtab, tmp_shstrtab_size, ZG_CHECK);
+4 -2
View File
@@ -195,7 +195,8 @@ Elf64_Shdr *read_elf_shdrs(const struct zg_fh *fh, const Elf64_Ehdr *ehdr,
* *
* To read the section content the offset of @fh is changed. * To read the section content the offset of @fh is changed.
*/ */
unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *shdr, size_t *size); unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *shdr, size_t *size,
const size_t max_size);
/* /*
* Read ELF section header string table * Read ELF section header string table
@@ -203,7 +204,8 @@ unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *s
* To read the section header string table the offset of @fh is changed. * To read the section header string table the offset of @fh is changed.
*/ */
char *read_elf_shstrtab(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, const Elf64_Shdr *shdrs, char *read_elf_shstrtab(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, const Elf64_Shdr *shdrs,
const unsigned int shnum, size_t *shstrtab_size); const unsigned int shnum, size_t *shstrtab_size,
const size_t max_shstrtab_size);
/* /*
* Find ELF section header by section name * Find ELF section header by section name
+19 -9
View File
@@ -46,17 +46,19 @@ WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(Elf64_Ehdr, free);
* read_elf_section_data_as_gbytes: * read_elf_section_data_as_gbytes:
* @fh: (not nullable): open input file * @fh: (not nullable): open input file
* @shdr: (not nullable): section header of the section to read * @shdr: (not nullable): section header of the section to read
* @max_size: maximum section data size in bytes
* *
* Try to read section data and return it as #GBytes. * Try to read section data and return it as #GBytes.
* *
* Returns: #GBytes on success, %NULL if an error occurred * Returns: #GBytes on success, %NULL if an error occurred
*/ */
static GBytes *read_elf_section_data_as_gbytes(const struct zg_fh *fh, const Elf64_Shdr *shdr) static GBytes *read_elf_section_data_as_gbytes(const struct zg_fh *fh, const Elf64_Shdr *shdr,
const size_t max_size)
{ {
unsigned char *data; unsigned char *data;
size_t size; size_t size;
data = read_elf_section_data(fh, shdr, &size); data = read_elf_section_data(fh, shdr, &size, max_size);
if (!data) if (!data)
return NULL; return NULL;
return g_bytes_new_with_free_func(data, size, free, data); return g_bytes_new_with_free_func(data, size, free, data);
@@ -106,6 +108,12 @@ static dfi_cpu_t *nt_s390_pv_cpu_data_read(const struct zg_fh *fh, const Elf64_N
g_assert(dump_key); g_assert(dump_key);
if (note_descsz > PV_MAX_NT_S390_PV_CPU_DATA_SIZE) {
g_set_error(error, ZDUMP_PV_UTILS_ERROR, ZDUMP_ERR_CORRUPTED_NOTE,
_("Unable to read confidential CPU data. Dump probably corrupted."));
return NULL;
}
note_data = g_malloc(note_descsz); note_data = g_malloc(note_descsz);
if (nt_read(fh, note_hdr, note_data, note_descsz) < 0) { if (nt_read(fh, note_hdr, note_data, note_descsz) < 0) {
g_set_error(error, ZDUMP_PV_UTILS_ERROR, ZDUMP_ERR_CORRUPTED_NOTE, g_set_error(error, ZDUMP_PV_UTILS_ERROR, ZDUMP_ERR_CORRUPTED_NOTE,
@@ -164,7 +172,7 @@ static int pt_notes_add(const struct zg_fh *fh, const Elf64_Phdr *phdr, const un
dfi_cpu_add(g_steal_pointer(&cpu_current)); dfi_cpu_add(g_steal_pointer(&cpu_current));
break; break;
default: default:
util_log_print(UTIL_LOG_WARN, _("Unknown ELF-Note %#x"), note.n_type); util_log_print(UTIL_LOG_WARN, _("Unknown ELF-Note %#x\n"), note.n_type);
__attribute__((fallthrough)); __attribute__((fallthrough));
case NT_PRSTATUS: case NT_PRSTATUS:
case NT_FPREGSET: case NT_FPREGSET:
@@ -224,7 +232,7 @@ static int dfi_pv_elf_init(void)
if (!shdrs) if (!shdrs)
return -ENODEV; return -ENODEV;
shstrtab = read_elf_shstrtab(fh, ehdr, shdrs, shnum, &shstrtab_size); shstrtab = read_elf_shstrtab(fh, ehdr, shdrs, shnum, &shstrtab_size, PV_MAX_SHSTRTAB_SIZE);
if (!shstrtab) if (!shstrtab)
return -ENODEV; return -ENODEV;
@@ -255,7 +263,8 @@ static int dfi_pv_elf_init(void)
return -EINVAL; return -EINVAL;
/* Read the PV completion configuration section data */ /* Read the PV completion configuration section data */
completion_sdata = read_elf_section_data_as_gbytes(fh, completion_shdr); completion_sdata =
read_elf_section_data_as_gbytes(fh, completion_shdr, PV_MAX_COMPL_DATA_SIZE);
if (!completion_sdata) if (!completion_sdata)
return -EINVAL; return -EINVAL;
@@ -263,9 +272,9 @@ static int dfi_pv_elf_init(void)
* completion configuration data and store it in `@cpl_conf_decr`. In addition, mmap the * completion configuration data and store it in `@cpl_conf_decr`. In addition, mmap the
* configuration storage state area and use the `tweak_nonce`. * configuration storage state area and use the `tweak_nonce`.
*/ */
if (pv_process_section_data(fh->fh, completion_sdata, storage_state_shdr->sh_offset, if (pv_process_section_data(fh->fh, fh->sb.st_size, completion_sdata,
storage_state_shdr->sh_size, key, &cpl_conf_decr, &dump_key, storage_state_shdr->sh_offset, storage_state_shdr->sh_size, key,
&storage_state_data, &error) < 0) { &cpl_conf_decr, &dump_key, &storage_state_data, &error) < 0) {
ERR(_("Unable to read decryption information:" ERR_NEWLINE "%s."), error->message); ERR(_("Unable to read decryption information:" ERR_NEWLINE "%s."), error->message);
return -EINVAL; return -EINVAL;
} }
@@ -313,7 +322,8 @@ static int dfi_pv_elf_init(void)
} }
break; break;
default: default:
util_log_print(UTIL_LOG_WARN, _("Unknown ELF-PHDR type %#x"), phdr->p_type); util_log_print(UTIL_LOG_WARN, _("Unknown ELF-PHDR type %#x\n"),
phdr->p_type);
break; break;
} }
} }
+1 -1
View File
@@ -271,7 +271,7 @@ int ngdump_get_dump_part(struct zg_fh *zg_fh)
__func__, comp_entry.type, __func__, comp_entry.type,
comp_entry.compdat.load_address); comp_entry.compdat.load_address);
/* Is this a kernel image ? */ /* Is this a kernel image ? */
if (comp_entry.type == COMPONENT_LOAD && if (comp_entry.type == COMPONENT_TYPE_LOAD &&
comp_entry.compdat.load_address == IMAGE_ENTRY) comp_entry.compdat.load_address == IMAGE_ENTRY)
break; break;
} }
+10
View File
@@ -20,6 +20,16 @@
#define PV_ELF_SECTION_NAME_COMPL "pv_compl" #define PV_ELF_SECTION_NAME_COMPL "pv_compl"
#define PV_ELF_SECTION_NAME_TWEAKS "pv_mem_meta" #define PV_ELF_SECTION_NAME_TWEAKS "pv_mem_meta"
/* Maximum size (in bytes) of completion section data */
#define PV_MAX_COMPL_DATA_SIZE ROUNDUP(sizeof(pv_dump_completion_data_v1_t), PAGE_SIZE)
/* Maximum size (in bytes) of section header string table */
#define PV_MAX_SHSTRTAB_SIZE \
ROUNDUP(sizeof(PV_ELF_SECTION_NAME_COMPL) + sizeof(PV_ELF_SECTION_NAME_TWEAKS) + \
sizeof(".shstrtab"), \
PAGE_SIZE)
/* Maximum size of NT_S390_PV_CPU_DATA */
#define PV_MAX_NT_S390_PV_CPU_DATA_SIZE ROUNDUP(sizeof(pv_cpu_dump_v1_t), PAGE_SIZE)
#define PV_COMPL_DATA_VERSION_1 ((uint32_t)1) #define PV_COMPL_DATA_VERSION_1 ((uint32_t)1)
#define PV_SEC_CPU_DATA_VERSION_1 ((uint32_t)1) #define PV_SEC_CPU_DATA_VERSION_1 ((uint32_t)1)
+44 -13
View File
@@ -239,7 +239,7 @@ dfi_cpu_t *pv_decrypt_cpu_note_data(const unsigned int expected_version, GBytes
/* Check dump flags */ /* Check dump flags */
if (pv_cpu->has_osii) if (pv_cpu->has_osii)
util_log_print(UTIL_LOG_WARN, util_log_print(UTIL_LOG_WARN,
_("CPU state may contain partial instruction results")); _("CPU state may contain partial instruction results\n"));
return pv_dfi_cpu_from_pv_cpu(pv_cpu); return pv_dfi_cpu_from_pv_cpu(pv_cpu);
} }
@@ -608,14 +608,26 @@ ssize_t pv_process_pglist(pv_crypto_ctx_t *ctx, BIO *output,
return -1; return -1;
} }
} }
g_assert(!(page_state & ~PV_ZERO_PAGE)); if (page_state & ~PV_ZERO_PAGE) {
g_set_error(error, ZDUMP_PV_UTILS_ERROR,
ZDUMP_ERR_PGLIST_INVAL_STATE,
_("Invalid page state. page-idx: %#lx, state: %#lx"),
page_idx, page_state);
return -1;
}
continue; continue;
} }
if (page_state & PV_SHARED_PAGE) { if (page_state & PV_SHARED_PAGE) {
/* shared pages are not encrypted */ /* shared pages are not encrypted */
input = ctx->input; input = ctx->input;
g_assert(!(page_state & ~PV_SHARED_PAGE)); if (page_state & ~PV_SHARED_PAGE) {
g_set_error(error, ZDUMP_PV_UTILS_ERROR,
ZDUMP_ERR_PGLIST_INVAL_STATE,
_("Invalid page state. page-idx: %#lx, state: %#lx"),
page_idx, page_state);
return -1;
}
} else if (page_state & PV_ENCRYPTED_PAGE) { } else if (page_state & PV_ENCRYPTED_PAGE) {
input = ctx->filter; input = ctx->filter;
calculate_tweak(tweak_comp, ctx->nonce, &ctx->tweak_scratch); calculate_tweak(tweak_comp, ctx->nonce, &ctx->tweak_scratch);
@@ -624,7 +636,13 @@ ssize_t pv_process_pglist(pv_crypto_ctx_t *ctx, BIO *output,
if (update_tweak(ctx, error) < 0) if (update_tweak(ctx, error) < 0)
return -1; return -1;
g_assert(!(page_state & ~PV_ENCRYPTED_PAGE)); if (page_state & ~PV_ENCRYPTED_PAGE) {
g_set_error(error, ZDUMP_PV_UTILS_ERROR,
ZDUMP_ERR_PGLIST_INVAL_STATE,
_("Invalid page state. page-idx: %#lx, state: %#lx"),
page_idx, page_state);
return -1;
}
} else { } else {
g_set_error(error, ZDUMP_PV_UTILS_ERROR, ZDUMP_ERR_PGLIST_INVAL_STATE, g_set_error(error, ZDUMP_PV_UTILS_ERROR, ZDUMP_ERR_PGLIST_INVAL_STATE,
_("Invalid page state. page-idx: %#lx, state: %#lx"), page_idx, _("Invalid page state. page-idx: %#lx, state: %#lx"), page_idx,
@@ -659,10 +677,10 @@ struct _storage_state_mmap {
gatomicrefcount ref_count; gatomicrefcount ref_count;
}; };
storage_state_mmap_t *storage_state_mmap_new(const int fd, const u64 offset, const u64 size, storage_state_mmap_t *storage_state_mmap_new(const int fd, const size_t file_size, const u64 offset,
GError **error) const u64 size, GError **error)
{ {
size_t tweak_components_cnt, start_addr, in_page_offset, mmapped_size; size_t tweak_components_cnt, start_addr, min_size, in_page_offset, mmapped_size;
g_autoptr(storage_state_mmap_t) ret = NULL; g_autoptr(storage_state_mmap_t) ret = NULL;
int saved_errno = 0; int saved_errno = 0;
u8 *ptr; u8 *ptr;
@@ -688,6 +706,19 @@ storage_state_mmap_t *storage_state_mmap_new(const int fd, const u64 offset, con
start_addr); start_addr);
return NULL; return NULL;
} }
if (G_UNLIKELY(!g_uint64_checked_add(&min_size, start_addr, mmapped_size))) {
g_set_error(error, ZDUMP_PV_UTILS_ERROR, ZDUMP_ERR_PAGE_END_ADDR_OVERFLOW,
_("UInt overflow detected: %s: start_addr %#lx mmap_size %#lx"),
__func__, start_addr, mmapped_size);
return NULL;
}
if (file_size < min_size) {
g_set_error(error, ZDUMP_PV_UTILS_ERROR, ZDUMP_ERR_MMAP,
_("mmap failed: file too small"));
return NULL;
}
ptr = mmap(NULL, mmapped_size, PROT_READ, MAP_POPULATE | MAP_PRIVATE, fd, ptr = mmap(NULL, mmapped_size, PROT_READ, MAP_POPULATE | MAP_PRIVATE, fd,
(ssize_t)start_addr); (ssize_t)start_addr);
saved_errno = errno; saved_errno = errno;
@@ -722,7 +753,7 @@ void storage_state_mmap_unref(storage_state_mmap_t *storage_state)
if (storage_state->first_page_ptr) { if (storage_state->first_page_ptr) {
int rc = munmap(storage_state->first_page_ptr, storage_state->mapped_size); int rc = munmap(storage_state->first_page_ptr, storage_state->mapped_size);
if (rc != 0) if (rc != 0)
util_log_print(UTIL_LOG_WARN, _("munmap has failed")); util_log_print(UTIL_LOG_WARN, _("munmap has failed\n"));
} }
g_free(storage_state); g_free(storage_state);
} }
@@ -796,9 +827,9 @@ static long completion_data_get_version(GBytes *cpl_data, GError **error)
return *version; return *version;
} }
int pv_process_section_data(const int fd, GBytes *completion_sec, const u64 storage_state_offset, int pv_process_section_data(const int fd, const size_t file_size, GBytes *completion_sec,
const size_t storage_state_size, GBytes *cck, const u64 storage_state_offset, const size_t storage_state_size,
pv_dump_completion_t **completion_decr, GBytes **dump_key, GBytes *cck, pv_dump_completion_t **completion_decr, GBytes **dump_key,
storage_state_mmap_t **storage_state, GError **error) storage_state_mmap_t **storage_state, GError **error)
{ {
g_autoptr(pv_dump_completion_t) _completion_decr = NULL; g_autoptr(pv_dump_completion_t) _completion_decr = NULL;
@@ -852,8 +883,8 @@ int pv_process_section_data(const int fd, GBytes *completion_sec, const u64 stor
return -1; return -1;
} }
_storage_state_data = _storage_state_data = storage_state_mmap_new(fd, file_size, storage_state_offset,
storage_state_mmap_new(fd, storage_state_offset, storage_state_size, error); storage_state_size, error);
if (!_storage_state_data) if (!_storage_state_data)
return -1; return -1;
+6 -5
View File
@@ -258,9 +258,9 @@ bool pv_is_pv_elf(const Elf64_Shdr *shdrs, const unsigned int shnum, const char
* *
* Returns: 0 in case of success, -1 otherwise. * Returns: 0 in case of success, -1 otherwise.
*/ */
int pv_process_section_data(const int fd, GBytes *completion_sec, const u64 storage_state_offset, int pv_process_section_data(const int fd, const size_t file_size, GBytes *completion_sec,
const size_t storage_state_size, GBytes *cck, const u64 storage_state_offset, const size_t storage_state_size,
pv_dump_completion_t **completion_decr, GBytes **dump_key, GBytes *cck, pv_dump_completion_t **completion_decr, GBytes **dump_key,
storage_state_mmap_t **storage_state_data, GError **error); storage_state_mmap_t **storage_state_data, GError **error);
/** /**
@@ -283,14 +283,15 @@ int pv_elf_read(const pv_elf_ctx_t *elf_ctx, const u64 start_addr, void *dst, co
/** /**
* storage_state_mmap_new: * storage_state_mmap_new:
* @fd: file descriptor for which to create the mapping * @fd: file descriptor for which to create the mapping
* @file_size: file size in bytes
* @offset: offset in fd to pv_mem_meta section * @offset: offset in fd to pv_mem_meta section
* @size: size of mapping (and pv_mem_meta section) * @size: size of mapping (and pv_mem_meta section)
* @error: return value for GError * @error: return value for GError
* *
* Returns: new storage_state_mmap context * Returns: new storage_state_mmap context
*/ */
storage_state_mmap_t *storage_state_mmap_new(const int fd, const u64 offset, const u64 size, storage_state_mmap_t *storage_state_mmap_new(const int fd, const size_t file_size, const u64 offset,
GError **error); const u64 size, GError **error);
/** /**
* storage_state_ref: * storage_state_ref:
+3 -3
View File
@@ -43,17 +43,17 @@ ziorep_utilization: ziorep_utilization.o ziorep_framer.o ziorep_frameset.o \
install: all install: all
$(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \ $(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
< ziomon > $(DESTDIR)$(USRSBINDIR)/ziomon; < ziomon > $(DESTDIR)$(USRSBINDIR)/ziomon;
chown $(OWNER).$(GROUP) $(DESTDIR)$(USRSBINDIR)/ziomon; chown $(OWNER):$(GROUP) $(DESTDIR)$(USRSBINDIR)/ziomon;
chmod 755 $(DESTDIR)$(USRSBINDIR)/ziomon; chmod 755 $(DESTDIR)$(USRSBINDIR)/ziomon;
$(SED) -e \ $(SED) -e \
's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \ 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
< ziomon_fcpconf > $(DESTDIR)$(USRSBINDIR)/ziomon_fcpconf; < ziomon_fcpconf > $(DESTDIR)$(USRSBINDIR)/ziomon_fcpconf;
chown $(OWNER).$(GROUP) $(DESTDIR)$(USRSBINDIR)/ziomon_fcpconf; chown $(OWNER):$(GROUP) $(DESTDIR)$(USRSBINDIR)/ziomon_fcpconf;
chmod 755 $(DESTDIR)$(USRSBINDIR)/ziomon_fcpconf; chmod 755 $(DESTDIR)$(USRSBINDIR)/ziomon_fcpconf;
$(SED) -e \ $(SED) -e \
's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \ 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
< ziorep_config > $(DESTDIR)$(USRSBINDIR)/ziorep_config; < ziorep_config > $(DESTDIR)$(USRSBINDIR)/ziorep_config;
chown $(OWNER).$(GROUP) $(DESTDIR)$(USRSBINDIR)/ziorep_config; chown $(OWNER):$(GROUP) $(DESTDIR)$(USRSBINDIR)/ziorep_config;
chmod 755 $(DESTDIR)$(USRSBINDIR)/ziorep_config; chmod 755 $(DESTDIR)$(USRSBINDIR)/ziorep_config;
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 ziomon.8 \ $(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 ziomon.8 \
$(DESTDIR)$(MANDIR)/man8 $(DESTDIR)$(MANDIR)/man8
+5 -3
View File
@@ -15,14 +15,16 @@
int extract_length(void *data) int extract_length(void *data)
{ {
struct eckd_blockptr *blockptr = (struct eckd_blockptr *)data; struct eckd_blockptr_legacy *blockptr =
(struct eckd_blockptr_legacy *)data;
return blockptr->size * (blockptr->blockct + 1); return blockptr->size * (blockptr->blockct + 1);
} }
int is_zero_block(void *data) int is_zero_block(void *data)
{ {
struct eckd_blockptr *blockptr = (struct eckd_blockptr *)data; struct eckd_blockptr_legacy *blockptr =
(struct eckd_blockptr_legacy *)data;
return blockptr->cyl || blockptr->head || blockptr->sec; return blockptr->cyl || blockptr->head || blockptr->sec;
} }
@@ -30,7 +32,7 @@ int is_zero_block(void *data)
void * load_direct(disk_blockptr_t *data, struct subchannel_id subchannel_id, void * load_direct(disk_blockptr_t *data, struct subchannel_id subchannel_id,
void *load_addr) void *load_addr)
{ {
struct eckd_blockptr *blockptr = &data->eckd; struct eckd_blockptr_legacy *blockptr = &data->eckd;
struct ccw1 *ccws; struct ccw1 *ccws;
unsigned long record_size; unsigned long record_size;
struct seek_arg seek_addr; struct seek_arg seek_addr;
+4 -4
View File
@@ -120,9 +120,9 @@ void __noreturn start(void)
/* skip header */ /* skip header */
entry = (struct component_entry *) entry = (struct component_entry *)
(load_address + sizeof(struct component_header)); (load_address + sizeof(struct component_header));
while (entry->type == COMPONENT_LOAD || while (entry->type == COMPONENT_TYPE_LOAD ||
entry->type == COMPONENT_SIGNATURE) { entry->type == COMPONENT_TYPE_SIGNATURE) {
if (entry->type == COMPONENT_SIGNATURE) { if (entry->type == COMPONENT_TYPE_SIGNATURE) {
/* Skip unhandled signature components */ /* Skip unhandled signature components */
entry++; entry++;
continue; continue;
@@ -132,7 +132,7 @@ void __noreturn start(void)
load_blocklist(entry, subchannel_id, load_address); load_blocklist(entry, subchannel_id, load_address);
entry++; entry++;
} }
if (entry->type != COMPONENT_EXECUTE) if (entry->type != COMPONENT_TYPE_EXECUTE)
panic(EWRONGTYPE, ""); panic(EWRONGTYPE, "");
load_psw = entry->compdat.load_psw; load_psw = entry->compdat.load_psw;
+1 -1
View File
@@ -27,7 +27,7 @@
#include "error.h" #include "error.h"
typedef union { typedef union {
struct eckd_blockptr eckd; struct eckd_blockptr_legacy eckd;
struct linear_blockptr linear; struct linear_blockptr linear;
} disk_blockptr_t; } disk_blockptr_t;
+4 -2
View File
@@ -158,8 +158,8 @@ struct mvdump_parm_table {
void boot_get_dump_info(struct boot_info *boot_info, uint8_t dev_type, void boot_get_dump_info(struct boot_info *boot_info, uint8_t dev_type,
void *param); void *param);
void boot_get_ipl_info(struct boot_info *boot_info, uint8_t dev_type, void boot_get_ipl_info_ccw(struct boot_info *boot_info, uint8_t dev_type,
disk_blockptr_t *bm_ptr, struct disk_info *info); disk_blockptr_t *bm_ptr, struct disk_info *info);
int boot_check_data(void); int boot_check_data(void);
int boot_init_fba_stage0(struct boot_fba_stage0* stage0, int boot_init_fba_stage0(struct boot_fba_stage0* stage0,
@@ -187,6 +187,8 @@ int boot_get_tape_ipl(void** data, size_t* size, address_t parm_addr,
address_t initrd_addr, address_t image_addr); address_t initrd_addr, address_t image_addr);
int boot_get_tape_dump(void** data, size_t* size, uint64_t mem); int boot_get_tape_dump(void** data, size_t* size, uint64_t mem);
int boot_get_eckd_dump_stage2(void** data, size_t* size, uint64_t mem); int boot_get_eckd_dump_stage2(void** data, size_t* size, uint64_t mem);
int boot_get_eckd_ld_ipl_br(void **br_ptr, size_t *size_ptr,
disk_blockptr_t *table, struct disk_info *info);
int boot_get_eckd_mvdump_stage2(void** data, size_t* size, uint64_t mem, int boot_get_eckd_mvdump_stage2(void** data, size_t* size, uint64_t mem,
uint8_t force, struct mvdump_parm_table); uint8_t force, struct mvdump_parm_table);
int boot_get_fba_dump_stage2(void** data, size_t* size, uint64_t mem); int boot_get_fba_dump_stage2(void** data, size_t* size, uint64_t mem);
+2 -6
View File
@@ -51,11 +51,7 @@ struct file_signature {
int bootmap_header_init(int fd); int bootmap_header_init(int fd);
int bootmap_header_read(int fd, struct bootmap_header *bh); int bootmap_header_read(int fd, struct bootmap_header *bh);
int bootmap_header_write(int fd, struct bootmap_header *bh); int bootmap_header_write(int fd, struct bootmap_header *bh);
int bootmap_create(struct job_data* job, disk_blockptr_t* program_table, void bootmap_store_blockptr(void *buffer, disk_blockptr_t *ptr,
disk_blockptr_t *scsi_dump_sb_blockptr, struct disk_info *info, int fid);
disk_blockptr_t** stage2_list, blocknum_t* stage2_count,
char** device, struct disk_info** new_info);
void bootmap_store_blockptr(void* buffer, disk_blockptr_t* ptr,
struct disk_info* info);
#endif /* if not BOOTMAP_H */ #endif /* if not BOOTMAP_H */
+3 -9
View File
@@ -16,6 +16,7 @@
#include <sys/types.h> #include <sys/types.h>
#include "zipl.h" #include "zipl.h"
#include "lib/vtoc.h"
/* Type for representing disk block numbers */ /* Type for representing disk block numbers */
@@ -23,7 +24,7 @@ typedef uint64_t blocknum_t;
/* Pointer to block on a disk with cyl/head/sec layout */ /* Pointer to block on a disk with cyl/head/sec layout */
struct disk_blockptr_chs { struct disk_blockptr_chs {
int cyl; unsigned int cyl;
int head; int head;
int sec; int sec;
int size; int size;
@@ -52,14 +53,6 @@ typedef enum {
disk_type_eckd_cdl, disk_type_eckd_cdl,
} disk_type_t; } disk_type_t;
/* from linux/hdregs.h */
struct hd_geometry {
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
unsigned long start;
};
/* Disk information source */ /* Disk information source */
typedef enum { typedef enum {
source_auto, source_auto,
@@ -108,6 +101,7 @@ int disk_get_info_from_file(const char* filename,
struct disk_info** info); struct disk_info** info);
void disk_free_info(struct disk_info* info); void disk_free_info(struct disk_info* info);
char* disk_get_type_name(disk_type_t type); char* disk_get_type_name(disk_type_t type);
char *disk_get_ipl_type(disk_type_t type);
int disk_is_large_volume(struct disk_info* info); int disk_is_large_volume(struct disk_info* info);
int disk_cyl_from_blocknum(blocknum_t blocknum, struct disk_info* info); int disk_cyl_from_blocknum(blocknum_t blocknum, struct disk_info* info);
int disk_head_from_blocknum(blocknum_t blocknum, struct disk_info* info); int disk_head_from_blocknum(blocknum_t blocknum, struct disk_info* info);
+82 -4
View File
@@ -15,12 +15,90 @@
#include "disk.h" #include "disk.h"
#include "job.h" #include "job.h"
#include "zipl.h" #include "zipl.h"
#include "boot/boot_defs.h"
/*
* For compatibility reasons zIPL can build multiple "similar"
* program tables, which differ only in block pointers format
*/
enum program_table_id {
PROGRAM_TABLE_0,
PROGRAM_TABLE_1,
NR_PROGRAM_TABLES
};
int install_bootloader(const char* device, disk_blockptr_t* program_table, enum program_component_id {
disk_blockptr_t* scsi_dump_sb_blockptr, COMPONENT_ID_HEAP_AREA,
disk_blockptr_t* stage2_data, blocknum_t stage2_count, COMPONENT_ID_STACK_AREA,
struct disk_info* info, struct job_data* job); COMPONENT_ID_LOADER_SIGNATURE,
COMPONENT_ID_LOADER,
COMPONENT_ID_PARAMETERS,
COMPONENT_ID_IMAGE_SIGNATURE,
COMPONENT_ID_KERNEL_IMAGE,
COMPONENT_ID_PARMLINE,
COMPONENT_ID_RAMDISK_SIGNATURE,
COMPONENT_ID_RAMDISK,
COMPONENT_ID_ENVBLK,
COMPONENT_ID_SEGMENT_FILE,
NR_PROGRAM_COMPONENTS
};
struct component_loc {
address_t addr;
size_t size;
};
struct component_footer {
component_type type;
const char *desc;
};
struct program_component {
struct component_loc loc;
disk_blockptr_t *list;
blocknum_t count;
};
struct program_table {
disk_blockptr_t table;
disk_blockptr_t *stage1b_list;
blocknum_t stage1b_count;
};
/* Bootloader Installation Set */
struct install_set {
struct program_table tables[NR_PROGRAM_TABLES];
struct program_component *components[NR_PROGRAM_COMPONENTS];
int nr_tables; /* number of "similar" program tables to be installed */
int nr_menu_entries;
int fd;
char *device;
char *filename;
struct disk_info *info;
disk_blockptr_t scsi_dump_sb_blockptr;
};
extern struct component_footer component_footers[NR_PROGRAM_COMPONENTS];
static inline component_type component_type_by_id(enum program_component_id id)
{
return component_footers[id].type;
}
static inline const char *component_desc_by_id(enum program_component_id id)
{
return component_footers[id].desc;
}
static inline struct program_component *get_component(struct install_set *bis,
int i, int j)
{
return bis->components[i] + j;
}
int prepare_bootloader(struct job_data *job, struct install_set *bis);
int install_bootloader(struct job_data *job, struct install_set *bis);
void free_bootloader(struct install_set *bis);
int install_tapeloader(const char* device, const char* image, int install_tapeloader(const char* device, const char* image,
const char* parmline, const char* ramdisk, const char* parmline, const char* ramdisk,
address_t image_addr, address_t parm_addr, address_t image_addr, address_t parm_addr,
+2 -1
View File
@@ -7,7 +7,8 @@ ALL_CPPFLAGS += -I../include -I../boot \
-D_FILE_OFFSET_BITS=64 $(NO_PIE_CFLAGS) -D_FILE_OFFSET_BITS=64 $(NO_PIE_CFLAGS)
ALL_LDFLAGS += -Wl,-z,noexecstack $(NO_PIE_LDFLAGS) ALL_LDFLAGS += -Wl,-z,noexecstack $(NO_PIE_LDFLAGS)
libs = $(rootdir)/libutil/libutil.a libs = $(rootdir)/libutil/libutil.a \
$(rootdir)/libvtoc/libvtoc.a \
objects = misc.o error.o scan.o job.o boot.o bootmap.o fs-map.o disk.o \ objects = misc.o error.o scan.o job.o boot.o bootmap.o fs-map.o disk.o \
bootmap_header.o envblk.o install.o zipl.o $(rootdir)/zipl/boot/data.o bootmap_header.o envblk.o install.o zipl.o $(rootdir)/zipl/boot/data.o
+31 -3
View File
@@ -16,6 +16,7 @@
#include <string.h> #include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "lib/util_libc.h"
#include "stage3.h" #include "stage3.h"
@@ -560,9 +561,12 @@ boot_get_dump_info(struct boot_info *boot_info, uint8_t dev_type, void *param)
sizeof(boot_info->bp.dump.param)); sizeof(boot_info->bp.dump.param));
} }
/*
* Helper function to install a boot record for CCW-type IPL from DASD
*/
void void
boot_get_ipl_info(struct boot_info *boot_info, uint8_t dev_type, boot_get_ipl_info_ccw(struct boot_info *boot_info, uint8_t dev_type,
disk_blockptr_t *bm_ptr, struct disk_info *info) disk_blockptr_t *bm_ptr, struct disk_info *info)
{ {
memset(boot_info, 0, sizeof(*boot_info)); memset(boot_info, 0, sizeof(*boot_info));
memcpy(&boot_info->magic, BOOT_INFO_MAGIC, sizeof(boot_info->magic)); memcpy(&boot_info->magic, BOOT_INFO_MAGIC, sizeof(boot_info->magic));
@@ -570,6 +574,30 @@ boot_get_ipl_info(struct boot_info *boot_info, uint8_t dev_type,
boot_info->dev_type = dev_type; boot_info->dev_type = dev_type;
boot_info->bp_type = BOOT_INFO_BP_TYPE_IPL; boot_info->bp_type = BOOT_INFO_BP_TYPE_IPL;
boot_info->version = BOOT_INFO_VERSION; boot_info->version = BOOT_INFO_VERSION;
bootmap_store_blockptr(&boot_info->bp, bm_ptr, info); bootmap_store_blockptr(&boot_info->bp, bm_ptr, info,
LEGACY_BLKPTR_FORMAT_ID);
} }
/**
* Allocate and initialize a boot record for List-Directed IPL from DASD
*
* TABLE: address of an actual program table
*/
int boot_get_eckd_ld_ipl_br(void **br_ptr, size_t *size_ptr,
disk_blockptr_t *table, struct disk_info *info)
{
struct eckd_boot_record *br;
br = util_zalloc(info->phy_block_size);
if (!br)
return -1;
memcpy(&br->magic, ZIPL_MAGIC, ZIPL_MAGIC_SIZE);
br->version_id = DISK_LAYOUT_ID;
bootmap_store_blockptr(&br->program_table_pointer, table, info,
BLKPTR_FORMAT_ID);
br->os_id = 0x55aa; /* LINUX */
*br_ptr = br;
*size_ptr = info->phy_block_size;
return 0;
}
+729 -545
View File
File diff suppressed because it is too large Load Diff
+26 -18
View File
@@ -28,6 +28,7 @@
#include "lib/util_proc.h" #include "lib/util_proc.h"
#include "lib/util_sys.h" #include "lib/util_sys.h"
#include "lib/util_libc.h"
#include "disk.h" #include "disk.h"
#include "error.h" #include "error.h"
#include "install.h" #include "install.h"
@@ -755,7 +756,6 @@ disk_write_block_buffer_align(int fd, int fd_is_basedisk, const void *buffer,
size_t bytecount, disk_blockptr_t **blocklist, size_t bytecount, disk_blockptr_t **blocklist,
struct disk_info *info, int align, off_t *offset) struct disk_info *info, int align, off_t *offset)
{ {
disk_blockptr_t* list;
blocknum_t count; blocknum_t count;
blocknum_t i; blocknum_t i;
size_t written; size_t written;
@@ -764,13 +764,12 @@ disk_write_block_buffer_align(int fd, int fd_is_basedisk, const void *buffer,
int rc; int rc;
count = (bytecount + info->phy_block_size - 1) / info->phy_block_size; count = (bytecount + info->phy_block_size - 1) / info->phy_block_size;
list = (disk_blockptr_t *) misc_malloc(sizeof(disk_blockptr_t) * *blocklist = (disk_blockptr_t *)util_zalloc(sizeof(disk_blockptr_t) *
count); count);
if (list == NULL) { if (*blocklist == NULL) {
close(fd); close(fd);
return 0; return 0;
} }
memset((void *) list, 0, sizeof(disk_blockptr_t) * count);
/* Build list */ /* Build list */
for (i=0, written=0; i < count; i++, written += chunk_size) { for (i=0, written=0; i < count; i++, written += chunk_size) {
chunk_size = bytecount - written; chunk_size = bytecount - written;
@@ -778,17 +777,15 @@ disk_write_block_buffer_align(int fd, int fd_is_basedisk, const void *buffer,
chunk_size = info->phy_block_size; chunk_size = info->phy_block_size;
rc = disk_write_block_aligned_base(fd, fd_is_basedisk, rc = disk_write_block_aligned_base(fd, fd_is_basedisk,
VOID_ADD(buffer, written), VOID_ADD(buffer, written),
chunk_size, &list[i], info, chunk_size, &(*blocklist)[i],
info,
i == 0 ? align : info->phy_block_size, i == 0 ? align : info->phy_block_size,
&pos); &pos);
if (rc) { if (rc)
free(list);
return 0; return 0;
}
if (offset != NULL && i == 0) if (offset != NULL && i == 0)
*offset = pos; *offset = pos;
} }
*blocklist = list;
return count; return count;
} }
@@ -830,6 +827,21 @@ disk_get_type_name(disk_type_t type)
} }
} }
/* Return IPL types supported for a given disk TYPE */
char *disk_get_ipl_type(disk_type_t type)
{
switch (type) {
case disk_type_scsi:
return "LD-";
case disk_type_fba:
case disk_type_eckd_ldl:
return "CCW-";
case disk_type_eckd_cdl:
return "CCW- and LD-";
default:
return "";
}
}
/* Return non-zero for ECKD large volumes. */ /* Return non-zero for ECKD large volumes. */
int int
@@ -1050,7 +1062,6 @@ disk_get_blocklist_from_file(const char *filename, struct file_range *reg,
disk_blockptr_t **blocklist, disk_blockptr_t **blocklist,
struct disk_info* info) struct disk_info* info)
{ {
disk_blockptr_t* list;
struct stat stats; struct stat stats;
int fd; int fd;
off_t off; off_t off;
@@ -1094,24 +1105,21 @@ disk_get_blocklist_from_file(const char *filename, struct file_range *reg,
blk_count = ((blocknum_t) count + blk_count = ((blocknum_t) count +
info->phy_block_size - 1) / info->phy_block_size; info->phy_block_size - 1) / info->phy_block_size;
list = (disk_blockptr_t *) misc_malloc(sizeof(disk_blockptr_t) * *blocklist = (disk_blockptr_t *)util_zalloc(sizeof(disk_blockptr_t) *
blk_count); blk_count);
if (list == NULL) { if (*blocklist == NULL) {
close(fd); close(fd);
return 0; return 0;
} }
memset((void *) list, 0, sizeof(disk_blockptr_t) * blk_count);
/* Build list */ /* Build list */
for (i = 0; i < blk_count; i++) { for (i = 0; i < blk_count; i++) {
if (disk_get_blocknum(fd, 0, blk_off + i, &blocknum, info)) { if (disk_get_blocknum(fd, 0, blk_off + i, &blocknum, info)) {
free(list);
close(fd); close(fd);
return 0; return 0;
} }
disk_blockptr_from_blocknum(&list[i], blocknum, info); disk_blockptr_from_blocknum(&(*blocklist)[i], blocknum, info);
} }
close(fd); close(fd);
*blocklist = list;
return blk_count; return blk_count;
} }
+113 -36
View File
@@ -25,6 +25,7 @@
#include "lib/zt_common.h" #include "lib/zt_common.h"
#include "lib/util_sys.h" #include "lib/util_sys.h"
#include "lib/vtoc.h"
#include "boot.h" #include "boot.h"
#include "bootmap.h" #include "bootmap.h"
@@ -109,7 +110,8 @@ update_scsi_mbr(void* bootblock, disk_blockptr_t* table,
memset(buffer, 0, sizeof(struct scsi_mbr)); memset(buffer, 0, sizeof(struct scsi_mbr));
memcpy(&mbr->magic, ZIPL_MAGIC, ZIPL_MAGIC_SIZE); memcpy(&mbr->magic, ZIPL_MAGIC, ZIPL_MAGIC_SIZE);
mbr->version_id = DISK_LAYOUT_ID; mbr->version_id = DISK_LAYOUT_ID;
bootmap_store_blockptr(&mbr->program_table_pointer, table, info); bootmap_store_blockptr(&mbr->program_table_pointer, table, info,
0 /* this argument is ignored for scsi */);
if (scsi_dump_sb_blockptr->linear.block != 0) { if (scsi_dump_sb_blockptr->linear.block != 0) {
/* Write dump boot_info */ /* Write dump boot_info */
param.block = scsi_dump_sb_blockptr->linear.block * param.block = scsi_dump_sb_blockptr->linear.block *
@@ -168,11 +170,11 @@ install_scsi(int fd, disk_blockptr_t* program_table, struct disk_info* info,
} }
/* Install bootloader for initial program load from an FBA type disk. */ /* Install bootloader for CCW-type IPL from a FBA type disk */
static int static int
install_fba(int fd, disk_blockptr_t *program_table, install_fba_ccw(int fd, disk_blockptr_t *program_table,
disk_blockptr_t *stage1b_list, blocknum_t stage1b_count, disk_blockptr_t *stage1b_list, blocknum_t stage1b_count,
struct disk_info *info) struct disk_info *info)
{ {
struct boot_fba_stage0 stage0; struct boot_fba_stage0 stage0;
@@ -180,8 +182,8 @@ install_fba(int fd, disk_blockptr_t *program_table,
if (boot_init_fba_stage0(&stage0, stage1b_list, stage1b_count)) if (boot_init_fba_stage0(&stage0, stage1b_list, stage1b_count))
return -1; return -1;
boot_get_ipl_info(&stage0.boot_info, BOOT_INFO_DEV_TYPE_FBA, boot_get_ipl_info_ccw(&stage0.boot_info, BOOT_INFO_DEV_TYPE_FBA,
program_table, info); program_table, info);
if (DRY_RUN_FUNC(misc_pwrite(fd, &stage0, sizeof(stage0), 0))) if (DRY_RUN_FUNC(misc_pwrite(fd, &stage0, sizeof(stage0), 0)))
return -1; return -1;
@@ -218,12 +220,14 @@ out:
return rc; return rc;
} }
/* Install bootloader for initial program load from an ECKD type disk with /*
* Linux Disk Layout. */ * Install bootloader for CCW-type IPL from ECKD type disk with
* Linux Disk Layout
*/
static int static int
install_eckd_ldl(int fd, disk_blockptr_t *program_table, install_eckd_ldl_ccw(int fd, disk_blockptr_t *program_table,
disk_blockptr_t *stage1b_list, blocknum_t stage1b_count, disk_blockptr_t *stage1b_list, blocknum_t stage1b_count,
struct disk_info *info) struct disk_info *info)
{ {
struct boot_eckd_ldl_stage0 stage0; struct boot_eckd_ldl_stage0 stage0;
struct boot_eckd_stage1 stage1; struct boot_eckd_stage1 stage1;
@@ -236,8 +240,8 @@ install_eckd_ldl(int fd, disk_blockptr_t *program_table,
if (boot_init_eckd_stage1(&stage1, stage1b_list, stage1b_count)) if (boot_init_eckd_stage1(&stage1, stage1b_list, stage1b_count))
return -1; return -1;
boot_get_ipl_info(&stage1.boot_info, BOOT_INFO_DEV_TYPE_ECKD, boot_get_ipl_info_ccw(&stage1.boot_info, BOOT_INFO_DEV_TYPE_ECKD,
program_table, info); program_table, info);
if (DRY_RUN_FUNC(misc_pwrite(fd, &stage1, sizeof(stage1), if (DRY_RUN_FUNC(misc_pwrite(fd, &stage1, sizeof(stage1),
sizeof(stage0)))) sizeof(stage0))))
@@ -246,12 +250,14 @@ install_eckd_ldl(int fd, disk_blockptr_t *program_table,
return 0; return 0;
} }
/* Install bootloader for initial program load from an ECKD type disk with /**
* OS/390 compatible disk layout. */ * Install bootloader for CCW-type IPL from ECKD type disk with
static int * OS/390 compatible disk layout
install_eckd_cdl(int fd, disk_blockptr_t *program_table, */
disk_blockptr_t *stage1b_list, blocknum_t stage1b_count, static int install_eckd_cdl_ccw(int fd, disk_blockptr_t *program_table,
struct disk_info *info) disk_blockptr_t *stage1b_list,
blocknum_t stage1b_count,
struct disk_info *info)
{ {
struct boot_eckd_cdl_stage0 stage0; struct boot_eckd_cdl_stage0 stage0;
struct boot_eckd_stage1 stage1; struct boot_eckd_stage1 stage1;
@@ -264,8 +270,8 @@ install_eckd_cdl(int fd, disk_blockptr_t *program_table,
if (boot_init_eckd_stage1(&stage1, stage1b_list, stage1b_count)) if (boot_init_eckd_stage1(&stage1, stage1b_list, stage1b_count))
return -1; return -1;
boot_get_ipl_info(&stage1.boot_info, BOOT_INFO_DEV_TYPE_ECKD, boot_get_ipl_info_ccw(&stage1.boot_info, BOOT_INFO_DEV_TYPE_ECKD,
program_table, info); program_table, info);
if (DRY_RUN_FUNC(misc_pwrite(fd, &stage1, sizeof(stage1), if (DRY_RUN_FUNC(misc_pwrite(fd, &stage1, sizeof(stage1),
4 + info->phy_block_size))) 4 + info->phy_block_size)))
@@ -273,16 +279,74 @@ install_eckd_cdl(int fd, disk_blockptr_t *program_table,
return 0; return 0;
} }
int /**
install_bootloader(const char *device, disk_blockptr_t *program_table, * Install a program table for List-Directed IPL on a CDL-formatted DASD.
disk_blockptr_t *scsi_dump_sb_blockptr, *
disk_blockptr_t *stage1b_list, blocknum_t stage1b_count, * The installation means storing an actual boot record address in the
struct disk_info *info, struct job_data *job) * volume label.
*
* BR: represents an actual boot record address.
*/
static int install_eckd_cdl_ld(int fd, disk_blockptr_t *br,
struct disk_info *info)
{ {
struct vol_label_cdl vl;
int rc;
/* Read a volume label from CDL-formatted DASD */
if (misc_seek(fd, 2 * info->phy_block_size))
return -1;
rc = misc_read(fd, &vl, sizeof(vl));
if (rc) {
error_text("Could not read volume label");
return rc;
}
/* Verify that we have a VOL1 label */
if (!is_vol1(vl.vollbl)) {
error_text("Volume label 'vol1' not initialized");
return -1;
}
/* Pack the actual boot record address */
vtoc_set_cchhb(&vl.br, br->chs.cyl, br->chs.head, br->chs.sec);
/* Write out the updated volume label */
if (misc_seek(fd, 2 * info->phy_block_size))
return -1;
rc = DRY_RUN_FUNC(misc_write(fd, &vl, sizeof(vl)));
if (rc)
error_text("Could not update volume lablel 'vol1'");
return 0;
}
/**
* Install a "compatible" boot record referring one, or two "similar"
* program tables.
*
* The picture below shows which program table is used for IPL
* of specified type from disk of specified type.
* E.g. program table "0" is used for CCW-type IPL from ECKD DASD,
* LD-IPL from DASD FBA is unsupported (respectively, only one program
* table "0" is used), etc.
*
* CCW-IPL LD-IPL
*
* SCSI X 0
* DASD FBA 0 X
* ECKD DASD LDL 0 X
* ECKD DASD CDL 0 1
*/
int install_bootloader(struct job_data *job, struct install_set *bis)
{
disk_blockptr_t *scsi_dump_sb_blockptr = &bis->scsi_dump_sb_blockptr;
struct program_table *pt0 = &bis->tables[PROGRAM_TABLE_0];
struct program_table *pt1 = &bis->tables[PROGRAM_TABLE_1];
struct disk_info *info = bis->info;
char *device = bis->device;
int fd, rc; int fd, rc;
/* Inform user about what we're up to */ /* Inform user about what we're up to */
printf("Preparing boot device: "); printf("Preparing boot device for %sIPL: ",
disk_get_ipl_type(info->type));
if (info->name) { if (info->name) {
printf("%s", info->name); printf("%s", info->name);
if (info->devno >= 0) if (info->devno >= 0)
@@ -310,27 +374,40 @@ install_bootloader(const char *device, disk_blockptr_t *program_table,
"caches.\n"); "caches.\n");
} }
} }
/* Call disk specific install functions */ /*
* Depending on disk type, install one or two program tables
* for CCW-type IPL and (or) for List-Directed IPL (see the
* picture in comments above)
*/
rc = -1; rc = -1;
switch (info->type) { switch (info->type) {
case disk_type_scsi: case disk_type_scsi:
rc = install_scsi(fd, program_table, info, rc = install_scsi(fd, &pt0->table, info,
scsi_dump_sb_blockptr); scsi_dump_sb_blockptr);
if (rc == 0 && job->id == job_dump_partition && if (rc == 0 && job->id == job_dump_partition &&
!is_ngdump_enabled(device, &job->target)) !is_ngdump_enabled(device, &job->target))
rc = overwrite_partition_start(fd, info, 0); rc = overwrite_partition_start(fd, info, 0);
break; break;
case disk_type_fba: case disk_type_fba:
rc = install_fba(fd, program_table, stage1b_list, rc = install_fba_ccw(fd,
stage1b_count, info); &pt0->table,
pt0->stage1b_list,
pt0->stage1b_count, info);
break; break;
case disk_type_eckd_ldl: case disk_type_eckd_ldl:
rc = install_eckd_ldl(fd, program_table, stage1b_list, rc = install_eckd_ldl_ccw(fd,
stage1b_count, info); &pt0->table,
pt0->stage1b_list,
pt0->stage1b_count, info);
break; break;
case disk_type_eckd_cdl: case disk_type_eckd_cdl:
rc = install_eckd_cdl(fd, program_table, stage1b_list, rc = install_eckd_cdl_ccw(fd,
stage1b_count, info); &pt0->table,
pt0->stage1b_list,
pt0->stage1b_count, info);
if (rc)
break;
rc = install_eckd_cdl_ld(fd, pt1->stage1b_list, info);
break; break;
case disk_type_diag: case disk_type_diag:
/* Should not happen */ /* Should not happen */
+58 -17
View File
@@ -126,11 +126,8 @@ check_for_root(void)
int int
main(int argc, char* argv[]) main(int argc, char* argv[])
{ {
struct disk_info* info; struct install_set bis;
disk_blockptr_t program_table, scsi_dump_sb_blockptr, *stage1b_list;
blocknum_t stage1b_count;
struct job_data* job; struct job_data* job;
char* device;
int rc; int rc;
/* Check internals */ /* Check internals */
@@ -197,21 +194,11 @@ main(int argc, char* argv[])
case job_ipl: case job_ipl:
case job_segment: case job_segment:
case job_menu: case job_menu:
/* Create bootmap */ rc = prepare_bootloader(job, &bis);
stage1b_list = NULL;
rc = bootmap_create(job, &program_table, &scsi_dump_sb_blockptr,
&stage1b_list, &stage1b_count, &device,
&info);
if (rc) if (rc)
break; break;
/* Install boot loader */ rc = install_bootloader(job, &bis);
rc = install_bootloader(device, &program_table, free_bootloader(&bis);
&scsi_dump_sb_blockptr, stage1b_list,
stage1b_count, info, job);
if (stage1b_list != NULL)
free(stage1b_list);
misc_free_temp_dev(device);
disk_free_info(info);
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,
@@ -251,3 +238,57 @@ main(int argc, char* argv[])
job_free(job); job_free(job);
return abs(rc); return abs(rc);
} }
/**
* Program Component Footers
*/
struct component_footer component_footers[NR_PROGRAM_COMPONENTS] = {
[COMPONENT_ID_HEAP_AREA] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "heap area"
},
[COMPONENT_ID_STACK_AREA] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "stack area"
},
[COMPONENT_ID_LOADER_SIGNATURE] = {
.type = COMPONENT_TYPE_SIGNATURE,
.desc = "loader signature"
},
[COMPONENT_ID_LOADER] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "internal loader"
},
[COMPONENT_ID_PARAMETERS] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "parameters"
},
[COMPONENT_ID_IMAGE_SIGNATURE] = {
.type = COMPONENT_TYPE_SIGNATURE,
.desc = "image signature"
},
[COMPONENT_ID_KERNEL_IMAGE] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "kernel image"
},
[COMPONENT_ID_PARMLINE] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "parmline"
},
[COMPONENT_ID_RAMDISK_SIGNATURE] = {
.type = COMPONENT_TYPE_SIGNATURE,
.desc = "ramdisk signature"
},
[COMPONENT_ID_RAMDISK] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "initial ramdisk"
},
[COMPONENT_ID_ENVBLK] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "environment blk"
},
[COMPONENT_ID_SEGMENT_FILE] = {
.type = COMPONENT_TYPE_EXECUTE,
.desc = "segment file"
}
};