mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Compare commits
67 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4014087876 | ||
|
|
8a878a0d61 | ||
|
|
2b511aa2b9 | ||
|
|
6d8243d1b1 | ||
|
|
7ecaeb1a3d | ||
|
|
9ada8332d8 | ||
|
|
ca25f71a6e | ||
|
|
67790d3787 | ||
|
|
d301668811 | ||
|
|
6097ee3f9d | ||
|
|
43967feb2c | ||
|
|
8f4535f5eb | ||
|
|
dfe8a4f803 | ||
|
|
fe0d42e295 | ||
|
|
baf7e9aa2e | ||
|
|
60d03262d8 | ||
|
|
4bed503aa7 | ||
|
|
4518bf7d73 | ||
|
|
3d168fac14 | ||
|
|
746a703079 | ||
|
|
4aa5534f1d | ||
|
|
7c24855ba1 | ||
|
|
6222c38495 | ||
|
|
8709a47f6f | ||
|
|
1fb05038cd | ||
|
|
4f5d33988d | ||
|
|
75513ee975 | ||
|
|
b8fff9b750 | ||
|
|
d5f853c460 | ||
|
|
067dd5c7ef | ||
|
|
af1d05c4a4 | ||
|
|
c5ec01420f | ||
|
|
f25984e716 | ||
|
|
7babd82e6f | ||
|
|
d030874050 | ||
|
|
394a6dd5ea | ||
|
|
db6eb7d554 | ||
|
|
032304d503 | ||
|
|
f75c923627 | ||
|
|
bca8fa3f9c | ||
|
|
d713ea6389 | ||
|
|
f9fbe79e4f | ||
|
|
3cc0b4cdea | ||
|
|
eef9f622c0 | ||
|
|
889293e557 | ||
|
|
0c5b9f5d11 | ||
|
|
02af069d48 | ||
|
|
5e0056db8d | ||
|
|
4b5937f142 | ||
|
|
8d8d5e9746 | ||
|
|
5bdabe3e06 | ||
|
|
8a1db94d37 | ||
|
|
1911cba130 | ||
|
|
f4ed0b0ec6 | ||
|
|
6e42c527d7 | ||
|
|
f7d2339c6a | ||
|
|
cf5f373142 | ||
|
|
e09c675b70 | ||
|
|
6bd93f475c | ||
|
|
3f12bdf4c7 | ||
|
|
3aa7f6e298 | ||
|
|
4e28047eb4 | ||
|
|
f654b971d0 | ||
|
|
e742d1c9ae | ||
|
|
803b87e324 | ||
|
|
5107a7be16 | ||
|
|
1178291686 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -78,7 +78,6 @@ systemd/ttyrun-getty@.service
|
|||||||
tape390/tape390_crypt
|
tape390/tape390_crypt
|
||||||
tape390/tape390_display
|
tape390/tape390_display
|
||||||
tunedasd/src/tunedasd
|
tunedasd/src/tunedasd
|
||||||
vmconvert/vmconvert
|
|
||||||
vmcp/vmcp
|
vmcp/vmcp
|
||||||
vmur/vmur
|
vmur/vmur
|
||||||
zconf/chp/chchp
|
zconf/chp/chchp
|
||||||
@@ -95,6 +94,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
|
||||||
@@ -107,6 +109,7 @@ ziomon/ziorep_traffic
|
|||||||
ziomon/ziorep_utilization
|
ziomon/ziorep_utilization
|
||||||
zipl/boot/*.bin
|
zipl/boot/*.bin
|
||||||
zipl/boot/*.exec
|
zipl/boot/*.exec
|
||||||
|
zipl/boot/.loaders
|
||||||
zipl/boot/data.h
|
zipl/boot/data.h
|
||||||
zipl/src/chreipl_helper.device-mapper
|
zipl/src/chreipl_helper.device-mapper
|
||||||
zdev/src/zdev_id
|
zdev/src/zdev_id
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -89,6 +90,7 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Mikhail Zaslonko
|
- Mikhail Zaslonko
|
||||||
- Nikita Dubrovskii
|
- Nikita Dubrovskii
|
||||||
- Niklas Schnelle
|
- Niklas Schnelle
|
||||||
|
- Nikolay Gueorguiev
|
||||||
- Peter Oberparleiter
|
- Peter Oberparleiter
|
||||||
- Peter Tiedemann
|
- Peter Tiedemann
|
||||||
- Philipp Kern
|
- Philipp Kern
|
||||||
|
|||||||
33
CHANGELOG.md
33
CHANGELOG.md
@@ -1,6 +1,39 @@
|
|||||||
Release history for s390-tools (MIT version)
|
Release history for s390-tools (MIT version)
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
|
* __v2.26.0 (2023-02-14)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.2
|
||||||
|
|
||||||
|
Remove tools / libraries:
|
||||||
|
- Remove vmconvert and libvmdump in favor of vmdump file support in zdump
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- ipl_tools: Add support for list-directed IPL from ECKD DASD
|
||||||
|
- lszcrypt: Display hardware filtering support capability
|
||||||
|
- vmur: Remove option -c for dump file conversion (See zdump changes)
|
||||||
|
- zdev: Add zfcp ber_stop parameter handling
|
||||||
|
- zdump: Add vmdump dfi for vmdump format to elf format
|
||||||
|
- zkey: Support EP11 host library version
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- zipl: Move dump parmline processing and verification
|
||||||
|
- zipl/genprotimg: Various build improvements
|
||||||
|
|
||||||
|
* __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
|
||||||
|
|||||||
4
Makefile
4
Makefile
@@ -9,11 +9,11 @@ include common.mak
|
|||||||
# TOOLS: Tools that can have a dependency to base libraries or libraries
|
# TOOLS: Tools that can have a dependency to base libraries or libraries
|
||||||
#
|
#
|
||||||
BASELIB_DIRS = libutil libseckey
|
BASELIB_DIRS = libutil libseckey
|
||||||
LIB_DIRS = libvtoc libzds libdasd libvmdump libccw libvmcp libekmfweb \
|
LIB_DIRS = libvtoc libzds libdasd libccw libvmcp libekmfweb \
|
||||||
libkmipclient libcpumf libap libpv
|
libkmipclient libcpumf libap libpv
|
||||||
TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
|
TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
|
||||||
tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \
|
tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \
|
||||||
vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
|
vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
|
||||||
ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
|
ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
|
||||||
systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl \
|
systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl \
|
||||||
genprotimg lsstp hsci hsavmcore chreipl-fcp-mpath ap_tools pvattest
|
genprotimg lsstp hsci hsavmcore chreipl-fcp-mpath ap_tools pvattest
|
||||||
|
|||||||
@@ -98,11 +98,6 @@ Package contents
|
|||||||
* tunedasd:
|
* tunedasd:
|
||||||
Adjust tunable parameters on DASD devices.
|
Adjust tunable parameters on DASD devices.
|
||||||
|
|
||||||
* vmconvert:
|
|
||||||
Convert system dumps created by the z/VM VMDUMP command into dumps with
|
|
||||||
LKCD format. These LKCD dumps can then be analyzed with the dump analysis
|
|
||||||
tool lcrash.
|
|
||||||
|
|
||||||
* vmcp:
|
* vmcp:
|
||||||
Send commands from Linux as a z/VM guest to the z/VM control program (CP).
|
Send commands from Linux as a z/VM guest to the z/VM control program (CP).
|
||||||
Call vmcp with the CP command as an argument. The response of z/VM is
|
Call vmcp with the CP command as an argument. The response of z/VM is
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -23,15 +26,26 @@ ap-check: ap-check.o $(libs)
|
|||||||
install: all
|
install: all
|
||||||
@if [ ! -d $(DESTDIR)$(MDEVCTL_CALLOUTS) ]; then \
|
@if [ ! -d $(DESTDIR)$(MDEVCTL_CALLOUTS) ]; then \
|
||||||
mkdir -p $(DESTDIR)$(MDEVCTL_CALLOUTS); \
|
mkdir -p $(DESTDIR)$(MDEVCTL_CALLOUTS); \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(MDEVCTL_DIR); \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(MDEVCTL_DIR); \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(MDEVCTL_SCRIPTS); \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(MDEVCTL_SCRIPTS); \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(MDEVCTL_CALLOUTS); \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(MDEVCTL_CALLOUTS); \
|
||||||
chmod 755 $(DESTDIR)$(MDEVCTL_DIR); \
|
chmod 755 $(DESTDIR)$(MDEVCTL_DIR); \
|
||||||
chmod 755 $(DESTDIR)$(MDEVCTL_SCRIPTS); \
|
chmod 755 $(DESTDIR)$(MDEVCTL_SCRIPTS); \
|
||||||
chmod 755 $(DESTDIR)$(MDEVCTL_CALLOUTS); \
|
chmod 755 $(DESTDIR)$(MDEVCTL_CALLOUTS); \
|
||||||
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
ap_tools/ap-check.sh
Normal file
15
ap_tools/ap-check.sh
Normal 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 "$@"
|
||||||
31
common.mak
31
common.mak
@@ -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 = 26
|
||||||
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
|
||||||
@@ -145,6 +145,20 @@ then \
|
|||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test for linker option
|
||||||
|
#
|
||||||
|
# $1: Linker option
|
||||||
|
#
|
||||||
|
# Returns the linker option if available and nothing otherwise
|
||||||
|
#
|
||||||
|
define test_linker_flag
|
||||||
|
$(shell printf "int main(void) {return 0;}\n" | \
|
||||||
|
( $(CC) "-Wl,$1" -o /dev/null -x c - ) >/dev/null 2>&1 && printf -- '-Wl,%s' "$1")
|
||||||
|
endef
|
||||||
|
|
||||||
|
NO_WARN_RWX_SEGMENTS_LDFLAGS := $(call test_linker_flag,"--no-warn-rwx-segments")
|
||||||
|
|
||||||
#
|
#
|
||||||
# Support alternate install root
|
# Support alternate install root
|
||||||
#
|
#
|
||||||
@@ -261,7 +275,7 @@ else
|
|||||||
NO_PIE_LDFLAGS :=
|
NO_PIE_LDFLAGS :=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Overwrite implicite makefile rules for having nice compile output
|
# Overwrite implicit makefile rules for having nice compile output
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
ifeq ("${C}","1")
|
ifeq ("${C}","1")
|
||||||
$(CHECKTOOL) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c $< -o $@
|
$(CHECKTOOL) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c $< -o $@
|
||||||
@@ -364,10 +378,6 @@ $(rootdir)/libzds/libzds.a: $(rootdir)/libzds
|
|||||||
$(MAKE) -C $(rootdir)/libzds/ libzds.a
|
$(MAKE) -C $(rootdir)/libzds/ libzds.a
|
||||||
.PHONY: $(rootdir)/libzds
|
.PHONY: $(rootdir)/libzds
|
||||||
|
|
||||||
$(rootdir)/libvmdump/libvmdump.a: $(rootdir)/libvmdump
|
|
||||||
$(MAKE) -C $(rootdir)/libvmdump/ libvmdump.a
|
|
||||||
.PHONY: $(rootdir)/libvmdump
|
|
||||||
|
|
||||||
$(rootdir)/libvmcp/libvmcp.a: $(rootdir)/libvmcp
|
$(rootdir)/libvmcp/libvmcp.a: $(rootdir)/libvmcp
|
||||||
$(MAKE) -C $(rootdir)/libvmcp/ libvmcp.a
|
$(MAKE) -C $(rootdir)/libvmcp/ libvmcp.a
|
||||||
.PHONY: $(rootdir)/libvmcp
|
.PHONY: $(rootdir)/libvmcp
|
||||||
@@ -396,8 +406,8 @@ $(rootdir)/libpv/libpv.a: $(rootdir)/libpv
|
|||||||
$(MAKE) -C $(rootdir)/libpv libpv.a
|
$(MAKE) -C $(rootdir)/libpv libpv.a
|
||||||
.PHONY: $(rootdir)/libpv
|
.PHONY: $(rootdir)/libpv
|
||||||
|
|
||||||
$(rootdir)/zipl/boot/data.o:
|
$(rootdir)/zipl/boot/.loaders:
|
||||||
$(MAKE) -C $(rootdir)/zipl/boot/ data.o
|
$(MAKE) -C $(rootdir)/zipl/boot/ .loaders
|
||||||
|
|
||||||
install_dirs:
|
install_dirs:
|
||||||
for dir in $(INSTDIRS); do \
|
for dir in $(INSTDIRS); do \
|
||||||
@@ -422,4 +432,3 @@ clean_dep:
|
|||||||
|
|
||||||
clean: clean_echo clean_gcov clean_dep
|
clean: clean_echo clean_gcov clean_dep
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
@@ -69,27 +69,15 @@ endif
|
|||||||
|
|
||||||
stage3b_reloc.o: stage3b.bin
|
stage3b_reloc.o: stage3b.bin
|
||||||
|
|
||||||
stage3a.elf: head.o stage3a_init.o stage3a.o stage3a.lds $(ZIPL_OBJS)
|
stage3a.elf: head.o stage3a_init.o $(ZIPL_OBJS)
|
||||||
stage3b.elf: head.o stage3b.o stage3b.lds $(ZIPL_OBJS)
|
stage3b.elf: head.o $(ZIPL_OBJS)
|
||||||
stage3b_reloc.elf:
|
|
||||||
|
|
||||||
%.elf: %.o
|
%.elf: %.lds %.o
|
||||||
case $* in \
|
$(LINK) $(NO_PIE_LDFLAGS) $(NO_WARN_RWX_SEGMENTS_LDFLAGS) -Wl,-T,$< -Wl,--build-id=none -m64 -static -nostdlib $(filter %.o, $^) -o $@
|
||||||
stage3a) SFLAGS="-Wl,-T,stage3a.lds";; \
|
|
||||||
stage3b) SFLAGS="-Wl,-T,stage3b.lds";; \
|
|
||||||
stage3b_reloc) SFLAGS="-Wl,-estage3b_reloc_start,-Ttext,0";; \
|
|
||||||
esac; \
|
|
||||||
$(LINK) $$SFLAGS $(NO_PIE_LDFLAGS) -m64 -static -nostdlib $(filter %.o, $^) -o $@
|
|
||||||
@chmod a-x $@
|
@chmod a-x $@
|
||||||
|
|
||||||
%.bin: %.elf
|
%.bin: %.elf
|
||||||
$(OBJCOPY) -O binary \
|
$(OBJCOPY) -O binary $< $@
|
||||||
--only-section=.text* \
|
|
||||||
--only-section=.ex_table* \
|
|
||||||
--only-section=.fixup* \
|
|
||||||
--only-section=.data* \
|
|
||||||
--only-section=.rodata* \
|
|
||||||
$< $@
|
|
||||||
@chmod a-x $@
|
@chmod a-x $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
@@ -29,3 +29,8 @@ _start:
|
|||||||
brasl %r14, initialize
|
brasl %r14, initialize
|
||||||
.Lstack: .long STACK_ADDRESS + STACK_SIZE - STACK_FRAME_OVERHEAD
|
.Lstack: .long STACK_ADDRESS + STACK_SIZE - STACK_FRAME_OVERHEAD
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
|
/* The code doesn't require an executable stack */
|
||||||
|
#if defined(__linux__) && defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ ENTRY(_init)
|
|||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0x0;
|
|
||||||
|
|
||||||
. = HEAP_ADDRESS;
|
. = HEAP_ADDRESS;
|
||||||
__heap_start = .;
|
__heap_start = .;
|
||||||
.heap : {
|
.heap : {
|
||||||
@@ -46,7 +44,7 @@ SECTIONS
|
|||||||
. = STAGE3A_INIT_ENTRY;
|
. = STAGE3A_INIT_ENTRY;
|
||||||
__text_init_start = .;
|
__text_init_start = .;
|
||||||
.text : {
|
.text : {
|
||||||
stage3a_init.o(.text.init)
|
*(.text.init)
|
||||||
__text_init_stop = ABSOLUTE(.);
|
__text_init_stop = ABSOLUTE(.);
|
||||||
/* Text size of text_init must be smaller than 'PARMAREA - IMAGE_ENTRY',
|
/* Text size of text_init must be smaller than 'PARMAREA - IMAGE_ENTRY',
|
||||||
* otherwise the text data could be overwritten by the original zipl stage3
|
* otherwise the text data could be overwritten by the original zipl stage3
|
||||||
@@ -56,8 +54,8 @@ SECTIONS
|
|||||||
. = 0x1000;
|
. = 0x1000;
|
||||||
ASSERT(ABSOLUTE(.) == STAGE3A_ENTRY,
|
ASSERT(ABSOLUTE(.) == STAGE3A_ENTRY,
|
||||||
"Text section doesn't conform to the described memory layout");
|
"Text section doesn't conform to the described memory layout");
|
||||||
head.o(.text.start)
|
*(.text.start)
|
||||||
*(.text)
|
*(.text .text.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
.ex_table ALIGN(16) : {
|
.ex_table ALIGN(16) : {
|
||||||
@@ -74,7 +72,7 @@ SECTIONS
|
|||||||
|
|
||||||
.rodata ALIGN(16) : {
|
.rodata ALIGN(16) : {
|
||||||
*(.rodata)
|
*(.rodata)
|
||||||
*(.rodata.*)
|
*(.rodata*)
|
||||||
}
|
}
|
||||||
|
|
||||||
.data ALIGN(16) : {
|
.data ALIGN(16) : {
|
||||||
@@ -90,14 +88,10 @@ SECTIONS
|
|||||||
ASSERT(ABSOLUTE(.) < 0x13000, "Data section doesn't conform to the described memory layout");
|
ASSERT(ABSOLUTE(.) < 0x13000, "Data section doesn't conform to the described memory layout");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* List this explicitly as otherwise .note.gnu.build-id will be
|
|
||||||
* put at 0x0 */
|
|
||||||
.notes : {
|
|
||||||
*(.note.*)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sections to be discarded */
|
/* Sections to be discarded */
|
||||||
/DISCARD/ : {
|
/DISCARD/ : {
|
||||||
*(.eh_frame)
|
*(.eh_frame)
|
||||||
|
*(.interp)
|
||||||
|
*(.note.GNU-stack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,3 +26,8 @@ _init:
|
|||||||
br %r1
|
br %r1
|
||||||
.Lstage3a_entry: .long STAGE3A_ENTRY
|
.Lstage3a_entry: .long STAGE3A_ENTRY
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
|
/* The code doesn't require an executable stack */
|
||||||
|
#if defined(__linux__) && defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ ENTRY(_start)
|
|||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0x0;
|
|
||||||
|
|
||||||
. = HEAP_ADDRESS;
|
. = HEAP_ADDRESS;
|
||||||
__heap_start = .;
|
__heap_start = .;
|
||||||
.heap : {
|
.heap : {
|
||||||
@@ -34,8 +32,8 @@ SECTIONS
|
|||||||
|
|
||||||
. = STAGE3B_ENTRY;
|
. = STAGE3B_ENTRY;
|
||||||
.text : {
|
.text : {
|
||||||
head.o(.text.start)
|
*(.text.start)
|
||||||
*(.text)
|
*(.text .text.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
.ex_table ALIGN(16) : {
|
.ex_table ALIGN(16) : {
|
||||||
@@ -52,7 +50,7 @@ SECTIONS
|
|||||||
|
|
||||||
.rodata ALIGN(16) : {
|
.rodata ALIGN(16) : {
|
||||||
*(.rodata)
|
*(.rodata)
|
||||||
*(.rodata.*)
|
*(.rodata*)
|
||||||
}
|
}
|
||||||
|
|
||||||
.data ALIGN(16) : {
|
.data ALIGN(16) : {
|
||||||
@@ -74,14 +72,12 @@ SECTIONS
|
|||||||
}
|
}
|
||||||
__stack_end = .;
|
__stack_end = .;
|
||||||
|
|
||||||
/* List this explicitly as otherwise .note.gnu.build-id will be
|
ASSERT(. <= IMAGE_ENTRY, "stage3b size must be smaller than 0x10000 bytes")
|
||||||
* put at 0x0 */
|
|
||||||
.notes : {
|
|
||||||
*(.note.*)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sections to be discarded */
|
/* Sections to be discarded */
|
||||||
/DISCARD/ : {
|
/DISCARD/ : {
|
||||||
*(.eh_frame)
|
*(.eh_frame)
|
||||||
|
*(.interp)
|
||||||
|
*(.note.GNU-stack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,8 @@
|
|||||||
|
|
||||||
.org 0x0
|
.org 0x0
|
||||||
.section .text.start
|
.section .text.start
|
||||||
.globl stage3b_reloc_start
|
.globl _start
|
||||||
stage3b_reloc_start:
|
_start:
|
||||||
/* Might be called after a diag308 so better set
|
/* Might be called after a diag308 so better set
|
||||||
* architecture and addressing mode
|
* architecture and addressing mode
|
||||||
*/
|
*/
|
||||||
@@ -53,3 +53,8 @@ stage3b_start:
|
|||||||
.incbin "stage3b.bin"
|
.incbin "stage3b.bin"
|
||||||
stage3b_end:
|
stage3b_end:
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
|
/* The code doesn't require an executable stack */
|
||||||
|
#if defined(__linux__) && defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
|
|||||||
19
genprotimg/boot/stage3b_reloc.lds.S
Normal file
19
genprotimg/boot/stage3b_reloc.lds.S
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
|
||||||
|
OUTPUT_ARCH(s390:64-bit)
|
||||||
|
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.text : {
|
||||||
|
*(.text.start)
|
||||||
|
*(.text .text.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sections to be discarded */
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.eh_frame)
|
||||||
|
*(.interp)
|
||||||
|
*(.note.GNU-stack)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,7 +52,7 @@ install-scripts: lshmc
|
|||||||
cat $$i | \
|
cat $$i | \
|
||||||
sed -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
sed -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
||||||
>$(DESTDIR)$(USRSBINDIR)/$$i; \
|
>$(DESTDIR)$(USRSBINDIR)/$$i; \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(USRSBINDIR)/$$i; \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(USRSBINDIR)/$$i; \
|
||||||
chmod 755 $(DESTDIR)$(USRSBINDIR)/$$i; \
|
chmod 755 $(DESTDIR)$(USRSBINDIR)/$$i; \
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ all:
|
|||||||
install: hsci
|
install: hsci
|
||||||
$(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
$(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
||||||
< hsci >$(DESTDIR)$(BINDIR)/hsci; \
|
< hsci >$(DESTDIR)$(BINDIR)/hsci; \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(BINDIR)/hsci; \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(BINDIR)/hsci; \
|
||||||
chmod 755 $(DESTDIR)$(BINDIR)/hsci; \
|
chmod 755 $(DESTDIR)$(BINDIR)/hsci; \
|
||||||
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man8
|
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man8
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 hsci.8 \
|
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 hsci.8 \
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -14,12 +14,18 @@
|
|||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
#include "linux_layout.h"
|
#include "linux_layout.h"
|
||||||
|
|
||||||
|
#define STAGE0_LOAD_ADDRESS _AC(0x0, UL)
|
||||||
|
|
||||||
|
#define STAGE1_LOAD_ADDRESS _AC(0x18, UL)
|
||||||
|
#define STAGE1B_LOAD_ADDRESS _AC(0xe000, UL)
|
||||||
|
|
||||||
#define STAGE2_DESC _AC(0x78, UL)
|
#define STAGE2_DESC _AC(0x78, UL)
|
||||||
#define STAGE2_ENTRY _AC(0x2018, UL)
|
#define STAGE2_ENTRY _AC(0x2018, UL)
|
||||||
#define STAGE2_HEAP_ADDRESS _AC(0x6000, UL)
|
#define STAGE2_HEAP_ADDRESS _AC(0x6000, UL)
|
||||||
#define STAGE2_HEAP_SIZE _AC(0x3000, UL)
|
#define STAGE2_HEAP_SIZE _AC(0x3000, UL)
|
||||||
#define STAGE2_STACK_ADDRESS _AC(0xe400, UL)
|
#define STAGE2_STACK_ADDRESS _AC(0xe400, UL)
|
||||||
#define STAGE2_STACK_SIZE _AC(0x1c00, UL)
|
#define STAGE2_STACK_SIZE _AC(0x1c00, UL)
|
||||||
|
#define STAGE2_MAX_SIZE _AC(0x3000, UL)
|
||||||
|
|
||||||
#define STAGE3_ENTRY _AC(0xa000, UL)
|
#define STAGE3_ENTRY _AC(0xa000, UL)
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -18,6 +18,12 @@
|
|||||||
#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_56
|
#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_56
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_56
|
||||||
|
|
||||||
|
#ifdef __G_LIB_H__
|
||||||
|
#error "glib.h must be included via libpv/glib-helper.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <gmodule.h>
|
#include <gmodule.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ clean:
|
|||||||
install: ip_watcher.pl xcec-bridge start_hsnc.sh
|
install: ip_watcher.pl xcec-bridge start_hsnc.sh
|
||||||
$(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
$(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
||||||
< start_hsnc.sh >$(DESTDIR)$(USRSBINDIR)/start_hsnc.sh; \
|
< start_hsnc.sh >$(DESTDIR)$(USRSBINDIR)/start_hsnc.sh; \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(USRSBINDIR)/start_hsnc.sh; \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(USRSBINDIR)/start_hsnc.sh; \
|
||||||
chmod 755 $(DESTDIR)$(USRSBINDIR)/start_hsnc.sh; \
|
chmod 755 $(DESTDIR)$(USRSBINDIR)/start_hsnc.sh; \
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 ip_watcher.pl \
|
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 ip_watcher.pl \
|
||||||
$(DESTDIR)$(USRSBINDIR)
|
$(DESTDIR)$(USRSBINDIR)
|
||||||
|
|||||||
@@ -23,12 +23,15 @@
|
|||||||
#define BOOTPARMS_CCW_MAX 64
|
#define BOOTPARMS_CCW_MAX 64
|
||||||
#define BOOTPARMS_FCP_MAX 3452
|
#define BOOTPARMS_FCP_MAX 3452
|
||||||
|
|
||||||
|
#define OPT_BRCHR 0x80
|
||||||
|
|
||||||
enum target_type {
|
enum target_type {
|
||||||
TT_CCW,
|
TT_CCW,
|
||||||
TT_FCP,
|
TT_FCP,
|
||||||
TT_NSS,
|
TT_NSS,
|
||||||
TT_NODE,
|
TT_NODE,
|
||||||
TT_NVME,
|
TT_NVME,
|
||||||
|
TT_ECKD,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum reipl_type {
|
enum reipl_type {
|
||||||
@@ -36,12 +39,14 @@ enum reipl_type {
|
|||||||
REIPL_CCW,
|
REIPL_CCW,
|
||||||
REIPL_NSS,
|
REIPL_NSS,
|
||||||
REIPL_NVME,
|
REIPL_NVME,
|
||||||
|
REIPL_ECKD,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *const usage_chreipl =
|
static const char *const usage_chreipl =
|
||||||
"Usage: %s [TARGET] [ARGS] [OPTIONS]\n"
|
"Usage: %s [TARGET] [ARGS] [OPTIONS]\n"
|
||||||
"\n"
|
"\n"
|
||||||
" chreipl [ccw] [-d] <DEVICE> [OPTIONS]\n"
|
" chreipl [ccw] [-d] <DEVICE> [OPTIONS]\n"
|
||||||
|
" chreipl [eckd] [-d] <DEVICE> [OPTIONS]\n"
|
||||||
" chreipl [fcp] [-d] <DEVICE> [-w] <WWPN> [-l] <LUN> [OPTIONS]\n"
|
" chreipl [fcp] [-d] <DEVICE> [-w] <WWPN> [-l] <LUN> [OPTIONS]\n"
|
||||||
" chreipl nvme [-i] <FID> [-s] <NSID> [OPTIONS]\n"
|
" chreipl nvme [-i] <FID> [-s] <NSID> [OPTIONS]\n"
|
||||||
" chreipl [node] <NODE|DIR> [OPTIONS]\n"
|
" chreipl [node] <NODE|DIR> [OPTIONS]\n"
|
||||||
@@ -50,6 +55,7 @@ static const char *const usage_chreipl =
|
|||||||
"\n"
|
"\n"
|
||||||
"The following re-IPL targets are supported:\n"
|
"The following re-IPL targets are supported:\n"
|
||||||
" ccw IPL from CCW device\n"
|
" ccw IPL from CCW device\n"
|
||||||
|
" eckd IPL from ECKD device\n"
|
||||||
" fcp IPL from FCP device\n"
|
" fcp IPL from FCP device\n"
|
||||||
" nvme IPL from NVME device\n"
|
" nvme IPL from NVME device\n"
|
||||||
" nss IPL from NSS\n"
|
" nss IPL from NSS\n"
|
||||||
@@ -66,6 +72,13 @@ static const char *const usage_chreipl =
|
|||||||
" -L, --loadparm <PARM> Loadparm specification\n"
|
" -L, --loadparm <PARM> Loadparm specification\n"
|
||||||
" -c, --clear 0|1 Control if memory is cleared on re-IPL\n"
|
" -c, --clear 0|1 Control if memory is cleared on re-IPL\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"Options for eckd target:\n"
|
||||||
|
" -d, --device <DEVICE> Device number of the ECKD IPL device\n"
|
||||||
|
" -b, --bootprog <BPROG> Bootprog specification\n"
|
||||||
|
" --brchr <C,H,R> Boot record location in Cylinder,Head,Record format\n"
|
||||||
|
" -L, --loadparm <PARM> Loadparm specification\n"
|
||||||
|
" -c, --clear 0|1 Control if memory is cleared on re-IPL\n"
|
||||||
|
"\n"
|
||||||
"Options for fcp target:\n"
|
"Options for fcp target:\n"
|
||||||
" -d, --device <DEVICE> Device number of the adapter of the FCP IPL device\n"
|
" -d, --device <DEVICE> Device number of the adapter of the FCP IPL device\n"
|
||||||
" -l --lun <LUN> Logical unit number of the FCP IPL device\n"
|
" -l --lun <LUN> Logical unit number of the FCP IPL device\n"
|
||||||
@@ -114,6 +127,8 @@ static struct locals {
|
|||||||
int target_type_auto_mode;
|
int target_type_auto_mode;
|
||||||
enum reipl_type reipl_type; /* CCW, FCP, NVME, NSS */
|
enum reipl_type reipl_type; /* CCW, FCP, NVME, NSS */
|
||||||
int reipl_clear;
|
int reipl_clear;
|
||||||
|
char *brchr;
|
||||||
|
int brchr_set;
|
||||||
} l;
|
} l;
|
||||||
|
|
||||||
static void __noreturn print_usage_chreipl_exit(void)
|
static void __noreturn print_usage_chreipl_exit(void)
|
||||||
@@ -329,6 +344,19 @@ static void parse_ccw_args(char *nargv[], int nargc)
|
|||||||
set_device(nargv[0]);
|
set_device(nargv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_eckd_args(char *nargv[], int nargc)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* we might be called like this:
|
||||||
|
* chreipl eckd 4711
|
||||||
|
*/
|
||||||
|
if (l.busid_set)
|
||||||
|
ERR_EXIT("Use either options or positional parameters");
|
||||||
|
if (nargc > 1)
|
||||||
|
ERR_EXIT("Too many arguments specified for \"eckd\" re-IPL type");
|
||||||
|
set_device(nargv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_nss_args(char *nargv[], int nargc)
|
static void parse_nss_args(char *nargv[], int nargc)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -369,6 +397,8 @@ static int set_reipl_type(const char *dev_name)
|
|||||||
l.reipl_type = REIPL_FCP;
|
l.reipl_type = REIPL_FCP;
|
||||||
else if (strncmp(dev_name, "nvme", strlen("nvme")) == 0)
|
else if (strncmp(dev_name, "nvme", strlen("nvme")) == 0)
|
||||||
l.reipl_type = REIPL_NVME;
|
l.reipl_type = REIPL_NVME;
|
||||||
|
else if (strncmp(dev_name, "eckd", strlen("eckd")) == 0)
|
||||||
|
l.reipl_type = REIPL_ECKD;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -493,12 +523,15 @@ static void parse_pos_args(char *nargv[], int nargc)
|
|||||||
case TT_NODE:
|
case TT_NODE:
|
||||||
parse_node_args(nargv, nargc);
|
parse_node_args(nargv, nargc);
|
||||||
break;
|
break;
|
||||||
|
case TT_ECKD:
|
||||||
|
parse_eckd_args(nargv, nargc);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_fcp_opts(void)
|
static void check_fcp_opts(void)
|
||||||
{
|
{
|
||||||
if (l.nss_name_set)
|
if (l.nss_name_set || l.brchr_set)
|
||||||
ERR_EXIT("Invalid option for \"fcp\" target specified");
|
ERR_EXIT("Invalid option for \"fcp\" target specified");
|
||||||
if (!(l.busid_set && l.wwpn_set && l.lun_set))
|
if (!(l.busid_set && l.wwpn_set && l.lun_set))
|
||||||
ERR_EXIT("The \"fcp\" target requires device, WWPN, "
|
ERR_EXIT("The \"fcp\" target requires device, WWPN, "
|
||||||
@@ -507,7 +540,8 @@ static void check_fcp_opts(void)
|
|||||||
|
|
||||||
static void check_nvme_opts(void)
|
static void check_nvme_opts(void)
|
||||||
{
|
{
|
||||||
if (l.nss_name_set || l.wwpn_set || l.lun_set || l.busid_set)
|
if (l.nss_name_set || l.wwpn_set || l.lun_set || l.busid_set ||
|
||||||
|
l.brchr_set)
|
||||||
ERR_EXIT("Invalid option for \"nvme\" target specified");
|
ERR_EXIT("Invalid option for \"nvme\" target specified");
|
||||||
if (!(l.fid_set && l.nsid_set))
|
if (!(l.fid_set && l.nsid_set))
|
||||||
ERR_EXIT("The \"nvme\" target requires FID, and optional NSID");
|
ERR_EXIT("The \"nvme\" target requires FID, and optional NSID");
|
||||||
@@ -515,16 +549,25 @@ static void check_nvme_opts(void)
|
|||||||
|
|
||||||
static void check_ccw_opts(void)
|
static void check_ccw_opts(void)
|
||||||
{
|
{
|
||||||
if (l.bootprog_set || l.lun_set || l.wwpn_set || l.nss_name_set)
|
if (l.bootprog_set || l.lun_set || l.wwpn_set || l.nss_name_set ||
|
||||||
|
l.brchr_set)
|
||||||
ERR_EXIT("Invalid option for \"ccw\" target specified");
|
ERR_EXIT("Invalid option for \"ccw\" target specified");
|
||||||
if (!l.busid_set)
|
if (!l.busid_set)
|
||||||
ERR_EXIT("The \"ccw\" target requires device");
|
ERR_EXIT("The \"ccw\" target requires device");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void check_eckd_opts(void)
|
||||||
|
{
|
||||||
|
if (l.nss_name_set || l.wwpn_set || l.lun_set || l.fid_set)
|
||||||
|
ERR_EXIT("Invalid option for \"eckd\" target specified");
|
||||||
|
if (!(l.busid_set))
|
||||||
|
ERR_EXIT("The \"eckd\" target requires device");
|
||||||
|
}
|
||||||
|
|
||||||
static void check_nss_opts(void)
|
static void check_nss_opts(void)
|
||||||
{
|
{
|
||||||
if (l.bootprog_set || l.loadparm_set || l.busid_set || l.wwpn_set ||
|
if (l.bootprog_set || l.loadparm_set || l.busid_set || l.wwpn_set ||
|
||||||
l.lun_set)
|
l.lun_set || l.brchr_set)
|
||||||
ERR_EXIT("Invalid option for \"nss\" target specified");
|
ERR_EXIT("Invalid option for \"nss\" target specified");
|
||||||
if (!l.nss_name_set)
|
if (!l.nss_name_set)
|
||||||
ERR_EXIT("The \"nss\" target requires NSS name");
|
ERR_EXIT("The \"nss\" target requires NSS name");
|
||||||
@@ -563,6 +606,12 @@ static void set_reipl_clear(const char *arg)
|
|||||||
ERR_EXIT("re-IPL clear argument must be either 1 or 0");
|
ERR_EXIT("re-IPL clear argument must be either 1 or 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_brchr(const char *arg)
|
||||||
|
{
|
||||||
|
l.brchr = strdup(arg);
|
||||||
|
l.brchr_set = 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_chreipl_options(int argc, char *argv[])
|
static void parse_chreipl_options(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int opt, idx;
|
int opt, idx;
|
||||||
@@ -580,6 +629,7 @@ static void parse_chreipl_options(int argc, char *argv[])
|
|||||||
{ "force", no_argument, NULL, 'f' },
|
{ "force", no_argument, NULL, 'f' },
|
||||||
{ "version", no_argument, NULL, 'v' },
|
{ "version", no_argument, NULL, 'v' },
|
||||||
{ "clear", required_argument, NULL, 'c' },
|
{ "clear", required_argument, NULL, 'c' },
|
||||||
|
{ "brchr", required_argument, NULL, OPT_BRCHR },
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
static const char optstr[] = "hd:vw:l:fL:b:n:p:c:i:s:";
|
static const char optstr[] = "hd:vw:l:fL:b:n:p:c:i:s:";
|
||||||
@@ -592,6 +642,8 @@ static void parse_chreipl_options(int argc, char *argv[])
|
|||||||
set_target_type(TT_FCP, 0);
|
set_target_type(TT_FCP, 0);
|
||||||
else if (strcmp(argv[1], "ccw") == 0)
|
else if (strcmp(argv[1], "ccw") == 0)
|
||||||
set_target_type(TT_CCW, 0);
|
set_target_type(TT_CCW, 0);
|
||||||
|
else if (strcmp(argv[1], "eckd") == 0)
|
||||||
|
set_target_type(TT_ECKD, 0);
|
||||||
else if (strcmp(argv[1], "nss") == 0)
|
else if (strcmp(argv[1], "nss") == 0)
|
||||||
set_target_type(TT_NSS, 0);
|
set_target_type(TT_NSS, 0);
|
||||||
else if (strcmp(argv[1], "nvme") == 0)
|
else if (strcmp(argv[1], "nvme") == 0)
|
||||||
@@ -640,6 +692,9 @@ static void parse_chreipl_options(int argc, char *argv[])
|
|||||||
case 'c':
|
case 'c':
|
||||||
set_reipl_clear(optarg);
|
set_reipl_clear(optarg);
|
||||||
break;
|
break;
|
||||||
|
case OPT_BRCHR:
|
||||||
|
set_brchr(optarg);
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
print_version_exit();
|
print_version_exit();
|
||||||
default:
|
default:
|
||||||
@@ -737,6 +792,34 @@ static void chreipl_ccw(void)
|
|||||||
print_ccw(0);
|
print_ccw(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void chreipl_eckd(void)
|
||||||
|
{
|
||||||
|
check_eckd_opts();
|
||||||
|
|
||||||
|
if (!ccw_is_device(l.busid) && !l.force_set) {
|
||||||
|
if (is_ignored(l.busid))
|
||||||
|
ERR_EXIT("Device is on cio_ignore list, try \"cio_ignore -r %s\"?",
|
||||||
|
l.busid);
|
||||||
|
ERR_EXIT("Could not find DASD ECKD device \"%s\"", l.busid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l.reipl_clear >= 0) {
|
||||||
|
check_exists("reipl/eckd/clear", "ECKD re-IPL clear attribute");
|
||||||
|
write_str(l.reipl_clear ? "1" : "0", "reipl/eckd/clear");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!l.brchr_set)
|
||||||
|
l.brchr = "auto";
|
||||||
|
write_str(l.brchr, "reipl/eckd/br_chr");
|
||||||
|
if (!l.bootprog_set)
|
||||||
|
sprintf(l.bootprog, "0");
|
||||||
|
write_str(l.bootprog, "reipl/eckd/bootprog");
|
||||||
|
write_str(l.busid, "reipl/eckd/device");
|
||||||
|
write_str_optional(l.loadparm, "reipl/eckd/loadparm", l.loadparm_set, "loadparm");
|
||||||
|
write_str("eckd", "reipl/reipl_type");
|
||||||
|
print_eckd(0, "eckd");
|
||||||
|
}
|
||||||
|
|
||||||
static void chreipl_fcp(void)
|
static void chreipl_fcp(void)
|
||||||
{
|
{
|
||||||
check_fcp_opts();
|
check_fcp_opts();
|
||||||
@@ -850,6 +933,11 @@ static void chreipl_node(void)
|
|||||||
l.busid_set = 1;
|
l.busid_set = 1;
|
||||||
chreipl_ccw();
|
chreipl_ccw();
|
||||||
break;
|
break;
|
||||||
|
case REIPL_ECKD:
|
||||||
|
ccw_busid_get(l.dev, l.busid);
|
||||||
|
l.busid_set = 1;
|
||||||
|
chreipl_eckd();
|
||||||
|
break;
|
||||||
case REIPL_FCP:
|
case REIPL_FCP:
|
||||||
fcp_wwpn_get(l.dev, l.wwpn);
|
fcp_wwpn_get(l.dev, l.wwpn);
|
||||||
l.wwpn_set = 1;
|
l.wwpn_set = 1;
|
||||||
@@ -878,6 +966,9 @@ void cmd_chreipl(int argc, char *argv[])
|
|||||||
case TT_CCW:
|
case TT_CCW:
|
||||||
chreipl_ccw();
|
chreipl_ccw();
|
||||||
break;
|
break;
|
||||||
|
case TT_ECKD:
|
||||||
|
chreipl_eckd();
|
||||||
|
break;
|
||||||
case TT_FCP:
|
case TT_FCP:
|
||||||
chreipl_fcp();
|
chreipl_fcp();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -141,6 +141,30 @@ void print_ccw(int show_ipl)
|
|||||||
print_fw_str("clear: %s\n", dir, "clear");
|
print_fw_str("clear: %s\n", dir, "clear");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_eckd(int show_ipl, const char *name)
|
||||||
|
{
|
||||||
|
char *path_loadparm = show_ipl ? "/sys/firmware/ipl/loadparm" :
|
||||||
|
"/sys/firmware/reipl/eckd/loadparm";
|
||||||
|
char *dir = show_ipl ? "ipl" : "reipl/eckd";
|
||||||
|
char loadparm[9], loadparm_path[PATH_MAX];
|
||||||
|
|
||||||
|
printf("%-12s %s\n", get_ipl_banner(show_ipl), name);
|
||||||
|
|
||||||
|
print_fw_str("Device: %s\n", dir, "device");
|
||||||
|
print_fw_str("bootprog: %s\n", dir, "bootprog");
|
||||||
|
print_fw_str("br_chr: %s\n", dir, "br_chr");
|
||||||
|
print_fw_str("Bootparm: \"%s\"\n", dir, "scp_data");
|
||||||
|
if (access(path_loadparm, R_OK) == 0) {
|
||||||
|
sprintf(loadparm_path, "%s/%s", dir, "loadparm");
|
||||||
|
read_fw_str(loadparm, loadparm_path, sizeof(loadparm));
|
||||||
|
if (strcmp(loadparm, " ") == 0)
|
||||||
|
loadparm[0] = 0;
|
||||||
|
printf("Loadparm: \"%s\"\n", loadparm);
|
||||||
|
}
|
||||||
|
if (!show_ipl)
|
||||||
|
print_fw_str("clear: %s\n", dir, "clear");
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_lsreipl_options(int argc, char *argv[])
|
static void parse_lsreipl_options(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int opt, idx;
|
int opt, idx;
|
||||||
@@ -193,6 +217,9 @@ void cmd_lsreipl(int argc, char *argv[])
|
|||||||
print_nvme(l.ipl_set, 1);
|
print_nvme(l.ipl_set, 1);
|
||||||
else if (strcmp(reipl_type_str, "ccw") == 0)
|
else if (strcmp(reipl_type_str, "ccw") == 0)
|
||||||
print_ccw(l.ipl_set);
|
print_ccw(l.ipl_set);
|
||||||
|
else if (strcmp(reipl_type_str, "eckd") == 0 ||
|
||||||
|
strcmp(reipl_type_str, "eckd_dump") == 0)
|
||||||
|
print_eckd(l.ipl_set, reipl_type_str);
|
||||||
else if (strcmp(reipl_type_str, "nss") == 0)
|
else if (strcmp(reipl_type_str, "nss") == 0)
|
||||||
print_nss(l.ipl_set);
|
print_nss(l.ipl_set);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ extern void print_ccw(int show_ipl);
|
|||||||
extern void print_fcp(int show_ipl, int dump);
|
extern void print_fcp(int show_ipl, int dump);
|
||||||
extern void print_nvme(int show_ipl, int dump);
|
extern void print_nvme(int show_ipl, int dump);
|
||||||
extern void print_nss(int show_ipl);
|
extern void print_nss(int show_ipl);
|
||||||
|
extern void print_eckd(int show_ipl, const char *name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper
|
* Helper
|
||||||
@@ -75,6 +76,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);
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ The first argument specifies the re-IPL target:
|
|||||||
.RB "- " ccw :
|
.RB "- " ccw :
|
||||||
Specify a DASD CCW device for reboot
|
Specify a DASD CCW device for reboot
|
||||||
.TP
|
.TP
|
||||||
|
.RB "- " eckd :
|
||||||
|
Specify a DASD ECKD device for reboot
|
||||||
|
.TP
|
||||||
.RB "- " fcp :
|
.RB "- " fcp :
|
||||||
Specify a FCP device for reboot
|
Specify a FCP device for reboot
|
||||||
.TP
|
.TP
|
||||||
@@ -175,6 +178,63 @@ in the installed zIPL environment block for evaluation of zIPL environment
|
|||||||
variables in the kernel command line:
|
variables in the kernel command line:
|
||||||
|
|
||||||
\fB# chreipl ccw -d 0.0.7e78 -L 1S2\fP
|
\fB# chreipl ccw -d 0.0.7e78 -L 1S2\fP
|
||||||
|
|
||||||
|
.SH eckd
|
||||||
|
Use the eckd re-IPL target for DASD devices that are accessed by the hardware
|
||||||
|
using channel command word (CCW) channels. In contrast to the ccw re-IPL target,
|
||||||
|
the eckd target uses a list-directed bootloader that supports secure boot.
|
||||||
|
.TP
|
||||||
|
.BR "\-d" " or " "\-\-device"
|
||||||
|
Specifies the device bus-ID of the DASD. If the bus-ID starts with "0.0." this
|
||||||
|
prefix can be omitted and the four digit short notation can be used (e.g. 5000 is
|
||||||
|
the same as 0.0.5000).
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR "\-b" " or " "\-\-bootprog"
|
||||||
|
Specifies an entry in the ECKD boot configuration by defining the IPL boot
|
||||||
|
program selector. If omitted, '0' is used.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR "\-\-brchr"
|
||||||
|
Specifies the block on the DASD where the boot record is located. If omitted,
|
||||||
|
0 is used. The specification comprises comma-separated values for cylinder, head,
|
||||||
|
and record: "--brchr C,H,R". Alternatively, specifying "0" or "auto" makes the
|
||||||
|
bootloader determine the boot record location from the volume label.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR "\-L" " or " "\-\-loadparm"
|
||||||
|
The loadparm for the eckd re-IPL target is not used to control the ECKD boot
|
||||||
|
configuration that is defined by the
|
||||||
|
.BR zipl (8)
|
||||||
|
boot menu. Instead it can be used to control higher level boot loaders
|
||||||
|
like GRUB. For more details refer to distribution specific documentation.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR "\-c" " or " "\-\-clear"
|
||||||
|
Controls whether memory is cleared on re-IPL. Possible values are 0 to
|
||||||
|
disable and 1 to enable memory clearing on re-IPL.
|
||||||
|
Memory clearing is supported if the "clear" attribute is present in
|
||||||
|
/sys/firmware/reipl/eckd/.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
\fBExamples:\fP
|
||||||
|
.br
|
||||||
|
|
||||||
|
1. Next time reboot from the ECKD device with the bus-ID 0.0.7e78 and boot
|
||||||
|
program selector 0:
|
||||||
|
|
||||||
|
\fB# chreipl eckd 0.0.7e78\fP
|
||||||
|
|
||||||
|
2. Next time reboot from the ECKD device with the bus-ID 0.0.7e78 and boot
|
||||||
|
program selector 2:
|
||||||
|
|
||||||
|
\fB# chreipl eckd -d 0.0.7e78 -b 2\fP
|
||||||
|
|
||||||
|
3. Next time reboot from the ECKD device with the bus-ID 0.0.7e78 and tell
|
||||||
|
the bootloader that the bootrecord is located in Cylinder 3, Head 0, Record 1:
|
||||||
|
|
||||||
|
\fB# chreipl eckd -d 0.0.7e78 --brchr 3,0,1\fP
|
||||||
|
|
||||||
.SH fcp
|
.SH fcp
|
||||||
Use the fcp re-IPL target for SCSI disks that are accessed by the hardware
|
Use the fcp re-IPL target for SCSI disks that are accessed by the hardware
|
||||||
using Fibre Channel Protocol (FCP) channels.
|
using Fibre Channel Protocol (FCP) channels.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -552,6 +552,33 @@ static const OSSL_PARAM *sk_prov_cached_params_build(
|
|||||||
return provctx->cached_parms[index];
|
return provctx->cached_parms[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||||
|
static bool sk_prov_check_uint_param(const OSSL_PARAM params[],
|
||||||
|
const char *param_name,
|
||||||
|
const struct sk_prov_key *key,
|
||||||
|
int key_type,
|
||||||
|
unsigned int expected_value)
|
||||||
|
{
|
||||||
|
const OSSL_PARAM *p;
|
||||||
|
unsigned int value;
|
||||||
|
|
||||||
|
if (key == NULL)
|
||||||
|
return true;
|
||||||
|
if (key->type != key_type)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
p = OSSL_PARAM_locate_const(params, param_name);
|
||||||
|
if (p == NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (OSSL_PARAM_get_uint(p, &value) != 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return value == expected_value;
|
||||||
|
}
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
static struct sk_prov_op_ctx *sk_prov_op_newctx(struct sk_prov_ctx *provctx,
|
static struct sk_prov_op_ctx *sk_prov_op_newctx(struct sk_prov_ctx *provctx,
|
||||||
const char *propq,
|
const char *propq,
|
||||||
int type)
|
int type)
|
||||||
@@ -850,6 +877,20 @@ static int sk_prov_asym_op_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
|||||||
for (p = params; p != NULL && p->key != NULL; p++)
|
for (p = params; p != NULL && p->key != NULL; p++)
|
||||||
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
||||||
|
|
||||||
|
#ifdef OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION
|
||||||
|
/* OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION is for RSA decrypt only */
|
||||||
|
if (!sk_prov_check_uint_param(params,
|
||||||
|
OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION,
|
||||||
|
ctx->key, EVP_PKEY_RSA, 0) ||
|
||||||
|
!sk_prov_check_uint_param(params,
|
||||||
|
OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION,
|
||||||
|
ctx->key, EVP_PKEY_RSA_PSS, 0)) {
|
||||||
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
||||||
|
"Implicit rejection is not supported");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
default_set_params_fn = (OSSL_FUNC_asym_cipher_set_ctx_params_fn *)
|
default_set_params_fn = (OSSL_FUNC_asym_cipher_set_ctx_params_fn *)
|
||||||
sk_prov_get_default_asym_func(ctx->provctx,
|
sk_prov_get_default_asym_func(ctx->provctx,
|
||||||
ctx->type,
|
ctx->type,
|
||||||
@@ -1125,6 +1166,14 @@ static int sk_prov_asym_op_decrypt_init(void *vctx, void *vkey,
|
|||||||
struct sk_prov_op_ctx *ctx = vctx;
|
struct sk_prov_op_ctx *ctx = vctx;
|
||||||
struct sk_prov_key *key = vkey;
|
struct sk_prov_key *key = vkey;
|
||||||
const OSSL_PARAM *p;
|
const OSSL_PARAM *p;
|
||||||
|
#ifdef OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION
|
||||||
|
unsigned int implicit_rejection = 0;
|
||||||
|
OSSL_PARAM set_params[] = {
|
||||||
|
OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION,
|
||||||
|
&implicit_rejection),
|
||||||
|
OSSL_PARAM_END
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ctx == NULL || key == NULL)
|
if (ctx == NULL || key == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1133,6 +1182,20 @@ static int sk_prov_asym_op_decrypt_init(void *vctx, void *vkey,
|
|||||||
for (p = params; p != NULL && p->key != NULL; p++)
|
for (p = params; p != NULL && p->key != NULL; p++)
|
||||||
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
||||||
|
|
||||||
|
#ifdef OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION
|
||||||
|
/* OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION is for RSA decrypt only */
|
||||||
|
if (!sk_prov_check_uint_param(params,
|
||||||
|
OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION,
|
||||||
|
key, EVP_PKEY_RSA, 0) ||
|
||||||
|
!sk_prov_check_uint_param(params,
|
||||||
|
OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION,
|
||||||
|
key, EVP_PKEY_RSA_PSS, 0)) {
|
||||||
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
||||||
|
"Implicit rejection is not supported");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
default_decrypt_init_fn = (OSSL_FUNC_asym_cipher_decrypt_init_fn *)
|
default_decrypt_init_fn = (OSSL_FUNC_asym_cipher_decrypt_init_fn *)
|
||||||
sk_prov_get_default_asym_func(ctx->provctx,
|
sk_prov_get_default_asym_func(ctx->provctx,
|
||||||
ctx->type,
|
ctx->type,
|
||||||
@@ -1155,6 +1218,26 @@ static int sk_prov_asym_op_decrypt_init(void *vctx, void *vkey,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION
|
||||||
|
if ((key->type == EVP_PKEY_RSA || key->type == EVP_PKEY_RSA_PSS) &&
|
||||||
|
key->secure_key != NULL) {
|
||||||
|
/*
|
||||||
|
* By default, implicit rejection is enabled for the default
|
||||||
|
* provider. We currently do not support implicit rejection with
|
||||||
|
* secure keys, so disable implicit rejection in the default
|
||||||
|
* provider operation context to report its status correctly
|
||||||
|
* with get-params.
|
||||||
|
*/
|
||||||
|
implicit_rejection = 0;
|
||||||
|
if (!sk_prov_asym_op_set_ctx_params(ctx, set_params)) {
|
||||||
|
sk_debug_op_ctx(ctx,
|
||||||
|
"ERROR: sk_prov_asym_op_set_ctx_params "
|
||||||
|
"failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1361,6 +1444,16 @@ static int sk_prov_sign_op_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
|||||||
for (p = params; p != NULL && p->key != NULL; p++)
|
for (p = params; p != NULL && p->key != NULL; p++)
|
||||||
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
||||||
|
|
||||||
|
#ifdef OSSL_SIGNATURE_PARAM_NONCE_TYPE
|
||||||
|
/* OSSL_SIGNATURE_PARAM_NONCE_TYPE is used for EC sign ops only */
|
||||||
|
if (!sk_prov_check_uint_param(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE,
|
||||||
|
ctx->key, EVP_PKEY_EC, 0)) {
|
||||||
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
||||||
|
"Deterministic signature is not supported");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
default_set_params_fn = (OSSL_FUNC_signature_set_ctx_params_fn *)
|
default_set_params_fn = (OSSL_FUNC_signature_set_ctx_params_fn *)
|
||||||
sk_prov_get_default_sign_func(ctx->provctx,
|
sk_prov_get_default_sign_func(ctx->provctx,
|
||||||
ctx->type, OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS);
|
ctx->type, OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS);
|
||||||
@@ -1701,6 +1794,11 @@ static int sk_prov_sign_op_get_pss_saltlen(struct sk_prov_op_ctx *ctx,
|
|||||||
salt_len = max_saltlen;
|
salt_len = max_saltlen;
|
||||||
else if (strcmp(saltlen, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO) == 0)
|
else if (strcmp(saltlen, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO) == 0)
|
||||||
salt_len = max_saltlen;
|
salt_len = max_saltlen;
|
||||||
|
#ifdef OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX
|
||||||
|
else if (strcmp(saltlen,
|
||||||
|
OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX) == 0)
|
||||||
|
salt_len = MIN(max_saltlen, EVP_MD_size(mgf_md));
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
salt_len = atoi(saltlen);
|
salt_len = atoi(saltlen);
|
||||||
|
|
||||||
@@ -1729,6 +1827,16 @@ static int sk_prov_sign_op_sign_init(void *vctx, void *vkey,
|
|||||||
for (p = params; p != NULL && p->key != NULL; p++)
|
for (p = params; p != NULL && p->key != NULL; p++)
|
||||||
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
||||||
|
|
||||||
|
#ifdef OSSL_SIGNATURE_PARAM_NONCE_TYPE
|
||||||
|
/* OSSL_SIGNATURE_PARAM_NONCE_TYPE is used for EC sign ops only */
|
||||||
|
if (!sk_prov_check_uint_param(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE,
|
||||||
|
key, EVP_PKEY_EC, 0)) {
|
||||||
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
||||||
|
"Deterministic signature is not supported");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
default_sign_init_fn = (OSSL_FUNC_signature_sign_init_fn *)
|
default_sign_init_fn = (OSSL_FUNC_signature_sign_init_fn *)
|
||||||
sk_prov_get_default_sign_func(ctx->provctx,
|
sk_prov_get_default_sign_func(ctx->provctx,
|
||||||
ctx->type,
|
ctx->type,
|
||||||
@@ -1955,6 +2063,16 @@ static int sk_prov_sign_op_digest_sign_init(struct sk_prov_op_ctx *ctx,
|
|||||||
for (p = params; p != NULL && p->key != NULL; p++)
|
for (p = params; p != NULL && p->key != NULL; p++)
|
||||||
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
||||||
|
|
||||||
|
#ifdef OSSL_SIGNATURE_PARAM_NONCE_TYPE
|
||||||
|
/* OSSL_SIGNATURE_PARAM_NONCE_TYPE is used for EC sign ops only */
|
||||||
|
if (!sk_prov_check_uint_param(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE,
|
||||||
|
key, EVP_PKEY_EC, 0)) {
|
||||||
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
||||||
|
"Deterministic signature is not supported");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
default_digest_sign_init_fn =
|
default_digest_sign_init_fn =
|
||||||
(OSSL_FUNC_signature_digest_sign_init_fn *)
|
(OSSL_FUNC_signature_digest_sign_init_fn *)
|
||||||
sk_prov_get_default_sign_func(ctx->provctx,
|
sk_prov_get_default_sign_func(ctx->provctx,
|
||||||
|
|||||||
@@ -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,15 +0,0 @@
|
|||||||
include ../common.mak
|
|
||||||
|
|
||||||
lib = libvmdump.a
|
|
||||||
|
|
||||||
all: $(lib)
|
|
||||||
|
|
||||||
objects = register_content.o dump.o lkcd_dump.o register_content.o \
|
|
||||||
vmdump_convert.o vm_dump.o
|
|
||||||
|
|
||||||
$(lib): $(objects)
|
|
||||||
|
|
||||||
install: all
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *.o $(lib)
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* vmdump - z/VM dump conversion library
|
|
||||||
*
|
|
||||||
* Dump base class
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2004, 2017
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "dump.h"
|
|
||||||
|
|
||||||
int debug = 0;
|
|
||||||
|
|
||||||
void s390TodToTimeval(uint64_t todval, struct timeval *xtime)
|
|
||||||
{
|
|
||||||
/* adjust todclock to 1970 */
|
|
||||||
todval -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
|
|
||||||
|
|
||||||
todval >>= 12;
|
|
||||||
xtime->tv_sec = todval / 1000000;
|
|
||||||
xtime->tv_usec = todval % 1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dump::Dump(const char *filename, const char *mode)
|
|
||||||
{
|
|
||||||
fh = fopen(filename, mode);
|
|
||||||
if(!fh){
|
|
||||||
throw(DumpErrnoException("Open dump file failed!"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Dump::~Dump(void)
|
|
||||||
{
|
|
||||||
if(fh){
|
|
||||||
fclose(fh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProgressBar::initProgress(void)
|
|
||||||
{
|
|
||||||
progressPercentage = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProgressBar::displayProgress(uint64_t value, uint64_t maxValue)
|
|
||||||
{
|
|
||||||
char progress_bar[51];
|
|
||||||
int j;
|
|
||||||
|
|
||||||
if (progressPercentage == (int) (value * 100 / maxValue))
|
|
||||||
fprintf(stderr, "%6lld of %6lld |\r",
|
|
||||||
(long long) value, (long long) maxValue);
|
|
||||||
else { /* percent value has changed */
|
|
||||||
progressPercentage = (value * 100 / maxValue);
|
|
||||||
for (j = 0; j < progressPercentage / 2; j++)
|
|
||||||
progress_bar[j] = '#';
|
|
||||||
for (j = progressPercentage / 2; j < 50; j++)
|
|
||||||
progress_bar[j] = '-';
|
|
||||||
progress_bar[50] = 0;
|
|
||||||
fprintf(stderr, "%6lld of %6lld |%s| %3d%% \r",
|
|
||||||
(long long) value, (long long) maxValue,
|
|
||||||
progress_bar, progressPercentage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
* vmdump - z/VM dump conversion library
|
|
||||||
*
|
|
||||||
* Dump base class
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2004, 2017
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DUMP_H
|
|
||||||
#define DUMP_H
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
extern int debug;
|
|
||||||
|
|
||||||
class DumpException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DumpException(void) {
|
|
||||||
msg[0] = 0;
|
|
||||||
errorCode = 0;
|
|
||||||
}
|
|
||||||
DumpException(const char *m) {
|
|
||||||
sprintf(msg, "%s", m);
|
|
||||||
errorCode = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *what(void) const { return msg; }
|
|
||||||
int code(void) const { return errorCode; }
|
|
||||||
protected:
|
|
||||||
char msg[2048];
|
|
||||||
int errorCode;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DumpErrnoException : public DumpException
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DumpErrnoException(const char *m) {
|
|
||||||
sprintf(msg, "%s (%s)", m, strerror(errno));
|
|
||||||
errorCode = errno;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class Dump
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Dump(const char *filename, const char *mode);
|
|
||||||
Dump(void) : fh(0) {}
|
|
||||||
virtual ~Dump(void);
|
|
||||||
typedef enum {DT_VM32, DT_VM64, DT_VM64_BIG, DT_LKCD32, DT_LKCD64,
|
|
||||||
DT_UNKNOWN} DumpType;
|
|
||||||
|
|
||||||
virtual void readMem(char *buf, int size) = 0;
|
|
||||||
virtual int seekMem(uint64_t offset) = 0;
|
|
||||||
virtual uint64_t getMemSize(void) const = 0;
|
|
||||||
virtual struct timeval getDumpTime(void) const = 0;
|
|
||||||
protected:
|
|
||||||
FILE *fh;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ProgressBar
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ProgressBar(void) { progressPercentage = -1; }
|
|
||||||
void initProgress(void);
|
|
||||||
void displayProgress(uint64_t value, uint64_t maxValue);
|
|
||||||
private:
|
|
||||||
int progressPercentage;
|
|
||||||
};
|
|
||||||
|
|
||||||
void s390TodToTimeval(uint64_t todval, struct timeval *xtime);
|
|
||||||
int vm_convert(const char *inputFileName, const char *outputFileName,
|
|
||||||
const char *progName);
|
|
||||||
|
|
||||||
static inline void dump_read(void *ptr, size_t size, size_t nmemb,
|
|
||||||
FILE *stream)
|
|
||||||
{
|
|
||||||
if (fread(ptr, size, nmemb, stream) != nmemb)
|
|
||||||
throw(DumpErrnoException("fread failed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dump_seek(FILE *stream, long offset, int whence)
|
|
||||||
{
|
|
||||||
if (fseek(stream, offset, whence) == -1)
|
|
||||||
throw(DumpErrnoException("fseek failed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* DUMP_H */
|
|
||||||
@@ -1,261 +0,0 @@
|
|||||||
/*
|
|
||||||
* vmdump - z/VM dump conversion library
|
|
||||||
*
|
|
||||||
* LKCD dump classes: LKCDDump, LKCDDump32, LKCDDump64
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2004, 2017
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
#include "lkcd_dump.h"
|
|
||||||
|
|
||||||
LKCDDump::LKCDDump(Dump* dump, const char* arch) {
|
|
||||||
referenceDump = dump;
|
|
||||||
dumpHeader.magic_number = DUMP_MAGIC_NUMBER;
|
|
||||||
dumpHeader.version = DUMP_VERSION_NUMBER;
|
|
||||||
dumpHeader.header_size = sizeof(struct _lkcd_dump_header);
|
|
||||||
dumpHeader.time.tv_sec = dump->getDumpTime().tv_sec;
|
|
||||||
dumpHeader.time.tv_usec = dump->getDumpTime().tv_usec;
|
|
||||||
strcpy(dumpHeader.utsname_machine, arch);
|
|
||||||
dumpHeader.memory_size = dump->getMemSize();
|
|
||||||
dumpHeader.memory_start = 0;
|
|
||||||
dumpHeader.memory_end = dump->getMemSize();
|
|
||||||
dumpHeader.num_dump_pages = dump->getMemSize()/0x1000;
|
|
||||||
dumpHeader.page_size = 0x1000;
|
|
||||||
dumpHeader.dump_compress = DUMP_COMPRESS_GZIP;
|
|
||||||
dumpHeader.dump_level = DUMP_LEVEL_ALL;
|
|
||||||
|
|
||||||
dumpHeaderAsm.magic_number = DUMP_ASM_MAGIC_NUMBER;
|
|
||||||
dumpHeaderAsm.version = 1;
|
|
||||||
dumpHeaderAsm.header_size = sizeof(dumpHeaderAsm);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LKCDDump::compressGZIP(const char *old, uint32_t old_size, char *n,
|
|
||||||
uint32_t new_size)
|
|
||||||
{
|
|
||||||
unsigned long len = old_size;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = compress((Bytef*)n, &len, (const Bytef*)old, new_size);
|
|
||||||
switch(rc) {
|
|
||||||
case Z_OK:
|
|
||||||
rc = len;
|
|
||||||
break;
|
|
||||||
case Z_BUF_ERROR:
|
|
||||||
/* In this case the compressed output is bigger than */
|
|
||||||
/* the uncompressed */
|
|
||||||
rc = GZIP_NOT_COMPRESSED;
|
|
||||||
break;
|
|
||||||
case Z_MEM_ERROR:
|
|
||||||
throw(DumpException("gzip call failed: out of memory"));
|
|
||||||
case Z_DATA_ERROR:
|
|
||||||
throw(DumpException("gzip call failed: input data " \
|
|
||||||
"corrupted!"));
|
|
||||||
default:
|
|
||||||
throw(DumpException("gzip call failed: unknown error"));
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LKCDDump::writeDump(const char* fileName)
|
|
||||||
{
|
|
||||||
char dump_header_buf[DUMP_HEADER_SIZE] = {};
|
|
||||||
char dump_page_buf[DUMP_BUFFER_SIZE];
|
|
||||||
char dpcpage[DUMP_PAGE_SIZE];
|
|
||||||
uint32_t dp_size,dp_flags;
|
|
||||||
ProgressBar progressBar;
|
|
||||||
char buf[DUMP_PAGE_SIZE];
|
|
||||||
struct _dump_page dp;
|
|
||||||
uint64_t mem_loc = 0;
|
|
||||||
ssize_t buf_loc = 0;
|
|
||||||
int size, fd;
|
|
||||||
|
|
||||||
if (fileName == NULL) {
|
|
||||||
fd = STDOUT_FILENO;
|
|
||||||
} else {
|
|
||||||
fd = open(fileName, O_WRONLY | O_CREAT | O_TRUNC,
|
|
||||||
S_IRUSR | S_IWUSR);
|
|
||||||
if (fd == -1) {
|
|
||||||
char msg[1024];
|
|
||||||
sprintf(msg, "Open of dump '%s' failed.", fileName);
|
|
||||||
throw(DumpErrnoException(msg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write dump header */
|
|
||||||
|
|
||||||
memcpy(dump_header_buf, &dumpHeader, sizeof(dumpHeader));
|
|
||||||
memcpy(&dump_header_buf[sizeof(dumpHeader)], &dumpHeaderAsm,
|
|
||||||
sizeof(dumpHeaderAsm));
|
|
||||||
if (write(fd, dump_header_buf, sizeof(dump_header_buf)) !=
|
|
||||||
sizeof(dump_header_buf)) {
|
|
||||||
throw(DumpErrnoException("write failed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write memory */
|
|
||||||
|
|
||||||
referenceDump->seekMem(0);
|
|
||||||
|
|
||||||
while (mem_loc < dumpHeader.memory_size) {
|
|
||||||
referenceDump->readMem(buf, DUMP_PAGE_SIZE);
|
|
||||||
copyRegsToPage(mem_loc,buf);
|
|
||||||
|
|
||||||
memset(dpcpage, 0, DUMP_PAGE_SIZE);
|
|
||||||
/*
|
|
||||||
* Get the new compressed page size
|
|
||||||
*/
|
|
||||||
size = compressGZIP((char *)buf, DUMP_PAGE_SIZE,
|
|
||||||
(char *)dpcpage, DUMP_PAGE_SIZE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If compression failed or compressed was ineffective,
|
|
||||||
* we write an uncompressed page
|
|
||||||
*/
|
|
||||||
if (size == GZIP_NOT_COMPRESSED) {
|
|
||||||
dp_flags = DUMP_DH_RAW;
|
|
||||||
dp_size = DUMP_PAGE_SIZE;
|
|
||||||
} else {
|
|
||||||
dp_flags = DUMP_DH_COMPRESSED;
|
|
||||||
dp_size = size;
|
|
||||||
}
|
|
||||||
dp.address = mem_loc;
|
|
||||||
dp.size = dp_size;
|
|
||||||
dp.flags = dp_flags;
|
|
||||||
memcpy((void *)(dump_page_buf + buf_loc),
|
|
||||||
(const void *)&dp, sizeof(dp));
|
|
||||||
buf_loc += sizeof(dp);
|
|
||||||
/*
|
|
||||||
* Copy the page of memory
|
|
||||||
*/
|
|
||||||
if (dp_flags & DUMP_DH_COMPRESSED) {
|
|
||||||
/* Copy the compressed page */
|
|
||||||
memcpy((void *)(dump_page_buf + buf_loc),
|
|
||||||
(const void *)dpcpage, dp_size);
|
|
||||||
} else {
|
|
||||||
/* Copy directly from memory */
|
|
||||||
memcpy((void *)(dump_page_buf + buf_loc),
|
|
||||||
(const void *)buf, dp_size);
|
|
||||||
}
|
|
||||||
buf_loc += dp_size;
|
|
||||||
if(write(fd, dump_page_buf, buf_loc) != buf_loc){
|
|
||||||
throw(DumpErrnoException("write failed"));
|
|
||||||
}
|
|
||||||
buf_loc = 0;
|
|
||||||
mem_loc += DUMP_PAGE_SIZE;
|
|
||||||
progressBar.displayProgress(mem_loc/(1024*1024),
|
|
||||||
dumpHeader.memory_size/(1024*1024));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write end marker
|
|
||||||
*/
|
|
||||||
dp.address = 0x0;
|
|
||||||
dp.size = 0x0;
|
|
||||||
dp.flags = DUMP_DH_END;
|
|
||||||
if(write(fd, &dp, sizeof(dp)) != sizeof(dp)){
|
|
||||||
throw(DumpErrnoException("write failed"));
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
if (fd != STDOUT_FILENO)
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct timeval LKCDDump::getDumpTime(void) const
|
|
||||||
{
|
|
||||||
struct timeval rc;
|
|
||||||
|
|
||||||
rc.tv_sec = dumpHeader.time.tv_sec;
|
|
||||||
rc.tv_usec = dumpHeader.time.tv_usec;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
LKCDDump32::LKCDDump32(Dump* dump, const RegisterContent32& r)
|
|
||||||
: LKCDDump(dump,"s390")
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
dumpHeaderAsm.real_cpu_cnt = (uint32_t) r.getNumCpus();
|
|
||||||
for (i = 0; i < dumpHeaderAsm.real_cpu_cnt; i++) {
|
|
||||||
if (!r.regSets[i].prefix)
|
|
||||||
continue;
|
|
||||||
dumpHeaderAsm.lc_vec[i] = r.regSets[i].prefix;
|
|
||||||
dumpHeaderAsm.cpu_cnt++;
|
|
||||||
}
|
|
||||||
registerContent = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LKCDDump32::copyRegsToPage(uint64_t offset, char *buf)
|
|
||||||
{
|
|
||||||
int cpu;
|
|
||||||
|
|
||||||
for(cpu = 0; cpu < registerContent.getNumCpus(); cpu++){
|
|
||||||
if(offset == registerContent.regSets[cpu].prefix){
|
|
||||||
memcpy(buf+0xd8,®isterContent.regSets[cpu].cpuTimer,
|
|
||||||
sizeof(registerContent.regSets[cpu].cpuTimer));
|
|
||||||
memcpy(buf+0xe0,®isterContent.regSets[cpu].clkCmp,
|
|
||||||
sizeof(registerContent.regSets[cpu].clkCmp));
|
|
||||||
memcpy(buf+0x100,®isterContent.regSets[cpu].psw,
|
|
||||||
sizeof(registerContent.regSets[cpu].psw));
|
|
||||||
memcpy(buf+0x108,®isterContent.regSets[cpu].prefix,
|
|
||||||
sizeof(registerContent.regSets[cpu].prefix));
|
|
||||||
memcpy(buf+0x120,®isterContent.regSets[cpu].acrs,
|
|
||||||
sizeof(registerContent.regSets[cpu].acrs));
|
|
||||||
memcpy(buf+0x160,®isterContent.regSets[cpu].fprs,
|
|
||||||
sizeof(registerContent.regSets[cpu].fprs));
|
|
||||||
memcpy(buf+0x180,®isterContent.regSets[cpu].gprs,
|
|
||||||
sizeof(registerContent.regSets[cpu].gprs));
|
|
||||||
memcpy(buf+0x1c0,®isterContent.regSets[cpu].crs,
|
|
||||||
sizeof(registerContent.regSets[cpu].crs));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LKCDDump64::LKCDDump64(Dump* dump, const RegisterContent64& r)
|
|
||||||
: LKCDDump(dump,"s390x")
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
dumpHeaderAsm.real_cpu_cnt = (uint32_t) r.getNumCpus();
|
|
||||||
for (i = 0; i < dumpHeaderAsm.real_cpu_cnt; i++) {
|
|
||||||
if (!r.regSets[i].prefix)
|
|
||||||
continue;
|
|
||||||
dumpHeaderAsm.lc_vec[i] = r.regSets[i].prefix;
|
|
||||||
dumpHeaderAsm.cpu_cnt++;
|
|
||||||
}
|
|
||||||
registerContent = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LKCDDump64::copyRegsToPage(uint64_t offset, char *buf)
|
|
||||||
{
|
|
||||||
int cpu;
|
|
||||||
|
|
||||||
for(cpu = 0; cpu < registerContent.getNumCpus(); cpu++){
|
|
||||||
if(offset == (registerContent.regSets[cpu].prefix + 0x1000)){
|
|
||||||
memcpy(buf+0x328,®isterContent.regSets[cpu].cpuTimer,
|
|
||||||
sizeof(registerContent.regSets[cpu].cpuTimer));
|
|
||||||
memcpy(buf+0x330,®isterContent.regSets[cpu].clkCmp,
|
|
||||||
sizeof(registerContent.regSets[cpu].clkCmp));
|
|
||||||
memcpy(buf+0x300,®isterContent.regSets[cpu].psw,
|
|
||||||
sizeof(registerContent.regSets[cpu].psw));
|
|
||||||
memcpy(buf+0x318,®isterContent.regSets[cpu].prefix,
|
|
||||||
sizeof(registerContent.regSets[cpu].prefix));
|
|
||||||
memcpy(buf+0x340,®isterContent.regSets[cpu].acrs,
|
|
||||||
sizeof(registerContent.regSets[cpu].acrs));
|
|
||||||
memcpy(buf+0x200,®isterContent.regSets[cpu].fprs,
|
|
||||||
sizeof(registerContent.regSets[cpu].fprs));
|
|
||||||
memcpy(buf+0x280,®isterContent.regSets[cpu].gprs,
|
|
||||||
sizeof(registerContent.regSets[cpu].gprs));
|
|
||||||
memcpy(buf+0x380,®isterContent.regSets[cpu].crs,
|
|
||||||
sizeof(registerContent.regSets[cpu].crs));
|
|
||||||
memcpy(buf+0x31c,®isterContent.regSets[cpu].fpCr,
|
|
||||||
sizeof(registerContent.regSets[cpu].fpCr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
/*
|
|
||||||
* vmdump - z/VM dump conversion library
|
|
||||||
*
|
|
||||||
* LKCD dump classes: LKCDDump, LKCDDump32, LKCDDump64
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2004, 2017
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LKCD_DUMP_H
|
|
||||||
#define LKCD_DUMP_H
|
|
||||||
|
|
||||||
#include "lib/zt_common.h"
|
|
||||||
|
|
||||||
#include "dump.h"
|
|
||||||
#include "register_content.h"
|
|
||||||
|
|
||||||
#define UTS_LEN 65
|
|
||||||
#define DUMP_BUFFER_SIZE 0x2000 /* Size of dump buffer */
|
|
||||||
|
|
||||||
/* Standard header definitions */
|
|
||||||
#define DUMP_HEADER_SIZE 0x10000
|
|
||||||
#define DUMP_MAGIC_NUMBER 0xa8190173618f23edULL /* Dump magic number */
|
|
||||||
#define DUMP_ASM_MAGIC_NUMBER 0x733339302d64756dULL /* asm magic number */
|
|
||||||
#define DUMP_VERSION_NUMBER 0x8 /* Dump version number */
|
|
||||||
#define DUMP_PANIC_LEN 0x100 /* Dump panic string length */
|
|
||||||
|
|
||||||
/* Dump levels - type specific stuff added later */
|
|
||||||
#define DUMP_LEVEL_ALL 0x10 /* Dump all memory RAM and firmware */
|
|
||||||
|
|
||||||
/* Dump compression options */
|
|
||||||
#define DUMP_COMPRESS_GZIP 0x2 /* Use GZIP compression */
|
|
||||||
|
|
||||||
/* Dump header flags */
|
|
||||||
#define DUMP_DH_RAW 0x1 /* Raw page (no compression) */
|
|
||||||
#define DUMP_DH_COMPRESSED 0x2 /* Page is compressed */
|
|
||||||
#define DUMP_DH_END 0x4 /* End marker on a full dump */
|
|
||||||
|
|
||||||
/* Dump page defines */
|
|
||||||
#define DUMP_PAGE_SHIFT 12ULL
|
|
||||||
#define DUMP_PAGE_SIZE (1ULL << DUMP_PAGE_SHIFT)
|
|
||||||
|
|
||||||
#define GZIP_NOT_COMPRESSED -1
|
|
||||||
|
|
||||||
class LKCDDump : public Dump
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LKCDDump(Dump*, const char *);
|
|
||||||
virtual ~LKCDDump(void) {}
|
|
||||||
inline virtual void readMem(char *UNUSED(buf), int UNUSED(size))
|
|
||||||
{
|
|
||||||
throw(DumpException("LKCDDump::readMem() not implemented!"));
|
|
||||||
}
|
|
||||||
inline int seekMem(uint64_t UNUSED(offset))
|
|
||||||
{
|
|
||||||
throw(DumpException("LKCDDump::seekMem() not implemented!"));
|
|
||||||
}
|
|
||||||
inline virtual uint64_t getMemSize() const
|
|
||||||
{
|
|
||||||
return dumpHeader.memory_size;
|
|
||||||
}
|
|
||||||
virtual struct timeval getDumpTime(void) const;
|
|
||||||
virtual void writeDump(const char *fileName);
|
|
||||||
virtual void copyRegsToPage(uint64_t offset, char *buf) = 0;
|
|
||||||
protected:
|
|
||||||
struct _lkcd_dump_header {
|
|
||||||
uint64_t magic_number; /* dump magic number,unique to verify */
|
|
||||||
/* dump */
|
|
||||||
uint32_t version; /* version number of this dump */
|
|
||||||
uint32_t header_size; /* size of this header */
|
|
||||||
uint32_t dump_level; /* level of this dump */
|
|
||||||
uint32_t page_size; /* page size (e.g. 4K, 8K, 16K, etc.) */
|
|
||||||
uint64_t memory_size; /* size of entire physical memory */
|
|
||||||
uint64_t memory_start; /* start of physical memory */
|
|
||||||
uint64_t memory_end; /* end of physical memory */
|
|
||||||
/* the number of dump pages in this dump specifically */
|
|
||||||
uint32_t num_dump_pages;
|
|
||||||
char panic_string[DUMP_PANIC_LEN];
|
|
||||||
|
|
||||||
/* timeval depends on machine, two long values */
|
|
||||||
struct {uint64_t tv_sec;
|
|
||||||
uint64_t tv_usec;
|
|
||||||
} time; /* the time of the system crash */
|
|
||||||
|
|
||||||
/* the NEW utsname (uname) information -- in character form */
|
|
||||||
/* we do this so we don't have to include utsname.h */
|
|
||||||
/* plus it helps us be more architecture independent */
|
|
||||||
char utsname_sysname[UTS_LEN];
|
|
||||||
char utsname_nodename[UTS_LEN];
|
|
||||||
char utsname_release[UTS_LEN];
|
|
||||||
char utsname_version[UTS_LEN];
|
|
||||||
char utsname_machine[UTS_LEN];
|
|
||||||
char utsname_domainname[UTS_LEN];
|
|
||||||
|
|
||||||
uint64_t current_task;
|
|
||||||
uint32_t dump_compress; /* compression type used in this dump */
|
|
||||||
uint32_t dump_flags; /* any additional flags */
|
|
||||||
uint32_t dump_device; /* any additional flags */
|
|
||||||
uint64_t s390_asm_magic;
|
|
||||||
uint16_t cpu_cnt;
|
|
||||||
uint32_t lowcore_ptr[512];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct _lkcd_dump_header_asm {
|
|
||||||
uint64_t magic_number;
|
|
||||||
uint32_t version;
|
|
||||||
uint32_t header_size;
|
|
||||||
uint16_t cpu_cnt;
|
|
||||||
uint16_t real_cpu_cnt;
|
|
||||||
uint32_t lc_vec[512];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct _dump_page {
|
|
||||||
uint64_t address; /* the address of this dump page */
|
|
||||||
uint32_t size; /* the size of this dump page */
|
|
||||||
uint32_t flags; /* flags (DUMP_COMPRESSED, DUMP_RAW */
|
|
||||||
/* or DUMP_END) */
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct _lkcd_dump_header dumpHeader;
|
|
||||||
struct _lkcd_dump_header_asm dumpHeaderAsm;
|
|
||||||
|
|
||||||
private:
|
|
||||||
int compressGZIP(const char *old, uint32_t old_size, char *n,
|
|
||||||
uint32_t new_size);
|
|
||||||
Dump *referenceDump;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LKCDDump32 : public LKCDDump
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LKCDDump32(Dump *dump, const RegisterContent32 &rc);
|
|
||||||
virtual void copyRegsToPage(uint64_t offset, char *buf);
|
|
||||||
private:
|
|
||||||
RegisterContent32 registerContent;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LKCDDump64 : public LKCDDump
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LKCDDump64(Dump *dump, const RegisterContent64 &rc);
|
|
||||||
virtual void copyRegsToPage(uint64_t offset, char *buf);
|
|
||||||
private:
|
|
||||||
RegisterContent64 registerContent;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* LKCD_DUMP_H */
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* vmdump - z/VM dump conversion library
|
|
||||||
*
|
|
||||||
* Register content classes
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2004, 2017
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "register_content.h"
|
|
||||||
#include "dump.h"
|
|
||||||
|
|
||||||
RegisterContent32::RegisterContent32(void)
|
|
||||||
: regSets(), nrCpus(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterContent32::RegisterContent32(const RegisterContent32& r)
|
|
||||||
{
|
|
||||||
nrCpus = r.nrCpus;
|
|
||||||
memcpy(®Sets,&r.regSets,sizeof(regSets));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterContent32::addRegisterSet(const RegisterSet32& rs)
|
|
||||||
{
|
|
||||||
if(nrCpus < MAX_CPUS){
|
|
||||||
regSets[nrCpus++] = rs;
|
|
||||||
} else {
|
|
||||||
throw(DumpException("RegisterContent32::addRegisterSet - " \
|
|
||||||
"No more register sets available"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterSet32 RegisterContent32::getRegisterSet(int cpu){
|
|
||||||
if(cpu <= nrCpus){
|
|
||||||
return regSets[cpu];
|
|
||||||
} else {
|
|
||||||
throw(DumpException("RegisterContent32::getRegisterSet - " \
|
|
||||||
"No register set for cpu"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterContent64::RegisterContent64(void)
|
|
||||||
: regSets(), nrCpus(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterContent64::RegisterContent64(const RegisterContent64& r)
|
|
||||||
{
|
|
||||||
nrCpus = r.nrCpus;
|
|
||||||
memcpy(®Sets,&r.regSets,sizeof(regSets));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterContent64::addRegisterSet(const RegisterSet64& rs)
|
|
||||||
{
|
|
||||||
if(nrCpus < MAX_CPUS){
|
|
||||||
regSets[nrCpus++] = rs;
|
|
||||||
} else {
|
|
||||||
throw(DumpException("RegisterContent64::addRegisterSet - " \
|
|
||||||
"No more register sets available"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterSet64 RegisterContent64::getRegisterSet(int cpu)
|
|
||||||
{
|
|
||||||
if(cpu <= nrCpus){
|
|
||||||
return regSets[cpu];
|
|
||||||
} else {
|
|
||||||
throw(DumpException("RegisterContent64::getRegisterSet - " \
|
|
||||||
"No register set for cpu"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* vmdump - z/VM dump conversion library
|
|
||||||
*
|
|
||||||
* Register content classes
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2004, 2017
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef REGISTER_CONTENT_H
|
|
||||||
#define REGISTER_CONTENT_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define MAX_CPUS 512
|
|
||||||
|
|
||||||
class RegisterSet64
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
uint64_t gprs[16];
|
|
||||||
uint64_t crs[16];
|
|
||||||
uint32_t acrs[16];
|
|
||||||
uint64_t fprs[16];
|
|
||||||
uint32_t fpCr;
|
|
||||||
uint64_t psw[2];
|
|
||||||
uint32_t prefix;
|
|
||||||
uint64_t cpuTimer;
|
|
||||||
uint64_t clkCmp;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RegisterSet32
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
uint32_t gprs[16];
|
|
||||||
uint32_t crs[16];
|
|
||||||
uint32_t acrs[16];
|
|
||||||
uint64_t fprs[4];
|
|
||||||
uint32_t psw[2];
|
|
||||||
uint32_t prefix;
|
|
||||||
uint64_t cpuTimer;
|
|
||||||
uint64_t clkCmp;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RegisterContent64{
|
|
||||||
public:
|
|
||||||
RegisterContent64(void);
|
|
||||||
RegisterContent64(const RegisterContent64&);
|
|
||||||
RegisterSet64 getRegisterSet(int cpu);
|
|
||||||
void addRegisterSet(const RegisterSet64&);
|
|
||||||
inline int getNumCpus(void) const { return nrCpus; }
|
|
||||||
RegisterContent64& operator=(const RegisterContent64&) = default;
|
|
||||||
|
|
||||||
RegisterSet64 regSets[MAX_CPUS];
|
|
||||||
private:
|
|
||||||
int nrCpus;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class RegisterContent32{
|
|
||||||
public:
|
|
||||||
RegisterContent32(void);
|
|
||||||
RegisterContent32(const RegisterContent32&);
|
|
||||||
RegisterSet32 getRegisterSet(int cpu);
|
|
||||||
void addRegisterSet(const RegisterSet32&);
|
|
||||||
inline int getNumCpus(void) const { return nrCpus; }
|
|
||||||
RegisterContent32& operator=(const RegisterContent32&) = default;
|
|
||||||
|
|
||||||
RegisterSet32 regSets[MAX_CPUS];
|
|
||||||
private:
|
|
||||||
int nrCpus;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* REGISTER_CONTENT_H */
|
|
||||||
@@ -1,624 +0,0 @@
|
|||||||
/*
|
|
||||||
* vmdump - z/VM dump conversion library
|
|
||||||
*
|
|
||||||
* Register content classes:
|
|
||||||
* VMDump, VMDumpClassic, VMDump64, VMDump64Big, VMDump32
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2004, 2017
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "vm_dump.h"
|
|
||||||
|
|
||||||
Dump::DumpType VMDump::getDumpType(const char* inputFileName)
|
|
||||||
{
|
|
||||||
uint8_t fmbk_id[8] = {0xc8, 0xc3, 0xd7, 0xc4, 0xc6, 0xd4, 0xc2, 0xd2};
|
|
||||||
struct _fir_basic fir;
|
|
||||||
struct _fmbk fmbk;
|
|
||||||
struct _adsr adsr;
|
|
||||||
char msg[200];
|
|
||||||
FILE* fh;
|
|
||||||
|
|
||||||
fh = fopen(inputFileName,"r");
|
|
||||||
if (!fh) {
|
|
||||||
sprintf(msg,"Could not open '%s'",inputFileName);
|
|
||||||
throw DumpErrnoException(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Record 1: adsr */
|
|
||||||
dump_read(&adsr, sizeof(adsr), 1, fh);
|
|
||||||
|
|
||||||
/* Record 2: fmbk */
|
|
||||||
dump_seek(fh, 0x1000, SEEK_SET);
|
|
||||||
if (fread(&fmbk, sizeof(fmbk), 1, fh) != 1) {
|
|
||||||
if(ferror(fh)) {
|
|
||||||
sprintf(msg,"Could not read header of vmdump '%s'",
|
|
||||||
inputFileName);
|
|
||||||
fclose(fh);
|
|
||||||
throw DumpErrnoException(msg);
|
|
||||||
} else{
|
|
||||||
sprintf(msg,"Input file '%s' is not a vmdump",
|
|
||||||
inputFileName);
|
|
||||||
fclose(fh);
|
|
||||||
throw DumpException(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if this is a vmdump */
|
|
||||||
if (memcmp(fmbk.id, fmbk_id, 8) != 0 ||
|
|
||||||
adsr.dump_type != 0xe5d4c4e4d4d74040ULL) {
|
|
||||||
fclose(fh);
|
|
||||||
sprintf(msg, "Input file '%s' is not a vmdump", inputFileName);
|
|
||||||
throw DumpException(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Record 3-7: fir */
|
|
||||||
dump_seek(fh, (fmbk.rec_nr_fir - 1) * 0x1000, SEEK_SET);
|
|
||||||
if(fread(&fir, sizeof(fir), 1, fh) != 1) {
|
|
||||||
if (ferror(fh)) {
|
|
||||||
sprintf(msg,"Could not read header of vmdump '%s'",
|
|
||||||
inputFileName);
|
|
||||||
fclose(fh);
|
|
||||||
throw DumpErrnoException(msg);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
sprintf(msg, "Could not read header of vmdump '%s'",
|
|
||||||
inputFileName);
|
|
||||||
fclose(fh);
|
|
||||||
throw DumpException(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(fh);
|
|
||||||
if (fir.fir_format == 0) {
|
|
||||||
return DT_VM32;
|
|
||||||
} else if (fir.fir_format == 0x02) {/*XXX && (fir.dump_format == 0x1))*/
|
|
||||||
return DT_VM64_BIG;
|
|
||||||
} else if (fir.fir_format == 0x82) {
|
|
||||||
return DT_VM64;
|
|
||||||
} else {
|
|
||||||
return DT_UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VMDump::VMDump(const char *fileName) : Dump(fileName, "rb")
|
|
||||||
{
|
|
||||||
uint8_t fmbk_id[8] = {0xc8, 0xc3, 0xd7, 0xc4, 0xc6, 0xd4, 0xc2, 0xd2};
|
|
||||||
|
|
||||||
ebcdicAsciiConv = iconv_open("ISO-8859-1", "EBCDIC-US");
|
|
||||||
|
|
||||||
/* Record 1: adsrRecord */
|
|
||||||
|
|
||||||
dump_seek(fh,0,SEEK_SET);
|
|
||||||
dump_read(&adsrRecord,sizeof(adsrRecord),1,fh);
|
|
||||||
|
|
||||||
if(debug) {
|
|
||||||
char buf_asc[1024];
|
|
||||||
char buf[1024];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
fprintf(stderr, "off=%d\n", adsrRecord.sec5_offset);
|
|
||||||
dump_seek(fh, adsrRecord.sec5_offset, SEEK_SET);
|
|
||||||
dump_read(buf, adsrRecord.sec5_len, 1, fh);
|
|
||||||
ebcAsc(buf, buf_asc, adsrRecord.sec5_len);
|
|
||||||
for (i=0; i < adsrRecord.sec5_len; i++) {
|
|
||||||
if ((buf_asc[i]==0) || iscntrl(buf_asc[i]))
|
|
||||||
buf_asc[i]=' ';
|
|
||||||
}
|
|
||||||
buf_asc[adsrRecord.sec5_len] = 0;
|
|
||||||
printf("symptom string1: %s\n",buf_asc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Record 2: fmbk */
|
|
||||||
|
|
||||||
dump_seek(fh,0x1000,SEEK_SET);
|
|
||||||
dump_read(&fmbkRecord,sizeof(fmbkRecord),1,fh);
|
|
||||||
|
|
||||||
/* Check if this is a vmdump */
|
|
||||||
if(memcmp(fmbkRecord.id, fmbk_id, 8) != 0) {
|
|
||||||
throw DumpException("Input file is not a vmdump");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Record 3-7: fir records read by subclasses */
|
|
||||||
|
|
||||||
/* Record 8: albk */
|
|
||||||
|
|
||||||
dump_seek(fh,(fmbkRecord.rec_nr_access-1)*0x1000 ,SEEK_SET);
|
|
||||||
dump_read(&albkRecord,sizeof(albkRecord),1,fh);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct timeval VMDump::getDumpTime(void) const
|
|
||||||
{
|
|
||||||
struct timeval rc;
|
|
||||||
|
|
||||||
s390TodToTimeval(adsrRecord.tod,&rc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VMDump::printDebug(void)
|
|
||||||
{
|
|
||||||
struct timeval time;
|
|
||||||
char fmbk_id[8];
|
|
||||||
char albk_id[8];
|
|
||||||
|
|
||||||
s390TodToTimeval(adsrRecord.tod, &time);
|
|
||||||
|
|
||||||
/* adsr */
|
|
||||||
|
|
||||||
printf("time : %s\n", ctime(&time.tv_sec));
|
|
||||||
printf("stat1 : %x\n", adsrRecord.record_status_flag1);
|
|
||||||
printf("stat2 : %x\n", adsrRecord.record_status_flag2);
|
|
||||||
printf("sec 2 len: %i\n", adsrRecord.sec2_len);
|
|
||||||
printf("sec 2.1 len: %i/%i\n", adsrRecord.sec2_1_len,
|
|
||||||
adsrRecord.sec2_1_offset);
|
|
||||||
printf("sec 3 len: %i/%i\n", adsrRecord.sec3_len,
|
|
||||||
adsrRecord.sec3_offset);
|
|
||||||
printf("sec 4 len: %i/%i\n", adsrRecord.sec4_len,
|
|
||||||
adsrRecord.sec4_offset);
|
|
||||||
printf("sec 5 len: %i/%i\n", adsrRecord.sec5_len,
|
|
||||||
adsrRecord.sec5_offset);
|
|
||||||
printf("sec 6 len: %i/%i\n", adsrRecord.sec6_len,
|
|
||||||
adsrRecord.sec6_offset);
|
|
||||||
|
|
||||||
/* fmbk */
|
|
||||||
|
|
||||||
ebcAsc(fmbkRecord.id, fmbk_id, sizeof(fmbkRecord.id));
|
|
||||||
fmbk_id[7] = 0;
|
|
||||||
printf("id : %s\n", fmbk_id);
|
|
||||||
printf("fir rec nr: %i\n", fmbkRecord.rec_nr_fir);
|
|
||||||
printf("vec rec nr: %i\n", fmbkRecord.rec_nr_vector);
|
|
||||||
printf("access rec nr: %i\n", fmbkRecord.rec_nr_access);
|
|
||||||
|
|
||||||
|
|
||||||
/* albk */
|
|
||||||
|
|
||||||
ebcAsc(albkRecord.id, albk_id, sizeof(albkRecord.id));
|
|
||||||
albk_id[7]=0;
|
|
||||||
printf("ALBK id : %s\n",albk_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VMDump::printInfo(void)
|
|
||||||
{
|
|
||||||
struct timeval time;
|
|
||||||
|
|
||||||
s390TodToTimeval(adsrRecord.tod,&time);
|
|
||||||
fprintf(stderr, " date........: %s",ctime(&time.tv_sec));
|
|
||||||
}
|
|
||||||
|
|
||||||
int VMDump::seekMem(uint64_t offset)
|
|
||||||
{
|
|
||||||
if (offset != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pageOffset = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VMDump::readMem(char* buf, int size)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (pageOffset == 0)
|
|
||||||
dump_seek(fh, memoryStartRecord, SEEK_SET);
|
|
||||||
|
|
||||||
if (size % 0x1000 != 0) {
|
|
||||||
throw(DumpException("internal error: VMDump::readMem() " \
|
|
||||||
"can only handle sizes which are multiples of page size"));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < size; i += 0x1000) {
|
|
||||||
if(testPage(pageOffset)) {
|
|
||||||
dump_read(buf + i, 0x1000, 1, fh);
|
|
||||||
} else {
|
|
||||||
memset(buf + i, 0, 0x1000);
|
|
||||||
}
|
|
||||||
pageOffset += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VMDump::~VMDump(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* VMDumpClassic: traditional 32/64 bit vmdump (before z/VM 5.2) */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
VMDumpClassic::VMDumpClassic(const char *fileName) : VMDump(fileName)
|
|
||||||
{
|
|
||||||
int storageKeyPages,bitMapPages;
|
|
||||||
|
|
||||||
pageOffset = 0;
|
|
||||||
|
|
||||||
/* Record 9: asibk */
|
|
||||||
|
|
||||||
dump_seek(fh,fmbkRecord.rec_nr_access * 0x1000,SEEK_SET);
|
|
||||||
dump_read(&asibkRecord,sizeof(asibkRecord),1,fh);
|
|
||||||
|
|
||||||
/* Record 10: bitmaps */
|
|
||||||
|
|
||||||
dump_seek(fh,(fmbkRecord.rec_nr_access + 1)* 0x1000 ,SEEK_SET);
|
|
||||||
bitmap = new char[asibkRecord.storage_size_2GB / (0x1000 * 8)];
|
|
||||||
dump_read(bitmap,asibkRecord.storage_size_2GB / (0x1000*8),1,fh);
|
|
||||||
|
|
||||||
bitMapPages=asibkRecord.storage_size_2GB / (0x1000 * 8);
|
|
||||||
if (bitMapPages % 0x1000 != 0)
|
|
||||||
bitMapPages = bitMapPages/0x1000 + 1;
|
|
||||||
else
|
|
||||||
bitMapPages = bitMapPages/0x1000;
|
|
||||||
|
|
||||||
storageKeyPages=asibkRecord.storage_size_2GB / 0x1000;
|
|
||||||
if(storageKeyPages % 0x1000 != 0) {
|
|
||||||
storageKeyPages = storageKeyPages/0x1000 + 1;
|
|
||||||
} else {
|
|
||||||
storageKeyPages = storageKeyPages/0x1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip storage keys */
|
|
||||||
|
|
||||||
memoryStartRecord = (fmbkRecord.rec_nr_access + 1) *0x1000 /* 0x9000 */
|
|
||||||
+ (bitMapPages + storageKeyPages)*0x1000;
|
|
||||||
if(debug) {
|
|
||||||
printf("Mem Offset: %llx\n", (long long) memoryStartRecord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VMDumpClassic::printInfo(void)
|
|
||||||
{
|
|
||||||
VMDump::printInfo();
|
|
||||||
fprintf(stderr, " storage.....: %i MB\n",
|
|
||||||
asibkRecord.storage_size_2GB/(1024*1024));
|
|
||||||
}
|
|
||||||
|
|
||||||
VMDumpClassic::~VMDumpClassic(void)
|
|
||||||
{
|
|
||||||
delete bitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* VMDump32: 32 bit vmdump */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
VMDump32::VMDump32(const char* filename) : VMDumpClassic(filename)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if(!fh) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_seek(fh,(fmbkRecord.rec_nr_fir-1)* 0x1000 ,SEEK_SET);
|
|
||||||
dump_read(&fir32Record,sizeof(fir32Record),1,fh);
|
|
||||||
|
|
||||||
fir32OtherRecords = new _fir_other_32[fir32Record.online_cpus];
|
|
||||||
for(i=0; i < fir32Record.online_cpus; i++) {
|
|
||||||
/* fir other */
|
|
||||||
dump_read(&fir32OtherRecords[i],sizeof(fir32OtherRecords[i]),1,
|
|
||||||
fh);
|
|
||||||
}
|
|
||||||
if(debug)
|
|
||||||
printDebug();
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterContent32 VMDump32::getRegisterContent(void)
|
|
||||||
{
|
|
||||||
RegisterContent32 rc;
|
|
||||||
RegisterSet32 rs;
|
|
||||||
int cpu;
|
|
||||||
|
|
||||||
/* First CPU */
|
|
||||||
|
|
||||||
memcpy(&rs.gprs, &fir32Record.gprs, sizeof(rs.gprs));
|
|
||||||
memcpy(&rs.crs, &fir32Record.crs, sizeof(rs.crs));
|
|
||||||
memcpy(&rs.acrs, &fir32Record.acrs, sizeof(rs.acrs));
|
|
||||||
memcpy(&rs.psw, &fir32Record.psw, sizeof(rs.psw));
|
|
||||||
memcpy(&rs.prefix, &fir32Record.prefix, sizeof(rs.prefix));
|
|
||||||
memcpy(&rs.fprs, &fir32Record.fprs, sizeof(rs.fprs));
|
|
||||||
memcpy(&rs.cpuTimer, &fir32Record.cpu_timer, sizeof(rs.cpuTimer));
|
|
||||||
memcpy(&rs.clkCmp, &fir32Record.clock_cmp, sizeof(rs.clkCmp));
|
|
||||||
|
|
||||||
rc.addRegisterSet(rs);
|
|
||||||
|
|
||||||
/* Other online cpus */
|
|
||||||
|
|
||||||
for(cpu = 0; cpu < fir32Record.online_cpus; cpu++) {
|
|
||||||
memcpy(&rs.gprs, &fir32OtherRecords[cpu].gprs, sizeof(rs.gprs));
|
|
||||||
memcpy(&rs.crs, &fir32OtherRecords[cpu].crs, sizeof(rs.crs));
|
|
||||||
memcpy(&rs.acrs, &fir32OtherRecords[cpu].acrs, sizeof(rs.acrs));
|
|
||||||
/* No psw for ESA vmdumps */
|
|
||||||
rs.psw[0] = 0xdeadbeef;
|
|
||||||
rs.psw[1] = 0xdeadbeef;
|
|
||||||
memcpy(&rs.prefix, &fir32OtherRecords[cpu].prefix,
|
|
||||||
sizeof(rs.prefix));
|
|
||||||
memcpy(&rs.fprs, &fir32OtherRecords[cpu].fprs, sizeof(rs.fprs));
|
|
||||||
memcpy(&rs.cpuTimer, &fir32OtherRecords[cpu].cpu_timer,
|
|
||||||
sizeof(rs.cpuTimer));
|
|
||||||
memcpy(&rs.clkCmp, &fir32OtherRecords[cpu].clock_cmp,
|
|
||||||
sizeof(rs.clkCmp));
|
|
||||||
rc.addRegisterSet(rs);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VMDump32::printDebug(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
VMDump::printDebug();
|
|
||||||
printf("prefix: %x\n", fir32Record.prefix);
|
|
||||||
printf("cpus: %x\n", fir32Record.online_cpus);
|
|
||||||
printf("psw: %08x %08x\n", fir32Record.psw[0], fir32Record.psw[1]);
|
|
||||||
|
|
||||||
for (i=0; i < fir32Record.online_cpus; i++) {
|
|
||||||
/* fir other */
|
|
||||||
printf("prefix (%i): %x\n", i, fir32OtherRecords[i].prefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
VMDump32::printInfo(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "vmdump information:\n");
|
|
||||||
fprintf(stderr, " architecture: 32 bit\n");
|
|
||||||
VMDumpClassic::printInfo();
|
|
||||||
fprintf(stderr, " cpus........: %x\n", fir32Record.online_cpus + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VMDump32::~VMDump32(void)
|
|
||||||
{
|
|
||||||
delete fir32OtherRecords;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* VMDump64: 64 bit vmdump for old vmdump format (z/VM < 5.2) */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
VMDump64::VMDump64(const char* filename) : VMDumpClassic(filename)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if(!fh) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_seek(fh,(fmbkRecord.rec_nr_fir-1)* 0x1000 ,SEEK_SET);
|
|
||||||
dump_read(&fir64Record,sizeof(fir64Record),1,fh);
|
|
||||||
|
|
||||||
fir64OtherRecords = new _fir_other_64[fir64Record.online_cpus];
|
|
||||||
for (i=0; i < fir64Record.online_cpus; i++) {
|
|
||||||
/* fir other */
|
|
||||||
dump_read(&fir64OtherRecords[i], sizeof(fir64OtherRecords[i]),
|
|
||||||
1, fh);
|
|
||||||
}
|
|
||||||
if(debug)
|
|
||||||
printDebug();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VMDump64::printDebug(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
VMDump::printDebug();
|
|
||||||
printf("prefix: %x\n", fir64Record.prefix);
|
|
||||||
printf("cpus: %x\n", fir64Record.online_cpus);
|
|
||||||
printf("psw: %016llx %016llx\n", (long long)fir64Record.psw[0],
|
|
||||||
(long long)fir64Record.psw[1]);
|
|
||||||
|
|
||||||
for (i=0; i < fir64Record.online_cpus; i++) {
|
|
||||||
/* fir other */
|
|
||||||
printf("prefix (%i): %x\n", i, fir64OtherRecords[i].prefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VMDump64::printInfo(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "vmdump information:\n");
|
|
||||||
fprintf(stderr, " architecture: 64 bit\n");
|
|
||||||
VMDumpClassic::printInfo();
|
|
||||||
fprintf(stderr, " cpus........: %x\n",fir64Record.online_cpus + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RegisterContent64 VMDump64::getRegisterContent(void)
|
|
||||||
{
|
|
||||||
RegisterContent64 rc;
|
|
||||||
RegisterSet64 rs;
|
|
||||||
int cpu;
|
|
||||||
|
|
||||||
/* First CPU */
|
|
||||||
|
|
||||||
memcpy(&rs.gprs, &fir64Record.gprs, sizeof(rs.gprs));
|
|
||||||
memcpy(&rs.crs, &fir64Record.crs, sizeof(rs.crs));
|
|
||||||
memcpy(&rs.acrs, &fir64Record.acrs, sizeof(rs.acrs));
|
|
||||||
memcpy(&rs.psw, &fir64Record.psw, sizeof(rs.psw));
|
|
||||||
memcpy(&rs.prefix, &fir64Record.prefix, sizeof(rs.prefix));
|
|
||||||
memcpy(&rs.fprs, &fir64Record.fprs, sizeof(rs.fprs));
|
|
||||||
memcpy(&rs.cpuTimer, &fir64Record.cpu_timer, sizeof(rs.cpuTimer));
|
|
||||||
memcpy(&rs.clkCmp, &fir64Record.clock_cmp, sizeof(rs.clkCmp));
|
|
||||||
memcpy(&rs.fpCr, &fir64Record.fp_cntrl_reg, sizeof(rs.fpCr));
|
|
||||||
|
|
||||||
rc.addRegisterSet(rs);
|
|
||||||
|
|
||||||
/* other online cpus */
|
|
||||||
|
|
||||||
for (cpu = 0; cpu < fir64Record.online_cpus; cpu++) {
|
|
||||||
memcpy(&rs.gprs, &fir64OtherRecords[cpu].gprs, sizeof(rs.gprs));
|
|
||||||
memcpy(&rs.crs, &fir64OtherRecords[cpu].crs, sizeof(rs.crs));
|
|
||||||
memcpy(&rs.acrs, &fir64OtherRecords[cpu].acrs, sizeof(rs.acrs));
|
|
||||||
memcpy(&rs.psw, &fir64OtherRecords[cpu].psw, sizeof(rs.psw));
|
|
||||||
memcpy(&rs.prefix, &fir64OtherRecords[cpu].prefix,
|
|
||||||
sizeof(rs.prefix));
|
|
||||||
memcpy(&rs.fprs, &fir64OtherRecords[cpu].fprs, sizeof(rs.fprs));
|
|
||||||
memcpy(&rs.cpuTimer, &fir64OtherRecords[cpu].cpu_timer,
|
|
||||||
sizeof(rs.cpuTimer));
|
|
||||||
memcpy(&rs.clkCmp, &fir64OtherRecords[cpu].clock_cmp,
|
|
||||||
sizeof(rs.clkCmp));
|
|
||||||
memcpy(&rs.fpCr, &fir64OtherRecords[cpu].fp_cntrl_reg,
|
|
||||||
sizeof(rs.fpCr));
|
|
||||||
rc.addRegisterSet(rs);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
VMDump64::~VMDump64(void)
|
|
||||||
{
|
|
||||||
delete fir64OtherRecords;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* VMDump64Big: 64 bit vmdump with new big storage dump format */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
VMDump64Big::VMDump64Big(const char* filename) : VMDump(filename)
|
|
||||||
{
|
|
||||||
uint64_t pageNum, nrDumpedPages;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
if(!fh) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Record 9: asibk */
|
|
||||||
|
|
||||||
dump_seek(fh, fmbkRecord.rec_nr_access * 0x1000,SEEK_SET);
|
|
||||||
dump_read(&asibkRecordNew, sizeof(asibkRecordNew), 1, fh);
|
|
||||||
|
|
||||||
/* Record 10: bitmaps: */
|
|
||||||
/* Read all bitmap pages and setup bitmap array */
|
|
||||||
|
|
||||||
pageNum = 0;
|
|
||||||
nrDumpedPages = asibkRecordNew.storage_size_def_store / 0x1000;
|
|
||||||
memoryStartRecord = (fmbkRecord.rec_nr_access + 1) * 0x1000;
|
|
||||||
bitmap = new char[asibkRecordNew.storage_size_def_store/(0x1000 * 8)];
|
|
||||||
if(!bitmap) {
|
|
||||||
throw(DumpErrnoException("out of memory"));
|
|
||||||
}
|
|
||||||
memset(bitmap,0,asibkRecordNew.storage_size_def_store/(0x1000 * 8));
|
|
||||||
|
|
||||||
dump_seek(fh,(fmbkRecord.rec_nr_access + 1)* 0x1000 ,SEEK_SET);
|
|
||||||
|
|
||||||
do {
|
|
||||||
char bmIndexPage[0x1000];
|
|
||||||
|
|
||||||
dump_read(bmIndexPage, sizeof(bmIndexPage), 1, fh);
|
|
||||||
memoryStartRecord += 0x1000;
|
|
||||||
for (i=0; i < 0x1000; i++) {
|
|
||||||
if(testBitmapPage(bmIndexPage, i)) {
|
|
||||||
char bmPage[0x1000];
|
|
||||||
|
|
||||||
dump_read(bmPage,sizeof(bmPage),1,fh);
|
|
||||||
memoryStartRecord += 0x1000;
|
|
||||||
for(j = 0; j < 0x1000; j++) {
|
|
||||||
if(testBitmapKeyPage(bmPage, j)) {
|
|
||||||
setPageBit(pageNum);
|
|
||||||
}
|
|
||||||
pageNum++;
|
|
||||||
if(pageNum == nrDumpedPages) {
|
|
||||||
goto all_bitmaps_read;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pageNum += 0x1000; /* Empty pages */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (pageNum < nrDumpedPages);
|
|
||||||
|
|
||||||
all_bitmaps_read:
|
|
||||||
|
|
||||||
if(debug)
|
|
||||||
printf("Mem Offset: %llx\n", (long long)memoryStartRecord);
|
|
||||||
|
|
||||||
dump_seek(fh, (fmbkRecord.rec_nr_fir-1)* 0x1000, SEEK_SET);
|
|
||||||
dump_read(&fir64Record, sizeof(fir64Record), 1, fh);
|
|
||||||
|
|
||||||
fir64OtherRecords = new _fir_other_64[fir64Record.online_cpus];
|
|
||||||
for (i=0; i < fir64Record.online_cpus; i++) {
|
|
||||||
/* fir other */
|
|
||||||
dump_read(&fir64OtherRecords[i], sizeof(fir64OtherRecords[i]),
|
|
||||||
1, fh);
|
|
||||||
}
|
|
||||||
if(debug)
|
|
||||||
printDebug();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VMDump64Big::printDebug(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
VMDump::printDebug();
|
|
||||||
printf("prefix: %x\n", fir64Record.prefix);
|
|
||||||
printf("cpus: %x\n", fir64Record.online_cpus);
|
|
||||||
printf("psw: %016llx %016llx\n", (long long)fir64Record.psw[0],
|
|
||||||
(long long)fir64Record.psw[1]);
|
|
||||||
|
|
||||||
for (i=0; i < fir64Record.online_cpus; i++) {
|
|
||||||
/* fir other */
|
|
||||||
printf("prefix (%i): %x\n", i, fir64OtherRecords[i].prefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VMDump64Big::printInfo(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "vmdump information:\n");
|
|
||||||
fprintf(stderr, " architecture: 64 bit (big)\n");
|
|
||||||
fprintf(stderr, " storage.....: %lli MB\n",
|
|
||||||
(long long)asibkRecordNew.storage_size_def_store / (1024*1024));
|
|
||||||
VMDump::printInfo();
|
|
||||||
fprintf(stderr, " cpus........: %x\n", fir64Record.online_cpus + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RegisterContent64 VMDump64Big::getRegisterContent(void)
|
|
||||||
{
|
|
||||||
RegisterContent64 rc;
|
|
||||||
RegisterSet64 rs;
|
|
||||||
int cpu;
|
|
||||||
|
|
||||||
/* First CPU */
|
|
||||||
|
|
||||||
memcpy(&rs.gprs, &fir64Record.gprs, sizeof(rs.gprs));
|
|
||||||
memcpy(&rs.crs, &fir64Record.crs, sizeof(rs.crs));
|
|
||||||
memcpy(&rs.acrs, &fir64Record.acrs, sizeof(rs.acrs));
|
|
||||||
memcpy(&rs.psw, &fir64Record.psw, sizeof(rs.psw));
|
|
||||||
memcpy(&rs.prefix, &fir64Record.prefix, sizeof(rs.prefix));
|
|
||||||
memcpy(&rs.fprs, &fir64Record.fprs, sizeof(rs.fprs));
|
|
||||||
memcpy(&rs.cpuTimer, &fir64Record.cpu_timer, sizeof(rs.cpuTimer));
|
|
||||||
memcpy(&rs.clkCmp, &fir64Record.clock_cmp, sizeof(rs.clkCmp));
|
|
||||||
memcpy(&rs.fpCr, &fir64Record.fp_cntrl_reg, sizeof(rs.fpCr));
|
|
||||||
|
|
||||||
rc.addRegisterSet(rs);
|
|
||||||
|
|
||||||
/* other online cpus */
|
|
||||||
|
|
||||||
for(cpu = 0; cpu < fir64Record.online_cpus; cpu++) {
|
|
||||||
memcpy(&rs.gprs, &fir64OtherRecords[cpu].gprs, sizeof(rs.gprs));
|
|
||||||
memcpy(&rs.crs, &fir64OtherRecords[cpu].crs, sizeof(rs.crs));
|
|
||||||
memcpy(&rs.acrs, &fir64OtherRecords[cpu].acrs, sizeof(rs.acrs));
|
|
||||||
memcpy(&rs.psw, &fir64OtherRecords[cpu].psw, sizeof(rs.psw));
|
|
||||||
memcpy(&rs.prefix, &fir64OtherRecords[cpu].prefix,
|
|
||||||
sizeof(rs.prefix));
|
|
||||||
memcpy(&rs.fprs, &fir64OtherRecords[cpu].fprs, sizeof(rs.fprs));
|
|
||||||
memcpy(&rs.cpuTimer, &fir64OtherRecords[cpu].cpu_timer,
|
|
||||||
sizeof(rs.cpuTimer));
|
|
||||||
memcpy(&rs.clkCmp, &fir64OtherRecords[cpu].clock_cmp,
|
|
||||||
sizeof(rs.clkCmp));
|
|
||||||
memcpy(&rs.fpCr, &fir64OtherRecords[cpu].fp_cntrl_reg,
|
|
||||||
sizeof(rs.fpCr));
|
|
||||||
rc.addRegisterSet(rs);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
VMDump64Big::~VMDump64Big(void)
|
|
||||||
{
|
|
||||||
delete bitmap;
|
|
||||||
delete fir64OtherRecords;
|
|
||||||
}
|
|
||||||
@@ -1,484 +0,0 @@
|
|||||||
/*
|
|
||||||
* vmdump - z/VM dump conversion library
|
|
||||||
*
|
|
||||||
* Register content classes:
|
|
||||||
* VMDump, VMDumpClassic, VMDump64, VMDump64Big, VMDump32
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2004, 2017
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*===========================*
|
|
||||||
* The format of an vmdump: *
|
|
||||||
*===========================*
|
|
||||||
*---------------------------*
|
|
||||||
* Symptom Record *
|
|
||||||
* (ADSR COPY) Record 1 *
|
|
||||||
*---------------------------*
|
|
||||||
* Dump File Map Record *
|
|
||||||
* (HCPDFMBK COPY) Record 2 *
|
|
||||||
*---------------------------*
|
|
||||||
* Dump File Info Record *
|
|
||||||
* (HCPDFIR COPY) Records 3-7*
|
|
||||||
*---------------------------*
|
|
||||||
* Vector Registers *
|
|
||||||
* (optional) *
|
|
||||||
*---------------------------*
|
|
||||||
* Access Lists (HCPDALBK) *
|
|
||||||
*---------------------------*
|
|
||||||
* Address Space A *
|
|
||||||
* Information and Map *
|
|
||||||
* Record (HCPASIBK) *
|
|
||||||
*---------------------------*
|
|
||||||
* Address Space A *
|
|
||||||
* Bit Maps *
|
|
||||||
*---------------------------*
|
|
||||||
* Address Space A *
|
|
||||||
* Key Maps *
|
|
||||||
*---------------------------*
|
|
||||||
* Address Space A *
|
|
||||||
* Guest Storage *
|
|
||||||
*---------------------------*
|
|
||||||
* Additional Address Spaces *
|
|
||||||
* ASIBK *
|
|
||||||
* Bit Maps *
|
|
||||||
* Key Maps *
|
|
||||||
* Guest Storage *
|
|
||||||
* *NOTE* These probably *
|
|
||||||
* aren't in a Linux guest. *
|
|
||||||
*---------------------------*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef VMDUMP_H
|
|
||||||
#define VMDUMP_H
|
|
||||||
|
|
||||||
#include <iconv.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "lib/zt_common.h"
|
|
||||||
|
|
||||||
#include "dump.h"
|
|
||||||
#include "register_content.h"
|
|
||||||
|
|
||||||
class VMDump : public Dump
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VMDump(const char *filename);
|
|
||||||
virtual ~VMDump(void);
|
|
||||||
virtual void readMem(char *buf, int size);
|
|
||||||
virtual int seekMem(uint64_t offset);
|
|
||||||
virtual struct timeval getDumpTime(void) const;
|
|
||||||
|
|
||||||
void printDebug(void);
|
|
||||||
void printInfo(void);
|
|
||||||
|
|
||||||
static DumpType getDumpType(const char *);
|
|
||||||
inline int testPage(uint64_t bit) const
|
|
||||||
{
|
|
||||||
return (bitmap[bit/8] & (1 << (7-(bit % 8))));
|
|
||||||
}
|
|
||||||
inline void setPageBit(uint64_t bit) const
|
|
||||||
{
|
|
||||||
bitmap[bit/8] |= (1 << (7-(bit % 8)));
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
/* Types */
|
|
||||||
struct _adsr {
|
|
||||||
/* Section 1*/
|
|
||||||
uint16_t sr;
|
|
||||||
uint32_t cpu_model;
|
|
||||||
char cpu_serial[6];
|
|
||||||
uint32_t time_zone_conversion_factor;
|
|
||||||
uint64_t tod;
|
|
||||||
char time_stamp_str[4];
|
|
||||||
char date_str[6];
|
|
||||||
char node_name[8];
|
|
||||||
char product_id[4];
|
|
||||||
char feature_level[8];
|
|
||||||
uint8_t record_status_flag1;
|
|
||||||
uint8_t record_status_flag2;
|
|
||||||
uint64_t dump_type;
|
|
||||||
|
|
||||||
/* Section 2*/
|
|
||||||
char arch_level[2];
|
|
||||||
uint16_t sec2_len;
|
|
||||||
uint16_t sec2_1_len;
|
|
||||||
uint16_t sec2_1_offset;
|
|
||||||
uint16_t sec3_len;
|
|
||||||
uint16_t sec3_offset;
|
|
||||||
uint16_t sec4_len;
|
|
||||||
uint16_t sec4_offset;
|
|
||||||
uint16_t sec5_len;
|
|
||||||
uint16_t sec5_offset;
|
|
||||||
uint16_t sec6_len;
|
|
||||||
uint16_t sec6_offset;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct _fmbk {
|
|
||||||
char id[8];
|
|
||||||
uint32_t rec_nr_fir;
|
|
||||||
uint32_t rec_nr_vector;
|
|
||||||
uint32_t rec_nr_access;
|
|
||||||
uint32_t num_acc_recs;
|
|
||||||
uint32_t num_addr_spaces;
|
|
||||||
uint32_t rec_nr_asibk;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct _fir_basic {
|
|
||||||
char filler1[15];
|
|
||||||
uint8_t dump_format;/* 0x1 for big storage dump, 0x2 for cp */
|
|
||||||
/* hard abend, 0x3 for cp soft abend */
|
|
||||||
char filler2[171];
|
|
||||||
uint8_t fir_format; /* 0x2 for big esame, 0x82 for esame, */
|
|
||||||
/* 0x00 for esa */
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct _albk {
|
|
||||||
char id[8];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/* Methods */
|
|
||||||
inline void ebcAsc(char *in, char *out, size_t size) const
|
|
||||||
{
|
|
||||||
size_t size_out = size;
|
|
||||||
size_t size_in = size;
|
|
||||||
size_t rc;
|
|
||||||
|
|
||||||
rc = iconv(ebcdicAsciiConv, &in, &size_in, &out, &size_out);
|
|
||||||
if (rc == (size_t) -1)
|
|
||||||
throw(DumpException("Code page translation EBCDIC-ASCII failed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Members */
|
|
||||||
struct _adsr adsrRecord;
|
|
||||||
struct _fmbk fmbkRecord;
|
|
||||||
struct _albk albkRecord;
|
|
||||||
uint64_t memoryStartRecord;
|
|
||||||
char *bitmap;
|
|
||||||
uint64_t pageOffset;
|
|
||||||
private:
|
|
||||||
iconv_t ebcdicAsciiConv;
|
|
||||||
};
|
|
||||||
|
|
||||||
class VMDumpClassic : public VMDump
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VMDumpClassic(const char *filename);
|
|
||||||
virtual ~VMDumpClassic(void);
|
|
||||||
void printInfo(void);
|
|
||||||
inline virtual uint64_t getMemSize(void) const
|
|
||||||
{
|
|
||||||
return (uint64_t)asibkRecord.storage_size_2GB;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
/* Types */
|
|
||||||
struct _asibk {
|
|
||||||
char id[8];
|
|
||||||
char as_token[8];
|
|
||||||
char spaceid[33];
|
|
||||||
char reserved1[3];
|
|
||||||
uint32_t storage_size_2GB;
|
|
||||||
uint32_t dcss_bitmap_first_rec;
|
|
||||||
uint32_t byte_past_highest_defined_byte;
|
|
||||||
uint64_t format_of_as;
|
|
||||||
char dump_id[100];
|
|
||||||
uint32_t nr_of_recs_of_first_bit_map;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
|
|
||||||
/* Members */
|
|
||||||
struct _asibk asibkRecord;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX_BKEY_PAGES 2
|
|
||||||
|
|
||||||
class VMDump64Big : public VMDump
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VMDump64Big(const char *filename);
|
|
||||||
virtual ~VMDump64Big(void);
|
|
||||||
RegisterContent64 getRegisterContent(void);
|
|
||||||
|
|
||||||
void printDebug(void);
|
|
||||||
void printInfo(void);
|
|
||||||
|
|
||||||
inline virtual uint64_t getMemSize(void) const
|
|
||||||
{
|
|
||||||
return (uint64_t)asibkRecordNew.storage_size_def_store;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
inline int testBitmapPage(char *page, uint64_t bit) const
|
|
||||||
{
|
|
||||||
return (page[bit/8] & (1 << (7-(bit % 8))));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int testBitmapKeyPage(char *page, uint64_t bit) const
|
|
||||||
{
|
|
||||||
return (page[bit] & 0x01);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* types */
|
|
||||||
struct _asibk_64_new {
|
|
||||||
char id[8];
|
|
||||||
char as_token[8];
|
|
||||||
char spaceid[33];
|
|
||||||
char reserved1[2];
|
|
||||||
uint8_t asibk_format;
|
|
||||||
char filler1[12];
|
|
||||||
uint64_t storage_size_with_dcss;
|
|
||||||
uint64_t storage_size_def_store;
|
|
||||||
char filler2[136];
|
|
||||||
uint64_t online_storage_table[8]; /* for "def store config" */
|
|
||||||
uint64_t fence1;
|
|
||||||
uint64_t requested_range_table[8];
|
|
||||||
uint64_t fence2;
|
|
||||||
uint32_t record_number_of_first_bit_map; /* XXX */
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct _fir_64 {
|
|
||||||
char id[8];
|
|
||||||
uint64_t reserved1;
|
|
||||||
uint64_t gprs[16];
|
|
||||||
uint32_t prefix;
|
|
||||||
char reserved2[5];
|
|
||||||
uint64_t tod;
|
|
||||||
char reserved3[8];
|
|
||||||
uint64_t cpu_timer;
|
|
||||||
char reserved4[7];
|
|
||||||
uint8_t flag;
|
|
||||||
uint8_t type;
|
|
||||||
uint8_t complete;
|
|
||||||
uint8_t fir_format; /* 0x82 for esame - 0x00 for esa */
|
|
||||||
uint8_t cont_flags;
|
|
||||||
uint8_t crypto_domain_index_reg;
|
|
||||||
uint8_t virt_cpu_info;
|
|
||||||
uint8_t arch_mode_id;
|
|
||||||
uint64_t psw[2];
|
|
||||||
uint64_t crs[16];
|
|
||||||
uint64_t fprs[16];
|
|
||||||
uint8_t reserved5;
|
|
||||||
uint64_t clock_cmp;
|
|
||||||
char reserved6[3];
|
|
||||||
uint32_t tod_programmable_reg;
|
|
||||||
uint32_t reserved_for_dvf[20];
|
|
||||||
uint32_t acrs[16];
|
|
||||||
uint32_t storage_size_2GB;
|
|
||||||
uint32_t reserved7;
|
|
||||||
uint32_t hcpsys_addr;
|
|
||||||
uint32_t reserved8;
|
|
||||||
uint64_t storage_size;
|
|
||||||
uint32_t snap_area_map_blk;
|
|
||||||
uint32_t reserved9;
|
|
||||||
char loc_mem[256];
|
|
||||||
uint16_t online_cpus;
|
|
||||||
uint16_t cpu_addr;
|
|
||||||
uint16_t section_size_vector;
|
|
||||||
uint16_t reserved10;
|
|
||||||
char asit_primary[8];
|
|
||||||
char space_id_primary[33];
|
|
||||||
char reserved12[3];
|
|
||||||
uint16_t crypto_domain_index_mask;
|
|
||||||
uint16_t reserved11;
|
|
||||||
uint32_t fp_cntrl_reg;
|
|
||||||
uint32_t reserved13;
|
|
||||||
uint64_t reserved14[16];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct _fir_other_64 {
|
|
||||||
uint16_t cpu_addr;
|
|
||||||
uint16_t vector_sec_size;
|
|
||||||
uint8_t crypto_index_reg;
|
|
||||||
uint8_t virt_cpu_info;
|
|
||||||
uint16_t crypto_index_mask;
|
|
||||||
uint32_t reserved1[2];
|
|
||||||
uint64_t fprs[16];
|
|
||||||
uint64_t gprs[16];
|
|
||||||
uint64_t psw[2];
|
|
||||||
uint32_t reserved2[2];
|
|
||||||
uint32_t prefix;
|
|
||||||
uint32_t fp_cntrl_reg;
|
|
||||||
uint32_t reserved3;
|
|
||||||
uint32_t tod;
|
|
||||||
uint64_t cpu_timer;
|
|
||||||
uint64_t clock_cmp;
|
|
||||||
uint32_t reserved4[2];
|
|
||||||
uint32_t acrs[16];
|
|
||||||
uint64_t crs[16];
|
|
||||||
uint64_t mc_interrupt_code;
|
|
||||||
uint32_t reserved5;
|
|
||||||
uint32_t external_damage_code;
|
|
||||||
uint64_t mc_failing_storage_addr;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/* Members */
|
|
||||||
struct _asibk_64_new asibkRecordNew;
|
|
||||||
struct _fir_64 fir64Record;
|
|
||||||
struct _fir_other_64 *fir64OtherRecords;
|
|
||||||
};
|
|
||||||
|
|
||||||
class VMDump64 : public VMDumpClassic
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VMDump64(const char *filename);
|
|
||||||
virtual ~VMDump64(void);
|
|
||||||
RegisterContent64 getRegisterContent(void);
|
|
||||||
|
|
||||||
void printDebug(void);
|
|
||||||
void printInfo(void);
|
|
||||||
private:
|
|
||||||
/* Types */
|
|
||||||
struct _fir_64 {
|
|
||||||
char id[8];
|
|
||||||
uint64_t reserved1;
|
|
||||||
uint64_t gprs[16];
|
|
||||||
uint32_t prefix;
|
|
||||||
char reserved2[5];
|
|
||||||
uint64_t tod;
|
|
||||||
char reserved3[8];
|
|
||||||
uint64_t cpu_timer;
|
|
||||||
char reserved4[7];
|
|
||||||
uint8_t flag;
|
|
||||||
uint8_t type;
|
|
||||||
uint8_t complete;
|
|
||||||
uint8_t fir_format; /* 0x82 for esame - 0x00 for esa */
|
|
||||||
uint8_t cont_flags;
|
|
||||||
uint8_t crypto_domain_index_reg;
|
|
||||||
uint8_t virt_cpu_info;
|
|
||||||
uint8_t arch_mode_id;
|
|
||||||
uint64_t psw[2];
|
|
||||||
uint64_t crs[16];
|
|
||||||
uint64_t fprs[16];
|
|
||||||
uint8_t reserved5;
|
|
||||||
uint64_t clock_cmp;
|
|
||||||
char reserved6[3];
|
|
||||||
uint32_t tod_programmable_reg;
|
|
||||||
uint32_t reserved_for_dvf[20];
|
|
||||||
uint32_t acrs[16];
|
|
||||||
uint32_t storage_size_2GB;
|
|
||||||
uint32_t reserved7;
|
|
||||||
uint32_t hcpsys_addr;
|
|
||||||
uint32_t reserved8;
|
|
||||||
uint64_t storage_size;
|
|
||||||
uint32_t snap_area_map_blk;
|
|
||||||
uint32_t reserved9;
|
|
||||||
char loc_mem[256];
|
|
||||||
uint16_t online_cpus;
|
|
||||||
uint16_t cpu_addr;
|
|
||||||
uint16_t section_size_vector;
|
|
||||||
uint16_t reserved10;
|
|
||||||
char asit_primary[8];
|
|
||||||
char space_id_primary[33];
|
|
||||||
char reserved12[3];
|
|
||||||
uint16_t crypto_domain_index_mask;
|
|
||||||
uint16_t reserved11;
|
|
||||||
uint32_t fp_cntrl_reg;
|
|
||||||
uint32_t reserved13;
|
|
||||||
uint64_t reserved14[16];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct _fir_other_64 {
|
|
||||||
uint16_t cpu_addr;
|
|
||||||
uint16_t vector_sec_size;
|
|
||||||
uint8_t crypto_index_reg;
|
|
||||||
uint8_t virt_cpu_info;
|
|
||||||
uint16_t crypto_index_mask;
|
|
||||||
uint32_t reserved1[2];
|
|
||||||
uint64_t fprs[16];
|
|
||||||
uint64_t gprs[16];
|
|
||||||
uint64_t psw[2];
|
|
||||||
uint32_t reserved2[2];
|
|
||||||
uint32_t prefix;
|
|
||||||
uint32_t fp_cntrl_reg;
|
|
||||||
uint32_t reserved3;
|
|
||||||
uint32_t tod;
|
|
||||||
uint64_t cpu_timer;
|
|
||||||
uint64_t clock_cmp;
|
|
||||||
uint32_t reserved4[2];
|
|
||||||
uint32_t acrs[16];
|
|
||||||
uint64_t crs[16];
|
|
||||||
uint64_t mc_interrupt_code;
|
|
||||||
uint32_t reserved5;
|
|
||||||
uint32_t external_damage_code;
|
|
||||||
uint64_t mc_failing_storage_addr;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/* Members */
|
|
||||||
struct _fir_64 fir64Record;
|
|
||||||
struct _fir_other_64 *fir64OtherRecords;
|
|
||||||
};
|
|
||||||
|
|
||||||
class VMDump32 : public VMDumpClassic
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VMDump32(const char *filename);
|
|
||||||
virtual ~VMDump32(void);
|
|
||||||
RegisterContent32 getRegisterContent(void);
|
|
||||||
void printDebug(void);
|
|
||||||
void printInfo(void);
|
|
||||||
private:
|
|
||||||
/* Types */
|
|
||||||
struct _fir_32 {
|
|
||||||
uint32_t gprs[16];
|
|
||||||
uint32_t crs[16];
|
|
||||||
uint64_t fprs[4];
|
|
||||||
uint64_t tod;
|
|
||||||
uint64_t cpu_timer;
|
|
||||||
uint64_t clock_cmp;
|
|
||||||
uint8_t flag;
|
|
||||||
uint8_t type;
|
|
||||||
uint8_t complete;
|
|
||||||
uint8_t fir_format;
|
|
||||||
uint32_t storage_size_2GB;
|
|
||||||
char loc_mem[256];
|
|
||||||
uint32_t prefix;
|
|
||||||
uint16_t online_cpus;
|
|
||||||
uint8_t cont_flags;
|
|
||||||
uint8_t crypto_domain_index_reg;
|
|
||||||
uint8_t virt_cpu_info;
|
|
||||||
uint8_t arch_mode_id;
|
|
||||||
uint16_t crypto_domain_index_mask;
|
|
||||||
uint32_t reserved1;
|
|
||||||
uint32_t snap_area_map_blk;
|
|
||||||
uint64_t reserved2;
|
|
||||||
uint32_t hcpsys_addr;
|
|
||||||
uint32_t reserved3[20];
|
|
||||||
uint32_t psw[2];
|
|
||||||
uint16_t cpu_addr;
|
|
||||||
uint16_t section_size_vector;
|
|
||||||
uint32_t acrs[16];
|
|
||||||
char asit_primary[8];
|
|
||||||
char space_id_primary[33];
|
|
||||||
char reserved4[131];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct _fir_other_32 {
|
|
||||||
uint16_t cpu_addr;
|
|
||||||
uint16_t vector_sec_size;
|
|
||||||
uint32_t prefix;
|
|
||||||
uint8_t crypto_index_reg;
|
|
||||||
uint8_t virt_cpu_info;
|
|
||||||
uint16_t crypto_index_mask;
|
|
||||||
uint32_t reserved1;
|
|
||||||
uint64_t cpu_timer;
|
|
||||||
uint64_t clock_cmp;
|
|
||||||
uint64_t mc_interrupt_code;
|
|
||||||
uint64_t reserved2;
|
|
||||||
uint32_t mc_failing_storage_addr;
|
|
||||||
uint32_t machine_dependent_region_code;
|
|
||||||
uint32_t lixed_logout_area[4];
|
|
||||||
char reserved3[16];
|
|
||||||
uint32_t acrs[16];
|
|
||||||
uint64_t fprs[4];
|
|
||||||
uint32_t gprs[16];
|
|
||||||
uint32_t crs[16];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/* Members */
|
|
||||||
struct _fir_32 fir32Record;
|
|
||||||
struct _fir_other_32 *fir32OtherRecords;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* VMDUMP_H */
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* vmdump - z/VM dump conversion library
|
|
||||||
*
|
|
||||||
* Dump convert function: Converts VMDUMP to LKCD dump
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2004, 2017
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lkcd_dump.h"
|
|
||||||
#include "vm_dump.h"
|
|
||||||
|
|
||||||
int vmdump_convert(const char* inputFileName, const char* outputFileName,
|
|
||||||
const char* progName)
|
|
||||||
{
|
|
||||||
/* Do the conversion */
|
|
||||||
try {
|
|
||||||
switch(VMDump::getDumpType(inputFileName)){
|
|
||||||
case Dump::DT_VM64_BIG:
|
|
||||||
{
|
|
||||||
LKCDDump64* lkcddump;
|
|
||||||
VMDump64Big* vmdump;
|
|
||||||
|
|
||||||
vmdump = new VMDump64Big(inputFileName);
|
|
||||||
vmdump->printInfo();
|
|
||||||
lkcddump = new LKCDDump64(vmdump,
|
|
||||||
vmdump->getRegisterContent());
|
|
||||||
lkcddump->writeDump(outputFileName);
|
|
||||||
delete vmdump;
|
|
||||||
delete lkcddump;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Dump::DT_VM64:
|
|
||||||
{
|
|
||||||
LKCDDump64* lkcddump;
|
|
||||||
VMDump64* vmdump;
|
|
||||||
|
|
||||||
vmdump = new VMDump64(inputFileName);
|
|
||||||
vmdump->printInfo();
|
|
||||||
lkcddump = new LKCDDump64(vmdump,
|
|
||||||
vmdump->getRegisterContent());
|
|
||||||
lkcddump->writeDump(outputFileName);
|
|
||||||
delete vmdump;
|
|
||||||
delete lkcddump;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Dump::DT_VM32:
|
|
||||||
{
|
|
||||||
LKCDDump32* lkcddump;
|
|
||||||
VMDump32* vmdump;
|
|
||||||
|
|
||||||
vmdump = new VMDump32(inputFileName);
|
|
||||||
vmdump->printInfo();
|
|
||||||
lkcddump = new LKCDDump32(vmdump,
|
|
||||||
vmdump->getRegisterContent());
|
|
||||||
lkcddump->writeDump(outputFileName);
|
|
||||||
delete vmdump;
|
|
||||||
delete lkcddump;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw DumpException("This is not a vmdump");
|
|
||||||
}
|
|
||||||
} catch (DumpException ex) {
|
|
||||||
printf("%s: %s\n", progName, ex.what());
|
|
||||||
fflush(stdout);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ install: install-scripts
|
|||||||
install-scripts: $(SCRIPTS)
|
install-scripts: $(SCRIPTS)
|
||||||
@if [ ! -d $(DESTDIR)$(NETBOOT_SAMPLEDIR) ]; then \
|
@if [ ! -d $(DESTDIR)$(NETBOOT_SAMPLEDIR) ]; then \
|
||||||
mkdir -p $(DESTDIR)$(NETBOOT_SAMPLEDIR); \
|
mkdir -p $(DESTDIR)$(NETBOOT_SAMPLEDIR); \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(NETBOOT_SAMPLEDIR); \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(NETBOOT_SAMPLEDIR); \
|
||||||
chmod 755 $(DESTDIR)$(NETBOOT_SAMPLEDIR); \
|
chmod 755 $(DESTDIR)$(NETBOOT_SAMPLEDIR); \
|
||||||
fi; \
|
fi; \
|
||||||
for i in $^; do \
|
for i in $^; do \
|
||||||
$(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
$(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
||||||
< $$i >$(DESTDIR)$(NETBOOT_SAMPLEDIR)/$$i; \
|
< $$i >$(DESTDIR)$(NETBOOT_SAMPLEDIR)/$$i; \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(NETBOOT_SAMPLEDIR)/$$i; \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(NETBOOT_SAMPLEDIR)/$$i; \
|
||||||
chmod 755 $(DESTDIR)$(NETBOOT_SAMPLEDIR)/$$i; \
|
chmod 755 $(DESTDIR)$(NETBOOT_SAMPLEDIR)/$$i; \
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -11,10 +11,10 @@
|
|||||||
/* Must be included before any other header */
|
/* Must be included before any other header */
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <glib/gi18n.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "libpv/glib-helper.h"
|
#include "libpv/glib-helper.h"
|
||||||
|
#include <glib/gi18n.h>
|
||||||
#include "libpv/macros.h"
|
#include "libpv/macros.h"
|
||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ all:
|
|||||||
install: qethconf
|
install: qethconf
|
||||||
$(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
$(SED) -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
||||||
< qethconf >$(DESTDIR)$(BINDIR)/qethconf; \
|
< qethconf >$(DESTDIR)$(BINDIR)/qethconf; \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(BINDIR)/qethconf; \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(BINDIR)/qethconf; \
|
||||||
chmod 755 $(DESTDIR)$(BINDIR)/qethconf; \
|
chmod 755 $(DESTDIR)$(BINDIR)/qethconf; \
|
||||||
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man8
|
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man8
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 qethconf.8 \
|
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 qethconf.8 \
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#
|
#
|
||||||
# dbginfo.sh - Tool to collect runtime, configuration, and trace information
|
# dbginfo.sh - Tool to collect runtime, configuration, and trace information
|
||||||
#
|
#
|
||||||
# Copyright IBM Corp. 2002, 2022
|
# Copyright IBM Corp. 2002, 2023
|
||||||
#
|
#
|
||||||
# s390-tools is free software; you can redistribute it and/or modify
|
# s390-tools is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the MIT license. See LICENSE for details.
|
# it under the terms of the MIT license. See LICENSE for details.
|
||||||
@@ -71,7 +71,7 @@ paramWORKDIR_BASE="/tmp" # initial default path
|
|||||||
print_version() {
|
print_version() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
${SCRIPTNAME}: Debug information script version %S390_TOOLS_VERSION%
|
${SCRIPTNAME}: Debug information script version %S390_TOOLS_VERSION%
|
||||||
Copyright IBM Corp. 2002, 2022
|
Copyright IBM Corp. 2002, 2023
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,6 +525,7 @@ CMDS="${CMDS}\
|
|||||||
# product / distro specific commands
|
# product / distro specific commands
|
||||||
CMDS="${CMDS}\
|
CMDS="${CMDS}\
|
||||||
:java -version\
|
:java -version\
|
||||||
|
:qemu-ga -V\
|
||||||
:SPident # SLES service package\
|
:SPident # SLES service package\
|
||||||
"
|
"
|
||||||
|
|
||||||
@@ -655,10 +656,10 @@ VM_CMDS="q userid\
|
|||||||
:q quickdsp VMUSERID\
|
:q quickdsp VMUSERID\
|
||||||
:q pcifunction\
|
:q pcifunction\
|
||||||
:q vmrelocate\
|
:q vmrelocate\
|
||||||
|
:q syscontrol\
|
||||||
:ind load\
|
:ind load\
|
||||||
:ind sp\
|
:ind sp\
|
||||||
:ind user\
|
:ind user\
|
||||||
:qemu-ga -V\
|
|
||||||
"
|
"
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -1192,6 +1193,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}
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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 */
|
|
||||||
fd = open (device, O_RDONLY);
|
|
||||||
if (fd == -1) {
|
|
||||||
error_print ("<%s> - %s", device, strerror (errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the given caching attributes */
|
rc = dasd_get_cache(device, &attrib_data);
|
||||||
if (ioctl (fd, BIODASDGATTR, &attrib_data)) {
|
if (rc)
|
||||||
error_print ("Could not get cache attributes for device <%s>",
|
return rc;
|
||||||
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 */
|
||||||
@@ -648,38 +491,26 @@ disk_profile (char* device, char* prof_item)
|
|||||||
} else {
|
} else {
|
||||||
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
include ../common.mak
|
|
||||||
|
|
||||||
ALL_CPPFLAGS += -D_FILE_OFFSET_BITS=64
|
|
||||||
LDLIBS += -lz
|
|
||||||
|
|
||||||
all: vmconvert
|
|
||||||
|
|
||||||
libs = $(rootdir)/libvmdump/libvmdump.a
|
|
||||||
objects = vmconvert.o
|
|
||||||
|
|
||||||
vmconvert: $(objects) $(libs)
|
|
||||||
$(LINKXX) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
|
||||||
|
|
||||||
install: all
|
|
||||||
$(INSTALL) -d -m 755 $(DESTDIR)$(USRBINDIR) $(DESTDIR)$(MANDIR)/man1
|
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 vmconvert \
|
|
||||||
$(DESTDIR)$(USRBINDIR)
|
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 vmconvert.1 \
|
|
||||||
$(DESTDIR)\$(MANDIR)/man1
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *.o vmconvert
|
|
||||||
|
|
||||||
.PHONY: all install clean
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
.\" Copyright 2017 IBM Corp.
|
|
||||||
.\" s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
.\"
|
|
||||||
.TH VMCONVERT 1 "Apr 2006" "s390-tools"
|
|
||||||
.SH NAME
|
|
||||||
vmconvert \- convert VMDUMPs into lkcd dumps
|
|
||||||
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B vmconvert
|
|
||||||
-f \fIVMDUMPFILE\fR [-o \fIOUTPUTFILE\fR] [-h] [-v]
|
|
||||||
|
|
||||||
.B vmconvert
|
|
||||||
\fIVMDUMPFILE\fR [\fIOUTPUTFILE\fR]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.B vmconvert
|
|
||||||
is a tool to convert VMDUMPs into lkcd dumps, which can be analyzed by Linux
|
|
||||||
dumpanalysis tools (e.g. lcrash or crash).
|
|
||||||
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.BR "\-h" " or " "\-\-help"
|
|
||||||
Print usage information, then exit.
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.BR "\-v" " or " "\-\-version"
|
|
||||||
Print version information, then exit.
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.BR "\-f VMDUMPFILE" " or " "\-\-file=VMDUMPFILE"
|
|
||||||
Use the specified VMDUMPFILE as input file.
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.BR "\-o OUTPUTFILE" " or " "\-\-output=OUTPUTFILE"
|
|
||||||
Use the specified OUTPUTFILE as filename for the lkcd dump. The default
|
|
||||||
filename is 'dump.lkcd'
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
* vmconvert - Convert z/VM VMDUMPs into Linux lkcd dumps
|
|
||||||
*
|
|
||||||
* Main program
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2004, 2017
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "lib/vmdump.h"
|
|
||||||
#include "lib/zt_common.h"
|
|
||||||
|
|
||||||
static struct option longopts[] = {
|
|
||||||
{"file",required_argument,0,'f'},
|
|
||||||
{"help",no_argument,0,'h'},
|
|
||||||
{"version",no_argument,0,'v'},
|
|
||||||
{"output",required_argument,0,'o'},
|
|
||||||
{0,0,0,0}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define OPTSTRING "f:o:vh"
|
|
||||||
extern char *optarg;
|
|
||||||
|
|
||||||
/* Version info */
|
|
||||||
static const char version_text[] = "vmconvert: vmdump converter tool version "\
|
|
||||||
RELEASE_STRING;
|
|
||||||
|
|
||||||
/* Copyright notice */
|
|
||||||
static const char copyright_notice[] = "Copyright IBM Corp. 2004, 2017";
|
|
||||||
|
|
||||||
/* Usage information */
|
|
||||||
static const char usage_text[] = \
|
|
||||||
"Usage: vmconvert -f VMDUMPFILE [-o OUTPUTFILE]\n" \
|
|
||||||
" vmconvert VMDUMPFILE [OUTPUTFILE]\n" \
|
|
||||||
"\n" \
|
|
||||||
"Convert a vmdump into a lkcd (linux kernel crash dumps) dump.\n" \
|
|
||||||
"\n" \
|
|
||||||
"-h, --help Print this help, then exit.\n" \
|
|
||||||
"-v, --version Print version information, then exit.\n" \
|
|
||||||
"-f, --file VMDUMPFILE The vmdump file VMDUMPFILE, which should be\n"\
|
|
||||||
" converted.\n" \
|
|
||||||
"-o, --output OUTPUTFILE The converted lkcd dump file OUTPUTFILE.\n"\
|
|
||||||
" The default file name is 'dump.lkcd'.\n";
|
|
||||||
|
|
||||||
/* Globals */
|
|
||||||
char inputFileName[1024];
|
|
||||||
char outputFileName[1024] = "dump.lkcd";
|
|
||||||
|
|
||||||
void
|
|
||||||
parseOpts(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
int inputFileSet = 0;
|
|
||||||
int outputFileSet = 0;
|
|
||||||
int c, longIndex;
|
|
||||||
while((c = getopt_long(argc, argv, OPTSTRING, longopts,
|
|
||||||
&longIndex)) != -1) {
|
|
||||||
switch (c) {
|
|
||||||
case 'f':
|
|
||||||
strcpy(inputFileName, optarg);
|
|
||||||
inputFileSet = 1;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
strcpy(outputFileName, optarg);
|
|
||||||
outputFileSet = 1;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
printf("%s", usage_text);
|
|
||||||
exit(0);
|
|
||||||
case 'v':
|
|
||||||
printf("%s\n", version_text);
|
|
||||||
printf("%s\n", copyright_notice);
|
|
||||||
exit(0);
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "Try 'vmconvert --help' for"
|
|
||||||
" more information.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* check for positional parameters */
|
|
||||||
if (optind < argc) {
|
|
||||||
int count = 0;
|
|
||||||
while (optind < argc){
|
|
||||||
if(!inputFileSet && count==0){
|
|
||||||
strcpy(inputFileName, argv[optind]);
|
|
||||||
inputFileSet = 1;
|
|
||||||
} else if(!outputFileSet && count==1){
|
|
||||||
strcpy(outputFileName, argv[optind]);
|
|
||||||
outputFileSet = 1;
|
|
||||||
} else if(count == 2){
|
|
||||||
printf("%s", usage_text);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
count++;
|
|
||||||
optind++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!inputFileSet){
|
|
||||||
printf("%s: input file required - use '-f' option!\n",argv[0]);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
struct stat s;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
parseOpts(argc,argv);
|
|
||||||
|
|
||||||
/* Check if output file already exists */
|
|
||||||
if(stat(outputFileName,&s) == 0){
|
|
||||||
char answer[100];
|
|
||||||
printf("%s: overwrite file '%s'? ",argv[0],outputFileName);
|
|
||||||
if(scanf("%s",answer) != 1)
|
|
||||||
exit(1);
|
|
||||||
if((strcmp(answer,"y") != 0) && (strcmp(answer,"yes") != 0))
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
rc = vmdump_convert(inputFileName, outputFileName, argv[0]);
|
|
||||||
if (!rc)
|
|
||||||
printf("'%s' has been written successfully.\n", outputFileName);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
@@ -5,13 +5,12 @@ LDLIBS += -lz
|
|||||||
|
|
||||||
all: vmur
|
all: vmur
|
||||||
|
|
||||||
libs = $(rootdir)/libvmdump/libvmdump.a \
|
libs = $(rootdir)/libvmcp/libvmcp.a $(rootdir)/libutil/libutil.a
|
||||||
$(rootdir)/libvmcp/libvmcp.a $(rootdir)/libutil/libutil.a
|
|
||||||
|
|
||||||
objects = vmur.o
|
objects = vmur.o
|
||||||
|
|
||||||
vmur: $(objects) $(libs)
|
vmur: $(objects) $(libs)
|
||||||
$(LINKXX) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
$(INSTALL) -d -m 755 $(DESTDIR)$(USRSBINDIR) $(DESTDIR)$(MANDIR)/man8
|
$(INSTALL) -d -m 755 $(DESTDIR)$(USRSBINDIR) $(DESTDIR)$(MANDIR)/man8
|
||||||
|
|||||||
25
vmur/vmur.8
25
vmur/vmur.8
@@ -50,7 +50,7 @@ Position a file at the top of a spool file queue
|
|||||||
The \*v program requires the vmcp kernel module as prerequisite.
|
The \*v program requires the vmcp kernel module as prerequisite.
|
||||||
For the receive, punch, and print commands the vmur kernel module is also
|
For the receive, punch, and print commands the vmur kernel module is also
|
||||||
required, and the corresponding z/VM virtual unit record devices
|
required, and the corresponding z/VM virtual unit record devices
|
||||||
(in most cases 000c as reader, 000d as punch, and 000e as printer)
|
(in most cases 000c as reader, 000d as punch, and 000e as printer)
|
||||||
must be set online.
|
must be set online.
|
||||||
See
|
See
|
||||||
.BR chccwdev (8)
|
.BR chccwdev (8)
|
||||||
@@ -77,7 +77,7 @@ respective command context.
|
|||||||
.IP "" 0
|
.IP "" 0
|
||||||
Synopsis:
|
Synopsis:
|
||||||
.IP "" 2
|
.IP "" 2
|
||||||
receive [-fH] [-d dev_node] [-C class] [-t | -b sep.pad | -c]
|
receive [-fH] [-d dev_node] [-C class] [-t | -b sep.pad]
|
||||||
spoolid
|
spoolid
|
||||||
[-O | outfile]
|
[-O | outfile]
|
||||||
.PP
|
.PP
|
||||||
@@ -124,7 +124,7 @@ If omitted, /dev/vmrdr-0.0.000c is assumed.
|
|||||||
.IP "" 0
|
.IP "" 0
|
||||||
\fB-t or --text\fR
|
\fB-t or --text\fR
|
||||||
.IP "" 2
|
.IP "" 2
|
||||||
Specifies that a text file requiring EBCDIC-to-ASCII conversion is to be
|
Specifies that a text file requiring EBCDIC-to-ASCII conversion is to be
|
||||||
received. Character sets IBM037 and ISO-8859-1 are used for the conversion.
|
received. Character sets IBM037 and ISO-8859-1 are used for the conversion.
|
||||||
An ASCII line feed character (0x0a) is inserted for each 80-byte input
|
An ASCII line feed character (0x0a) is inserted for each 80-byte input
|
||||||
record read from the z/VM reader. Trailing EBCDIC blanks (0x40) in the
|
record read from the z/VM reader. Trailing EBCDIC blanks (0x40) in the
|
||||||
@@ -150,8 +150,14 @@ using the appropriate character sets, for example:
|
|||||||
.IP "" 0
|
.IP "" 0
|
||||||
\fB-c or --convert\fR
|
\fB-c or --convert\fR
|
||||||
.IP "" 2
|
.IP "" 2
|
||||||
Specifies to convert the VMDUMP spool file into a
|
Dump file conversion has been removed from
|
||||||
format appropriate for further analysis with crash or lcrash.
|
.BR vmur (8)
|
||||||
|
and -c is no longer a valid option.
|
||||||
|
An error message is displayed and the program terminates.
|
||||||
|
Use
|
||||||
|
.BR zgetdump (8)
|
||||||
|
to convert VMDUMP files to a format
|
||||||
|
appropriate for further analysis with crash.
|
||||||
.SP
|
.SP
|
||||||
.IP "" 0
|
.IP "" 0
|
||||||
\fB-O or --stdout\fR
|
\fB-O or --stdout\fR
|
||||||
@@ -299,7 +305,7 @@ residual of the record is filled up with the specified padding byte.
|
|||||||
If a line exceeds the record length, an error is printed.
|
If a line exceeds the record length, an error is printed.
|
||||||
.br
|
.br
|
||||||
.BR iconv (1)
|
.BR iconv (1)
|
||||||
output can be piped to punch or print, for example:
|
output can be piped to punch or print, for example:
|
||||||
.IP "" 2
|
.IP "" 2
|
||||||
# iconv xyz -f ISO-8859-1 -t EBCDIC-US | vmur pun -b 0x25,0x40 -N abc
|
# iconv xyz -f ISO-8859-1 -t EBCDIC-US | vmur pun -b 0x25,0x40 -N abc
|
||||||
.SP
|
.SP
|
||||||
@@ -403,7 +409,7 @@ The following command argument is supported by \fBlist\fR:
|
|||||||
\fBspoolid\fR
|
\fBspoolid\fR
|
||||||
.IP "" 2
|
.IP "" 2
|
||||||
Identifies the z/VM spool file to be listed.
|
Identifies the z/VM spool file to be listed.
|
||||||
If omitted, all spool files on the specified queue are listed
|
If omitted, all spool files on the specified queue are listed
|
||||||
.PD
|
.PD
|
||||||
.IP "" 0
|
.IP "" 0
|
||||||
.SP
|
.SP
|
||||||
@@ -530,7 +536,7 @@ In the example below, the spool ID is 398:
|
|||||||
.in +0.25in
|
.in +0.25in
|
||||||
.nf
|
.nf
|
||||||
# vmcp sp cons clo \(rs* rdr
|
# vmcp sp cons clo \(rs* rdr
|
||||||
RDR FILE 0398 SENT FROM LINUX025 CON WAS 0398 RECS 1872
|
RDR FILE 0398 SENT FROM LINUX025 CON WAS 0398 RECS 1872
|
||||||
.fi
|
.fi
|
||||||
.in -0.25in
|
.in -0.25in
|
||||||
.ft
|
.ft
|
||||||
@@ -605,6 +611,7 @@ Prepare re-IPL from the z/VM reader and reboot:
|
|||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR chccwdev (8),
|
.BR chccwdev (8),
|
||||||
.BR vmcp (8),
|
.BR vmcp (8),
|
||||||
.BR iconv (1)
|
.BR iconv (1),
|
||||||
|
.BR zgetdump (8)
|
||||||
|
|
||||||
.I "Linux on System z - Device Drivers, Features, and Commands"
|
.I "Linux on System z - Device Drivers, Features, and Commands"
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ struct vmur {
|
|||||||
int force_specified;
|
int force_specified;
|
||||||
int stdout_specified;
|
int stdout_specified;
|
||||||
int hold_specified;
|
int hold_specified;
|
||||||
int convert_specified;
|
|
||||||
enum ur_action action;
|
enum ur_action action;
|
||||||
int devno;
|
int devno;
|
||||||
int ur_reclen;
|
int ur_reclen;
|
||||||
@@ -183,8 +182,6 @@ static char HELP_TEXT[] =
|
|||||||
"-t, --text Indicates text data causing EBCDIC to ASCII\n"
|
"-t, --text Indicates text data causing EBCDIC to ASCII\n"
|
||||||
" conversion.\n"
|
" conversion.\n"
|
||||||
"-b, --blocked Use blocked mode.\n"
|
"-b, --blocked Use blocked mode.\n"
|
||||||
"-c, --convert Specifies to convert VMDUMP file into a format\n"
|
|
||||||
" appropriate for further analysis with (l)crash.\n"
|
|
||||||
"-O, --stdout Write spool file to stdout.\n"
|
"-O, --stdout Write spool file to stdout.\n"
|
||||||
"-f, --force Overwrite files without prompt.\n"
|
"-f, --force Overwrite files without prompt.\n"
|
||||||
"-H, --hold Hold spool file in reader after receive.\n"
|
"-H, --hold Hold spool file in reader after receive.\n"
|
||||||
@@ -814,7 +811,10 @@ static void parse_opts_receive(struct vmur *info, int argc, char *argv[])
|
|||||||
++info->hold_specified;
|
++info->hold_specified;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
++info->convert_specified;
|
fprintf(stderr, "%s: Option '-c' is no longer valid. "
|
||||||
|
"Use zgetdump for dump file conversion.\n",
|
||||||
|
prog_name);
|
||||||
|
std_usage_exit();
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
set_spool_class(info, optarg, 1);
|
set_spool_class(info, optarg, 1);
|
||||||
@@ -834,14 +834,12 @@ static void parse_opts_receive(struct vmur *info, int argc, char *argv[])
|
|||||||
CHECK_SPEC_MAX(info->force_specified, 1, "force");
|
CHECK_SPEC_MAX(info->force_specified, 1, "force");
|
||||||
CHECK_SPEC_MAX(info->hold_specified, 1, "hold");
|
CHECK_SPEC_MAX(info->hold_specified, 1, "hold");
|
||||||
CHECK_SPEC_MAX(info->stdout_specified, 1, "stdout");
|
CHECK_SPEC_MAX(info->stdout_specified, 1, "stdout");
|
||||||
CHECK_SPEC_MAX(info->convert_specified, 1, "convert");
|
|
||||||
CHECK_SPEC_MAX(info->spool_class_specified, 1, "class");
|
CHECK_SPEC_MAX(info->spool_class_specified, 1, "class");
|
||||||
|
|
||||||
if (info->stdout_specified && info->file_name_specified)
|
if (info->stdout_specified && info->file_name_specified)
|
||||||
ERR_EXIT("File name not allowed, when --stdout specified!\n");
|
ERR_EXIT("File name not allowed, when --stdout specified!\n");
|
||||||
if (info->blocked_specified + info->text_specified +
|
if (info->blocked_specified + info->text_specified)
|
||||||
info->convert_specified > 1)
|
ERR_EXIT("Conflicting options: -b and -t are mutually "
|
||||||
ERR_EXIT("Conflicting options: -b, -t and -c are mutually "
|
|
||||||
"exclusive.\n");
|
"exclusive.\n");
|
||||||
if (!info->spool_class_specified)
|
if (!info->spool_class_specified)
|
||||||
set_spool_class(info, "*", 1);
|
set_spool_class(info, "*", 1);
|
||||||
@@ -1749,25 +1747,6 @@ static void ur_receive(struct vmur *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
type = get_spoolfile_fmt(info, &sfdata[0]);
|
type = get_spoolfile_fmt(info, &sfdata[0]);
|
||||||
if (info->convert_specified) {
|
|
||||||
if (type != TYPE_VMDUMP) {
|
|
||||||
ERR("Reader file %s does not have VMDUMP format, "
|
|
||||||
"conversion not possible.\n", info->spoolid);
|
|
||||||
goto fail;
|
|
||||||
} else {
|
|
||||||
close(fhi);
|
|
||||||
if (info->stdout_specified)
|
|
||||||
rc = vmdump_convert(info->devnode, NULL,
|
|
||||||
prog_name);
|
|
||||||
else
|
|
||||||
rc = vmdump_convert(info->devnode,
|
|
||||||
info->file_name, prog_name);
|
|
||||||
if (rc)
|
|
||||||
goto fail;
|
|
||||||
else
|
|
||||||
goto vm_convert_done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type == TYPE_VMDUMP)
|
if (type == TYPE_VMDUMP)
|
||||||
ERR("INFO: Reader file %s has VMDUMP format.\n", info->spoolid);
|
ERR("INFO: Reader file %s has VMDUMP format.\n", info->spoolid);
|
||||||
if (type == TYPE_NETDATA)
|
if (type == TYPE_NETDATA)
|
||||||
@@ -1819,7 +1798,6 @@ static void ur_receive(struct vmur *info)
|
|||||||
if (fho != STDOUT_FILENO)
|
if (fho != STDOUT_FILENO)
|
||||||
close(fho);
|
close(fho);
|
||||||
close(fhi);
|
close(fhi);
|
||||||
vm_convert_done:
|
|
||||||
if (info->hold_specified)
|
if (info->hold_specified)
|
||||||
close_reader(info, "HOLD");
|
close_reader(info, "HOLD");
|
||||||
else
|
else
|
||||||
@@ -25,7 +25,7 @@ install-scripts: $(SCRIPTS)
|
|||||||
cat $$i | \
|
cat $$i | \
|
||||||
sed -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
sed -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
||||||
>$(DESTDIR)$(BINDIR)/$$i; \
|
>$(DESTDIR)$(BINDIR)/$$i; \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(BINDIR)/$$i; \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(BINDIR)/$$i; \
|
||||||
chmod 755 $(DESTDIR)$(BINDIR)/$$i; \
|
chmod 755 $(DESTDIR)$(BINDIR)/$$i; \
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -34,15 +34,15 @@ install-usrsbin-scripts: $(USRSBIN_SCRIPTS)
|
|||||||
cat $$i | \
|
cat $$i | \
|
||||||
sed -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
sed -e 's/%S390_TOOLS_VERSION%/$(S390_TOOLS_RELEASE)/' \
|
||||||
>$(DESTDIR)$(USRSBINDIR)/$$i; \
|
>$(DESTDIR)$(USRSBINDIR)/$$i; \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(USRSBINDIR)/$$i; \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(USRSBINDIR)/$$i; \
|
||||||
chmod 755 $(DESTDIR)$(USRSBINDIR)/$$i; \
|
chmod 755 $(DESTDIR)$(USRSBINDIR)/$$i; \
|
||||||
done
|
done
|
||||||
|
|
||||||
install-manpages: $(MANPAGES)
|
install-manpages: $(MANPAGES)
|
||||||
@if [ ! -d $(DESTDIR)$(MANDIR) ]; then \
|
@if [ ! -d $(DESTDIR)$(MANDIR) ]; then \
|
||||||
mkdir -p $(DESTDIR)$(MANDIR)/man8; \
|
mkdir -p $(DESTDIR)$(MANDIR)/man8; \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(MANDIR); \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(MANDIR); \
|
||||||
chown $(OWNER).$(GROUP) $(DESTDIR)$(MANDIR)/man8; \
|
chown $(OWNER):$(GROUP) $(DESTDIR)$(MANDIR)/man8; \
|
||||||
chmod 755 $(DESTDIR)$(MANDIR); \
|
chmod 755 $(DESTDIR)$(MANDIR); \
|
||||||
chmod 755 $(DESTDIR)$(MANDIR)/man8; \
|
chmod 755 $(DESTDIR)$(MANDIR)/man8; \
|
||||||
fi; \
|
fi; \
|
||||||
|
|||||||
158
zconf/lsdasd
158
zconf/lsdasd
@@ -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
|
||||||
|
|||||||
@@ -218,6 +218,8 @@ X - Card/queue is providing EP11 functions (this is the EP11 Coprocessor mode).
|
|||||||
.br
|
.br
|
||||||
N - APXA available (ability to address more than 16 crypto cards and domains).
|
N - APXA available (ability to address more than 16 crypto cards and domains).
|
||||||
.br
|
.br
|
||||||
|
H - Hardware support for stateless filtering available.
|
||||||
|
.br
|
||||||
F - Full function support (opposed to restricted function support, see below).
|
F - Full function support (opposed to restricted function support, see below).
|
||||||
.br
|
.br
|
||||||
R - Restricted function support. The F and R flag both reflect if a
|
R - Restricted function support. The F and R flag both reflect if a
|
||||||
|
|||||||
@@ -45,15 +45,17 @@ static struct lszcrypt_l {
|
|||||||
#define CAP_RNG "Long RNG"
|
#define CAP_RNG "Long RNG"
|
||||||
#define CAP_EP11 "EP11 Secure Key"
|
#define CAP_EP11 "EP11 Secure Key"
|
||||||
#define CAP_APMMS "AP bus max message size limit %ld Kb"
|
#define CAP_APMMS "AP bus max message size limit %ld Kb"
|
||||||
|
#define CAP_HSL "Hardware support for stateless filtering"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Card types
|
* Card types and other feature masks
|
||||||
*/
|
*/
|
||||||
#define MASK_APSC 0x80000000
|
#define MASK_APSC 0x80000000
|
||||||
#define MASK_RSA4K 0x60000000
|
#define MASK_RSA4K 0x60000000
|
||||||
#define MASK_COPRO 0x10000000
|
#define MASK_COPRO 0x10000000
|
||||||
#define MASK_ACCEL 0x08000000
|
#define MASK_ACCEL 0x08000000
|
||||||
#define MASK_EP11 0x04000000
|
#define MASK_EP11 0x04000000
|
||||||
|
#define MASK_HSL 0x01000000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Classification
|
* Classification
|
||||||
@@ -66,20 +68,21 @@ static struct lszcrypt_l {
|
|||||||
/*
|
/*
|
||||||
* facility bits
|
* facility bits
|
||||||
*/
|
*/
|
||||||
#define MAX_FAC_BITS 9
|
#define MAX_FAC_BITS 10
|
||||||
static struct fac_bits_s {
|
static struct fac_bits_s {
|
||||||
int mask;
|
int mask;
|
||||||
char c;
|
char c;
|
||||||
} fac_bits[MAX_FAC_BITS] = {
|
} fac_bits[MAX_FAC_BITS] = {
|
||||||
{ 0x80000000, 'S' },
|
{ 0x80000000, 'S' }, /* bit 0 */
|
||||||
{ 0x40000000, 'M' },
|
{ 0x40000000, 'M' }, /* bit 1 */
|
||||||
{ 0x20000000, 'C' },
|
{ 0x20000000, 'C' }, /* bit 2 */
|
||||||
{ 0x10000000, 'D' },
|
{ 0x10000000, 'D' }, /* bit 3, cca mode */
|
||||||
{ 0x08000000, 'A' },
|
{ 0x08000000, 'A' }, /* bit 4, accel mode */
|
||||||
{ 0x04000000, 'X' },
|
{ 0x04000000, 'X' }, /* bit 5, ep11 mode */
|
||||||
{ 0x02000000, 'N' },
|
{ 0x02000000, 'N' }, /* bit 6, apxa */
|
||||||
{ 0x00800000, 'F' },
|
{ 0x01000000, 'H' }, /* bit 7, stateless filtering by hardware */
|
||||||
{ 0x00400000, 'R' },
|
{ 0x00800000, 'F' }, /* bit 8, full function set */
|
||||||
|
{ 0x00400000, 'R' }, /* bit 9, restricted function set */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -444,6 +447,8 @@ static void show_capability(const char *id_str)
|
|||||||
printf("%s (%s)\n", CAP_CCA, cbuf);
|
printf("%s (%s)\n", CAP_CCA, cbuf);
|
||||||
else
|
else
|
||||||
printf("%s\n", CAP_CCA);
|
printf("%s\n", CAP_CCA);
|
||||||
|
if (func_val & MASK_HSL)
|
||||||
|
printf("%s\n", CAP_HSL);
|
||||||
printf("%s\n", CAP_RNG);
|
printf("%s\n", CAP_RNG);
|
||||||
} else if (func_val & MASK_EP11) {
|
} else if (func_val & MASK_EP11) {
|
||||||
printf("%s\n", CAP_EP11);
|
printf("%s\n", CAP_EP11);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -144,6 +144,19 @@ static struct attrib zfcp_tattr_port_scan_backoff = {
|
|||||||
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 4294967295)),
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 4294967295)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct attrib zfcp_tattr_ber_stop = {
|
||||||
|
.name = "ber_stop",
|
||||||
|
.title = "Stop FCP devices on bit-error threshold",
|
||||||
|
.desc =
|
||||||
|
"Control the automatic shutdown of FCP devices for FCP channels\n"
|
||||||
|
"that report a bit-error count in excess of its threshold:\n"
|
||||||
|
" 0: Stop on bit-error threshold is disabled\n"
|
||||||
|
" 1: Stop on bit-error threshold is enabled\n",
|
||||||
|
.nounload = 1,
|
||||||
|
.defval = "1",
|
||||||
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ZFCP methods.
|
* ZFCP methods.
|
||||||
*/
|
*/
|
||||||
@@ -171,6 +184,7 @@ static void all_bools_to_num(struct setting_list *list)
|
|||||||
|
|
||||||
util_list_iterate(&list->list, s) {
|
util_list_iterate(&list->list, s) {
|
||||||
if (s->attrib == &zfcp_tattr_allow_lun_scan ||
|
if (s->attrib == &zfcp_tattr_allow_lun_scan ||
|
||||||
|
s->attrib == &zfcp_tattr_ber_stop ||
|
||||||
s->attrib == &zfcp_tattr_dif ||
|
s->attrib == &zfcp_tattr_dif ||
|
||||||
s->attrib == &zfcp_tattr_dix ||
|
s->attrib == &zfcp_tattr_dix ||
|
||||||
s->attrib == &zfcp_tattr_datarouter ||
|
s->attrib == &zfcp_tattr_datarouter ||
|
||||||
@@ -313,6 +327,7 @@ struct devtype zfcp_devtype = {
|
|||||||
&zfcp_tattr_no_auto_port_rescan,
|
&zfcp_tattr_no_auto_port_rescan,
|
||||||
&zfcp_tattr_port_scan_ratelimit,
|
&zfcp_tattr_port_scan_ratelimit,
|
||||||
&zfcp_tattr_port_scan_backoff,
|
&zfcp_tattr_port_scan_backoff,
|
||||||
|
&zfcp_tattr_ber_stop,
|
||||||
),
|
),
|
||||||
.unknown_type_attribs = 1,
|
.unknown_type_attribs = 1,
|
||||||
|
|
||||||
|
|||||||
@@ -346,6 +346,7 @@ static struct attrib zfcp_lun_attr_scsi_queue_depth = {
|
|||||||
"of a SCSI device. Note that storage servers typically limit the\n"
|
"of a SCSI device. Note that storage servers typically limit the\n"
|
||||||
"total number of outstanding SCSI commands of all SCSI devices\n"
|
"total number of outstanding SCSI commands of all SCSI devices\n"
|
||||||
"accessed from all attached hosts.\n",
|
"accessed from all attached hosts.\n",
|
||||||
|
.defval = "32",
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_NUM_GE(1)),
|
.accept = ACCEPT_ARRAY(ACCEPT_NUM_GE(1)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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", \
|
||||||
@@ -75,7 +76,7 @@ OBJECTS = zgetdump.o opts.o zg.o zg_error.o zg_print.o \
|
|||||||
dt.o dt_s390sv.o dt_s390sv_ext.o \
|
dt.o dt_s390sv.o dt_s390sv_ext.o \
|
||||||
dt_s390mv.o dt_s390mv_ext.o \
|
dt_s390mv.o dt_s390mv_ext.o \
|
||||||
dt_scsi.o output.o \
|
dt_scsi.o output.o \
|
||||||
ngdump.o dt_ngdump.o dfi_ngdump.o \
|
ngdump.o dt_ngdump.o dfi_ngdump.o dfi_vmdump.o \
|
||||||
pv_utils.o
|
pv_utils.o
|
||||||
|
|
||||||
ifneq ($(shell sh -c 'command -v pkg-config'),)
|
ifneq ($(shell sh -c 'command -v pkg-config'),)
|
||||||
@@ -118,7 +119,9 @@ libs = $(rootdir)/libutil/libutil.a $(LIBPV)
|
|||||||
|
|
||||||
all: $(BUILD_TARGETS)
|
all: $(BUILD_TARGETS)
|
||||||
|
|
||||||
zgetdump: .check_dep_zgetdump $(OBJECTS) $(libs)
|
$(OBJECTS): .check_dep_zgetdump
|
||||||
|
|
||||||
|
zgetdump: $(OBJECTS) $(libs)
|
||||||
|
|
||||||
skip-zgetdump:
|
skip-zgetdump:
|
||||||
echo " SKIP zgetdump due to unresolved dependencies"
|
echo " SKIP zgetdump due to unresolved dependencies"
|
||||||
@@ -131,6 +134,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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
208
zdump/df_vmdump.h
Normal file
208
zdump/df_vmdump.h
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* zgetdump - Tool for copying and converting System z dumps
|
||||||
|
*
|
||||||
|
* VMDUMP format definitions
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2023
|
||||||
|
*
|
||||||
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DF_VMDUMP_H
|
||||||
|
#define DF_VMDUMP_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The format of an vmdump
|
||||||
|
*
|
||||||
|
* Symptom Record: (ADSR COPY) Record 1
|
||||||
|
* Dump File Map Record: (HCPDFMBK COPY) Record 2
|
||||||
|
* Dump File Info Record: (HCPDFIR COPY) Records 3-7
|
||||||
|
* Vector Registers: (optional)
|
||||||
|
* Access Lists (HCPDALBK):
|
||||||
|
* Address Space A: Information and Map Record (HCPASIBK)
|
||||||
|
* Address Space A: Bit Maps
|
||||||
|
* Address Space A: Key Maps
|
||||||
|
* Address Space A: Guest Storage
|
||||||
|
* Additional Address Spaces (not in linux):
|
||||||
|
* - ASIBK
|
||||||
|
* - Bit Maps
|
||||||
|
* - Key Maps
|
||||||
|
* - Guest Storage
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defines for VMDUMP magic numbers.
|
||||||
|
*/
|
||||||
|
/* ID 0xe2d9 --> 'S' 'R' */
|
||||||
|
const u8 ADSR_MAGIC[2] = { 0xe2, 0xd9 };
|
||||||
|
/* ID e5d4c4e4d4d74040 --> 'V' 'M' 'D' 'U' 'M' 'P' ' ' ' ' */
|
||||||
|
const u8 VMDUMP_MAGIC[8] = { 0xe5, 0xd4, 0xc4, 0xe4, 0xd4, 0xd7, 0x40, 0x40 };
|
||||||
|
/* ID c8c3d7c4c6d4c2d3 --> 'H' 'C' 'P' 'D' 'F' 'M' 'B' 'K' */
|
||||||
|
const u8 FMBK_MAGIC[8] = { 0xc8, 0xc3, 0xd7, 0xc4, 0xc6, 0xd4, 0xc2, 0xd2 };
|
||||||
|
/* ID c8c3d7c4c6d4c2d3 --> 'H' 'C' 'P' 'D' 'A' 'L' 'B' 'K' */
|
||||||
|
const u8 ALBK_MAGIC[8] = { 0xc8, 0xc3, 0xd7, 0xc4, 0xc1, 0xd3, 0xc2, 0xd2 };
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Layout of dump symptom record . The ADSR is always the first record in
|
||||||
|
* a dump file. Its size varies between 200 bytes and 4000 bytes
|
||||||
|
*/
|
||||||
|
struct vmd_adsr {
|
||||||
|
/* Section 1*/
|
||||||
|
u8 sr[sizeof(ADSR_MAGIC)];
|
||||||
|
u32 cpu_model;
|
||||||
|
u8 cpu_serial[6];
|
||||||
|
u32 time_zone_conversion_factor;
|
||||||
|
u64 tod;
|
||||||
|
u8 time_stamp_str[4];
|
||||||
|
u8 date_str[6];
|
||||||
|
u8 node_name[8];
|
||||||
|
u8 product_id[4];
|
||||||
|
u8 feature_level[8];
|
||||||
|
u8 record_status_flag1;
|
||||||
|
u8 record_status_flag2;
|
||||||
|
u8 dump_type[sizeof(VMDUMP_MAGIC)];
|
||||||
|
|
||||||
|
/* Section 2*/
|
||||||
|
u8 arch_level[2];
|
||||||
|
u16 sec2_len;
|
||||||
|
u16 sec2_1_len;
|
||||||
|
u16 sec2_1_offset;
|
||||||
|
u16 sec3_len;
|
||||||
|
u16 sec3_offset;
|
||||||
|
u16 sec4_len;
|
||||||
|
u16 sec4_offset;
|
||||||
|
u16 sec5_len;
|
||||||
|
u16 sec5_offset;
|
||||||
|
u16 sec6_len;
|
||||||
|
u16 sec6_offset;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Layout of Dump file map record. The DFMBK is always the second record in
|
||||||
|
* a dump file. Its size is 4 KB
|
||||||
|
*/
|
||||||
|
struct vmd_fmbk {
|
||||||
|
u8 id[sizeof(FMBK_MAGIC)];
|
||||||
|
u32 rec_nr_fir;
|
||||||
|
u32 rec_nr_vector;
|
||||||
|
u32 rec_nr_access;
|
||||||
|
u32 num_acc_recs;
|
||||||
|
u32 num_addr_spaces;
|
||||||
|
u32 rec_nr_asibk;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct vmd_fir_basic { /* Dump file (basic) information record */
|
||||||
|
u8 filler1[15];
|
||||||
|
u8 dump_format; /* 0x1 --> big storage dump
|
||||||
|
* 0x2 --> cp hard abend
|
||||||
|
* 0x3 --> cp soft abend
|
||||||
|
*/
|
||||||
|
u8 filler2[171];
|
||||||
|
u8 fir_format; /* 0x02 --> big esame (only one supported)
|
||||||
|
* 0x82 --> esame
|
||||||
|
* 0x00 --> esa
|
||||||
|
*/
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct vmd_albk {
|
||||||
|
u8 id[sizeof(ALBK_MAGIC)];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct vmd_asibk_64_new {
|
||||||
|
u8 id[8];
|
||||||
|
u8 as_token[8];
|
||||||
|
u8 spaceid[33];
|
||||||
|
u8 reserved1[2];
|
||||||
|
u8 asibk_format;
|
||||||
|
u8 filler1[12];
|
||||||
|
u64 storage_size_with_dcss;
|
||||||
|
u64 storage_size_def_store;
|
||||||
|
u8 filler2[136];
|
||||||
|
u64 online_storage_table[8]; /* For "def store config" */
|
||||||
|
u64 fence1;
|
||||||
|
u64 requested_range_table[8];
|
||||||
|
u64 fence2;
|
||||||
|
u32 record_number_of_first_bit_map;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct vmd_fir_64 {
|
||||||
|
u8 id[8];
|
||||||
|
u64 reserved1;
|
||||||
|
u64 gprs[16];
|
||||||
|
u32 prefix;
|
||||||
|
u8 reserved2[5];
|
||||||
|
u64 tod;
|
||||||
|
u8 reserved3[8];
|
||||||
|
u64 cpu_timer;
|
||||||
|
u8 reserved4[7];
|
||||||
|
u8 flag;
|
||||||
|
u8 type;
|
||||||
|
u8 complete;
|
||||||
|
u8 fir_format; /* 0x82 for esame - 0x00 for esa */
|
||||||
|
u8 cont_flags;
|
||||||
|
u8 crypto_domain_index_reg;
|
||||||
|
u8 virt_cpu_info;
|
||||||
|
u8 arch_mode_id;
|
||||||
|
u64 psw[2];
|
||||||
|
u64 crs[16];
|
||||||
|
u64 fprs[16];
|
||||||
|
u8 reserved5;
|
||||||
|
u64 clock_cmp;
|
||||||
|
u8 reserved6[3];
|
||||||
|
u32 tod_programmable_reg;
|
||||||
|
u32 reserved_for_dvf[20];
|
||||||
|
u32 acrs[16];
|
||||||
|
u32 storage_size_2GB;
|
||||||
|
u32 reserved7;
|
||||||
|
u32 hcpsys_addr;
|
||||||
|
u32 reserved8;
|
||||||
|
u64 storage_size;
|
||||||
|
u32 snap_area_map_blk;
|
||||||
|
u32 reserved9;
|
||||||
|
u8 loc_mem[256];
|
||||||
|
u16 online_cpus;
|
||||||
|
u16 cpu_addr;
|
||||||
|
u16 section_size_vector;
|
||||||
|
u16 reserved10;
|
||||||
|
u8 asit_primary[8];
|
||||||
|
u8 space_id_primary[33];
|
||||||
|
u8 reserved12[3];
|
||||||
|
u16 crypto_domain_index_mask;
|
||||||
|
u16 reserved11;
|
||||||
|
u32 fp_cntrl_reg;
|
||||||
|
u32 reserved13;
|
||||||
|
u64 reserved14[16];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct vmd_fir_other_64 {
|
||||||
|
u16 cpu_addr;
|
||||||
|
u16 vector_sec_size;
|
||||||
|
u8 crypto_index_reg;
|
||||||
|
u8 virt_cpu_info;
|
||||||
|
u16 crypto_index_mask;
|
||||||
|
u32 reserved1[2];
|
||||||
|
u64 fprs[16];
|
||||||
|
u64 gprs[16];
|
||||||
|
u64 psw[2];
|
||||||
|
u32 reserved2[2];
|
||||||
|
u32 prefix;
|
||||||
|
u32 fp_cntrl_reg;
|
||||||
|
u32 reserved3;
|
||||||
|
u32 tod;
|
||||||
|
u64 cpu_timer;
|
||||||
|
u64 clock_cmp;
|
||||||
|
u32 reserved4[2];
|
||||||
|
u32 acrs[16];
|
||||||
|
u64 crs[16];
|
||||||
|
u64 mc_interrupt_code;
|
||||||
|
u32 reserved5;
|
||||||
|
u32 external_damage_code;
|
||||||
|
u64 mc_failing_storage_addr;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define DF_VMDUMP_HDR_SIZE \
|
||||||
|
(sizeof(struct vmd_adsr) + sizeof(struct vmd_fmbk) + sizeof(struct vmd_fir_basic) + \
|
||||||
|
sizeof(struct vmd_albk) + sizeof(struct vmd_asibk_64_new) + sizeof(struct vmd_fir_64))
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Generic input dump format functions (DFI - Dump Format Input)
|
* Generic input dump format functions (DFI - Dump Format Input)
|
||||||
*
|
*
|
||||||
* Copyright IBM Corp. 2001, 2018
|
* Copyright IBM Corp. 2001, 2023
|
||||||
*
|
*
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
@@ -34,6 +34,7 @@ static struct dfi *dfi_vec[] = {
|
|||||||
&dfi_s390_ext,
|
&dfi_s390_ext,
|
||||||
&dfi_s390,
|
&dfi_s390,
|
||||||
&dfi_lkcd,
|
&dfi_lkcd,
|
||||||
|
&dfi_vmdump,
|
||||||
&dfi_pv_elf,
|
&dfi_pv_elf,
|
||||||
&dfi_elf,
|
&dfi_elf,
|
||||||
&dfi_kdump,
|
&dfi_kdump,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Generic input dump format functions (DFI - Dump Format Input)
|
* Generic input dump format functions (DFI - Dump Format Input)
|
||||||
*
|
*
|
||||||
* Copyright IBM Corp. 2001, 2018
|
* Copyright IBM Corp. 2001, 2023
|
||||||
*
|
*
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
@@ -255,5 +255,6 @@ extern struct dfi dfi_kdump;
|
|||||||
extern struct dfi dfi_kdump_flat;
|
extern struct dfi dfi_kdump_flat;
|
||||||
extern struct dfi dfi_devmem;
|
extern struct dfi dfi_devmem;
|
||||||
extern struct dfi dfi_ngdump;
|
extern struct dfi dfi_ngdump;
|
||||||
|
extern struct dfi dfi_vmdump;
|
||||||
|
|
||||||
#endif /* DFI_H */
|
#endif /* DFI_H */
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
#include <openssl/bio.h>
|
#include <openssl/bio.h>
|
||||||
#include <openssl/crypto.h>
|
#include <openssl/crypto.h>
|
||||||
|
|
||||||
@@ -46,17 +45,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 +107,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 +171,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 +231,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 +262,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 +271,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 +321,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
468
zdump/dfi_vmdump.c
Normal file
468
zdump/dfi_vmdump.c
Normal file
@@ -0,0 +1,468 @@
|
|||||||
|
/*
|
||||||
|
* zgetdump - Tool for copying and converting IBM zSystem dumps
|
||||||
|
*
|
||||||
|
* VMDUMP input format - Convert a vmdump 64big format to internal format.
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2023
|
||||||
|
*
|
||||||
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <iconv.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mtio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include "zgetdump.h"
|
||||||
|
#include "df_vmdump.h"
|
||||||
|
#include "dfi.h"
|
||||||
|
#include "dfi_mem_chunk.h"
|
||||||
|
#include "lib/util_log.h"
|
||||||
|
#include "lib/util_libc.h"
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
struct vmd_adsr adsr; /* Dump file symptom record */
|
||||||
|
struct vmd_fmbk fmbk; /* Dump file map record */
|
||||||
|
struct vmd_fir_basic fir_basic; /* Dump file info record */
|
||||||
|
struct vmd_albk albk; /* Dump access list record */
|
||||||
|
|
||||||
|
struct vmd_asibk_64_new asibk_new;
|
||||||
|
struct vmd_fir_64 fir;
|
||||||
|
struct vmd_fir_other_64 *fir_other;
|
||||||
|
|
||||||
|
u64 memory_start_record;
|
||||||
|
u8 *bitmap;
|
||||||
|
} l;
|
||||||
|
|
||||||
|
/* Convert EBCDIC to ASCII. Used for very few selective fields. */
|
||||||
|
static void ebc_2_asc(u8 *in, u8 *out, const size_t size)
|
||||||
|
{
|
||||||
|
iconv_t etoa = iconv_open("ISO-8859-1", "EBCDIC-US");
|
||||||
|
size_t size_out = size;
|
||||||
|
size_t size_in = size;
|
||||||
|
size_t rc;
|
||||||
|
|
||||||
|
rc = iconv(etoa, (char **)&in, &size_in, (char **)&out, &size_out);
|
||||||
|
if (rc == (size_t)-1)
|
||||||
|
errx(EXIT_FAILURE, "Code page translation EBCDIC-ASCII failed");
|
||||||
|
iconv_close(etoa);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vmdump_tod_to_timeval(u64 todval, struct timeval *xtime)
|
||||||
|
{
|
||||||
|
/* adjust todclock to 1970 */
|
||||||
|
todval -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
|
||||||
|
|
||||||
|
todval >>= 12;
|
||||||
|
xtime->tv_sec = todval / 1000000;
|
||||||
|
xtime->tv_usec = todval % 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vmdump64big_debug(void)
|
||||||
|
{
|
||||||
|
u8 fmbk_id[sizeof(FMBK_MAGIC)];
|
||||||
|
u8 albk_id[sizeof(ALBK_MAGIC)];
|
||||||
|
struct timeval time;
|
||||||
|
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Memory Offset: %#lx\n", l.memory_start_record);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Dumped Pages: %d\n",
|
||||||
|
l.asibk_new.storage_size_def_store / PAGE_SIZE);
|
||||||
|
|
||||||
|
/* adsr */
|
||||||
|
vmdump_tod_to_timeval(l.adsr.tod, &time);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Time: %s", ctime(&time.tv_sec));
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Statusflag 1: %#x\n", l.adsr.record_status_flag1);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Statusflag 2: %#x\n", l.adsr.record_status_flag2);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Section 2 len: %i\n", l.adsr.sec2_len);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Section 2.1 len: %i/%i\n", l.adsr.sec2_1_len,
|
||||||
|
l.adsr.sec2_1_offset);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Section 3 len: %i/%i\n", l.adsr.sec3_len,
|
||||||
|
l.adsr.sec3_offset);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Section 4 len: %i/%i\n", l.adsr.sec4_len,
|
||||||
|
l.adsr.sec4_offset);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Section 5 len: %i/%i\n", l.adsr.sec5_len,
|
||||||
|
l.adsr.sec5_offset);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Section 6 len: %i/%i\n", l.adsr.sec6_len,
|
||||||
|
l.adsr.sec6_offset);
|
||||||
|
|
||||||
|
/* fmbk */
|
||||||
|
ebc_2_asc(l.fmbk.id, fmbk_id, sizeof(l.fmbk.id));
|
||||||
|
fmbk_id[sizeof(fmbk_id) - 1] = 0;
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Fmbk id: %8.8s\n", fmbk_id);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Fir rec nr: %i\n", l.fmbk.rec_nr_fir);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Vec rec nr: %i\n", l.fmbk.rec_nr_vector);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Access rec nr: %i\n", l.fmbk.rec_nr_access);
|
||||||
|
|
||||||
|
/* albk */
|
||||||
|
ebc_2_asc(l.albk.id, albk_id, sizeof(l.albk.id));
|
||||||
|
albk_id[sizeof(albk_id) - 1] = 0;
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Albk id: %8.8s\n", albk_id);
|
||||||
|
|
||||||
|
/* fir */
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Cpus: %d\n", l.fir.online_cpus + 1);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "PSW: %#016lx %#016lx\n", l.fir.psw[0], l.fir.psw[1]);
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Prefix (CPU 0): %#010x\n", l.fir.prefix);
|
||||||
|
for (unsigned int i = 0; i < l.fir.online_cpus; i++)
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Prefix (CPU %i): %#010x\n", i + 1,
|
||||||
|
l.fir_other[i].prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool test_bitmap_key_page(u8 *page, const u64 bit)
|
||||||
|
{
|
||||||
|
return page[bit] & 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool test_page_bit(u8 *bitmap, const u64 bit)
|
||||||
|
{
|
||||||
|
return bitmap[bit / 8] & (1 << (7 - (bit % 8)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_page_bit(u8 *bitmap, const u64 bit)
|
||||||
|
{
|
||||||
|
bitmap[bit / 8] |= (1 << (7 - (bit % 8)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read VMDUMP headers, page index bit maps and page bit maps to
|
||||||
|
* construct a list of non-zero pages with memory locations. Zeroed pages
|
||||||
|
* are not bitmapped and are detected by memory location without bitmap
|
||||||
|
* entry.
|
||||||
|
*/
|
||||||
|
static void vmdump64big_init(void)
|
||||||
|
{
|
||||||
|
u64 page_num = 0, nr_dumped_pages;
|
||||||
|
size_t bitmap_sz;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Record 1: adsr */
|
||||||
|
zg_seek(g.fh, 0, ZG_CHECK);
|
||||||
|
zg_read(g.fh, &l.adsr, sizeof(l.adsr), ZG_CHECK);
|
||||||
|
|
||||||
|
if (g.opts.verbose) {
|
||||||
|
u8 buf_asc[1024], buf[1024];
|
||||||
|
|
||||||
|
zg_seek(g.fh, l.adsr.sec5_offset, ZG_CHECK);
|
||||||
|
zg_read(g.fh, buf, l.adsr.sec5_len, ZG_CHECK);
|
||||||
|
ebc_2_asc(buf, buf_asc, l.adsr.sec5_len);
|
||||||
|
for (i = 0; i < l.adsr.sec5_len; i++) {
|
||||||
|
if (buf_asc[i] == 0 || iscntrl(buf_asc[i]))
|
||||||
|
buf_asc[i] = ' ';
|
||||||
|
}
|
||||||
|
buf_asc[l.adsr.sec5_len] = 0;
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Symptom string: %s\n", buf_asc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record 2: fmbk */
|
||||||
|
zg_seek(g.fh, PAGE_SIZE, ZG_CHECK);
|
||||||
|
zg_read(g.fh, &l.fmbk, sizeof(l.fmbk), ZG_CHECK);
|
||||||
|
|
||||||
|
/* Record 3-7: fir records */
|
||||||
|
zg_seek(g.fh, (l.fmbk.rec_nr_fir - 1) * PAGE_SIZE, ZG_CHECK);
|
||||||
|
zg_read(g.fh, &l.fir, sizeof(l.fir), ZG_CHECK);
|
||||||
|
|
||||||
|
bitmap_sz = sizeof(struct vmd_fir_other_64) * l.fir.online_cpus;
|
||||||
|
l.fir_other = util_zalloc(bitmap_sz);
|
||||||
|
for (i = 0; i < l.fir.online_cpus; i++)
|
||||||
|
zg_read(g.fh, &l.fir_other[i], sizeof(l.fir_other[0]), ZG_CHECK);
|
||||||
|
|
||||||
|
/* Record 8: albk */
|
||||||
|
zg_seek(g.fh, (l.fmbk.rec_nr_access - 1) * PAGE_SIZE, SEEK_SET);
|
||||||
|
zg_read(g.fh, &l.albk, sizeof(l.albk), SEEK_SET);
|
||||||
|
|
||||||
|
/* Record 9: asibk */
|
||||||
|
zg_seek(g.fh, l.fmbk.rec_nr_access * PAGE_SIZE, ZG_CHECK);
|
||||||
|
zg_read(g.fh, &l.asibk_new, sizeof(l.asibk_new), ZG_CHECK);
|
||||||
|
|
||||||
|
l.memory_start_record = (l.fmbk.rec_nr_access + 1) * PAGE_SIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record 10: bitmaps:
|
||||||
|
* Read all bitmap pages and setup bitmap array
|
||||||
|
*/
|
||||||
|
nr_dumped_pages = l.asibk_new.storage_size_def_store / PAGE_SIZE;
|
||||||
|
bitmap_sz = l.asibk_new.storage_size_def_store / (PAGE_SIZE * 8);
|
||||||
|
if (!bitmap_sz)
|
||||||
|
ERR_EXIT("Dump file inconsistent, no bitmap detected");
|
||||||
|
l.bitmap = util_zalloc(bitmap_sz);
|
||||||
|
zg_seek(g.fh, (l.fmbk.rec_nr_access + 1) * PAGE_SIZE, ZG_CHECK);
|
||||||
|
|
||||||
|
do {
|
||||||
|
u8 bm_index_page[PAGE_SIZE];
|
||||||
|
|
||||||
|
zg_read(g.fh, bm_index_page, sizeof(bm_index_page), ZG_CHECK);
|
||||||
|
l.memory_start_record += PAGE_SIZE;
|
||||||
|
for (i = 0; i < PAGE_SIZE; i++) {
|
||||||
|
if (test_page_bit(bm_index_page, i)) {
|
||||||
|
u8 bm_page[PAGE_SIZE];
|
||||||
|
|
||||||
|
zg_read(g.fh, bm_page, sizeof(bm_page), ZG_CHECK);
|
||||||
|
l.memory_start_record += PAGE_SIZE;
|
||||||
|
for (unsigned int j = 0; j < PAGE_SIZE; j++) {
|
||||||
|
if (page_num / 8 >= bitmap_sz)
|
||||||
|
ERR_EXIT("Dump file inconsistent,"
|
||||||
|
" corrupted bitmap detected");
|
||||||
|
if (test_bitmap_key_page(bm_page, j))
|
||||||
|
set_page_bit(l.bitmap, page_num);
|
||||||
|
page_num++;
|
||||||
|
if (page_num == nr_dumped_pages)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
page_num += PAGE_SIZE; /* Empty page */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (page_num < nr_dumped_pages);
|
||||||
|
|
||||||
|
out:
|
||||||
|
vmdump64big_debug();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void display_register(const struct dfi_cpu *cpu)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
util_log_print(UTIL_LOG_TRACE, "CPU %d\n", cpu->cpu_id);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(cpu->gprs); i += 2)
|
||||||
|
util_log_print(UTIL_LOG_TRACE, "gpr%02d: %016lx\t gpr%02d: %016lx\n", i,
|
||||||
|
cpu->gprs[i], i + 1, cpu->gprs[i + 1]);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(cpu->ctrs); i += 2)
|
||||||
|
util_log_print(UTIL_LOG_TRACE, "ctr%02d: %016lx\t ctr%02d: %016lx\n", i,
|
||||||
|
cpu->ctrs[i], i + 1, cpu->ctrs[i + 1]);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(cpu->acrs); i += 2)
|
||||||
|
util_log_print(UTIL_LOG_TRACE, "acr%02d: %016lx\t acr%02d: %016lx\n", i,
|
||||||
|
cpu->acrs[i], i + 1, cpu->acrs[i + 1]);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(cpu->fprs); i += 2)
|
||||||
|
util_log_print(UTIL_LOG_TRACE, "fpr%02d: %016lx\t fpr%02d: %016lx\n", i,
|
||||||
|
cpu->fprs[i], i + 1, cpu->fprs[i + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read out register setting for each CPU.
|
||||||
|
*/
|
||||||
|
static void vmdump_read_register(int cpu_nr)
|
||||||
|
{
|
||||||
|
struct dfi_cpu *cpu;
|
||||||
|
|
||||||
|
if (cpu_nr >= l.fir.online_cpus + 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cpu = dfi_cpu_alloc();
|
||||||
|
cpu->cpu_id = dfi_cpu_cnt();
|
||||||
|
if (!cpu_nr) { /* First CPU in fir */
|
||||||
|
memcpy(cpu->gprs, l.fir.gprs, sizeof(cpu->gprs));
|
||||||
|
memcpy(cpu->ctrs, &l.fir.crs, sizeof(cpu->ctrs));
|
||||||
|
memcpy(cpu->acrs, &l.fir.acrs, sizeof(cpu->acrs));
|
||||||
|
memcpy(cpu->fprs, &l.fir.fprs, sizeof(cpu->fprs));
|
||||||
|
memcpy(cpu->psw, &l.fir.psw, sizeof(cpu->psw));
|
||||||
|
memcpy(&cpu->prefix, &l.fir.prefix, sizeof(cpu->prefix));
|
||||||
|
memcpy(&cpu->timer, &l.fir.cpu_timer, sizeof(cpu->timer));
|
||||||
|
memcpy(&cpu->todcmp, &l.fir.clock_cmp, sizeof(cpu->todcmp));
|
||||||
|
memcpy(&cpu->fpc, &l.fir.fp_cntrl_reg, sizeof(cpu->fpc));
|
||||||
|
} else {
|
||||||
|
cpu_nr -= 1; /* Other CPUs start at offset 0 in fir_other */
|
||||||
|
memcpy(cpu->gprs, l.fir_other[cpu_nr].gprs, sizeof(cpu->gprs));
|
||||||
|
memcpy(cpu->ctrs, &l.fir_other[cpu_nr].crs, sizeof(cpu->ctrs));
|
||||||
|
memcpy(cpu->acrs, &l.fir_other[cpu_nr].acrs, sizeof(cpu->acrs));
|
||||||
|
memcpy(cpu->fprs, &l.fir_other[cpu_nr].fprs, sizeof(cpu->fprs));
|
||||||
|
memcpy(cpu->psw, &l.fir_other[cpu_nr].psw, sizeof(cpu->psw));
|
||||||
|
memcpy(&cpu->prefix, &l.fir_other[cpu_nr].prefix, sizeof(cpu->prefix));
|
||||||
|
memcpy(&cpu->timer, &l.fir_other[cpu_nr].cpu_timer, sizeof(cpu->timer));
|
||||||
|
memcpy(&cpu->todcmp, &l.fir_other[cpu_nr].clock_cmp, sizeof(cpu->todcmp));
|
||||||
|
memcpy(&cpu->fpc, &l.fir_other[cpu_nr].fp_cntrl_reg, sizeof(cpu->fpc));
|
||||||
|
}
|
||||||
|
display_register(cpu);
|
||||||
|
dfi_cpu_add(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize z/VM VMDUMP file DFI. Check if the input file is vmdump file
|
||||||
|
* with format 64big. Other formats are not supported.
|
||||||
|
*/
|
||||||
|
static int read_vmdump_hdr(void)
|
||||||
|
{
|
||||||
|
if (zg_type(g.fh) != ZG_TYPE_FILE)
|
||||||
|
return -EBADF;
|
||||||
|
if (zg_size(g.fh) < DF_VMDUMP_HDR_SIZE)
|
||||||
|
return -ENODEV;
|
||||||
|
zg_read(g.fh, &l.adsr, sizeof(l.adsr), ZG_CHECK);
|
||||||
|
if (memcmp(l.adsr.sr, ADSR_MAGIC, sizeof(l.adsr.sr)))
|
||||||
|
return -EBADF; /* Not an ADSR record */
|
||||||
|
if (memcmp(l.adsr.dump_type, VMDUMP_MAGIC, sizeof(l.adsr.dump_type)))
|
||||||
|
return -EBADF; /* Not a vmdump */
|
||||||
|
zg_seek(g.fh, PAGE_SIZE, ZG_CHECK);
|
||||||
|
zg_read(g.fh, &l.fmbk, sizeof(l.fmbk), ZG_CHECK);
|
||||||
|
if (memcmp(l.fmbk.id, FMBK_MAGIC, sizeof(l.fmbk.id)))
|
||||||
|
return -EBADF; /* Not a FMBK record */
|
||||||
|
|
||||||
|
/* Record 3-7: fir */
|
||||||
|
zg_seek(g.fh, (l.fmbk.rec_nr_fir - 1) * PAGE_SIZE, ZG_CHECK);
|
||||||
|
zg_read(g.fh, &l.fir, sizeof(l.fir), ZG_CHECK);
|
||||||
|
switch (l.fir.fir_format) {
|
||||||
|
case 0x0:
|
||||||
|
case 0x82:
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Vmdump %d bit format not supported anymore\n",
|
||||||
|
l.fir.fir_format ? 64 : 32);
|
||||||
|
return -EBADF;
|
||||||
|
case 0x2:
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "%s: Vmdump 64big format\n", g.opts.device);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
util_log_print(UTIL_LOG_DEBUG, "Vmdump unknown format\n");
|
||||||
|
return -EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read vmdump page. Need to check if page was dumped or is located in a
|
||||||
|
* hole. Holes are ranges of pages full of zeroes.
|
||||||
|
* The vmdump file format has a 64KB header followed by some bitmaps for
|
||||||
|
* valid non-zero pages and the 4KB memory pages itself. Only non-zero pages
|
||||||
|
* are stored. The memory pages start at vmdump file location stored in
|
||||||
|
* member named memory_start_record.
|
||||||
|
*
|
||||||
|
* Bit map organization:
|
||||||
|
* Page 0: bitmap byte 0 bit 0 (most signification bit)
|
||||||
|
* Page 1: bitmap byte 0 bit 1 (seconds most signification bit)
|
||||||
|
* ...
|
||||||
|
* Page 15: bitmap byte 1 bit 7 (least signification bit)
|
||||||
|
*
|
||||||
|
* If a bit for a page is set, this page is stored in the vmdump file.
|
||||||
|
* The location in the file depends on the number of previous non-zero pages.
|
||||||
|
* If bitmap byte zero has value 1 and bitmap byte one has value 5, three
|
||||||
|
* bits are set and page 15 is located at file offset:
|
||||||
|
* memory_start_record + 2 * PAGE_SIZE.
|
||||||
|
*
|
||||||
|
* Calculate the number of bits set to determine the file location of a
|
||||||
|
* given page in the vmdump file.
|
||||||
|
*/
|
||||||
|
static unsigned int count_bits(u8 x)
|
||||||
|
{
|
||||||
|
unsigned int bits_set = 0;
|
||||||
|
|
||||||
|
while (x) {
|
||||||
|
bits_set += x & 1;
|
||||||
|
x >>= 1;
|
||||||
|
}
|
||||||
|
return bits_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return byte offset into vmdump file for a given page number.
|
||||||
|
*/
|
||||||
|
static u64 bitmap_2_fileoffset(const u64 pg_num)
|
||||||
|
{
|
||||||
|
unsigned int bytes_to_check = pg_num / 8;
|
||||||
|
unsigned int bits_to_check = pg_num % 8;
|
||||||
|
unsigned int bits_set = 0;
|
||||||
|
|
||||||
|
/* Count bits set in first to second last byte */
|
||||||
|
for (unsigned int i = 0; i < bytes_to_check; i++)
|
||||||
|
bits_set += count_bits(l.bitmap[i]);
|
||||||
|
|
||||||
|
/* Count bits set in last byte */
|
||||||
|
bits_set += count_bits(l.bitmap[bytes_to_check] >> (8 - bits_to_check));
|
||||||
|
return bits_set * PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_page(const u64 pg_num, void *buf)
|
||||||
|
{
|
||||||
|
if (test_page_bit(l.bitmap, pg_num)) {
|
||||||
|
u64 file_off = bitmap_2_fileoffset(pg_num);
|
||||||
|
|
||||||
|
zg_seek(g.fh, l.memory_start_record + file_off, ZG_CHECK);
|
||||||
|
zg_read(g.fh, buf, PAGE_SIZE, ZG_CHECK);
|
||||||
|
} else {
|
||||||
|
memset(buf, 0, PAGE_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VMDUMP mem chunk read callback
|
||||||
|
*/
|
||||||
|
static void dfi_vmdump_mem_chunk_read_fn(struct dfi_mem_chunk *mem_chunk, u64 off, void *buf,
|
||||||
|
u64 cnt)
|
||||||
|
{
|
||||||
|
u64 copied = 0, size, pg_nr, addr = off + mem_chunk->start;
|
||||||
|
char pg_buf[PAGE_SIZE];
|
||||||
|
unsigned int pg_off;
|
||||||
|
|
||||||
|
while (copied != cnt) {
|
||||||
|
pg_nr = (addr + copied) / PAGE_SIZE;
|
||||||
|
pg_off = (addr + copied) % PAGE_SIZE;
|
||||||
|
size = MIN(cnt - copied, PAGE_SIZE - pg_off);
|
||||||
|
read_page(pg_nr, pg_buf);
|
||||||
|
memcpy(buf + copied, &pg_buf[pg_off], size);
|
||||||
|
copied += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpu_init(void)
|
||||||
|
{
|
||||||
|
dfi_cpu_info_init(DFI_CPU_CONTENT_ALL);
|
||||||
|
for (unsigned int i = 0; i <= l.fir.online_cpus; i++)
|
||||||
|
vmdump_read_register(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk bitmap and find consecutive bitstring consisting of '1' or '0'.
|
||||||
|
* Return its length.
|
||||||
|
*/
|
||||||
|
static u64 find_bitrange(u8 *bitmap, const u64 bit, const u64 max, const bool isset)
|
||||||
|
{
|
||||||
|
u64 pos;
|
||||||
|
|
||||||
|
for (pos = bit + 1; pos < max && test_page_bit(bitmap, pos) == isset; pos++)
|
||||||
|
;
|
||||||
|
return pos - bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mem_init(void)
|
||||||
|
{
|
||||||
|
u64 nr_dumped_pages = l.asibk_new.storage_size_def_store / PAGE_SIZE;
|
||||||
|
u64 pos, more;
|
||||||
|
|
||||||
|
for (pos = 0; pos < nr_dumped_pages;) {
|
||||||
|
bool isset = test_page_bit(l.bitmap, pos);
|
||||||
|
|
||||||
|
more = find_bitrange(l.bitmap, pos, nr_dumped_pages, isset);
|
||||||
|
dfi_mem_chunk_add(pos * PAGE_SIZE, more * PAGE_SIZE, NULL,
|
||||||
|
isset ? dfi_vmdump_mem_chunk_read_fn : dfi_mem_chunk_read_zero,
|
||||||
|
NULL);
|
||||||
|
pos += more;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dfi_vmdump_init(void)
|
||||||
|
{
|
||||||
|
if (read_vmdump_hdr())
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
vmdump64big_init();
|
||||||
|
dfi_attr_version_set(l.fir.fir_format);
|
||||||
|
dfi_arch_set(DFI_ARCH_64);
|
||||||
|
dfi_attr_real_cpu_cnt_set(l.fir.online_cpus + 1);
|
||||||
|
mem_init();
|
||||||
|
cpu_init();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* z/VM VMDUMP DFI operations
|
||||||
|
*/
|
||||||
|
struct dfi dfi_vmdump = {
|
||||||
|
.name = "vmdump",
|
||||||
|
.init = dfi_vmdump_init,
|
||||||
|
.feat_bits = DFI_FEAT_SEEK | DFI_FEAT_COPY,
|
||||||
|
};
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -656,13 +674,13 @@ struct _storage_state_mmap {
|
|||||||
size_t mapped_size;
|
size_t mapped_size;
|
||||||
pv_tweak_component_t *tweak_components;
|
pv_tweak_component_t *tweak_components;
|
||||||
size_t num_tweaks;
|
size_t num_tweaks;
|
||||||
gatomicrefcount ref_count;
|
int 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;
|
||||||
@@ -702,14 +733,14 @@ storage_state_mmap_t *storage_state_mmap_new(const int fd, const u64 offset, con
|
|||||||
ret->tweak_components = (pv_tweak_component_t *)(ptr + in_page_offset);
|
ret->tweak_components = (pv_tweak_component_t *)(ptr + in_page_offset);
|
||||||
ret->num_tweaks = tweak_components_cnt;
|
ret->num_tweaks = tweak_components_cnt;
|
||||||
ret->mapped_size = mmapped_size;
|
ret->mapped_size = mmapped_size;
|
||||||
g_atomic_ref_count_init(&ret->ref_count);
|
ret->ref_count = 1;
|
||||||
return g_steal_pointer(&ret);
|
return g_steal_pointer(&ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
storage_state_mmap_t *storage_state_mmap_ref(storage_state_mmap_t *storage_state)
|
storage_state_mmap_t *storage_state_mmap_ref(storage_state_mmap_t *storage_state)
|
||||||
{
|
{
|
||||||
g_assert(storage_state);
|
g_assert(storage_state);
|
||||||
g_atomic_ref_count_inc(&storage_state->ref_count);
|
g_atomic_int_inc(&storage_state->ref_count);
|
||||||
return storage_state;
|
return storage_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -717,12 +748,12 @@ void storage_state_mmap_unref(storage_state_mmap_t *storage_state)
|
|||||||
{
|
{
|
||||||
if (!storage_state)
|
if (!storage_state)
|
||||||
return;
|
return;
|
||||||
if (storage_state->ref_count && !g_atomic_ref_count_dec(&storage_state->ref_count))
|
if (storage_state->ref_count && !g_atomic_int_dec_and_test(&storage_state->ref_count))
|
||||||
return;
|
return;
|
||||||
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;
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
.\" Copyright 2022 IBM Corp.
|
.\" Copyright 2023 IBM Corp.
|
||||||
.\" s390-tools is free software; you can redistribute it and/or modify
|
.\" s390-tools is free software; you can redistribute it and/or modify
|
||||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||||
.\"
|
.\"
|
||||||
.TH ZGETDUMP 8 "October 2022" "s390-tools"
|
.TH ZGETDUMP 8 "January 2023" "s390-tools"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
zgetdump \- Tool for copying and converting System z dumps
|
zgetdump \- Tool for copying and converting IBM zSystems dumps
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|
||||||
\fBzgetdump\fR DUMP [-s SYS] [-f FMT] [-k KEY] > DUMP_FILE
|
\fBzgetdump\fR DUMP [-s SYS] [-f FMT] [-k KEY] > DUMP_FILE
|
||||||
@@ -107,6 +107,8 @@ source dump is located:
|
|||||||
.IP " -" 12
|
.IP " -" 12
|
||||||
Regular dump file (e.g. /dumps/dump.0)
|
Regular dump file (e.g. /dumps/dump.0)
|
||||||
.IP " -" 12
|
.IP " -" 12
|
||||||
|
vmdump file (e. g. VMDUMP.FILE)
|
||||||
|
.IP " -" 12
|
||||||
DASD partition device node (e.g. /dev/dasdc1)
|
DASD partition device node (e.g. /dev/dasdc1)
|
||||||
.IP " -" 12
|
.IP " -" 12
|
||||||
DASD device node for multi-volume dump (e.g. /dev/dasdc)
|
DASD device node for multi-volume dump (e.g. /dev/dasdc)
|
||||||
@@ -186,16 +188,21 @@ Linux user space core dumps.
|
|||||||
Protected virtualization vmcore dump in Executable and Linkable Format
|
Protected virtualization vmcore dump in Executable and Linkable Format
|
||||||
.TP
|
.TP
|
||||||
.BR "s390"
|
.BR "s390"
|
||||||
This dump format is System z specific and is used for DASD and tape dumps.
|
This dump format is IBM zSystems specific and is used for DASD and tape dumps.
|
||||||
.TP
|
.TP
|
||||||
The following dump formats are supported for the source dump only:
|
The following dump formats are supported for the source dump only:
|
||||||
.TP
|
.TP
|
||||||
.BR "s390_ext"
|
.BR "s390_ext"
|
||||||
This dump format is System z specific and is used for DASD dumps only.
|
This dump format is IBM zSystems specific and is used for DASD dumps only.
|
||||||
|
.TP
|
||||||
|
.BR "vmdump"
|
||||||
|
Dumps with this format are created by the z/VM vmdump command
|
||||||
|
and stored in the reader device.
|
||||||
|
Use the "vmur" tool to extract such dumps from the reader
|
||||||
|
device and save them on disk.
|
||||||
.TP
|
.TP
|
||||||
.BR "lkcd"
|
.BR "lkcd"
|
||||||
This dump format is used by the Linux Kernel Crash Dumps (LKCD) project
|
This dump format is used by the Linux Kernel Crash Dumps (LKCD) project.
|
||||||
and also on System z for the "vmconvert" dump tool.
|
|
||||||
.TP
|
.TP
|
||||||
.BR "devmem"
|
.BR "devmem"
|
||||||
On live systems the /dev/mem or /dev/crash device nodes can be used as source
|
On live systems the /dev/mem or /dev/crash device nodes can be used as source
|
||||||
@@ -505,5 +512,5 @@ attached SCSI disks can also be accessed directly without multipathing,
|
|||||||
for example via the "/dev/disk/by-path/" device nodes.
|
for example via the "/dev/disk/by-path/" device nodes.
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR zipl (8), crash (8), makedumpfile (8), dumpconf (8), vmconvert (1), vmur (8)
|
.BR zipl (8), crash (8), makedumpfile (8), dumpconf (8), vmur (8)
|
||||||
.BR fdisk (8), parted (8)
|
.BR fdisk (8), parted (8)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -19,7 +19,10 @@ FILES = fba0.bin fba1b.bin fba2.bin \
|
|||||||
tape0.bin \
|
tape0.bin \
|
||||||
eckd2dump_sv.bin tape2dump.bin fba2dump.bin eckd2dump_mv.bin
|
eckd2dump_sv.bin tape2dump.bin fba2dump.bin eckd2dump_mv.bin
|
||||||
|
|
||||||
all: data.o data.h tape0.bin stage3.bin
|
all: .loaders tape0.bin stage3.bin
|
||||||
|
|
||||||
|
.loaders: $(FILES)
|
||||||
|
touch .loaders
|
||||||
|
|
||||||
# Prevent make from using some default rules...
|
# Prevent make from using some default rules...
|
||||||
%: %.S
|
%: %.S
|
||||||
@@ -41,6 +44,15 @@ endif
|
|||||||
%.lds: %.lds.S
|
%.lds: %.lds.S
|
||||||
$(CPP) -Wp,-MD,.$@.d,-MT,$@ $(INCLUDE_PARMS) -P -C -o $@ $<
|
$(CPP) -Wp,-MD,.$@.d,-MT,$@ $(INCLUDE_PARMS) -P -C -o $@ $<
|
||||||
|
|
||||||
|
fba0.exec eckd0_ldl.exec eckd0_cdl.exec tape0.exec: \
|
||||||
|
stage0.lds
|
||||||
|
|
||||||
|
eckd1.exec: \
|
||||||
|
stage1.lds
|
||||||
|
|
||||||
|
eckd1b.exec fba1b.exec: \
|
||||||
|
stage1b.lds
|
||||||
|
|
||||||
eckd2dump_sv.exec: \
|
eckd2dump_sv.exec: \
|
||||||
head.o stage2dump.o cio.o eckd2dump.o eckd2dump_sv.o \
|
head.o stage2dump.o cio.o eckd2dump.o eckd2dump_sv.o \
|
||||||
libc.o ebcdic.o sclp.o entry.o stage2.lds
|
libc.o ebcdic.o sclp.o entry.o stage2.lds
|
||||||
@@ -61,64 +73,14 @@ stage3.exec: head.o stage3.o kdump3.o libc.o ebcdic.o ebcdic_conv.o sclp.o \
|
|||||||
sclp_stage3.o kdump.o entry.o stage3.lds
|
sclp_stage3.o kdump.o entry.o stage3.lds
|
||||||
|
|
||||||
%.exec: %.o
|
%.exec: %.o
|
||||||
STAGE=$$( \
|
$(LINK) -Wl,-T,$(filter %.lds,$^) $(NO_PIE_LDFLAGS) $(NO_WARN_RWX_SEGMENTS_LDFLAGS) -Wl,--build-id=none -m64 -static -nostdlib $(filter %.o, $^) -o $@
|
||||||
echo $@ | awk ' \
|
|
||||||
match($$0,/[0-9]+b*/){ \
|
|
||||||
print substr($$0,RSTART,RLENGTH) \
|
|
||||||
}' \
|
|
||||||
); \
|
|
||||||
case $$STAGE in \
|
|
||||||
0) SFLAGS="-Wl,-Ttext,0";; \
|
|
||||||
1) SFLAGS="-Wl,-Ttext,0x18";; \
|
|
||||||
1b) SFLAGS="-Wl,-Ttext,0xE000";; \
|
|
||||||
2) SFLAGS="-Wl,-T,stage2.lds";; \
|
|
||||||
3) SFLAGS="-Wl,-T,stage3.lds";; \
|
|
||||||
esac; \
|
|
||||||
$(LINK) $$SFLAGS $(NO_PIE_LDFLAGS) -m64 -static -nostdlib $(filter %.o, $^) -o $@
|
|
||||||
|
|
||||||
%.bin: %.exec
|
%.bin: %.exec
|
||||||
$(OBJCOPY) -O binary \
|
$(OBJCOPY) -O binary $< $@
|
||||||
--only-section=.stage2.head \
|
|
||||||
--only-section=.text.dummy \
|
|
||||||
--only-section=.text.start \
|
|
||||||
--only-section=.text \
|
|
||||||
--only-section=.ex_table \
|
|
||||||
--only-section=.data \
|
|
||||||
--only-section=.rodata.str1.2 \
|
|
||||||
--only-section=.rodata.cst8 \
|
|
||||||
--only-section=.rodata \
|
|
||||||
--only-section=.stage2dump.tail \
|
|
||||||
--only-section=.eckd2dump_mv.tail \
|
|
||||||
--only-section=.fixup \
|
|
||||||
$< $@
|
|
||||||
|
|
||||||
stage3.bin: stage3.exec
|
|
||||||
$(OBJCOPY) -O binary \
|
|
||||||
--only-section=.stage2.head \
|
|
||||||
--only-section=.text.dummy \
|
|
||||||
--only-section=.text.start \
|
|
||||||
--only-section=.text \
|
|
||||||
--only-section=.ex_table \
|
|
||||||
--only-section=.data \
|
|
||||||
--only-section=.rodata.str1.2 \
|
|
||||||
--only-section=.rodata.cst8 \
|
|
||||||
--only-section=.rodata \
|
|
||||||
--only-section=.stage2dump.tail \
|
|
||||||
--only-section=.eckd2dump_mv.tail \
|
|
||||||
--only-section=.fixup \
|
|
||||||
--only-section=.sb.trailer \
|
|
||||||
$< $@
|
|
||||||
|
|
||||||
data.o: $(FILES)
|
|
||||||
$(LINK) $(NO_PIE_LDFLAGS) -static -nostdlib -Wl,--relocatable -Wl,--format,binary -o data.o $(FILES)
|
|
||||||
|
|
||||||
data.h: data.o
|
|
||||||
rm -f data.h
|
|
||||||
$(NM) data.o | while read ADDR TYPE SYMBOL ; do \
|
|
||||||
echo "extern char $$SYMBOL;" >>data.h; done
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f -- *.o *.exec *.bin $(FILES) data.o data.h tape0.bin *.xxx *.yyy \
|
rm -f -- *.o *.exec *.bin $(FILES) tape0.bin *.xxx *.yyy \
|
||||||
stage3.bin *.lds .*.lds.d
|
stage3.bin *.lds .*.lds.d .loaders
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -18,3 +18,8 @@ pgm_check_handler:
|
|||||||
basr %r14,%r14
|
basr %r14,%r14
|
||||||
lmg %r0,%r15,__LC_SAVE_AREA_SYNC
|
lmg %r0,%r15,__LC_SAVE_AREA_SYNC
|
||||||
lpswe __LC_PGM_OLD_PSW(%r0)
|
lpswe __LC_PGM_OLD_PSW(%r0)
|
||||||
|
|
||||||
|
/* The code doesn't require an executable stack */
|
||||||
|
#if defined(__linux__) && defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -28,3 +28,8 @@ _start:
|
|||||||
brasl %r14,initialize
|
brasl %r14,initialize
|
||||||
.Lstack: .long 0x10000-160
|
.Lstack: .long 0x10000-160
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
|
/* The code doesn't require an executable stack */
|
||||||
|
#if defined(__linux__) && defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
|
|||||||
18
zipl/boot/stage0.lds.S
Normal file
18
zipl/boot/stage0.lds.S
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#include "boot/loaders_layout.h"
|
||||||
|
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = STAGE0_LOAD_ADDRESS;
|
||||||
|
.text : {
|
||||||
|
*(.text .text.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sections to be discarded */
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.eh_frame)
|
||||||
|
*(.interp)
|
||||||
|
*(.note.GNU-stack)
|
||||||
|
}
|
||||||
|
}
|
||||||
18
zipl/boot/stage1.lds.S
Normal file
18
zipl/boot/stage1.lds.S
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#include "boot/loaders_layout.h"
|
||||||
|
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = STAGE1_LOAD_ADDRESS;
|
||||||
|
.text : {
|
||||||
|
*(.text .text.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sections to be discarded */
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.eh_frame)
|
||||||
|
*(.interp)
|
||||||
|
*(.note.GNU-stack)
|
||||||
|
}
|
||||||
|
}
|
||||||
18
zipl/boot/stage1b.lds.S
Normal file
18
zipl/boot/stage1b.lds.S
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#include "boot/loaders_layout.h"
|
||||||
|
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = STAGE1B_LOAD_ADDRESS;
|
||||||
|
.text : {
|
||||||
|
*(.text .text.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sections to be discarded */
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.eh_frame)
|
||||||
|
*(.interp)
|
||||||
|
*(.note.GNU-stack)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user