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