mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
364b4c0686 | ||
|
|
8818e229cc | ||
|
|
ed18044925 | ||
|
|
3c80f7e025 | ||
|
|
70243b8135 | ||
|
|
2f461f673e | ||
|
|
c0dc514af8 | ||
|
|
e831269e74 | ||
|
|
063425d515 | ||
|
|
61b60baf57 | ||
|
|
cd085dc721 | ||
|
|
c2cb410b8f | ||
|
|
0b4686dd76 | ||
|
|
ca50924acb | ||
|
|
8ff6af3a4b | ||
|
|
221e74c27c | ||
|
|
6c3c721275 | ||
|
|
93d91679c3 | ||
|
|
6b8b336cf0 | ||
|
|
616d379c60 | ||
|
|
f3f16a7ca4 | ||
|
|
d029030308 | ||
|
|
097c498340 | ||
|
|
73d5e17026 | ||
|
|
f3e552d67c | ||
|
|
5ba519973f | ||
|
|
18f1730b92 | ||
|
|
f1a5ab20b7 | ||
|
|
39382ec5fd | ||
|
|
2e8ad91d3d | ||
|
|
7548b470c2 | ||
|
|
b4714e6113 | ||
|
|
fe0b2d96f7 | ||
|
|
b53793d1b6 | ||
|
|
9b5568d2ef |
@@ -2,8 +2,8 @@ List of all individuals having contributed content to s390-tools
|
|||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
- Alexey Ishchuk
|
- Alexey Ishchuk
|
||||||
- Andreas Herrmann
|
|
||||||
- Andre Wild
|
- Andre Wild
|
||||||
|
- Andreas Herrmann
|
||||||
- Antoinette Kaschner
|
- Antoinette Kaschner
|
||||||
- Arnd Bergmann
|
- Arnd Bergmann
|
||||||
- Axel Wirbser
|
- Axel Wirbser
|
||||||
@@ -11,13 +11,14 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Carsten Otte
|
- Carsten Otte
|
||||||
- Christian Borntraeger
|
- Christian Borntraeger
|
||||||
- Christof Schmitt
|
- Christof Schmitt
|
||||||
|
- Claudio Imbrenda
|
||||||
- Clemens von Mann
|
- Clemens von Mann
|
||||||
- Despina Papadopoulou
|
- Despina Papadopoulou
|
||||||
- Eberhard Pasch
|
- Eberhard Pasch
|
||||||
- Einar Lueck
|
- Einar Lueck
|
||||||
- Erwin Vicari
|
- Erwin Vicari
|
||||||
- Eugene Dvurechenski
|
|
||||||
- Eugene Crosser
|
- Eugene Crosser
|
||||||
|
- Eugene Dvurechenski
|
||||||
- Farhan Ali
|
- Farhan Ali
|
||||||
- Felix Beck
|
- Felix Beck
|
||||||
- Frank Blaschka
|
- Frank Blaschka
|
||||||
@@ -62,6 +63,7 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Mikhail Zaslonko
|
- Mikhail Zaslonko
|
||||||
- Peter Oberparleiter
|
- Peter Oberparleiter
|
||||||
- Peter Tiedemann
|
- Peter Tiedemann
|
||||||
|
- Philipp Kern
|
||||||
- Raimund Schroeder
|
- Raimund Schroeder
|
||||||
- Ralph Wuerthner
|
- Ralph Wuerthner
|
||||||
- Rene Trumpp
|
- Rene Trumpp
|
||||||
|
|||||||
30
CHANGELOG.md
30
CHANGELOG.md
@@ -1,11 +1,39 @@
|
|||||||
Release history for s390-tools (MIT version)
|
Release history for s390-tools (MIT version)
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
|
* __v2.1.0 (2017-09-25)__
|
||||||
|
|
||||||
|
Added new tools:
|
||||||
|
- netboot: Scripts for building a PXE-style netboot image for KVM
|
||||||
|
- 90-cpi.rules/cpictl: New udev rule to update CPI when KVM is used
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- lsqeth/zdev: Add VNIC Characteristics support
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- chzcrypt: Corrected handling of insufficient permissions
|
||||||
|
- cpacfstats: Add size setting to perf event
|
||||||
|
- fdasd: Skip partition check with the force option
|
||||||
|
- ttyrun: Fix deprecated BindTo usage in ttyrun-getty@.service.in
|
||||||
|
- lszcrypt: Fix core dump caused by stack overwrite
|
||||||
|
- lszcrypt: Fix random domain printout when no config available
|
||||||
|
- zdev: Fix segfault with unknown qeth attribute
|
||||||
|
- zdev: Fix IPv6 NDP proxy description
|
||||||
|
- zdev: Fix zdev dracut module temp file location
|
||||||
|
- zkey: Correctly detect abbreviated commands
|
||||||
|
- zkey: Validate XTS key: ignore domain and card
|
||||||
|
- zkey: Use octal values instead of S_IRWX* constants
|
||||||
|
- zkey: Properly set umask to prohibit permissions to group and others
|
||||||
|
- zkey: Add -ldl to LDLIBS (not LDFLAGS)
|
||||||
|
- znetconf: Re-add missing line in lsznet.raw
|
||||||
|
- Fix several gcc 7 warnings
|
||||||
|
|
||||||
* __v2.0.0 (2017-08-21)__
|
* __v2.0.0 (2017-08-21)__
|
||||||
|
|
||||||
- Publish package under the MIT license with the same contents as
|
- Publish package under the MIT license with the same contents as
|
||||||
the already available s390-tools-1.39.0
|
the already available s390-tools-1.39.0
|
||||||
|
|
||||||
Previous releases of s390-tools can be found on the IBM Developer Works web pages:
|
Previous releases of s390-tools can be found on the IBM Developer Works
|
||||||
|
web pages:
|
||||||
|
|
||||||
- https://www.ibm.com/developerworks/linux/linux390/s390-tools.html
|
- https://www.ibm.com/developerworks/linux/linux390/s390-tools.html
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -8,7 +8,7 @@ TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
|
|||||||
tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \
|
tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \
|
||||||
vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
|
vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
|
||||||
ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
|
ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
|
||||||
systemd hmcdrvfs cpacfstats zdev dump2tar zkey
|
systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot
|
||||||
SUB_DIRS = $(LIB_DIRS) $(TOOL_DIRS)
|
SUB_DIRS = $(LIB_DIRS) $(TOOL_DIRS)
|
||||||
|
|
||||||
all: $(TOOL_DIRS)
|
all: $(TOOL_DIRS)
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ Package contents
|
|||||||
- 57-osasnmpd.rules: udev rules for osasnmpd.
|
- 57-osasnmpd.rules: udev rules for osasnmpd.
|
||||||
- 60-readahead.rules: udev rules to set increased "default max readahead".
|
- 60-readahead.rules: udev rules to set increased "default max readahead".
|
||||||
- 40-z90crypt.rules: udev rules for z90crypt driver
|
- 40-z90crypt.rules: udev rules for z90crypt driver
|
||||||
|
- 90-cpi.rules: udev rule to update Control-Program-Information when KVM is
|
||||||
|
used.
|
||||||
|
|
||||||
* systemd units:
|
* systemd units:
|
||||||
- cpi.service: Unit to apply CPI settings
|
- cpi.service: Unit to apply CPI settings
|
||||||
@@ -234,6 +236,10 @@ Package contents
|
|||||||
arbitrary files. It works even when the size of the actual file content
|
arbitrary files. It works even when the size of the actual file content
|
||||||
is not known beforehand (e.g. FIFOs, sysfs files).
|
is not known beforehand (e.g. FIFOs, sysfs files).
|
||||||
|
|
||||||
|
* netboot:
|
||||||
|
Provides simple tools to create a binary that can be used to implement
|
||||||
|
simple network boot setups following the PXELINUX conventions.
|
||||||
|
|
||||||
For more information refer to the following publications:
|
For more information refer to the following publications:
|
||||||
|
|
||||||
* "Device Drivers, Features, and Commands" chapter "Useful Linux commands"
|
* "Device Drivers, Features, and Commands" chapter "Useful Linux commands"
|
||||||
|
|||||||
135
bin/mk-authors
Executable file
135
bin/mk-authors
Executable file
@@ -0,0 +1,135 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# mk-authors - Update the s390-tools authors file (AUTHORS.md)
|
||||||
|
#
|
||||||
|
# Invocation examples:
|
||||||
|
#
|
||||||
|
# $ mk-authors
|
||||||
|
# $ mk-authors -t v2.0.0
|
||||||
|
#
|
||||||
|
# Copyright IBM Corp. 2017
|
||||||
|
#
|
||||||
|
# s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
|
||||||
|
cmd=$(basename $0)
|
||||||
|
authors_file="AUTHORS.md"
|
||||||
|
|
||||||
|
cleanup()
|
||||||
|
{
|
||||||
|
test -f $authors_file_tmp && rm -f $authors_file_tmp
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
#
|
||||||
|
# Print usage information
|
||||||
|
#
|
||||||
|
print_usage()
|
||||||
|
{
|
||||||
|
cat <<EoUSAGE
|
||||||
|
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.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-t, --tag LAST_GIT_TAG Use git tag LAST_GIT_TAG as starting point
|
||||||
|
-h, --help Print this help, then exit
|
||||||
|
EoUSAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Print help hint for option parsing error
|
||||||
|
#
|
||||||
|
print_parse_error_and_exit()
|
||||||
|
{
|
||||||
|
echo "Try '$cmd -h' for more information." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Parse options
|
||||||
|
#
|
||||||
|
opts=$(getopt -o ht: -l help,tag: -n $cmd -- "$@")
|
||||||
|
if [ $? != 0 ]; then
|
||||||
|
print_parse_error_and_exit
|
||||||
|
fi
|
||||||
|
# Use eval to remove getopt quotes
|
||||||
|
eval set -- $opts
|
||||||
|
while [ -n $1 ]; do
|
||||||
|
case $1 in
|
||||||
|
-h | --help)
|
||||||
|
print_usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-t | --tag)
|
||||||
|
release_tag_last=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $# != 0 ]; then
|
||||||
|
echo "$cmd: Invalid argument $1" >&2
|
||||||
|
print_parse_error_and_exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get git root and last release tag
|
||||||
|
#
|
||||||
|
git_root=$(git rev-parse --show-toplevel 2> /dev/null)
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "$cmd: Use tool within s390-tools git repository" >&2
|
||||||
|
print_parse_error_and_exit
|
||||||
|
fi
|
||||||
|
authors_file_path=$git_root/$authors_file
|
||||||
|
# Get last release tag if not specified via -t
|
||||||
|
if [ -z $release_tag_last ]; then
|
||||||
|
tag_commit=$(git rev-list --tags --max-count=1)
|
||||||
|
release_tag_last=$(git describe --tags $tag_commit)
|
||||||
|
fi
|
||||||
|
# Verify release tag
|
||||||
|
git show $release_tag_last &> /dev/null
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "$cmd: Cannot find tag '$release_tag_last'" >&2
|
||||||
|
print_parse_error_and_exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Update authors file
|
||||||
|
#
|
||||||
|
|
||||||
|
# Create temporary file for new author list
|
||||||
|
authors_file_tmp=$(mktemp /tmp/authors.XXXXXX)
|
||||||
|
|
||||||
|
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..
|
||||||
|
# Then sort everything and remove duplicates
|
||||||
|
} | sort | uniq > $authors_file_tmp
|
||||||
|
# Create new AUTHORS file with header ...
|
||||||
|
cat <<EoHEADER > $authors_file_path
|
||||||
|
List of all individuals having contributed content to s390-tools
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
EoHEADER
|
||||||
|
# ... and add new content
|
||||||
|
cat $authors_file_tmp >> $authors_file_path
|
||||||
|
|
||||||
|
cat <<EoUPDATE_MSG
|
||||||
|
- Updated file: $authors_file_path
|
||||||
|
- Verify changes with: git diff $authors_file_path
|
||||||
|
- Do a manual *cleanup* before commiting if necessary.
|
||||||
|
EoUPDATE_MSG
|
||||||
@@ -5,7 +5,7 @@ COMMON_INCLUDED = true
|
|||||||
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
|
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
|
||||||
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
|
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
|
||||||
VERSION = 2
|
VERSION = 2
|
||||||
RELEASE = 0
|
RELEASE = 1
|
||||||
PATCHLEVEL = 0
|
PATCHLEVEL = 0
|
||||||
DISTRELEASE = build-$(shell date +%Y%m%d)
|
DISTRELEASE = build-$(shell date +%Y%m%d)
|
||||||
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
|
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ int perf_init(void)
|
|||||||
memset(&pfm_event, 0, sizeof(pfm_event));
|
memset(&pfm_event, 0, sizeof(pfm_event));
|
||||||
pfm_arg.attr = &pfm_event;
|
pfm_arg.attr = &pfm_event;
|
||||||
pfm_arg.size = sizeof(pfm_arg);
|
pfm_arg.size = sizeof(pfm_arg);
|
||||||
|
pfm_event.size = sizeof(pfm_event);
|
||||||
|
|
||||||
/* search for the counter's corresponding pfm name */
|
/* search for the counter's corresponding pfm name */
|
||||||
for (i = ALL_COUNTER-1; i >= 0; i--)
|
for (i = ALL_COUNTER-1; i >= 0; i--)
|
||||||
|
|||||||
@@ -23,11 +23,12 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "lib/util_base.h"
|
#include "lib/util_base.h"
|
||||||
|
#include "lib/util_file.h"
|
||||||
#include "lib/util_opt.h"
|
#include "lib/util_opt.h"
|
||||||
#include "lib/util_prg.h"
|
#include "lib/util_prg.h"
|
||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#define READCHUNK 80
|
#define RD_BUFFER_SIZE 80
|
||||||
#define BLKSSZGET _IO(0x12,104)
|
#define BLKSSZGET _IO(0x12,104)
|
||||||
#define DASD_IOCTL_LETTER 'D'
|
#define DASD_IOCTL_LETTER 'D'
|
||||||
#define BIODASDINFO _IOR(DASD_IOCTL_LETTER,1,struct dasd_information)
|
#define BIODASDINFO _IOR(DASD_IOCTL_LETTER,1,struct dasd_information)
|
||||||
@@ -236,29 +237,9 @@ static char *dinfo_ebcdic_dec (char *source, char *target, int l)
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dinfo_read_dasd_uid (char *uidfile, char *readbuf, int readbuflen)
|
static int dinfo_read_dasd_uid(char *uidfile, char *readbuf)
|
||||||
{
|
{
|
||||||
FILE *dasduid;
|
return util_file_read_line(readbuf, RD_BUFFER_SIZE, uidfile);
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
if ((dasduid = fopen(uidfile,"r")) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
while (fgets(readbuf + offset, READCHUNK, dasduid) &&
|
|
||||||
readbuf[strlen(readbuf)-1] != '\n' ) {
|
|
||||||
offset += READCHUNK-1;
|
|
||||||
if ( offset+READCHUNK-1 >= readbuflen ) {
|
|
||||||
readbuf = realloc(readbuf,
|
|
||||||
readbuflen + READCHUNK-1);
|
|
||||||
readbuflen += READCHUNK-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(dasduid);
|
|
||||||
|
|
||||||
if (strlen(readbuf) <= 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dinfo_read_dasd_vlabel (char *device, struct volume_label *vlabel,
|
static int dinfo_read_dasd_vlabel (char *device, struct volume_label *vlabel,
|
||||||
@@ -411,14 +392,14 @@ static void dinfo_free_devnode(char *device)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dinfo_extract_dev(dev_t *dev, char *str, int readbuflen)
|
static int dinfo_extract_dev(dev_t *dev, char *str)
|
||||||
{
|
{
|
||||||
char tmp[readbuflen];
|
char tmp[RD_BUFFER_SIZE];
|
||||||
char *p = NULL;
|
char *p = NULL;
|
||||||
int ma, mi;
|
int ma, mi;
|
||||||
|
|
||||||
bzero(tmp, readbuflen);
|
bzero(tmp, RD_BUFFER_SIZE);
|
||||||
strncpy(tmp, str, readbuflen);
|
strncpy(tmp, str, RD_BUFFER_SIZE);
|
||||||
if ((p = strchr(tmp, ':')) == NULL) {
|
if ((p = strchr(tmp, ':')) == NULL) {
|
||||||
printf("Error: unable to extract major/minor\n");
|
printf("Error: unable to extract major/minor\n");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -435,37 +416,17 @@ static int dinfo_extract_dev(dev_t *dev, char *str, int readbuflen)
|
|||||||
|
|
||||||
static int dinfo_get_dev_from_blockdev(char *blockdev, dev_t *dev)
|
static int dinfo_get_dev_from_blockdev(char *blockdev, dev_t *dev)
|
||||||
{
|
{
|
||||||
FILE *dasddev;
|
|
||||||
int offset = 0;
|
|
||||||
char *devfile = NULL;
|
|
||||||
char *readbuf = NULL;
|
char *readbuf = NULL;
|
||||||
int readbuflen = READCHUNK;
|
|
||||||
|
|
||||||
if ((devfile = dinfo_malloc(readbuflen)) == NULL)
|
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
||||||
return -1;
|
if (!readbuf) {
|
||||||
|
|
||||||
sprintf(devfile,"/sys/block/%s/dev", blockdev);
|
|
||||||
|
|
||||||
if ((readbuf = dinfo_malloc(readbuflen)) == NULL) {
|
|
||||||
printf("Error: Not enough memory to allocate readbuffer\n");
|
printf("Error: Not enough memory to allocate readbuffer\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (util_file_read_line(readbuf, RD_BUFFER_SIZE,
|
||||||
if ((dasddev = fopen(devfile,"r")) == NULL)
|
"/sys/block/%s/dev", blockdev) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (dinfo_extract_dev(dev, readbuf) != 0)
|
||||||
while (fgets(readbuf + offset, READCHUNK, dasddev) &&
|
|
||||||
readbuf[strlen(readbuf)-1] != '\n' ) {
|
|
||||||
offset += READCHUNK-1;
|
|
||||||
if (offset+READCHUNK-1 >= readbuflen) {
|
|
||||||
readbuf = realloc(readbuf,
|
|
||||||
readbuflen + READCHUNK-1);
|
|
||||||
readbuflen += READCHUNK-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(dasddev);
|
|
||||||
|
|
||||||
if (dinfo_extract_dev(dev, readbuf, readbuflen) != 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -580,14 +541,10 @@ out2:
|
|||||||
static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
|
static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
|
||||||
{
|
{
|
||||||
struct stat stat_buffer;
|
struct stat stat_buffer;
|
||||||
char stat_dev[READCHUNK];
|
char stat_dev[RD_BUFFER_SIZE];
|
||||||
char sys_dev_path[READCHUNK];
|
|
||||||
char *readbuf;
|
char *readbuf;
|
||||||
DIR *directory = NULL;
|
DIR *directory = NULL;
|
||||||
struct dirent *dir_entry = NULL;
|
struct dirent *dir_entry = NULL;
|
||||||
FILE *block_dev;
|
|
||||||
int readbuflen = READCHUNK;
|
|
||||||
int offset;
|
|
||||||
|
|
||||||
if (stat(devnode, &stat_buffer) != 0) {
|
if (stat(devnode, &stat_buffer) != 0) {
|
||||||
printf("Error: could not stat %s\n", devnode);
|
printf("Error: could not stat %s\n", devnode);
|
||||||
@@ -602,33 +559,22 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((readbuf = dinfo_malloc(readbuflen)) == NULL) {
|
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
||||||
|
if (!readbuf) {
|
||||||
printf("Error: Not enough memory to allocate readbuffer\n");
|
printf("Error: Not enough memory to allocate readbuffer\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((dir_entry = readdir(directory)) != NULL) {
|
while ((dir_entry = readdir(directory)) != NULL) {
|
||||||
sprintf(sys_dev_path, "/sys/block/%s/dev", dir_entry->d_name);
|
if (util_file_read_line(readbuf, RD_BUFFER_SIZE,
|
||||||
|
"/sys/block/%s/dev",
|
||||||
if ((block_dev = fopen(sys_dev_path,"r")) == NULL)
|
dir_entry->d_name) < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
offset = 0;
|
|
||||||
while (fgets(readbuf + offset, READCHUNK, block_dev) &&
|
|
||||||
readbuf[strlen(readbuf)-1] != '\n' ) {
|
|
||||||
offset += READCHUNK-1;
|
|
||||||
if ( offset+READCHUNK-1 >= readbuflen ) {
|
|
||||||
readbuf = realloc(readbuf,
|
|
||||||
readbuflen + READCHUNK-1);
|
|
||||||
readbuflen += READCHUNK-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(block_dev);
|
|
||||||
|
|
||||||
if (strncmp(stat_dev, readbuf,
|
if (strncmp(stat_dev, readbuf,
|
||||||
MAX(strlen(stat_dev), strlen(readbuf)-1)) == 0) {
|
MAX(strlen(stat_dev), strlen(readbuf)-1)) == 0) {
|
||||||
sprintf(*uidfile,"/sys/block/%s/device/uid",
|
snprintf(*uidfile, RD_BUFFER_SIZE,
|
||||||
dir_entry->d_name);
|
"/sys/block/%s/device/uid", dir_entry->d_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -644,7 +590,6 @@ int main(int argc, char * argv[])
|
|||||||
char *uidfile = NULL;
|
char *uidfile = NULL;
|
||||||
char *device = NULL;
|
char *device = NULL;
|
||||||
char *readbuf = NULL;
|
char *readbuf = NULL;
|
||||||
int readbuflen = READCHUNK;
|
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
int export = 0;
|
int export = 0;
|
||||||
int c;
|
int c;
|
||||||
@@ -733,8 +678,9 @@ int main(int argc, char * argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((readbuf = dinfo_malloc(readbuflen)) == NULL) ||
|
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
||||||
((uidfile = dinfo_malloc(readbuflen)) == NULL))
|
uidfile = dinfo_malloc(RD_BUFFER_SIZE);
|
||||||
|
if (!(readbuf && uidfile))
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
/* try to read the uid attribute */
|
/* try to read the uid attribute */
|
||||||
@@ -753,7 +699,7 @@ int main(int argc, char * argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (print_uid) {
|
if (print_uid) {
|
||||||
if (dinfo_read_dasd_uid(uidfile, readbuf, readbuflen) == 0) {
|
if (dinfo_read_dasd_uid(uidfile, readbuf) == 0) {
|
||||||
/* look for the 4th '.' and cut there */
|
/* look for the 4th '.' and cut there */
|
||||||
srchuid = readbuf - 1;
|
srchuid = readbuf - 1;
|
||||||
for (i = 0; i < 4; ++i) {
|
for (i = 0; i < 4; ++i) {
|
||||||
@@ -766,20 +712,20 @@ int main(int argc, char * argv[])
|
|||||||
srchuid[1] = 0;
|
srchuid[1] = 0;
|
||||||
}
|
}
|
||||||
if (export) {
|
if (export) {
|
||||||
printf("ID_UID=%s",readbuf);
|
printf("ID_UID=%s\n", readbuf);
|
||||||
} else
|
} else
|
||||||
printf("%s",readbuf);
|
printf("%s\n", readbuf);
|
||||||
if (!print_vlabel && !print_extended_uid)
|
if (!print_vlabel && !print_extended_uid)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (print_extended_uid) {
|
if (print_extended_uid) {
|
||||||
if (dinfo_read_dasd_uid(uidfile, readbuf, readbuflen) == 0) {
|
if (dinfo_read_dasd_uid(uidfile, readbuf) == 0) {
|
||||||
if (export) {
|
if (export) {
|
||||||
printf("ID_XUID=%s",readbuf);
|
printf("ID_XUID=%s\n", readbuf);
|
||||||
} else
|
} else
|
||||||
printf("%s",readbuf);
|
printf("%s\n", readbuf);
|
||||||
if (!print_vlabel)
|
if (!print_vlabel)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -808,7 +754,8 @@ int main(int argc, char * argv[])
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
} else if (devnode) {
|
} else if (devnode) {
|
||||||
if ((device = dinfo_malloc(readbuflen)) == NULL)
|
device = dinfo_malloc(RD_BUFFER_SIZE);
|
||||||
|
if (!device)
|
||||||
exit(1);
|
exit(1);
|
||||||
strcpy(device, devnode);
|
strcpy(device, devnode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
# The system and sysplex names consist of up to eight characters of
|
# The system and sysplex names consist of up to eight characters of
|
||||||
# the following set: A-Z, 0-9, $, @, #, and blank.
|
# the following set: A-Z, 0-9, $, @, #, and blank.
|
||||||
|
|
||||||
|
#
|
||||||
|
# CPI system type
|
||||||
|
#
|
||||||
|
CPI_SYSTEM_TYPE="LINUX"
|
||||||
|
|
||||||
#
|
#
|
||||||
# CPI system name
|
# CPI system name
|
||||||
#
|
#
|
||||||
|
|||||||
6
etc/udev/rules.d/90-cpi.rules
Normal file
6
etc/udev/rules.d/90-cpi.rules
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#
|
||||||
|
# Rules to trigger cpictl when KVM is used
|
||||||
|
# This file should be installed in /etc/udev/rules.d
|
||||||
|
#
|
||||||
|
|
||||||
|
SUBSYSTEM=="misc", KERNEL=="kvm", ENV{CREATED}=="1", ENV{EVENT}=="create", RUN+="/lib/s390-tools/cpictl -b kvm"
|
||||||
@@ -308,7 +308,7 @@ static void fdasd_cleanup(fdasd_anchor_t *anchor)
|
|||||||
/*
|
/*
|
||||||
* Exit fdasd.
|
* Exit fdasd.
|
||||||
*/
|
*/
|
||||||
static void fdasd_exit(fdasd_anchor_t *anchor, int rc)
|
static void __noreturn fdasd_exit(fdasd_anchor_t *anchor, int rc)
|
||||||
{
|
{
|
||||||
fdasd_cleanup(anchor);
|
fdasd_cleanup(anchor);
|
||||||
exit(rc);
|
exit(rc);
|
||||||
@@ -921,7 +921,7 @@ static void fdasd_verify_device(fdasd_anchor_t *anc, char *name)
|
|||||||
fdasd_error(anc, device_verification_failed, err_str);
|
fdasd_error(anc, device_verification_failed, err_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minor(dst.st_rdev) & PARTN_MASK) {
|
if (!anc->force_virtual && minor(dst.st_rdev) & PARTN_MASK) {
|
||||||
snprintf(err_str, ERROR_STRING_SIZE,
|
snprintf(err_str, ERROR_STRING_SIZE,
|
||||||
"Partition '%s' (%d/%d) detected where device is "
|
"Partition '%s' (%d/%d) detected where device is "
|
||||||
"required\n", name,
|
"required\n", name,
|
||||||
|
|||||||
@@ -348,7 +348,7 @@ void hyptop_text_mode(void)
|
|||||||
/*
|
/*
|
||||||
* Exit hyptop
|
* Exit hyptop
|
||||||
*/
|
*/
|
||||||
void hyptop_exit(int rc)
|
void __noreturn hyptop_exit(int rc)
|
||||||
{
|
{
|
||||||
hyptop_text_mode();
|
hyptop_text_mode();
|
||||||
exit(rc);
|
exit(rc);
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ extern void win_cpu_types_init(void);
|
|||||||
* Misc functions
|
* Misc functions
|
||||||
*/
|
*/
|
||||||
extern void hyptop_update_term(void);
|
extern void hyptop_update_term(void);
|
||||||
extern void hyptop_exit(int rc);
|
extern void __noreturn hyptop_exit(int rc);
|
||||||
extern void hyptop_text_mode(void);
|
extern void hyptop_text_mode(void);
|
||||||
|
|
||||||
#endif /* HYPTOP_H */
|
#endif /* HYPTOP_H */
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ static struct locals {
|
|||||||
enum reipl_type reipl_type; /* CCW, FCP, NSS */
|
enum reipl_type reipl_type; /* CCW, FCP, NSS */
|
||||||
} l;
|
} l;
|
||||||
|
|
||||||
static void print_usage_chreipl_exit(void)
|
static void __noreturn print_usage_chreipl_exit(void)
|
||||||
{
|
{
|
||||||
printf(usage_chreipl, g.prog_name);
|
printf(usage_chreipl, g.prog_name);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ static const char *const usage_chshut =
|
|||||||
" -h, --help Print this help, then exit\n"
|
" -h, --help Print this help, then exit\n"
|
||||||
" -v, --version Print version information, then exit\n";
|
" -v, --version Print version information, then exit\n";
|
||||||
|
|
||||||
static void print_usage_chshut_exit(void)
|
static void __noreturn print_usage_chshut_exit(void)
|
||||||
{
|
{
|
||||||
printf(usage_chshut, g.prog_name);
|
printf(usage_chshut, g.prog_name);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ static const char *const usage_lsreipl =
|
|||||||
" -h, --help Print this help, then exit\n"
|
" -h, --help Print this help, then exit\n"
|
||||||
" -v, --version Print version information, then exit\n";
|
" -v, --version Print version information, then exit\n";
|
||||||
|
|
||||||
static void print_usage_lsreipl_exit(void)
|
static void __noreturn print_usage_lsreipl_exit(void)
|
||||||
{
|
{
|
||||||
printf(usage_lsreipl, g.prog_name);
|
printf(usage_lsreipl, g.prog_name);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ static const char *const usage_lsshut =
|
|||||||
" -h, --help Print this help, then exit\n"
|
" -h, --help Print this help, then exit\n"
|
||||||
" -v, --version Print version information, then exit\n";
|
" -v, --version Print version information, then exit\n";
|
||||||
|
|
||||||
static void print_usage_lsshut_exit(void)
|
static __noreturn void print_usage_lsshut_exit(void)
|
||||||
{
|
{
|
||||||
printf(usage_lsshut, g.prog_name);
|
printf(usage_lsshut, g.prog_name);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <lib/zt_common.h>
|
||||||
|
|
||||||
#define IPL_TYPE_LEN_MAX 100
|
#define IPL_TYPE_LEN_MAX 100
|
||||||
#define NSS_NAME_LEN_MAX 8
|
#define NSS_NAME_LEN_MAX 8
|
||||||
|
|
||||||
@@ -57,8 +59,8 @@ extern void read_str(char *string, const char *file, size_t len);
|
|||||||
extern void read_fw_str(char *string, const char *file, size_t len);
|
extern void read_fw_str(char *string, const char *file, size_t len);
|
||||||
extern void print_fw_str(const char *fmt, const char *dir, const char *file);
|
extern void print_fw_str(const char *fmt, const char *dir, const char *file);
|
||||||
|
|
||||||
extern void print_version_exit(void);
|
extern void __noreturn print_version_exit(void);
|
||||||
extern void print_help_hint_exit(void);
|
extern void __noreturn print_help_hint_exit(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FCP
|
* FCP
|
||||||
|
|||||||
@@ -14,14 +14,14 @@
|
|||||||
|
|
||||||
struct globals g;
|
struct globals g;
|
||||||
|
|
||||||
void print_help_hint_exit(void)
|
void __noreturn print_help_hint_exit(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Try '%s' --help' for more information.\n",
|
fprintf(stderr, "Try '%s' --help' for more information.\n",
|
||||||
g.prog_name);
|
g.prog_name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_version_exit(void)
|
void __noreturn print_version_exit(void)
|
||||||
{
|
{
|
||||||
printf("%s: Linux on System z shutdown actions version %s\n",
|
printf("%s: Linux on System z shutdown actions version %s\n",
|
||||||
g.prog_name, RELEASE_STRING);
|
g.prog_name, RELEASE_STRING);
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ static const struct tool_info iucv_tool[2] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void usage_exit(const struct tool_info *prg, int is_error,
|
static void __noreturn usage_exit(const struct tool_info *prg, int is_error,
|
||||||
const char *msg)
|
const char *msg)
|
||||||
{
|
{
|
||||||
if (msg != NULL)
|
if (msg != NULL)
|
||||||
fprintf(stderr, _("%s: %s\n"), prg->name, msg);
|
fprintf(stderr, _("%s: %s\n"), prg->name, msg);
|
||||||
@@ -80,7 +80,7 @@ static void usage_exit(const struct tool_info *prg, int is_error,
|
|||||||
exit(is_error ? 1 : 0); /* rc=1 .. invalid args */
|
exit(is_error ? 1 : 0); /* rc=1 .. invalid args */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void version_exit(const struct tool_info *prg)
|
static void __noreturn version_exit(const struct tool_info *prg)
|
||||||
{
|
{
|
||||||
printf(_("%s: IUCV Terminal Applications, version %s\n"),
|
printf(_("%s: IUCV Terminal Applications, version %s\n"),
|
||||||
prg->name, RELEASE_STRING);
|
prg->name, RELEASE_STRING);
|
||||||
|
|||||||
@@ -62,13 +62,13 @@ static const char usage[] =
|
|||||||
"-h, --help Displays this help, then exits.\n"
|
"-h, --help Displays this help, then exits.\n"
|
||||||
"-v, --version Displays version information, then exits.\n";
|
"-v, --version Displays version information, then exits.\n";
|
||||||
|
|
||||||
static void help_exit(const char *prg)
|
static void __noreturn help_exit(const char *prg)
|
||||||
{
|
{
|
||||||
printf(usage, prg, prg);
|
printf(usage, prg, prg);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void version_exit(const char *prg)
|
static void __noreturn version_exit(const char *prg)
|
||||||
{
|
{
|
||||||
printf("%s: Start a program if a terminal device is available, "
|
printf("%s: Start a program if a terminal device is available, "
|
||||||
"version %s\n", prg, RELEASE_STRING);
|
"version %s\n", prg, RELEASE_STRING);
|
||||||
|
|||||||
21
netboot/Dockerfile
Normal file
21
netboot/Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#
|
||||||
|
# Sample Dockerfile to build PXE-style boot image for KVM on s390
|
||||||
|
#
|
||||||
|
|
||||||
|
FROM s390x/ubuntu:16.04
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
linux-image-4.4.0-78-generic \
|
||||||
|
make \
|
||||||
|
wget \
|
||||||
|
bzip2 \
|
||||||
|
linux-headers-4.4.0-78-generic \
|
||||||
|
gcc \
|
||||||
|
kexec-tools \
|
||||||
|
file
|
||||||
|
|
||||||
|
RUN mkdir /netboot
|
||||||
|
|
||||||
|
COPY . /netboot
|
||||||
|
|
||||||
|
RUN cd /netboot && make -f Makefile.pxelinux.0 KERNEL_VERSION=4.4.0-78-generic
|
||||||
16
netboot/Makefile
Normal file
16
netboot/Makefile
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Install the netboot image build scripts as samples
|
||||||
|
|
||||||
|
include ../common.mak
|
||||||
|
|
||||||
|
NETBOOT_SAMPLEDIR=$(TOOLS_DATADIR)/netboot
|
||||||
|
|
||||||
|
all:
|
||||||
|
|
||||||
|
install: all
|
||||||
|
$(INSTALL) -d -m 755 $(DESTDIR)$(NETBOOT_SAMPLEDIR)
|
||||||
|
$(INSTALL) -m 755 mk-s390image mk-pxelinux-ramfs \
|
||||||
|
$(DESTDIR)$(NETBOOT_SAMPLEDIR)
|
||||||
|
$(INSTALL) -m 644 Dockerfile Makefile.pxelinux.0 README.md \
|
||||||
|
$(DESTDIR)$(NETBOOT_SAMPLEDIR)
|
||||||
|
|
||||||
|
.PHONY: all install clean
|
||||||
46
netboot/Makefile.pxelinux.0
Normal file
46
netboot/Makefile.pxelinux.0
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Sample Makefile to produce a pxe-style netboot image
|
||||||
|
# matching the currently active kernel.
|
||||||
|
# If the image is to be build for a different kernel version
|
||||||
|
# the KERNEL_VERSION variable must be overridden
|
||||||
|
# To use a local busybox installation, change BBINSTALL
|
||||||
|
# to point to the local busybox install path
|
||||||
|
|
||||||
|
ifeq ("$(KERNEL_VERSION)","")
|
||||||
|
KERNEL_VERSION=$(shell uname -r)
|
||||||
|
endif
|
||||||
|
export KERNEL_VERSION
|
||||||
|
|
||||||
|
filetype=$(shell file $1 | grep "Linux S390")
|
||||||
|
s390_check=$(if $(call filetype,$1), $1)
|
||||||
|
prefixes=image vmlinux vmlinuz
|
||||||
|
kernel_images=$(foreach prefix, $(prefixes), \
|
||||||
|
$(call s390_check,/boot/$(prefix)-$(KERNEL_VERSION)))
|
||||||
|
KERNEL_IMAGE=$(firstword $(kernel_images))
|
||||||
|
|
||||||
|
ifeq ($(KERNEL_IMAGE),)
|
||||||
|
$(error Could not find a kernel image under /boot)
|
||||||
|
endif
|
||||||
|
|
||||||
|
BUSYBOX=busybox-1.27.1
|
||||||
|
BBINSTALL=$(BUSYBOX)/_install
|
||||||
|
|
||||||
|
all: $(KERNEL_IMAGE) pxelinux.initramfs
|
||||||
|
/bin/bash mk-s390image $(KERNEL_IMAGE) pxelinux.0 -r pxelinux.initramfs
|
||||||
|
|
||||||
|
pxelinux.initramfs: $(BBINSTALL)
|
||||||
|
/bin/bash mk-pxelinux-ramfs -b $< -k $(KERNEL_VERSION) $@
|
||||||
|
|
||||||
|
$(BUSYBOX)/_install:
|
||||||
|
wget https://busybox.net/downloads/$(BUSYBOX).tar.bz2
|
||||||
|
tar xjf $(BUSYBOX).tar.bz2
|
||||||
|
make -C $(BUSYBOX) defconfig
|
||||||
|
make -C $(BUSYBOX) install
|
||||||
|
|
||||||
|
install:
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) pxelinux.0 pxelinux.initramfs $(BUSYBOX).tar.bz2
|
||||||
|
$(RM) -r $(BUSYBOX)
|
||||||
|
|
||||||
|
.PHONY: all install clean
|
||||||
|
|
||||||
99
netboot/README.md
Normal file
99
netboot/README.md
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# How to build a PXELINUX-style network boot image for KVM
|
||||||
|
|
||||||
|
## Synopsis
|
||||||
|
|
||||||
|
To build a PXELINUX-style netboot image usable for KVM a s390 Linux system
|
||||||
|
with access to the internet is required.
|
||||||
|
|
||||||
|
Running the following command will generate the netboot image pxlinux.0:
|
||||||
|
|
||||||
|
` $ make -f Makefile.pxelinux.0`
|
||||||
|
|
||||||
|
Alternatively you can use docker to build the image:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ docker build -t pxelinux0 .
|
||||||
|
$ docker run --rm -v $(pwd):/out pxelinux0 cp /netboot/pxelinux.0 /out
|
||||||
|
$ docker rmi pxelinux0
|
||||||
|
```
|
||||||
|
|
||||||
|
The resulting file pxelinux.0 must be copied to the system acting as
|
||||||
|
DHCP/BOOTP server for the KVM installation.
|
||||||
|
|
||||||
|
## Full Description
|
||||||
|
|
||||||
|
Starting with QEMU 2.10 it is possible to boot s390 virtual machines over a
|
||||||
|
network interface using DHCP. As usual for DHCP/BOOTP a single bootable image
|
||||||
|
is copied from the boot server, loaded into memory and booted. In order to
|
||||||
|
boot a Linux Operating System, it is typically necessary to load a kernel
|
||||||
|
together with an initial ramdisk (initramfs) and optionally specify some kernel
|
||||||
|
command line parameters.
|
||||||
|
|
||||||
|
Alternatively, on s390 it is possible to load a single file consisting of
|
||||||
|
the kernel image followed by an initial ramdisk. Such single boot images can
|
||||||
|
be provided by a Linux distributor, e.g. on the installation media.
|
||||||
|
|
||||||
|
Single boot images can also easily be built from pre-existing kernel/initramfs
|
||||||
|
pairs by concatenating these files. In order to allow the kernel to find the
|
||||||
|
ramdisk, it is necessary to update the 8 bytes at location 0x10408 with the
|
||||||
|
offset value of the ramdisk in the new binary, and the 8 bytes at location
|
||||||
|
0x10410 with the size of the ramdisk. Both values need to be updated in binary,
|
||||||
|
big endian format.
|
||||||
|
|
||||||
|
Since PXELINUX, the PXE boot implementation provided by the Syslinux project,
|
||||||
|
has introduced a popular way to set up network boot servers for Linux, it
|
||||||
|
is desirable that s390 network boot setups can be done in a similar way.
|
||||||
|
A boot image simulating a PXELINUX-like boot for s390 can be easily
|
||||||
|
constructed by combining a Linux kernel with a small fit-to-purpose initial
|
||||||
|
ramdisk as described above. For practical purposes, using the host kernel is
|
||||||
|
a reasonable way for this kind of approach. If possible, the initial ramdisk
|
||||||
|
should be independent of the host, which is not always possible, as the kernel
|
||||||
|
might require modules for e.g. virtio network and block devices.
|
||||||
|
|
||||||
|
### Example: Building a PXELINUX-style boot image
|
||||||
|
|
||||||
|
The approach described below consists of bundling some shell scripts, busybox
|
||||||
|
and the kexec binary bundled into the initial ramdisk.
|
||||||
|
|
||||||
|
The init process can be a simple shell script that will mount a few essential
|
||||||
|
file systems, like /dev, /proc, and /sys, start a DHCP client (e.g. busybox's
|
||||||
|
udchpc) and then invoke another script to perform the network boot.
|
||||||
|
udchpc will invoke the script /usr/share/udhcpc/default.script in response
|
||||||
|
to DHCP server messages to perform configuration actions.
|
||||||
|
The sample default.script delivered with busybox can be used for that purpose,
|
||||||
|
but needs to be extended to evaluate the bootp specific DHCP options (most
|
||||||
|
important the tftp server address) and store them for use by the boot script.
|
||||||
|
|
||||||
|
The boot script itself has to retrieve the PXELINUX configuration from the
|
||||||
|
tftp server according to the rules described [here][1] then retrieve the
|
||||||
|
remote kernel and initial ramdisk and finally use kexec to boot the network
|
||||||
|
kernel.
|
||||||
|
|
||||||
|
In essence, the following steps are performed to produce the initial
|
||||||
|
ramdisk:
|
||||||
|
|
||||||
|
1. Create a skeleton initramfs directory structure
|
||||||
|
2. Create the init script, the boot script and the DHCP default script
|
||||||
|
3. Copy kexec and it's dependencies from the host into the initramfs
|
||||||
|
4. Copy virtio network and block modules of the host's active kernel into
|
||||||
|
the initramfs
|
||||||
|
5. Copy the busybox binaries into the initramfs.
|
||||||
|
6. Copy the DHCP configuration and PXE boot scripts to the initramfs
|
||||||
|
7. Build the ramdisk (in compressed CPIO format)
|
||||||
|
8. Concatenate the kernel image and the initial ramdisk, and adjust the
|
||||||
|
ramdisk offset as described above.
|
||||||
|
|
||||||
|
Steps 1 to 7 are performed by the sample script mk-pxelinux-ramfs, while step
|
||||||
|
8 is done with the help of mk-s390image.
|
||||||
|
|
||||||
|
The binary resulting from the procedure described above can now be deployed
|
||||||
|
to a DHCP/BOOTP server. This server should also act as a TFTP server for the
|
||||||
|
PXELINUX configuration and binary files needed to complete the network boot.
|
||||||
|
|
||||||
|
Alternatively, it is possible to use programs like [petitboot][2] or
|
||||||
|
[pxe-kexec][3] in the initial ramdisk, as these provide more sophisticated
|
||||||
|
and robust processing of PXELINUX-style configurations.
|
||||||
|
|
||||||
|
[1]: http://www.syslinux.org/wiki/index.php?title=PXELINUX
|
||||||
|
[2]: https://github.com/open-power/petitboot
|
||||||
|
[3]: https://sourceforge.net/projects/pxe-kexec.berlios/
|
||||||
402
netboot/mk-pxelinux-ramfs
Executable file
402
netboot/mk-pxelinux-ramfs
Executable file
@@ -0,0 +1,402 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# netboot - PXE-style boot for KVM on s390
|
||||||
|
#
|
||||||
|
# Sample script to build an initramfs image suitable for performing a
|
||||||
|
# PXELINUX-style boot for KVM guests from a DHCP/BOOTP Server.
|
||||||
|
# Has to be executed on the KVM host where it will be deployed and needs
|
||||||
|
# to be re-run after kernel updates on the host, unless the virtio
|
||||||
|
# drivers are statically built into the host kernel.
|
||||||
|
#
|
||||||
|
# The script requires a busybox install tree, e.g. resulting from a build
|
||||||
|
# from source, after make defconfig && make install
|
||||||
|
#
|
||||||
|
# To keep things simple, we don't include udev but use devtmpfs
|
||||||
|
# which means the host kernel must have been built with CONFIG_DEVTMPFS=y
|
||||||
|
#
|
||||||
|
# Sample invocation:
|
||||||
|
#
|
||||||
|
# ./mk-pxelinux-ramfs -b /downloads/busyboxdir pxelinux.initramfs
|
||||||
|
#
|
||||||
|
# Copyright IBM Corp. 2017
|
||||||
|
#
|
||||||
|
# s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
cmd=$(basename $0)
|
||||||
|
busyboxdir=
|
||||||
|
builddir=
|
||||||
|
initramfs=
|
||||||
|
success=no
|
||||||
|
|
||||||
|
# Cleanup on exit
|
||||||
|
cleanup()
|
||||||
|
{
|
||||||
|
if [ -n $builddir ]
|
||||||
|
then
|
||||||
|
rm -rf $builddir
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
cat <<-EOF
|
||||||
|
Usage: $cmd -b BUSYBOX_DIR [-k KERNEL_VERSION] INITRAMFS_FILE
|
||||||
|
|
||||||
|
Build a PXELINUX style boot initramfs INITRAMFS_FILE using a busybox installed
|
||||||
|
in BUSYBOX_DIR and kernel modules from the currently running kernel or from
|
||||||
|
the kernel version specified with the '-k KERNEL_VERSION' option.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-b Search installed busybox in directory BUSYBOX_DIR
|
||||||
|
-k Use KERNEL_VERSION instead of currently running kernel
|
||||||
|
-h Print this help, then exit
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get shared objects for binary
|
||||||
|
sharedobjs()
|
||||||
|
{
|
||||||
|
ldd $1 | sed -e 's?[^/]*??' -e 's/(.*)//'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check args
|
||||||
|
args=$(getopt b:k:h $*)
|
||||||
|
if [ $? = 0 ]
|
||||||
|
then
|
||||||
|
set -- $args
|
||||||
|
while [ -n $1 ]
|
||||||
|
do
|
||||||
|
case $1 in
|
||||||
|
-b) busyboxdir=$2; shift 2;;
|
||||||
|
-k) kernelversion=$2; shift 2;;
|
||||||
|
-h) usage; exit 0;;
|
||||||
|
--) shift; break;;
|
||||||
|
*) echo "$cmd: Unexpected argument $1, exiting..." >&2; exit 1;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# != 1 -o "$busyboxdir" = "" ]
|
||||||
|
then
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Full output file path
|
||||||
|
initramfs=$(readlink -m $(dirname $1))/$(basename $1)
|
||||||
|
|
||||||
|
# Exit on error
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Module locations
|
||||||
|
if [ -n $kernelversion ]; then
|
||||||
|
moddir=/lib/modules/$kernelversion
|
||||||
|
else
|
||||||
|
moddir=/lib/modules/$(uname -r)
|
||||||
|
fi
|
||||||
|
netdir=$moddir/kernel/drivers/net
|
||||||
|
blkdir=$moddir/kernel/drivers/block
|
||||||
|
|
||||||
|
# Setup build directory
|
||||||
|
builddir=$(mktemp -d)
|
||||||
|
echo "$cmd: Building in $builddir"
|
||||||
|
|
||||||
|
ramfsdirs="/bin /dev /etc /lib64 /lib /mnt /proc /run /sbin /sys /tmp /usr /var"
|
||||||
|
for d in $ramfsdirs
|
||||||
|
do
|
||||||
|
mkdir -p $builddir/$d
|
||||||
|
done
|
||||||
|
|
||||||
|
# Kexec
|
||||||
|
echo "$cmd: Copying kexec"
|
||||||
|
|
||||||
|
# Install both binary and required shared libraries
|
||||||
|
OLDPATH=$PATH
|
||||||
|
PATH=$OLDPATH:/sbin:/usr/sbin
|
||||||
|
kexec_bin=$(which kexec)
|
||||||
|
kexec_sos=$(sharedobjs $kexec_bin)
|
||||||
|
PATH=$OLDPATH
|
||||||
|
|
||||||
|
cp $kexec_bin $builddir/sbin
|
||||||
|
for so in $kexec_sos
|
||||||
|
do
|
||||||
|
mkdir -p $builddir/$(dirname $so)
|
||||||
|
cp $so $builddir/$(dirname $so)
|
||||||
|
done
|
||||||
|
|
||||||
|
# virtio module(s), if present
|
||||||
|
echo "$cmd: Copying virtio modules"
|
||||||
|
|
||||||
|
mkdir -p $builddir/$netdir
|
||||||
|
mkdir -p $builddir/$blkdir
|
||||||
|
set +e
|
||||||
|
cp $netdir/virtio_net.ko $builddir/$netdir 2> /dev/null
|
||||||
|
cp $blkdir/virtio_blk.ko $builddir/$blkdir 2> /dev/null
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Busybox (+ dependencies)
|
||||||
|
echo "$cmd: Copying busybox files"
|
||||||
|
|
||||||
|
cp -a $busyboxdir/* $builddir
|
||||||
|
busybox_sos=$(sharedobjs $busyboxdir/bin/busybox)
|
||||||
|
for so in $busybox_sos
|
||||||
|
do
|
||||||
|
mkdir -p $builddir/$(dirname $so)
|
||||||
|
cp $so $builddir/$(dirname $so)
|
||||||
|
done
|
||||||
|
|
||||||
|
# ad_packet module(s), if present
|
||||||
|
echo "$cmd: Copying af_packet modules"
|
||||||
|
|
||||||
|
packetdir=$moddir/kernel/net/packet
|
||||||
|
mkdir -p $builddir/$packetdir
|
||||||
|
set +e
|
||||||
|
cp $packetdir/* $builddir/$packetdir 2> /dev/null
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Init script
|
||||||
|
echo "$cmd: Making init script"
|
||||||
|
|
||||||
|
# --- begin init script
|
||||||
|
cat <<'EOF' > $builddir/init
|
||||||
|
#!/bin/sh
|
||||||
|
/bin/mount -t devtmpfs none /dev
|
||||||
|
/bin/mount -t proc none /proc
|
||||||
|
/bin/mount -t sysfs none /sys
|
||||||
|
/bin/mount -t tmpfs none /run
|
||||||
|
|
||||||
|
/sbin/modprobe virtio_net
|
||||||
|
/sbin/udhcpc -O pxeconffile -O pxepathprefix &
|
||||||
|
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
/sbin/pxeboot.script
|
||||||
|
/bin/sleep 1
|
||||||
|
done
|
||||||
|
EOF
|
||||||
|
# --- end init script
|
||||||
|
chmod +x $builddir/init
|
||||||
|
|
||||||
|
# udhcpc script
|
||||||
|
echo "$cmd: Making DHCP script"
|
||||||
|
|
||||||
|
mkdir -p $builddir/usr/share/udhcpc
|
||||||
|
# -- begin dhcp script
|
||||||
|
cat <<'EOF' > $builddir/usr/share/udhcpc/default.script
|
||||||
|
#!/bin/sh
|
||||||
|
# Setup name resolution and PXE boot configuration
|
||||||
|
# called by udhcpc
|
||||||
|
|
||||||
|
RESOLVCONF="/etc/resolv.conf"
|
||||||
|
PXECONF="/etc/pxe.conf"
|
||||||
|
|
||||||
|
ccidr()
|
||||||
|
{
|
||||||
|
# clumsy netmask to cidr transformation
|
||||||
|
# with minimal sanity checking
|
||||||
|
OLDIFS=$IFS
|
||||||
|
IFS=.
|
||||||
|
c=0
|
||||||
|
n=4
|
||||||
|
for i in $1
|
||||||
|
do
|
||||||
|
n=$(/usr/bin/expr $n - 1)
|
||||||
|
case $i in
|
||||||
|
255) c=$(/usr/bin/expr $c + 8);;
|
||||||
|
254) c=$(/usr/bin/expr $c + 7); break;;
|
||||||
|
252) c=$(/usr/bin/expr $c + 6); break;;
|
||||||
|
248) c=$(/usr/bin/expr $c + 5); break;;
|
||||||
|
240) c=$(/usr/bin/expr $c + 4); break;;
|
||||||
|
224) c=$(/usr/bin/expr $c + 3); break;;
|
||||||
|
192) c=$(/usr/bin/expr $c + 2); break;;
|
||||||
|
128) c=$(/usr/bin/expr $c + 1); break;;
|
||||||
|
0) break;;
|
||||||
|
*) c=0; break;;
|
||||||
|
esac
|
||||||
|
if [ $n = 0 ]
|
||||||
|
then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS=$OLDIFS
|
||||||
|
echo $c
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "DHCP response $1: "
|
||||||
|
case "$1" in
|
||||||
|
deconfig)
|
||||||
|
echo " interface: $interface"
|
||||||
|
/sbin/ip route flush table all
|
||||||
|
/sbin/ip addr flush $interface
|
||||||
|
/sbin/ip link set $interface up
|
||||||
|
/bin/rm -f $PXECONF $RESOLVCONF
|
||||||
|
;;
|
||||||
|
|
||||||
|
renew|bound)
|
||||||
|
echo " interface: $interface $ip $subnet"
|
||||||
|
echo " router: $router"
|
||||||
|
echo " domain: $domain $dns"
|
||||||
|
echo " tftp: $siaddr"
|
||||||
|
# flush routes
|
||||||
|
/sbin/ip route flush table all
|
||||||
|
# setup if link
|
||||||
|
/sbin/ip addr flush $interface
|
||||||
|
/sbin/ip link set $interface up
|
||||||
|
# setup if addr
|
||||||
|
if [ -n "$subnet" ]
|
||||||
|
then
|
||||||
|
maskedip="$ip"/$(ccidr $subnet)
|
||||||
|
else
|
||||||
|
maskedip="ip"
|
||||||
|
fi
|
||||||
|
/sbin/ip addr add $maskedip broadcast $broadcast dev $interface
|
||||||
|
# setup default routes
|
||||||
|
if [ -n "$router" ]
|
||||||
|
then
|
||||||
|
/sbin/ip route add default via $router
|
||||||
|
fi
|
||||||
|
|
||||||
|
# setup resolv.conf
|
||||||
|
if [ -n "$domain" ]
|
||||||
|
then
|
||||||
|
echo "search $domain" > $RESOLVCONF
|
||||||
|
for i in $dns
|
||||||
|
do
|
||||||
|
echo " nameserver $i" >> $RESOLVCONF
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# pxe control
|
||||||
|
if [ -n "$siaddr" ]
|
||||||
|
then
|
||||||
|
echo "siaddr=$siaddr" > $PXECONF
|
||||||
|
echo "interface=$interface" >> $PXECONF
|
||||||
|
echo "ip=$ip" >> $PXECONF
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
nak)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
EOF
|
||||||
|
# -- end dhcp script
|
||||||
|
chmod +x $builddir/usr/share/udhcpc/default.script
|
||||||
|
|
||||||
|
# pxeboot script
|
||||||
|
echo "$cmd: Making PXE boot script"
|
||||||
|
|
||||||
|
# -- begin pxeboot script
|
||||||
|
cat <<'EOF' > $builddir/sbin/pxeboot.script
|
||||||
|
#!/bin/sh
|
||||||
|
# Perform a PXE style boot using kexec
|
||||||
|
# Supports only super-simple config files
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Source the DHCP-generated TFTP info
|
||||||
|
# Currently we are just looking for siaddr
|
||||||
|
PXE_CONF=/etc/pxe.conf
|
||||||
|
if [ -f $PXE_CONF ]
|
||||||
|
then
|
||||||
|
. $PXE_CONF
|
||||||
|
else
|
||||||
|
echo waiting for PXE configuration
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Retrieve the config (default only for now)
|
||||||
|
CONFIGS=""
|
||||||
|
if [ -n "$siaddr" ];
|
||||||
|
then
|
||||||
|
# Enable UUID based config on s390
|
||||||
|
if [ $(/bin/uname -m) = "s390x" ]
|
||||||
|
then
|
||||||
|
set +e
|
||||||
|
uuid=$(/bin/grep UUID /proc/sysinfo | tail -1 | tr -d ' ' | cut -d ':' -f 2) 2> /dev/null
|
||||||
|
set -e
|
||||||
|
else
|
||||||
|
# not caring for other arches right now
|
||||||
|
uuid=""
|
||||||
|
fi
|
||||||
|
CONFIGS="$CONFIGS $uuid"
|
||||||
|
|
||||||
|
# Enable MAC based config
|
||||||
|
ifaddr=$(/bin/cat /sys/class/net/$interface/address | tr ':' '-')
|
||||||
|
CONFIGS="$CONFIGS 01-$ifaddr"
|
||||||
|
|
||||||
|
# Enable IP based config
|
||||||
|
iphex=$(printf %02X $(echo $ip | tr '.' ' '))
|
||||||
|
for i in 8 7 6 5 4 3 2 1
|
||||||
|
do
|
||||||
|
CONFIGS="$CONFIGS $(echo $iphex | cut -c 1-$i)"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Finally enable default config
|
||||||
|
CONFIGS="$CONFIGS default"
|
||||||
|
|
||||||
|
set +e
|
||||||
|
for c in $CONFIGS
|
||||||
|
do
|
||||||
|
if /usr/bin/tftp -g -l /tmp/config -r pxelinux.cfg/$c $siaddr
|
||||||
|
then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f /tmp/config ]
|
||||||
|
then
|
||||||
|
echo no config found
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Simple config file parsing, only one entry allowed
|
||||||
|
kernel=$(/bin/grep "^[[:space:]]*kernel" /tmp/config | sed "s/^[[:space:]]*kernel[[:space:]]*//")
|
||||||
|
initrd=$(/bin/grep "^[[:space:]]*initrd" /tmp/config | sed "s/^[[:space:]]*initrd[[:space:]]*//")
|
||||||
|
append=$(/bin/grep "^[[:space:]]*append" /tmp/config | sed "s/^[[:space:]]*append[[:space:]]*//")
|
||||||
|
|
||||||
|
if [ -z "$kernel" ]
|
||||||
|
then
|
||||||
|
echo no kernel statement found in config
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
/usr/bin/tftp -g -l /tmp/kernel -r $kernel $siaddr
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$initrd" ]
|
||||||
|
then
|
||||||
|
/usr/bin/tftp -g -l /tmp/initrd -r $initrd $siaddr
|
||||||
|
INITRD="--initrd=/tmp/initrd"
|
||||||
|
else
|
||||||
|
INITRD=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$append" ]
|
||||||
|
then
|
||||||
|
APPEND="--append=$append"
|
||||||
|
else
|
||||||
|
APPEND=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
kexec -l /tmp/kernel $INITRD $APPEND
|
||||||
|
kexec -e
|
||||||
|
EOF
|
||||||
|
# -- end pxeboot script
|
||||||
|
chmod +x $builddir/sbin/pxeboot.script
|
||||||
|
|
||||||
|
# The final initramfs
|
||||||
|
echo Building initramfs
|
||||||
|
|
||||||
|
cd $builddir
|
||||||
|
find . | cpio -o -Hnewc | gzip - > $initramfs
|
||||||
|
cd $OLDPWD
|
||||||
171
netboot/mk-s390image
Executable file
171
netboot/mk-s390image
Executable file
@@ -0,0 +1,171 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# netboot - PXE-style boot for KVM on s390
|
||||||
|
#
|
||||||
|
# Sample script to build a single s390 boot image consisting of
|
||||||
|
# kernel, an initial ramdisk and kernel parameters from
|
||||||
|
# individual components. Note that bash is required to run this script!
|
||||||
|
#
|
||||||
|
# Sample invocation:
|
||||||
|
#
|
||||||
|
# ./mk-s390image /boot/image -r /boot/initrd image
|
||||||
|
#
|
||||||
|
# The resulting image can be used to build a bootable
|
||||||
|
# ISO or as firmware image for KVM.
|
||||||
|
#
|
||||||
|
# Copyright IBM Corp. 2017
|
||||||
|
#
|
||||||
|
# s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
|
||||||
|
# Offsets
|
||||||
|
OFFS_INITRD_START_BYTES=66568
|
||||||
|
OFFS_INITRD_SIZE_BYTES=66576
|
||||||
|
OFFS_COMMANDLINE_BYTES=66688
|
||||||
|
MAX_PARMFILE_SIZE=896
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
cmd=$(basename $0)
|
||||||
|
kernel=
|
||||||
|
ramdisk=
|
||||||
|
parmfile=
|
||||||
|
image=
|
||||||
|
binval=
|
||||||
|
success=no
|
||||||
|
|
||||||
|
# Cleanup on exit
|
||||||
|
cleanup()
|
||||||
|
{
|
||||||
|
if [ -n "$binval" ]
|
||||||
|
then
|
||||||
|
rm -f $binval
|
||||||
|
fi
|
||||||
|
if [ -n "$image" -a $success = no ]
|
||||||
|
then
|
||||||
|
rm $image
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
cat <<-EOF
|
||||||
|
Usage: $cmd KERNEL BOOT_IMAGE [-r RAMDISK] [-p PARMFILE]
|
||||||
|
|
||||||
|
Build an s390 image BOOT_IMAGE suitable for CD/tape/network boot or as a
|
||||||
|
KVM firmware image using a stripped Linux kernel file KERNEL.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-p Use PARMFILE with kernel parameters in the image
|
||||||
|
-r Include RAMDISK in the image
|
||||||
|
-h Print this help, then exit
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Convert decimal number to big endian doubleword
|
||||||
|
dec2be64()
|
||||||
|
{
|
||||||
|
local num=$1
|
||||||
|
local b
|
||||||
|
local i
|
||||||
|
for i in $(seq 1 8)
|
||||||
|
do
|
||||||
|
b="\\x$(printf '%x' $(expr $num % 256))$b"
|
||||||
|
num=$(expr $num / 256) || true
|
||||||
|
done
|
||||||
|
printf $b
|
||||||
|
}
|
||||||
|
|
||||||
|
# Do the image build
|
||||||
|
dobuild()
|
||||||
|
{
|
||||||
|
local i
|
||||||
|
local kernel_size
|
||||||
|
local ramdisk_size
|
||||||
|
local ramdisk_offset
|
||||||
|
local parmfile_size
|
||||||
|
# check whether all specified files exist
|
||||||
|
for i in $kernel $ramdisk $parmfile
|
||||||
|
do
|
||||||
|
if [ ! -f $i ]
|
||||||
|
then
|
||||||
|
echo "$cmd: File $i not found" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if ! file -b $(readlink -f $kernel) | grep "Linux S390" > /dev/null
|
||||||
|
then
|
||||||
|
echo "$cmd: Unrecognized file format for $kernel" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# from now on we SHOULD only fail on disk shortage
|
||||||
|
# or file permissions, let the shell handle that
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# copy over kernel padded with zeroes to page boundary
|
||||||
|
dd if=$kernel of=$image bs=4096 conv=sync status=none
|
||||||
|
|
||||||
|
# append ramdisk if specified
|
||||||
|
if [ "$ramdisk" != "" ]
|
||||||
|
then
|
||||||
|
ramdisk_size=$(du -b $ramdisk | cut -f1)
|
||||||
|
kernel_size=$(du -b $kernel | cut -f1)
|
||||||
|
ramdisk_offset=$(du -b $image | cut -f1)
|
||||||
|
cat $ramdisk >> $image
|
||||||
|
binval=$(mktemp)
|
||||||
|
dec2be64 $ramdisk_offset > $binval
|
||||||
|
dd seek=$OFFS_INITRD_START_BYTES if=$binval of=$image bs=1 \
|
||||||
|
count=8 conv=notrunc status=none
|
||||||
|
dec2be64 $ramdisk_size > $binval
|
||||||
|
dd seek=$OFFS_INITRD_SIZE_BYTES if=$binval of=$image bs=1 \
|
||||||
|
count=8 conv=notrunc status=none
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set cmdline
|
||||||
|
if [ "$parmfile" != "" ]
|
||||||
|
then
|
||||||
|
parmfile_size=$(du -b $parmfile | cut -f1)
|
||||||
|
if [ $parmfile_size -le $MAX_PARMFILE_SIZE ]
|
||||||
|
then
|
||||||
|
dd seek=$OFFS_COMMANDLINE_BYTES bs=1 if=$parmfile \
|
||||||
|
of=$image conv=notrunc status=none
|
||||||
|
else
|
||||||
|
echo "$cmd: Size $parmfile_size of $parmfile exceeds command line limit of $MAX_PARMFILE_SIZE" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# we've done it
|
||||||
|
success=yes
|
||||||
|
}
|
||||||
|
|
||||||
|
# check args and build
|
||||||
|
args=$(getopt "r:p:h" $*)
|
||||||
|
if [ $? = 0 ]
|
||||||
|
then
|
||||||
|
set -- $args
|
||||||
|
while [ $1 != "" ]
|
||||||
|
do
|
||||||
|
case $1 in
|
||||||
|
-r) ramdisk=$2; shift 2;;
|
||||||
|
-p) parmfile=$2; shift 2;;
|
||||||
|
-h) usage; exit 0;;
|
||||||
|
--) shift; break;;
|
||||||
|
*) echo "$cmd: Unexpected argument $1, exiting..." >&2; exit 1;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# = 2 ]
|
||||||
|
then
|
||||||
|
kernel=$1
|
||||||
|
image=$2
|
||||||
|
dobuild
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# something wasn't right
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
@@ -16,6 +16,11 @@ install:
|
|||||||
chmod 755 $(DESTDIR)$(BINDIR)/$$i; \
|
chmod 755 $(DESTDIR)$(BINDIR)/$$i; \
|
||||||
done
|
done
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
@for i in $(MAN_PAGES); \
|
@for i in $(MAN_PAGES); \
|
||||||
do \
|
do \
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 $$i \
|
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 $$i \
|
||||||
|
|||||||
275
scripts/cpictl
Executable file
275
scripts/cpictl
Executable file
@@ -0,0 +1,275 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# cpictl - Configure the Control-Program-Information (CPI) settings
|
||||||
|
#
|
||||||
|
# This is an internal helper script that is used by the "cpi.service"
|
||||||
|
# systemd unit and the "90-cpi.rules" udev rule.
|
||||||
|
#
|
||||||
|
# The bash shell is really needed. Other shells have different ideas of how
|
||||||
|
# bitwise operators work.
|
||||||
|
#
|
||||||
|
# Copyright 2017 IBM Corp.
|
||||||
|
#
|
||||||
|
# s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
#
|
||||||
|
|
||||||
|
readonly CPI_LOCK="/var/lock/cpictl.lock"
|
||||||
|
|
||||||
|
readonly PRG="${0##*/}"
|
||||||
|
|
||||||
|
readonly SYSTEM_LEVEL_PATH="/sys/firmware/cpi/system_level"
|
||||||
|
readonly SYSTEM_TYPE_PATH="/sys/firmware/cpi/system_type"
|
||||||
|
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"
|
||||||
|
|
||||||
|
declare LEVEL
|
||||||
|
declare TYPE
|
||||||
|
declare NAME
|
||||||
|
declare SYSPLEX
|
||||||
|
|
||||||
|
declare -i DRYRUN=0
|
||||||
|
|
||||||
|
# Exit codes
|
||||||
|
readonly EXIT_SUCCESS=0
|
||||||
|
readonly EXIT_FAILURE=1
|
||||||
|
readonly EXIT_ARG_TOO_LONG=3
|
||||||
|
readonly EXIT_INVALID_CHARS=4
|
||||||
|
|
||||||
|
print_help_and_exit()
|
||||||
|
{
|
||||||
|
cat <<EndHelp
|
||||||
|
Usage: $PRG [OPTIONS]
|
||||||
|
|
||||||
|
Configure the Control-Program-Information (CPI) settings.
|
||||||
|
|
||||||
|
-b, --set-bit BIT Set and commit the bit BIT in the flags
|
||||||
|
-e, --environment Set and commit the system type, level, name and
|
||||||
|
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)
|
||||||
|
-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
|
||||||
|
-v, --version Print version information, then exit
|
||||||
|
--commit Ignore all other options and commit any uncommitted
|
||||||
|
values
|
||||||
|
--dry-run Do not actually set or commit anything, but show what
|
||||||
|
would be done
|
||||||
|
--show Ignore all other options and show current (possibly
|
||||||
|
uncommitted) values
|
||||||
|
|
||||||
|
Environment variables used for the --defaults option:
|
||||||
|
CPI_SYSTEM_TYPE, CPI_SYSTEM_LEVEL, CPI_SYSTEM_NAME, CPI_SYSPLEX_NAME
|
||||||
|
|
||||||
|
Available bits for the --set-bit option:
|
||||||
|
kvm: Indicate that system is a KVM host
|
||||||
|
|
||||||
|
The maximum length for system type, system name, and sysplex name is 8
|
||||||
|
characters. The allowed characters are: [A-Z0-9 @#$]
|
||||||
|
|
||||||
|
This tool should be called as root.
|
||||||
|
EndHelp
|
||||||
|
exit $EXIT_SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
print_version_and_exit()
|
||||||
|
{
|
||||||
|
cat <<EndVersion
|
||||||
|
$PRG: Configure the CPI settings version %S390_TOOLS_VERSION%
|
||||||
|
Copyright IBM Corp. 2017
|
||||||
|
EndVersion
|
||||||
|
exit $EXIT_SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
cpi_show()
|
||||||
|
{
|
||||||
|
cat <<-EndShow
|
||||||
|
System type: $(cat "$SYSTEM_TYPE_PATH")
|
||||||
|
System level: $(cat "$SYSTEM_LEVEL_PATH")
|
||||||
|
System name: $(cat "$SYSTEM_NAME_PATH")
|
||||||
|
Sysplex name: $(cat "$SYSPLEX_NAME_PATH")
|
||||||
|
EndShow
|
||||||
|
}
|
||||||
|
|
||||||
|
print_parse_error_and_exit()
|
||||||
|
{
|
||||||
|
echo "Try '$PRG --help' for more information." >&2
|
||||||
|
exit $EXIT_FAILURE
|
||||||
|
}
|
||||||
|
|
||||||
|
fail_with()
|
||||||
|
{
|
||||||
|
echo "$1" >&2
|
||||||
|
echo "Try '$PRG --help' for more information." >&2
|
||||||
|
exit ${2:-$EXIT_FAILURE}
|
||||||
|
}
|
||||||
|
|
||||||
|
cpi_commit()
|
||||||
|
{
|
||||||
|
echo 1 > "$CPI_SET"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_length_check()
|
||||||
|
{
|
||||||
|
[ ${#1} -gt 8 ] &&
|
||||||
|
fail_with "$PRG: Specified $2 too long. The maximum length is 8 characters." $EXIT_ARG_TOO_LONG
|
||||||
|
}
|
||||||
|
|
||||||
|
do_character_check()
|
||||||
|
{
|
||||||
|
echo "$1" | grep -q -E '^[a-zA-Z0-9@#$ ]*$' ||
|
||||||
|
fail_with "$PRG: Invalid characters in $2. Valid characters are: A-Z0-9 @#$" $EXIT_INVALID_CHARS
|
||||||
|
}
|
||||||
|
|
||||||
|
cpi_set_bit()
|
||||||
|
{
|
||||||
|
LEVEL=$(printf '0x%x' $((LEVEL | (1 << (63 - $1)) )) )
|
||||||
|
}
|
||||||
|
|
||||||
|
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)))
|
||||||
|
}
|
||||||
|
|
||||||
|
cpi_set_type()
|
||||||
|
{
|
||||||
|
TYPE="$1"
|
||||||
|
do_length_check "$TYPE" "system type"
|
||||||
|
do_character_check "$TYPE" "system type"
|
||||||
|
}
|
||||||
|
|
||||||
|
cpi_set_sysplex()
|
||||||
|
{
|
||||||
|
SYSPLEX="$1"
|
||||||
|
do_length_check "$SYSPLEX" "sysplex name"
|
||||||
|
do_character_check "$SYSPLEX" "sysplex name"
|
||||||
|
}
|
||||||
|
|
||||||
|
cpi_set_name()
|
||||||
|
{
|
||||||
|
NAME="$1"
|
||||||
|
do_length_check "$NAME" "system name"
|
||||||
|
do_character_check "$NAME" "system name"
|
||||||
|
}
|
||||||
|
|
||||||
|
# cpictl starts here
|
||||||
|
|
||||||
|
if [ $# -le 0 ]; then
|
||||||
|
echo "$PRG: No parameters specified"
|
||||||
|
print_parse_error_and_exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
opts=$(getopt -o b:ehL:N:S:T:v -l set-bit:,environment,help,level:,name:,sysplex:,type:,commit,dry-run,show,version -n $PRG -- "$@")
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
print_parse_error_and_exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This guarantees that only one instance will be running, and will serialize
|
||||||
|
# the execution of multiple instances
|
||||||
|
[ -e "$CPI_LOCK" -a ! -w "$CPI_LOCK" ] &&
|
||||||
|
fail_with "$PRG: Cannot access lock file: $CPI_LOCK"
|
||||||
|
[ ! -w "${CPI_LOCK%/*}" ] &&
|
||||||
|
fail_with "$PRG: Cannot access lock file: $CPI_LOCK"
|
||||||
|
|
||||||
|
exec 9<> "$CPI_LOCK"
|
||||||
|
flock -x 9
|
||||||
|
|
||||||
|
# Get current values from sys/firmware
|
||||||
|
read LEVEL < "$SYSTEM_LEVEL_PATH"
|
||||||
|
read TYPE < "$SYSTEM_TYPE_PATH"
|
||||||
|
read NAME < "$SYSTEM_NAME_PATH"
|
||||||
|
read SYSPLEX < "$SYSPLEX_NAME_PATH"
|
||||||
|
|
||||||
|
# Parse command line options: Use eval to remove getopt quotes
|
||||||
|
eval set -- $opts
|
||||||
|
while [ -n $1 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--help|-h)
|
||||||
|
print_help_and_exit
|
||||||
|
;;
|
||||||
|
--version|-v)
|
||||||
|
print_version_and_exit
|
||||||
|
;;
|
||||||
|
-b|--set-bit)
|
||||||
|
case "$2" in
|
||||||
|
kvm)
|
||||||
|
cpi_set_bit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
fail_with "$PRG: Unknown bit \"$2\" for the $1 option"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-L|--level)
|
||||||
|
cpi_set_oslevel "$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-e|--environment)
|
||||||
|
cpi_set_type "$CPI_SYSTEM_TYPE"
|
||||||
|
cpi_set_name "$CPI_SYSTEM_NAME"
|
||||||
|
cpi_set_oslevel "$CPI_SYSTEM_LEVEL"
|
||||||
|
cpi_set_sysplex "$CPI_SYSPLEX_NAME"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-T|--type)
|
||||||
|
cpi_set_type "$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-S|--sysplex)
|
||||||
|
cpi_set_sysplex "$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-N|--name)
|
||||||
|
cpi_set_name "$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--show)
|
||||||
|
cpi_show
|
||||||
|
exit $EXIT_SUCCESS
|
||||||
|
;;
|
||||||
|
--commit)
|
||||||
|
cpi_commit
|
||||||
|
exit $EXIT_SUCCESS
|
||||||
|
;;
|
||||||
|
--dry-run)
|
||||||
|
DRYRUN=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break;
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Print settings for --dry-run or commit them to sysfs otherwise
|
||||||
|
|
||||||
|
if [ $DRYRUN -eq 1 ]; then
|
||||||
|
cat <<-EndDryrun
|
||||||
|
System type: $TYPE
|
||||||
|
System level: $LEVEL
|
||||||
|
System name: $NAME
|
||||||
|
Sysplex name: $SYSPLEX
|
||||||
|
EndDryrun
|
||||||
|
else
|
||||||
|
echo "$LEVEL" > "$SYSTEM_LEVEL_PATH"
|
||||||
|
echo "$TYPE" > "$SYSTEM_TYPE_PATH"
|
||||||
|
echo "$NAME" > "$SYSTEM_NAME_PATH"
|
||||||
|
echo "$SYSPLEX" > "$SYSPLEX_NAME_PATH"
|
||||||
|
cpi_commit
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit $EXIT_SUCCESS
|
||||||
@@ -35,12 +35,6 @@ EnvironmentFile=/etc/sysconfig/cpi
|
|||||||
# Environment=CPI_SYSTEM_LEVEL=
|
# Environment=CPI_SYSTEM_LEVEL=
|
||||||
# Environment=CPI_SYSTEM_TYPE=LINUX
|
# Environment=CPI_SYSTEM_TYPE=LINUX
|
||||||
|
|
||||||
#
|
|
||||||
# Apply settings
|
|
||||||
ExecStartPre=/bin/sh -c 'if test -n "$CPI_SYSTEM_TYPE"; then echo $CPI_SYSTEM_TYPE |tr a-z A-Z > /sys/firmware/cpi/system_type; fi'
|
|
||||||
ExecStartPre=/bin/sh -c 'if test -n "$CPI_SYSTEM_NAME"; then echo $CPI_SYSTEM_NAME |tr a-z A-Z > /sys/firmware/cpi/system_name; fi'
|
|
||||||
ExecStartPre=/bin/sh -c 'if test -n "$CPI_SYSPLEX_NAME"; then echo $CPI_SYSPLEX_NAME |tr a-z A-Z > /sys/firmware/cpi/sysplex_name; fi'
|
|
||||||
ExecStartPre=/bin/sh -c 'test -n "$CPI_SYSTEM_LEVEL" || CPI_SYSTEM_LEVEL="$(uname -r)" ; echo $CPI_SYSTEM_LEVEL |cut -d- -f1 | tr . " " |xargs printf "0x0000000000%02x%02x%02x\n" > /sys/firmware/cpi/system_level'
|
|
||||||
#
|
#
|
||||||
# Sending data to the HMC/SE
|
# Sending data to the HMC/SE
|
||||||
ExecStart=/bin/sh -c 'echo 1 > /sys/firmware/cpi/set'
|
ExecStart=@toolslib_path@/cpictl -e
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=TTYRun on %I
|
Description=TTYRun on %I
|
||||||
Documentation=man:ttyrun(8) man:agetty(8)
|
Documentation=man:ttyrun(8) man:agetty(8)
|
||||||
BindTo=dev-%i.device
|
BindsTo=dev-%i.device
|
||||||
After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service
|
After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service
|
||||||
After=rc-local.service
|
After=rc-local.service
|
||||||
Before=getty.target
|
Before=getty.target
|
||||||
|
|||||||
@@ -41,8 +41,7 @@
|
|||||||
#define UUID_FORMAT "^[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}$"
|
#define UUID_FORMAT "^[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}$"
|
||||||
|
|
||||||
/* Misc constants */
|
/* Misc constants */
|
||||||
#define MAX_BUFFER_SIZE_FOR_SUBCHANNEL_ATTRIBUTES 37
|
#define MAX_BUF_SIZE 256
|
||||||
#define MAX_BUFFER_SIZE_FOR_DEVICE_ATTRIBUTES 16
|
|
||||||
#define PREFIX_ID_LENGTH 4
|
#define PREFIX_ID_LENGTH 4
|
||||||
#define SHORT_ID_LENGTH 4
|
#define SHORT_ID_LENGTH 4
|
||||||
#define CHPIDS_SEGMENT_LENGTH 8
|
#define CHPIDS_SEGMENT_LENGTH 8
|
||||||
@@ -310,8 +309,8 @@ static bool in_devtypes_list(char *dtype)
|
|||||||
*/
|
*/
|
||||||
static int fill_device_info(struct util_rec *rec, char *path, char *device)
|
static int fill_device_info(struct util_rec *rec, char *path, char *device)
|
||||||
{
|
{
|
||||||
char buf[MAX_BUFFER_SIZE_FOR_DEVICE_ATTRIBUTES];
|
|
||||||
unsigned long int val_ul;
|
unsigned long int val_ul;
|
||||||
|
char buf[MAX_BUF_SIZE];
|
||||||
|
|
||||||
if (!path || !device) {
|
if (!path || !device) {
|
||||||
if (cmd.opt_devtype && cmd.dev_count > 0)
|
if (cmd.opt_devtype && cmd.dev_count > 0)
|
||||||
@@ -403,7 +402,7 @@ static bool is_sch_vfio(char *path)
|
|||||||
*/
|
*/
|
||||||
static int fill_vfio_devid(struct util_rec *rec, char *path)
|
static int fill_vfio_devid(struct util_rec *rec, char *path)
|
||||||
{
|
{
|
||||||
char *device, buf[MAX_BUFFER_SIZE_FOR_SUBCHANNEL_ATTRIBUTES];
|
char *device, buf[MAX_BUF_SIZE];
|
||||||
struct dirent **de_vec;
|
struct dirent **de_vec;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
@@ -433,7 +432,7 @@ static int fill_vfio_devid(struct util_rec *rec, char *path)
|
|||||||
*/
|
*/
|
||||||
static int fill_io_devid(struct util_rec *rec, char *path)
|
static int fill_io_devid(struct util_rec *rec, char *path)
|
||||||
{
|
{
|
||||||
char *device, buf[MAX_BUFFER_SIZE_FOR_SUBCHANNEL_ATTRIBUTES];
|
char *device, buf[MAX_BUF_SIZE];
|
||||||
struct dirent **de_vec;
|
struct dirent **de_vec;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
@@ -479,8 +478,8 @@ static int fill_io_devid(struct util_rec *rec, char *path)
|
|||||||
*/
|
*/
|
||||||
static void print_sch_io(struct util_rec *rec, char *path, char *sch_dir)
|
static void print_sch_io(struct util_rec *rec, char *path, char *sch_dir)
|
||||||
{
|
{
|
||||||
char buf[MAX_BUFFER_SIZE_FOR_SUBCHANNEL_ATTRIBUTES];
|
|
||||||
unsigned int pim, pam, pom;
|
unsigned int pim, pam, pom;
|
||||||
|
char buf[MAX_BUF_SIZE];
|
||||||
|
|
||||||
/* Fill in subchannel ID */
|
/* Fill in subchannel ID */
|
||||||
if (cmd.opt_short) {
|
if (cmd.opt_short) {
|
||||||
@@ -560,7 +559,7 @@ static void print_sch_io(struct util_rec *rec, char *path, char *sch_dir)
|
|||||||
*/
|
*/
|
||||||
static void print_sch_chsc(struct util_rec *rec, char *sch_dir)
|
static void print_sch_chsc(struct util_rec *rec, char *sch_dir)
|
||||||
{
|
{
|
||||||
char buf[MAX_BUFFER_SIZE_FOR_DEVICE_ATTRIBUTES];
|
char buf[MAX_BUF_SIZE];
|
||||||
|
|
||||||
/* Skip entry if devrange or devtype option is active */
|
/* Skip entry if devrange or devtype option is active */
|
||||||
if (cmd.opt_devrange && cmd.rng_count > 0)
|
if (cmd.opt_devrange && cmd.rng_count > 0)
|
||||||
@@ -596,7 +595,7 @@ static void print_sch_chsc(struct util_rec *rec, char *sch_dir)
|
|||||||
*/
|
*/
|
||||||
static void print_sch_eadm(struct util_rec *rec, char *sch_dir)
|
static void print_sch_eadm(struct util_rec *rec, char *sch_dir)
|
||||||
{
|
{
|
||||||
char buf[MAX_BUFFER_SIZE_FOR_DEVICE_ATTRIBUTES];
|
char buf[MAX_BUF_SIZE];
|
||||||
|
|
||||||
/* Skip entry if devrange or devtype option is active */
|
/* Skip entry if devrange or devtype option is active */
|
||||||
if (cmd.opt_devrange && cmd.rng_count > 0)
|
if (cmd.opt_devrange && cmd.rng_count > 0)
|
||||||
@@ -632,7 +631,7 @@ static void print_sch_eadm(struct util_rec *rec, char *sch_dir)
|
|||||||
*/
|
*/
|
||||||
static void print_defunct_devices(struct util_rec *rec, char *path)
|
static void print_defunct_devices(struct util_rec *rec, char *path)
|
||||||
{
|
{
|
||||||
char *device, buf[MAX_BUFFER_SIZE_FOR_DEVICE_ATTRIBUTES];
|
char *device, buf[MAX_BUF_SIZE];
|
||||||
struct dirent **de_vec;
|
struct dirent **de_vec;
|
||||||
int i, count;
|
int i, count;
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ function debug() {
|
|||||||
function search_cu_tcpip() {
|
function search_cu_tcpip() {
|
||||||
local scu=$1
|
local scu=$1
|
||||||
local i
|
local i
|
||||||
|
for ((i=0; i < ${#CU_TCPIP[@]}; i++)); do
|
||||||
if [ "$scu" == "${CU_TCPIP[i]}" ]; then
|
if [ "$scu" == "${CU_TCPIP[i]}" ]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -547,6 +547,22 @@ static void setup_rec_long(struct util_rec *rec)
|
|||||||
util_rec_def(rec, "ipa", UTIL_REC_ALIGN_LEFT, 0, "ipa");
|
util_rec_def(rec, "ipa", UTIL_REC_ALIGN_LEFT, 0, "ipa");
|
||||||
util_rec_def(rec, "vipa", UTIL_REC_ALIGN_LEFT, 0, "vipa");
|
util_rec_def(rec, "vipa", UTIL_REC_ALIGN_LEFT, 0, "vipa");
|
||||||
util_rec_def(rec, "parp", UTIL_REC_ALIGN_LEFT, 0, "parp");
|
util_rec_def(rec, "parp", UTIL_REC_ALIGN_LEFT, 0, "parp");
|
||||||
|
util_rec_def(rec, "vnicc/bridge_invisible", UTIL_REC_ALIGN_LEFT, 0,
|
||||||
|
"vnicc/bridge_invisible");
|
||||||
|
util_rec_def(rec, "vnicc/flooding", UTIL_REC_ALIGN_LEFT, 0,
|
||||||
|
"vnicc/flooding");
|
||||||
|
util_rec_def(rec, "vnicc/learning", UTIL_REC_ALIGN_LEFT, 0,
|
||||||
|
"vnicc/learning");
|
||||||
|
util_rec_def(rec, "vnicc/learning_timeout", UTIL_REC_ALIGN_LEFT, 0,
|
||||||
|
"vnicc/learning_timeout");
|
||||||
|
util_rec_def(rec, "vnicc/mcast_flooding", UTIL_REC_ALIGN_LEFT, 0,
|
||||||
|
"vnicc/mcast_flooding");
|
||||||
|
util_rec_def(rec, "vnicc/rx_bcast", UTIL_REC_ALIGN_LEFT, 0,
|
||||||
|
"vnicc/rx_bcast");
|
||||||
|
util_rec_def(rec, "vnicc/takeover_learning", UTIL_REC_ALIGN_LEFT, 0,
|
||||||
|
"vnicc/takeover_learning");
|
||||||
|
util_rec_def(rec, "vnicc/takeover_setvmac", UTIL_REC_ALIGN_LEFT, 0,
|
||||||
|
"vnicc/takeover_setvmac");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -560,7 +576,7 @@ static struct util_rec *setup_rec()
|
|||||||
rec = util_rec_new_wide("-");
|
rec = util_rec_new_wide("-");
|
||||||
setup_rec_wide(rec);
|
setup_rec_wide(rec);
|
||||||
} else {
|
} else {
|
||||||
rec = util_rec_new_long("-", ":", "if_name", 30, 42);
|
rec = util_rec_new_long("-", ":", "if_name", 32, 40);
|
||||||
setup_rec_long(rec);
|
setup_rec_long(rec);
|
||||||
}
|
}
|
||||||
return rec;
|
return rec;
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
const char *online, *online_text = NULL, *poll_thread, *config_time;
|
const char *online, *online_text = NULL, *poll_thread, *config_time;
|
||||||
const char *poll_timeout, *default_domain;
|
const char *poll_timeout, *default_domain;
|
||||||
char *path, *dev_path, *dev, *dev_list, device[256], online_read[2];
|
char *path, *dev_path, *dev, *dev_list, device[256], online_read[32];
|
||||||
bool all = false, actionset = false;
|
bool all = false, actionset = false;
|
||||||
size_t len;
|
size_t len;
|
||||||
int id, dom, c, i, j;
|
int id, dom, c, i, j;
|
||||||
@@ -406,12 +406,14 @@ int main(int argc, char *argv[])
|
|||||||
if (!util_path_is_dir(dev_path))
|
if (!util_path_is_dir(dev_path))
|
||||||
errx(EXIT_FAILURE, "Error - cryptographic device %s does not exist.", device);
|
errx(EXIT_FAILURE, "Error - cryptographic device %s does not exist.", device);
|
||||||
if (!util_path_is_writable("%s/online", dev_path))
|
if (!util_path_is_writable("%s/online", dev_path))
|
||||||
continue;
|
errx(EXIT_FAILURE, "Error - can't write to %s/online.\n Wrong permissions"
|
||||||
|
" or wrong tools version.", dev_path);
|
||||||
verbose("Setting cryptographic device %s %s\n", device, online_text);
|
verbose("Setting cryptographic device %s %s\n", device, online_text);
|
||||||
util_file_write_s(online, "%s/online", dev_path);
|
util_file_write_s(online, "%s/online", dev_path);
|
||||||
util_file_read_line(online_read, sizeof(online_read), "%s/online", dev_path);
|
util_file_read_line(online_read, sizeof(online_read), "%s/online", dev_path);
|
||||||
if (strcmp(online, online_read) != 0)
|
if (strcmp(online, online_read) != 0)
|
||||||
errx(EXIT_FAILURE, "Error - unable to set cryptographic device %s %s.", device, online_text);
|
errx(EXIT_FAILURE, "Error - unable to set cryptographic device %s %s.",
|
||||||
|
device, online_text);
|
||||||
free(dev_path);
|
free(dev_path);
|
||||||
}
|
}
|
||||||
free(dev_list);
|
free(dev_list);
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ lszcrypt \- display zcrypt device and configuration information
|
|||||||
.B lszcrypt
|
.B lszcrypt
|
||||||
.RB "[ " -V " ] "
|
.RB "[ " -V " ] "
|
||||||
[
|
[
|
||||||
.I <device id>
|
.I <device-id>
|
||||||
[...]]
|
[...]]
|
||||||
.TP
|
.TP
|
||||||
.B lszcrypt
|
.B lszcrypt
|
||||||
.B -c
|
.B -c
|
||||||
<device id>
|
<card-id>
|
||||||
.TP
|
.TP
|
||||||
.B lszcrypt -b
|
.B lszcrypt -b
|
||||||
.TP
|
.TP
|
||||||
@@ -57,18 +57,17 @@ With this verbose level additional information like hardware card type,
|
|||||||
hardware queue depth, pending request queue count, outstanding
|
hardware queue depth, pending request queue count, outstanding
|
||||||
request queue count, and installed function facilities are displayed.
|
request queue count, and installed function facilities are displayed.
|
||||||
.TP 8
|
.TP 8
|
||||||
.B <device id>
|
.B <device-id>
|
||||||
Specifies a cryptographic device to display. A cryptographic device can be
|
Specifies a cryptographic device to display. A cryptographic device can be
|
||||||
either a card device or a queue device. If no devices are specified information
|
either a card device or a queue device. If no devices are specified information
|
||||||
about all available devices is displayed.
|
about all available devices is displayed.
|
||||||
|
Please note that the card device representation and the queue device
|
||||||
Please note that the card device representation and the queue device are both
|
are both in hexadecimal notation.
|
||||||
in hexadecimal notation.
|
|
||||||
.TP 8
|
.TP 8
|
||||||
.B -b, --bus
|
.B -b, --bus
|
||||||
Displays the AP bus attributes and exits.
|
Displays the AP bus attributes and exits.
|
||||||
.TP 8
|
.TP 8
|
||||||
.B -c, --capability <card device id>
|
.B -c, --capability <card-id>
|
||||||
Shows the capabilities of a cryptographic card device of hardware type 6 or
|
Shows the capabilities of a cryptographic card device of hardware type 6 or
|
||||||
higher. The card device id value may be given as decimal or hex value (with
|
higher. The card device id value may be given as decimal or hex value (with
|
||||||
a leading 0x). The capabilities of a cryptographic card device depend on
|
a leading 0x). The capabilities of a cryptographic card device depend on
|
||||||
@@ -92,12 +91,12 @@ Shows the usage and control domains of the cryptographic devices.
|
|||||||
The displayed domains of the cryptographic device depends on the initial
|
The displayed domains of the cryptographic device depends on the initial
|
||||||
cryptographic configuration.
|
cryptographic configuration.
|
||||||
.RS
|
.RS
|
||||||
.IP "o" 2
|
.IP "o" 3
|
||||||
'C' indicate a control domain
|
C - indicate a control domain
|
||||||
.IP "o"
|
.IP "o"
|
||||||
'U' indicate a usage domain
|
U - indicate a usage domain
|
||||||
.IP "o"
|
.IP "o"
|
||||||
'B' indicate both (control and usage domain)
|
B - indicate both (control and usage domain)
|
||||||
.RE
|
.RE
|
||||||
.TP 8
|
.TP 8
|
||||||
.B -h, --help
|
.B -h, --help
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ static void show_domains_util_rec(char *domain_array[])
|
|||||||
*/
|
*/
|
||||||
static void show_domains(void)
|
static void show_domains(void)
|
||||||
{
|
{
|
||||||
char ctrl_domain_mask[67], usag_domain_mask[67], byte_str[3] = {};
|
char ctrl_domain_mask[80], usag_domain_mask[80], byte_str[3] = {};
|
||||||
int ctrl_chunk, usag_chunk;
|
int ctrl_chunk, usag_chunk;
|
||||||
char *ap, *domain_array[32 * 8 + 4];
|
char *ap, *domain_array[32 * 8 + 4];
|
||||||
int i, x, n;
|
int i, x, n;
|
||||||
@@ -181,8 +181,12 @@ static void show_domains(void)
|
|||||||
|
|
||||||
util_file_read_line(ctrl_domain_mask, sizeof(ctrl_domain_mask),
|
util_file_read_line(ctrl_domain_mask, sizeof(ctrl_domain_mask),
|
||||||
"%s/ap_control_domain_mask", ap);
|
"%s/ap_control_domain_mask", ap);
|
||||||
|
if (strstr(ctrl_domain_mask, "not"))
|
||||||
|
errx(EXIT_FAILURE, "Control domain mask not available.");
|
||||||
util_file_read_line(usag_domain_mask, sizeof(usag_domain_mask),
|
util_file_read_line(usag_domain_mask, sizeof(usag_domain_mask),
|
||||||
"%s/ap_usage_domain_mask", ap);
|
"%s/ap_usage_domain_mask", ap);
|
||||||
|
if (strstr(usag_domain_mask, "not"))
|
||||||
|
errx(EXIT_FAILURE, "Usage domain mask not available.");
|
||||||
/* remove leading '0x' from domain mask string */
|
/* remove leading '0x' from domain mask string */
|
||||||
memmove(&ctrl_domain_mask[0], &ctrl_domain_mask[2],
|
memmove(&ctrl_domain_mask[0], &ctrl_domain_mask[2],
|
||||||
sizeof(ctrl_domain_mask) - 2);
|
sizeof(ctrl_domain_mask) - 2);
|
||||||
@@ -222,7 +226,7 @@ static void show_capability(const char *id_str)
|
|||||||
{
|
{
|
||||||
unsigned long func_val;
|
unsigned long func_val;
|
||||||
long hwtype, id;
|
long hwtype, id;
|
||||||
char *p, *ap, *dev, card[7];
|
char *p, *ap, *dev, card[16];
|
||||||
|
|
||||||
/* check if ap driver is available */
|
/* check if ap driver is available */
|
||||||
ap = util_path_sysfs("bus/ap");
|
ap = util_path_sysfs("bus/ap");
|
||||||
@@ -450,7 +454,7 @@ static void read_rec_verbose(struct util_rec *rec, const char *grp_dev)
|
|||||||
*/
|
*/
|
||||||
static void show_device(struct util_rec *rec, const char *device)
|
static void show_device(struct util_rec *rec, const char *device)
|
||||||
{
|
{
|
||||||
char *grp_dev, card[3];
|
char *grp_dev, card[16];
|
||||||
|
|
||||||
util_rec_set(rec, "card", card);
|
util_rec_set(rec, "card", card);
|
||||||
|
|
||||||
@@ -540,7 +544,7 @@ static void show_devices_argv(char *argv[])
|
|||||||
{
|
{
|
||||||
struct util_rec *rec = util_rec_new_wide("-");
|
struct util_rec *rec = util_rec_new_wide("-");
|
||||||
struct dirent **dev_vec, **subdev_vec;
|
struct dirent **dev_vec, **subdev_vec;
|
||||||
char *ap, *grp_dev, *path, card[7], sub_dev[7];
|
char *ap, *grp_dev, *path, card[16], sub_dev[16];
|
||||||
int id, dom, i, n, dev_cnt, sub_cnt;
|
int id, dom, i, n, dev_cnt, sub_cnt;
|
||||||
|
|
||||||
/* check if ap driver is available */
|
/* check if ap driver is available */
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ installkernel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
local _tempfile=$(mktemp dracut-zdev.XXXX)
|
local _tempfile=$(mktemp --tmpdir dracut-zdev.XXXXXX)
|
||||||
|
|
||||||
if chzdev --export - --persistent --by-path / >/dev/null 2>&1 ; then
|
if chzdev --export - --persistent --by-path / >/dev/null 2>&1 ; then
|
||||||
# Use persistent configuration
|
# Use persistent configuration
|
||||||
|
|||||||
306
zdev/src/qeth.c
306
zdev/src/qeth.c
@@ -258,11 +258,17 @@ struct qeth_attrib_data {
|
|||||||
layer_2,
|
layer_2,
|
||||||
layer_3
|
layer_3
|
||||||
} layer_type;
|
} layer_type;
|
||||||
|
enum qeth_attr_group_type {
|
||||||
|
group_none,
|
||||||
|
group_bridge,
|
||||||
|
group_vnicc
|
||||||
|
} attr_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define QETH_DATA(layer) \
|
#define QETH_DATA(layer, group) \
|
||||||
((struct qeth_attrib_data []) { { \
|
((struct qeth_attrib_data []) { { \
|
||||||
.layer_type = layer, \
|
.layer_type = layer, \
|
||||||
|
.attr_group = group, \
|
||||||
} })
|
} })
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -304,7 +310,7 @@ static struct attrib qeth_attr_portname = {
|
|||||||
.order_cmp = ccw_offline_only_order_cmp,
|
.order_cmp = ccw_offline_only_order_cmp,
|
||||||
.check = ccw_offline_only_check,
|
.check = ccw_offline_only_check,
|
||||||
.map = VALUE_MAP_ARRAY(VALUE_MAP("no portname required", "")),
|
.map = VALUE_MAP_ARRAY(VALUE_MAP("no portname required", "")),
|
||||||
.st_data = QETH_DATA(layer_any),
|
.st_data = QETH_DATA(layer_any, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_priority_queueing = {
|
static struct attrib qeth_attr_priority_queueing = {
|
||||||
@@ -335,7 +341,7 @@ static struct attrib qeth_attr_priority_queueing = {
|
|||||||
ACCEPT_STR("no_prio_queueing:3")
|
ACCEPT_STR("no_prio_queueing:3")
|
||||||
),
|
),
|
||||||
.unstable = 1,
|
.unstable = 1,
|
||||||
.st_data = QETH_DATA(layer_any),
|
.st_data = QETH_DATA(layer_any, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_buffer_count = {
|
static struct attrib qeth_attr_buffer_count = {
|
||||||
@@ -348,7 +354,7 @@ static struct attrib qeth_attr_buffer_count = {
|
|||||||
.order_cmp = ccw_offline_only_order_cmp,
|
.order_cmp = ccw_offline_only_order_cmp,
|
||||||
.check = ccw_offline_only_check,
|
.check = ccw_offline_only_check,
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(8, 128)),
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(8, 128)),
|
||||||
.st_data = QETH_DATA(layer_any),
|
.st_data = QETH_DATA(layer_any, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_portno = {
|
static struct attrib qeth_attr_portno = {
|
||||||
@@ -360,7 +366,7 @@ static struct attrib qeth_attr_portno = {
|
|||||||
.order_cmp = ccw_offline_only_order_cmp,
|
.order_cmp = ccw_offline_only_order_cmp,
|
||||||
.check = ccw_offline_only_check,
|
.check = ccw_offline_only_check,
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
.st_data = QETH_DATA(layer_any),
|
.st_data = QETH_DATA(layer_any, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_hsuid = {
|
static struct attrib qeth_attr_hsuid = {
|
||||||
@@ -370,7 +376,7 @@ static struct attrib qeth_attr_hsuid = {
|
|||||||
"Specify a 1-8 character identifier used to identify a HiperSockets\n"
|
"Specify a 1-8 character identifier used to identify a HiperSockets\n"
|
||||||
"QETH device in the AF_IUCV addressing family support.\n",
|
"QETH device in the AF_IUCV addressing family support.\n",
|
||||||
.defval = "",
|
.defval = "",
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_recover = {
|
static struct attrib qeth_attr_recover = {
|
||||||
@@ -386,7 +392,7 @@ static struct attrib qeth_attr_recover = {
|
|||||||
.accept = ACCEPT_ARRAY(ACCEPT_NUM(1)),
|
.accept = ACCEPT_ARRAY(ACCEPT_NUM(1)),
|
||||||
.writeonly = 1,
|
.writeonly = 1,
|
||||||
.activeonly = 1,
|
.activeonly = 1,
|
||||||
.st_data = QETH_DATA(layer_any),
|
.st_data = QETH_DATA(layer_any, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_isolation = {
|
static struct attrib qeth_attr_isolation = {
|
||||||
@@ -401,7 +407,7 @@ static struct attrib qeth_attr_isolation = {
|
|||||||
.defval = "none",
|
.defval = "none",
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_STR("none"), ACCEPT_STR("drop"),
|
.accept = ACCEPT_ARRAY(ACCEPT_STR("none"), ACCEPT_STR("drop"),
|
||||||
ACCEPT_STR("forward")),
|
ACCEPT_STR("forward")),
|
||||||
.st_data = QETH_DATA(layer_any),
|
.st_data = QETH_DATA(layer_any, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_performance_stats = {
|
static struct attrib qeth_attr_performance_stats = {
|
||||||
@@ -413,7 +419,7 @@ static struct attrib qeth_attr_performance_stats = {
|
|||||||
" 1: Performance statistics data is collected\n",
|
" 1: Performance statistics data is collected\n",
|
||||||
.defval = "0",
|
.defval = "0",
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
.st_data = QETH_DATA(layer_any),
|
.st_data = QETH_DATA(layer_any, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_hw_trap = {
|
static struct attrib qeth_attr_hw_trap = {
|
||||||
@@ -428,7 +434,7 @@ static struct attrib qeth_attr_hw_trap = {
|
|||||||
.defval = "disarm",
|
.defval = "disarm",
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_STR("disarm"), ACCEPT_STR("arm"),
|
.accept = ACCEPT_ARRAY(ACCEPT_STR("disarm"), ACCEPT_STR("arm"),
|
||||||
ACCEPT_STR("trap")),
|
ACCEPT_STR("trap")),
|
||||||
.st_data = QETH_DATA(layer_any),
|
.st_data = QETH_DATA(layer_any, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_route4 = {
|
static struct attrib qeth_attr_route4 = {
|
||||||
@@ -464,7 +470,7 @@ static struct attrib qeth_attr_route4 = {
|
|||||||
"secondary_connector"),
|
"secondary_connector"),
|
||||||
VALUE_MAP("secondary connector",
|
VALUE_MAP("secondary connector",
|
||||||
"secondary_connector")),
|
"secondary_connector")),
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_route6 = {
|
static struct attrib qeth_attr_route6 = {
|
||||||
@@ -501,7 +507,7 @@ static struct attrib qeth_attr_route6 = {
|
|||||||
VALUE_MAP("secondary connector",
|
VALUE_MAP("secondary connector",
|
||||||
"secondary_connector")),
|
"secondary_connector")),
|
||||||
.unstable = 1,
|
.unstable = 1,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_fake_broadcast = {
|
static struct attrib qeth_attr_fake_broadcast = {
|
||||||
@@ -515,7 +521,7 @@ static struct attrib qeth_attr_fake_broadcast = {
|
|||||||
.defval = "0",
|
.defval = "0",
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_ipa_takeover_enable = {
|
static struct attrib qeth_attr_ipa_takeover_enable = {
|
||||||
@@ -529,7 +535,7 @@ static struct attrib qeth_attr_ipa_takeover_enable = {
|
|||||||
.defval = "0",
|
.defval = "0",
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_ipa_takeover_add4 = {
|
static struct attrib qeth_attr_ipa_takeover_add4 = {
|
||||||
@@ -544,7 +550,7 @@ static struct attrib qeth_attr_ipa_takeover_add4 = {
|
|||||||
.multi = 1,
|
.multi = 1,
|
||||||
.activerem = 1,
|
.activerem = 1,
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_ipa_takeover_add6 = {
|
static struct attrib qeth_attr_ipa_takeover_add6 = {
|
||||||
@@ -559,7 +565,7 @@ static struct attrib qeth_attr_ipa_takeover_add6 = {
|
|||||||
.multi = 1,
|
.multi = 1,
|
||||||
.activerem = 1,
|
.activerem = 1,
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_ipa_takeover_del4 = {
|
static struct attrib qeth_attr_ipa_takeover_del4 = {
|
||||||
@@ -573,7 +579,7 @@ static struct attrib qeth_attr_ipa_takeover_del4 = {
|
|||||||
.writeonly = 1,
|
.writeonly = 1,
|
||||||
.activeonly = 1,
|
.activeonly = 1,
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_ipa_takeover_del6 = {
|
static struct attrib qeth_attr_ipa_takeover_del6 = {
|
||||||
@@ -586,7 +592,7 @@ static struct attrib qeth_attr_ipa_takeover_del6 = {
|
|||||||
.writeonly = 1,
|
.writeonly = 1,
|
||||||
.activeonly = 1,
|
.activeonly = 1,
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_ipa_takeover_invert4 = {
|
static struct attrib qeth_attr_ipa_takeover_invert4 = {
|
||||||
@@ -601,7 +607,7 @@ static struct attrib qeth_attr_ipa_takeover_invert4 = {
|
|||||||
.defval = "0",
|
.defval = "0",
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_ipa_takeover_invert6 = {
|
static struct attrib qeth_attr_ipa_takeover_invert6 = {
|
||||||
@@ -616,7 +622,7 @@ static struct attrib qeth_attr_ipa_takeover_invert6 = {
|
|||||||
.defval = "0",
|
.defval = "0",
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_rxip_add4 = {
|
static struct attrib qeth_attr_rxip_add4 = {
|
||||||
@@ -629,20 +635,20 @@ static struct attrib qeth_attr_rxip_add4 = {
|
|||||||
.multi = 1,
|
.multi = 1,
|
||||||
.activerem = 1,
|
.activerem = 1,
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_rxip_add6 = {
|
static struct attrib qeth_attr_rxip_add6 = {
|
||||||
.name = "rxip/add6",
|
.name = "rxip/add6",
|
||||||
.title = "Add IPv6 address to ARP proxy list",
|
.title = "Add IPv6 address to NDP proxy list",
|
||||||
.desc =
|
.desc =
|
||||||
"Write an IPv6 address to this attribute to add it to the list of\n"
|
"Write an IPv6 address to this attribute to add it to the list of\n"
|
||||||
"addresses for which this QETH device should act as ARP proxy.\n",
|
"addresses for which this QETH device should act as NDP proxy.\n",
|
||||||
.defval = "",
|
.defval = "",
|
||||||
.multi = 1,
|
.multi = 1,
|
||||||
.activerem = 1,
|
.activerem = 1,
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_rxip_del4 = {
|
static struct attrib qeth_attr_rxip_del4 = {
|
||||||
@@ -654,19 +660,19 @@ static struct attrib qeth_attr_rxip_del4 = {
|
|||||||
.writeonly = 1,
|
.writeonly = 1,
|
||||||
.activeonly = 1,
|
.activeonly = 1,
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_rxip_del6 = {
|
static struct attrib qeth_attr_rxip_del6 = {
|
||||||
.name = "rxip/del6",
|
.name = "rxip/del6",
|
||||||
.title = "Remove IPv6 address from ARP proxy list",
|
.title = "Remove IPv6 address from NDP proxy list",
|
||||||
.desc =
|
.desc =
|
||||||
"Write an IPv6 address to this attribute to remove it from the list\n"
|
"Write an IPv6 address to this attribute to remove it from the list\n"
|
||||||
"of addresses for which this QETH device acts as an ARP proxy.\n",
|
"of addresses for which this QETH device acts as an NDP proxy.\n",
|
||||||
.writeonly = 1,
|
.writeonly = 1,
|
||||||
.activeonly = 1,
|
.activeonly = 1,
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_sniffer = {
|
static struct attrib qeth_attr_sniffer = {
|
||||||
@@ -679,7 +685,7 @@ static struct attrib qeth_attr_sniffer = {
|
|||||||
.defval = "0",
|
.defval = "0",
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_vipa_add4 = {
|
static struct attrib qeth_attr_vipa_add4 = {
|
||||||
@@ -692,7 +698,7 @@ static struct attrib qeth_attr_vipa_add4 = {
|
|||||||
.multi = 1,
|
.multi = 1,
|
||||||
.activerem = 1,
|
.activerem = 1,
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_vipa_add6 = {
|
static struct attrib qeth_attr_vipa_add6 = {
|
||||||
@@ -705,7 +711,7 @@ static struct attrib qeth_attr_vipa_add6 = {
|
|||||||
.multi = 1,
|
.multi = 1,
|
||||||
.activerem = 1,
|
.activerem = 1,
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_vipa_del4 = {
|
static struct attrib qeth_attr_vipa_del4 = {
|
||||||
@@ -717,7 +723,7 @@ static struct attrib qeth_attr_vipa_del4 = {
|
|||||||
.writeonly = 1,
|
.writeonly = 1,
|
||||||
.activeonly = 1,
|
.activeonly = 1,
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_vipa_del6 = {
|
static struct attrib qeth_attr_vipa_del6 = {
|
||||||
@@ -729,7 +735,7 @@ static struct attrib qeth_attr_vipa_del6 = {
|
|||||||
.writeonly = 1,
|
.writeonly = 1,
|
||||||
.activeonly = 1,
|
.activeonly = 1,
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.st_data = QETH_DATA(layer_3),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_bridge_role = {
|
static struct attrib qeth_attr_bridge_role = {
|
||||||
@@ -739,13 +745,16 @@ static struct attrib qeth_attr_bridge_role = {
|
|||||||
"Configure a QETH device as a bridge port:\n"
|
"Configure a QETH device as a bridge port:\n"
|
||||||
" primary: The device acts as the primary bridge port\n"
|
" primary: The device acts as the primary bridge port\n"
|
||||||
" secondary: The device acts as a secondary bridge port\n"
|
" secondary: The device acts as a secondary bridge port\n"
|
||||||
" none: The device has no bridge port role\n",
|
" none: The device has no bridge port role\n"
|
||||||
|
" n/a (VNIC characteristics):\n"
|
||||||
|
" The device is configured with VNIC characteristics\n"
|
||||||
|
" and cannot have a bridge role (read-only)\n",
|
||||||
.defval = "none",
|
.defval = "none",
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_STR("primary"),
|
.accept = ACCEPT_ARRAY(ACCEPT_STR("primary"),
|
||||||
ACCEPT_STR("secondary"),
|
ACCEPT_STR("secondary"),
|
||||||
ACCEPT_STR("none")),
|
ACCEPT_STR("none")),
|
||||||
.st_data = QETH_DATA(layer_2),
|
.st_data = QETH_DATA(layer_2, group_bridge),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_bridge_hostnotify = {
|
static struct attrib qeth_attr_bridge_hostnotify = {
|
||||||
@@ -755,11 +764,14 @@ static struct attrib qeth_attr_bridge_hostnotify = {
|
|||||||
"Control whether host connection and disconnection events are\n"
|
"Control whether host connection and disconnection events are\n"
|
||||||
"reported through kernel uevents:\n"
|
"reported through kernel uevents:\n"
|
||||||
" 0: Notifications are disabled\n"
|
" 0: Notifications are disabled\n"
|
||||||
" 1: Notifications are enabled\n",
|
" 1: Notifications are enabled\n"
|
||||||
|
" n/a (VNIC characteristics):\n"
|
||||||
|
" The device is configured with VNIC characteristics\n"
|
||||||
|
" and cannot have a bridge role (read-only)\n",
|
||||||
.defval = "0",
|
.defval = "0",
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
.st_data = QETH_DATA(layer_2),
|
.st_data = QETH_DATA(layer_2, group_bridge),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_bridge_reflect_promisc = {
|
static struct attrib qeth_attr_bridge_reflect_promisc = {
|
||||||
@@ -773,13 +785,159 @@ static struct attrib qeth_attr_bridge_reflect_promisc = {
|
|||||||
" primary: Attempt to configure the device as the primary bridge\n"
|
" primary: Attempt to configure the device as the primary bridge\n"
|
||||||
" port\n"
|
" port\n"
|
||||||
" secondary: Attempt to configure the device as a secondary bridge\n"
|
" secondary: Attempt to configure the device as a secondary bridge\n"
|
||||||
" port\n",
|
" port\n"
|
||||||
|
" n/a (VNIC characteristics):\n"
|
||||||
|
" The device is configured with VNIC characteristics\n"
|
||||||
|
" and cannot have a bridge role (read-only)\n",
|
||||||
.defval = "none",
|
.defval = "none",
|
||||||
.order_cmp = after_layer2_order_cmp,
|
.order_cmp = after_layer2_order_cmp,
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_STR("primary"),
|
.accept = ACCEPT_ARRAY(ACCEPT_STR("primary"),
|
||||||
ACCEPT_STR("secondary"),
|
ACCEPT_STR("secondary"),
|
||||||
ACCEPT_STR("none")),
|
ACCEPT_STR("none")),
|
||||||
.st_data = QETH_DATA(layer_2),
|
.st_data = QETH_DATA(layer_2, group_bridge),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attrib qeth_attr_vnicc_flooding = {
|
||||||
|
.name = "vnicc/flooding",
|
||||||
|
.title = "Control setting of VNICC flooding",
|
||||||
|
.desc =
|
||||||
|
"Control and show the VNIC characteristic flooding\n"
|
||||||
|
"on the networking device:\n"
|
||||||
|
" 0: Flooding disabled\n"
|
||||||
|
" 1: Flooding enabled\n"
|
||||||
|
" n/a: Information unavailable (read-only)\n"
|
||||||
|
" n/a (BridgePort):\n"
|
||||||
|
" The device is part of a Linux bridge and cannot be\n"
|
||||||
|
" configured with VNIC characteristics (read-only)\n",
|
||||||
|
.defval = "0",
|
||||||
|
.order_cmp = after_layer2_order_cmp,
|
||||||
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
|
.st_data = QETH_DATA(layer_2, group_vnicc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attrib qeth_attr_vnicc_mcast_flooding = {
|
||||||
|
.name = "vnicc/mcast_flooding",
|
||||||
|
.title = "Control setting of VNICC multicast flooding",
|
||||||
|
.desc =
|
||||||
|
"Control and show the VNIC characteristic multicast flooding\n"
|
||||||
|
"on the networking device:\n"
|
||||||
|
" 0: Multicast flooding disabled\n"
|
||||||
|
" 1: Multicast flooding enabled\n"
|
||||||
|
" n/a: Information unavailable (read-only)\n"
|
||||||
|
" n/a (BridgePort):\n"
|
||||||
|
" The device is part of a Linux bridge and cannot be\n"
|
||||||
|
" configured with VNIC characteristics (read-only)\n",
|
||||||
|
.defval = "0",
|
||||||
|
.order_cmp = after_layer2_order_cmp,
|
||||||
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
|
.st_data = QETH_DATA(layer_2, group_vnicc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attrib qeth_attr_vnicc_learning = {
|
||||||
|
.name = "vnicc/learning",
|
||||||
|
.title = "Control setting of VNICC learning",
|
||||||
|
.desc =
|
||||||
|
"Control and show the VNIC characteristic learning\n"
|
||||||
|
"on the networking device:\n"
|
||||||
|
" 0: Learning disabled\n"
|
||||||
|
" 1: Learning enabled\n"
|
||||||
|
" n/a: Information unavailable (read-only)\n"
|
||||||
|
" n/a (BridgePort):\n"
|
||||||
|
" The device is part of a Linux bridge and cannot be\n"
|
||||||
|
" configured with VNIC characteristics (read-only)\n",
|
||||||
|
.defval = "0",
|
||||||
|
.order_cmp = after_layer2_order_cmp,
|
||||||
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
|
.st_data = QETH_DATA(layer_2, group_vnicc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attrib qeth_attr_vnicc_learning_timeout = {
|
||||||
|
.name = "vnicc/learning_timeout",
|
||||||
|
.title = "Control setting of the VNICC learning timeout",
|
||||||
|
.desc =
|
||||||
|
"Control and show the timeout of the VNIC characteristic learning\n"
|
||||||
|
"on the networking device:\n"
|
||||||
|
" <N>: Timeout in seconds\n"
|
||||||
|
" n/a: Information unavailable (read-only)\n"
|
||||||
|
" n/a (BridgePort):\n"
|
||||||
|
" The device is part of a Linux bridge and cannot be\n"
|
||||||
|
" configured with VNIC characteristics (read-only)\n",
|
||||||
|
.defval = "600",
|
||||||
|
.order_cmp = after_layer2_order_cmp,
|
||||||
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(60, 86400)),
|
||||||
|
.st_data = QETH_DATA(layer_2, group_vnicc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attrib qeth_attr_vnicc_takeover_setvmac = {
|
||||||
|
.name = "vnicc/takeover_setvmac",
|
||||||
|
.title = "Control setting of VNICC takeover SETVMAC",
|
||||||
|
.desc =
|
||||||
|
"Control and show the VNIC characteristic takeover SETVMAC\n"
|
||||||
|
"on the networking device:\n"
|
||||||
|
" 0: Takeover SETVMAC disabled\n"
|
||||||
|
" 1: Takeover SETVMAC enabled\n"
|
||||||
|
" n/a: Information unavailable (read-only)\n"
|
||||||
|
" n/a (BridgePort):\n"
|
||||||
|
" The device is part of a Linux bridge and cannot be\n"
|
||||||
|
" configured with VNIC characteristics (read-only)\n",
|
||||||
|
.defval = "0",
|
||||||
|
.order_cmp = after_layer2_order_cmp,
|
||||||
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
|
.st_data = QETH_DATA(layer_2, group_vnicc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attrib qeth_attr_vnicc_takeover_learning = {
|
||||||
|
.name = "vnicc/takeover_learning",
|
||||||
|
.title = "Control setting of VNICC takeover learning",
|
||||||
|
.desc =
|
||||||
|
"Control and show the VNIC characteristic takeover learning\n"
|
||||||
|
"on the networking device:\n"
|
||||||
|
" 0: Takeover learning disabled\n"
|
||||||
|
" 1: Takeover learning enabled\n"
|
||||||
|
" n/a: Information unavailable (read-only)\n"
|
||||||
|
" n/a (BridgePort):\n"
|
||||||
|
" The device is part of a Linux bridge and cannot be\n"
|
||||||
|
" configured with VNIC characteristics (read-only)\n",
|
||||||
|
.defval = "0",
|
||||||
|
.order_cmp = after_layer2_order_cmp,
|
||||||
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
|
.st_data = QETH_DATA(layer_2, group_vnicc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attrib qeth_attr_vnicc_bridge_invisible = {
|
||||||
|
.name = "vnicc/bridge_invisible",
|
||||||
|
.title = "Control setting of VNICC bridge invisible",
|
||||||
|
.desc =
|
||||||
|
"Control and show the VNIC characteristic bridge invisible\n"
|
||||||
|
"on the networking device:\n"
|
||||||
|
" 0: Bridge invisible disabled\n"
|
||||||
|
" 1: Bridge invisible enabled\n"
|
||||||
|
" n/a: Information unavailable (read-only)\n"
|
||||||
|
" n/a (BridgePort):\n"
|
||||||
|
" The device is part of a Linux bridge and cannot be\n"
|
||||||
|
" configured with VNIC characteristics (read-only)\n",
|
||||||
|
.defval = "0",
|
||||||
|
.order_cmp = after_layer2_order_cmp,
|
||||||
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
|
.st_data = QETH_DATA(layer_2, group_vnicc),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attrib qeth_attr_vnicc_rx_bcast = {
|
||||||
|
.name = "vnicc/rx_bcast",
|
||||||
|
.title = "Control setting of VNICC receive broadcast",
|
||||||
|
.desc =
|
||||||
|
"Control and show the VNIC characteristic receive broadcast\n"
|
||||||
|
"on the networking device:\n"
|
||||||
|
" 0: Receive broadcast disabled\n"
|
||||||
|
" 1: Receive broadcast enabled\n"
|
||||||
|
" n/a: Information unavailable (read-only)\n"
|
||||||
|
" n/a (BridgePort):\n"
|
||||||
|
" The device is part of a Linux bridge and cannot be\n"
|
||||||
|
" configured with VNIC characteristics (read-only)\n",
|
||||||
|
.defval = "1",
|
||||||
|
.order_cmp = after_layer2_order_cmp,
|
||||||
|
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
||||||
|
.st_data = QETH_DATA(layer_2, group_vnicc),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -913,7 +1071,11 @@ static exit_code_t setting_ineffective(struct setting *s, int layer2)
|
|||||||
|
|
||||||
static enum qeth_layer_type get_layer_type(struct setting *s)
|
static enum qeth_layer_type get_layer_type(struct setting *s)
|
||||||
{
|
{
|
||||||
struct qeth_attrib_data *data = s->attrib->st_data;
|
struct qeth_attrib_data *data;
|
||||||
|
|
||||||
|
if (!s->attrib)
|
||||||
|
return layer_any;
|
||||||
|
data = s->attrib->st_data;
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
return layer_any;
|
return layer_any;
|
||||||
@@ -921,6 +1083,20 @@ static enum qeth_layer_type get_layer_type(struct setting *s)
|
|||||||
return data->layer_type;
|
return data->layer_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum qeth_attr_group_type get_attr_group_type(struct setting *s)
|
||||||
|
{
|
||||||
|
struct qeth_attrib_data *data;
|
||||||
|
|
||||||
|
if (!s->attrib)
|
||||||
|
return group_none;
|
||||||
|
data = s->attrib->st_data;
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return group_none;
|
||||||
|
else
|
||||||
|
return data->attr_group;
|
||||||
|
}
|
||||||
|
|
||||||
static void add_layer2_setting(struct setting_list *list, int layer2)
|
static void add_layer2_setting(struct setting_list *list, int layer2)
|
||||||
{
|
{
|
||||||
setting_list_apply(list, &qeth_attr_layer2,
|
setting_list_apply(list, &qeth_attr_layer2,
|
||||||
@@ -994,6 +1170,38 @@ static exit_code_t check_ineffective_settings(struct setting_list *list,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if there are conflicting attribute settings */
|
||||||
|
static exit_code_t check_conflicting_settings(struct setting_list *list)
|
||||||
|
{
|
||||||
|
const char *text = "Settings %s and %s are in conflict\n";
|
||||||
|
struct setting *bridge = NULL, *vnicc = NULL;
|
||||||
|
enum qeth_attr_group_type t;
|
||||||
|
struct setting *s;
|
||||||
|
|
||||||
|
util_list_iterate(&list->list, s) {
|
||||||
|
if (s->removed)
|
||||||
|
continue;
|
||||||
|
t = get_attr_group_type(s);
|
||||||
|
if (t == group_bridge && (!bridge || !bridge->specified))
|
||||||
|
bridge = s;
|
||||||
|
if (t == group_vnicc && (!vnicc || !vnicc->specified))
|
||||||
|
vnicc = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BridgePort and VNICC cannot both be configured at the same time */
|
||||||
|
if (bridge && vnicc && (bridge->specified || vnicc->specified)) {
|
||||||
|
if (force) {
|
||||||
|
delayed_warn(text, bridge->attrib->name,
|
||||||
|
vnicc->attrib->name);
|
||||||
|
return EXIT_OK;
|
||||||
|
}
|
||||||
|
delayed_forceable(text, bridge->attrib->name,
|
||||||
|
vnicc->attrib->name);
|
||||||
|
return EXIT_INVALID_CONFIG;
|
||||||
|
}
|
||||||
|
return EXIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if layer2 setting can be correctly applied. */
|
/* Check if layer2 setting can be correctly applied. */
|
||||||
static exit_code_t check_layer2(struct device *dev, config_t config)
|
static exit_code_t check_layer2(struct device *dev, config_t config)
|
||||||
{
|
{
|
||||||
@@ -1045,7 +1253,17 @@ static exit_code_t check_layer2(struct device *dev, config_t config)
|
|||||||
if (SCOPE_PERSISTENT(config)) {
|
if (SCOPE_PERSISTENT(config)) {
|
||||||
rc = check_ineffective_settings(dev->persistent.settings,
|
rc = check_ineffective_settings(dev->persistent.settings,
|
||||||
layer2_persistent);
|
layer2_persistent);
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
/* check for conflicting layer2 attribute groups */
|
||||||
|
if (SCOPE_ACTIVE(config)) {
|
||||||
|
rc = check_conflicting_settings(dev->active.settings);
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (SCOPE_PERSISTENT(config))
|
||||||
|
rc = check_conflicting_settings(dev->persistent.settings);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
@@ -1195,6 +1413,14 @@ static struct subtype qeth_subtype_qeth = {
|
|||||||
&qeth_attr_bridge_role,
|
&qeth_attr_bridge_role,
|
||||||
&qeth_attr_bridge_hostnotify,
|
&qeth_attr_bridge_hostnotify,
|
||||||
&qeth_attr_bridge_reflect_promisc,
|
&qeth_attr_bridge_reflect_promisc,
|
||||||
|
&qeth_attr_vnicc_flooding,
|
||||||
|
&qeth_attr_vnicc_mcast_flooding,
|
||||||
|
&qeth_attr_vnicc_learning,
|
||||||
|
&qeth_attr_vnicc_learning_timeout,
|
||||||
|
&qeth_attr_vnicc_takeover_setvmac,
|
||||||
|
&qeth_attr_vnicc_takeover_learning,
|
||||||
|
&qeth_attr_vnicc_bridge_invisible,
|
||||||
|
&qeth_attr_vnicc_rx_bcast,
|
||||||
),
|
),
|
||||||
.unknown_dev_attribs = 1,
|
.unknown_dev_attribs = 1,
|
||||||
.support_definable = 1,
|
.support_definable = 1,
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ struct vol {
|
|||||||
u64 part_size;
|
u64 part_size;
|
||||||
u64 mem_start;
|
u64 mem_start;
|
||||||
u64 mem_end;
|
u64 mem_end;
|
||||||
char bus_id[9];
|
char bus_id[10];
|
||||||
u32 nr;
|
u32 nr;
|
||||||
u16 blk_size;
|
u16 blk_size;
|
||||||
struct df_s390_dumper dumper;
|
struct df_s390_dumper dumper;
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ static void init_defaults(void)
|
|||||||
/*
|
/*
|
||||||
* Print "help" hint
|
* Print "help" hint
|
||||||
*/
|
*/
|
||||||
static void print_usage_exit(void)
|
static void __noreturn print_usage_exit(void)
|
||||||
{
|
{
|
||||||
STDERR("Try '%s --help' for more information.\n", g.prog_name);
|
STDERR("Try '%s --help' for more information.\n", g.prog_name);
|
||||||
zg_exit(1);
|
zg_exit(1);
|
||||||
@@ -84,7 +84,7 @@ static void print_usage_exit(void)
|
|||||||
/*
|
/*
|
||||||
* Print help text
|
* Print help text
|
||||||
*/
|
*/
|
||||||
static void print_help_exit(void)
|
static void __noreturn print_help_exit(void)
|
||||||
{
|
{
|
||||||
STDOUT("%s", help_text);
|
STDOUT("%s", help_text);
|
||||||
zg_exit(0);
|
zg_exit(0);
|
||||||
@@ -93,7 +93,7 @@ static void print_help_exit(void)
|
|||||||
/*
|
/*
|
||||||
* Print version information
|
* Print version information
|
||||||
*/
|
*/
|
||||||
static void print_version_exit(void)
|
static void __noreturn print_version_exit(void)
|
||||||
{
|
{
|
||||||
STDOUT("%s: Tool for copying and converting dumps version %s\n",
|
STDOUT("%s: Tool for copying and converting dumps version %s\n",
|
||||||
g.prog_name, RELEASE_STRING);
|
g.prog_name, RELEASE_STRING);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
include ../common.mak
|
include ../common.mak
|
||||||
|
|
||||||
CPPFLAGS += -I../include
|
CPPFLAGS += -I../include
|
||||||
LDFLAGS += -ldl
|
LDLIBS += -ldl
|
||||||
|
|
||||||
all: zkey
|
all: zkey
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ master key in the \fBNEW\fP register.
|
|||||||
If both options are omitted, \fBzkey\fP automatically detects whether the
|
If both options are omitted, \fBzkey\fP automatically detects whether the
|
||||||
secure key is currently enciphered with the master key in the \fBOLD\fP
|
secure key is currently enciphered with the master key in the \fBOLD\fP
|
||||||
register or with the master key in the \fBCURRENT\fP register.
|
register or with the master key in the \fBCURRENT\fP register.
|
||||||
If currently enciphered with the master key in the i\fBOLD\fP register,
|
If currently enciphered with the master key in the \fBOLD\fP register,
|
||||||
it is re-enciphered with the master key in the \fBCURRENT\fP register.
|
it is re-enciphered with the master key in the \fBCURRENT\fP register.
|
||||||
If it is currently enciphered with the master key in the \fBCURRENT\fP
|
If it is currently enciphered with the master key in the \fBCURRENT\fP
|
||||||
register, it is re-enciphered with the master key in the \fBNEW\fP register.
|
register, it is re-enciphered with the master key in the \fBNEW\fP register.
|
||||||
@@ -137,7 +137,7 @@ to be installed.
|
|||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.SS "Options for the generate command"
|
.SS "Options for the generate command"
|
||||||
.TP
|
.TP
|
||||||
.BR \-k ", " \-\-keybits \fIsize\fP
|
.BR \-k ", " \-\-keybits\~\fIsize\fP
|
||||||
Specifies the size of the AES key to be generated in bits.
|
Specifies the size of the AES key to be generated in bits.
|
||||||
Valid sizes are 128, 192, and 256 bits. Secure keys for use with the
|
Valid sizes are 128, 192, and 256 bits. Secure keys for use with the
|
||||||
XTS cipher mode can only use keys of 128 or 256 bits.
|
XTS cipher mode can only use keys of 128 or 256 bits.
|
||||||
@@ -147,7 +147,7 @@ The default is 256 bits.
|
|||||||
Generates a secure AES key for the XTS cipher mode. A secure AES key for
|
Generates a secure AES key for the XTS cipher mode. A secure AES key for
|
||||||
the XTS cipher mode consist of two concatenated secure keys.
|
the XTS cipher mode consist of two concatenated secure keys.
|
||||||
.TP
|
.TP
|
||||||
.BR \-c ", " \-\-clearkey \fIclear\-key\-file\fP
|
.BR \-c ", " \-\-clearkey\~\fIclear\-key\-file\fP
|
||||||
Specifies a file path that contains the clear AES key in binary form.
|
Specifies a file path that contains the clear AES key in binary form.
|
||||||
If option \fB\-\-keybits\fP is omitted, the size of the specified file
|
If option \fB\-\-keybits\fP is omitted, the size of the specified file
|
||||||
determines the size of the AES key. If option \fB\-\-keybits\fP
|
determines the size of the AES key. If option \fB\-\-keybits\fP
|
||||||
@@ -165,7 +165,7 @@ master key in the CURRENT register with the master key in the NEW register.
|
|||||||
Re-enciphers a secure AES key that is currently enciphered with the
|
Re-enciphers a secure AES key that is currently enciphered with the
|
||||||
master key in the OLD register with the master key in the CURRENT register.
|
master key in the OLD register with the master key in the CURRENT register.
|
||||||
.TP
|
.TP
|
||||||
.BR \-f ", " \-\-output \fIoutput\-file\fP
|
.BR \-f ", " \-\-output\~\fIoutput\-file\fP
|
||||||
Specifies the name of the output file to which the re-enciphered secure key
|
Specifies the name of the output file to which the re-enciphered secure key
|
||||||
is written. If this option is omitted, the re-enciphered secure key
|
is written. If this option is omitted, the re-enciphered secure key
|
||||||
is replaced in the file that currently contains the secure key.
|
is replaced in the file that currently contains the secure key.
|
||||||
|
|||||||
33
zkey/zkey.c
33
zkey/zkey.c
@@ -138,7 +138,7 @@ static struct util_opt opt_vec[] = {
|
|||||||
*/
|
*/
|
||||||
struct zkey_command {
|
struct zkey_command {
|
||||||
char *command;
|
char *command;
|
||||||
unsigned int abrev_len;
|
unsigned int abbrev_len;
|
||||||
int (*function)(const char *keyfile);
|
int (*function)(const char *keyfile);
|
||||||
int need_cca_library;
|
int need_cca_library;
|
||||||
int need_pkey_device;
|
int need_pkey_device;
|
||||||
@@ -154,7 +154,7 @@ static int command_validate(const char *keyfile);
|
|||||||
static struct zkey_command zkey_commands[] = {
|
static struct zkey_command zkey_commands[] = {
|
||||||
{
|
{
|
||||||
.command = COMMAND_GENERATE,
|
.command = COMMAND_GENERATE,
|
||||||
.abrev_len = 3,
|
.abbrev_len = 3,
|
||||||
.function = command_generate,
|
.function = command_generate,
|
||||||
.need_pkey_device = 1,
|
.need_pkey_device = 1,
|
||||||
.short_desc = "Generate a secure AES key",
|
.short_desc = "Generate a secure AES key",
|
||||||
@@ -164,7 +164,7 @@ static struct zkey_command zkey_commands[] = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
.command = COMMAND_REENCIPHER,
|
.command = COMMAND_REENCIPHER,
|
||||||
.abrev_len = 2,
|
.abbrev_len = 2,
|
||||||
.function = command_reencipher,
|
.function = command_reencipher,
|
||||||
.need_cca_library = 1,
|
.need_cca_library = 1,
|
||||||
.need_pkey_device = 1,
|
.need_pkey_device = 1,
|
||||||
@@ -175,7 +175,7 @@ static struct zkey_command zkey_commands[] = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
.command = COMMAND_VALIDATE,
|
.command = COMMAND_VALIDATE,
|
||||||
.abrev_len = 3,
|
.abbrev_len = 3,
|
||||||
.function = command_validate,
|
.function = command_validate,
|
||||||
.need_pkey_device = 1,
|
.need_pkey_device = 1,
|
||||||
.short_desc = "Validate an existing secure AES key",
|
.short_desc = "Validate an existing secure AES key",
|
||||||
@@ -197,7 +197,7 @@ static void print_usage_command(const struct zkey_command *command)
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
strncpy(command_str, command->command, sizeof(command_str) - 1);
|
strncpy(command_str, command->command, sizeof(command_str) - 1);
|
||||||
for (i = 0; i < command->abrev_len; i++)
|
for (i = 0; i < command->abbrev_len; i++)
|
||||||
command_str[i] = toupper(command_str[i]);
|
command_str[i] = toupper(command_str[i]);
|
||||||
|
|
||||||
printf("Usage: %s %s SECURE-KEY-FILE",
|
printf("Usage: %s %s SECURE-KEY-FILE",
|
||||||
@@ -223,7 +223,7 @@ static void print_usage_command_list(void)
|
|||||||
printf("COMMANDS\n");
|
printf("COMMANDS\n");
|
||||||
while (cmd->command) {
|
while (cmd->command) {
|
||||||
strcpy(command_str, cmd->command);
|
strcpy(command_str, cmd->command);
|
||||||
for (i = 0; i < cmd->abrev_len; i++)
|
for (i = 0; i < cmd->abbrev_len; i++)
|
||||||
command_str[i] = toupper(command_str[i]);
|
command_str[i] = toupper(command_str[i]);
|
||||||
printf(" %s\t%s\n", command_str, cmd->short_desc);
|
printf(" %s\t%s\n", command_str, cmd->short_desc);
|
||||||
cmd++;
|
cmd++;
|
||||||
@@ -718,7 +718,6 @@ static int key_token_change(u8 *secure_key, unsigned int secure_key_size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int validate_secure_xts_key(u8 *secure_key, size_t secure_key_size,
|
static int validate_secure_xts_key(u8 *secure_key, size_t secure_key_size,
|
||||||
u16 part1_cardnr, u16 part1_domain,
|
|
||||||
u16 part1_keysize, u32 part1_attributes,
|
u16 part1_keysize, u32 part1_attributes,
|
||||||
size_t *clear_key_bitsize)
|
size_t *clear_key_bitsize)
|
||||||
{
|
{
|
||||||
@@ -765,18 +764,6 @@ static int validate_secure_xts_key(u8 *secure_key, size_t secure_key_size,
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verifykey.cardnr != part1_cardnr) {
|
|
||||||
pr_verbose("XTS secure key contains 2 keys using different "
|
|
||||||
"cards");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verifykey.domain != part1_domain) {
|
|
||||||
pr_verbose("XTS secure key contains 2 keys using different "
|
|
||||||
"domains");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verifykey.keysize != part1_keysize) {
|
if (verifykey.keysize != part1_keysize) {
|
||||||
pr_verbose("XTS secure key contains 2 keys using different "
|
pr_verbose("XTS secure key contains 2 keys using different "
|
||||||
"key sizes");
|
"key sizes");
|
||||||
@@ -827,8 +814,6 @@ static int validate_secure_key(u8 *secure_key, size_t secure_key_size,
|
|||||||
/* XTS uses 2 secure key tokens concatenated to each other */
|
/* XTS uses 2 secure key tokens concatenated to each other */
|
||||||
if (secure_key_size > SECURE_KEY_SIZE) {
|
if (secure_key_size > SECURE_KEY_SIZE) {
|
||||||
rc = validate_secure_xts_key(secure_key, secure_key_size,
|
rc = validate_secure_xts_key(secure_key, secure_key_size,
|
||||||
verifykey.cardnr,
|
|
||||||
verifykey.domain,
|
|
||||||
verifykey.keysize,
|
verifykey.keysize,
|
||||||
verifykey.attributes,
|
verifykey.attributes,
|
||||||
clear_key_bitsize);
|
clear_key_bitsize);
|
||||||
@@ -974,12 +959,12 @@ static bool is_command(struct zkey_command *command, const char *str)
|
|||||||
|
|
||||||
util_assert(sizeof(command_str) > strlen(command->command),
|
util_assert(sizeof(command_str) > strlen(command->command),
|
||||||
"Buffer 'command_str' too small for %s", command->command);
|
"Buffer 'command_str' too small for %s", command->command);
|
||||||
if (str_len < command->abrev_len)
|
if (str_len < command->abbrev_len)
|
||||||
return false;
|
return false;
|
||||||
if (str_len > strlen(command->command))
|
if (str_len > strlen(command->command))
|
||||||
return false;
|
return false;
|
||||||
strncpy(command_str, command->command, str_len);
|
strncpy(command_str, command->command, str_len);
|
||||||
if (strcasecmp(str, command_str) != 0)
|
if (strncasecmp(str, command_str, str_len) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1108,6 +1093,8 @@ int main(int argc, char *argv[])
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
umask(0077);
|
||||||
|
|
||||||
rc = command->function(keyfile);
|
rc = command->function(keyfile);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|||||||
Reference in New Issue
Block a user