Linux Archive

Linux Archive (http://www.linux-archive.org/)
-   Ubuntu Server Development (http://www.linux-archive.org/ubuntu-server-development/)
-   -   move linuxrc.s390 out of harm's way (http://www.linux-archive.org/ubuntu-server-development/632639-move-linuxrc-s390-out-harms-way.html)

Will Woods 02-13-2012 10:09 PM

move linuxrc.s390 out of harm's way
 
We still need linuxrc.s390 (that's a project for another year), so move
it out of loader/ while we warm up the orbital lasers.
---
data/Makefile.am | 5 +
data/linuxrc.s390 | 3079 ++++++++++++++++++++++++++++++++++++++++++++++++++ +
loader/linuxrc.s390 | 3079 ---------------------------------------------------
3 files changed, 3084 insertions(+), 3079 deletions(-)
create mode 100644 data/linuxrc.s390
delete mode 100644 loader/linuxrc.s390

diff --git a/data/Makefile.am b/data/Makefile.am
index 6e5b5b9..cc82ae5 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -29,6 +29,11 @@ langdir = $(datadir)/$(PACKAGE_NAME)
lang_DATA = lang-names
dist_lang_DATA = lang-table

+if IS_S390
+shareddir = $(datadir)/$(PACKAGE_NAME)
+dist_shared_SCRIPTS = linuxrc.s390
+endif
+
MAINTAINERCLEANFILES = Makefile.in

lang-names: lang-table
diff --git a/data/linuxrc.s390 b/data/linuxrc.s390
new file mode 100644
index 0000000..3280498
--- /dev/null
+++ b/data/linuxrc.s390
@@ -0,0 +1,3079 @@
+#! /bin/bash
+
+# linuxrc.s390: init process of Red Hat's installer initrd for s390(x)
+# Copyright (C) 2000-2004 by
+# Bernhard Rosenkraenzer <bero@redhat.com>
+# Oliver Paukstadt <opaukstadt@millenux.com>
+# Karsten Hopp <karsten@redhat.de>
+# Florian La Roche <laroche@redhat.com>
+# Nils Philippsen <nils@redhat.de>
+# Helge Deller <hdeller@redhat.de>
+# David Sainty <dsainty@redhat.com>
+# Copyright (C) IBM Corp. 2008,2009
+# Author: Steffen Maier <maier@de.ibm.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+# prerequisites of this script to run inside the installer initrd:
+# - udevadm and udevd need to be there
+# - have /etc/udev/udev.conf with at least one comment line as content
+# - if necessary, have udev rules
+# - lsznet.raw and znetcontrolunits from s390utils-base in /lib/s390-tools
+# - pack kernel modules and module-init-tools (no longer use busybox for that)
+# - "multi on" in /etc/host.conf [RH bugs 486457,486461,483244]
+
+# TODOs:
+# - make sure driver modules get loaded automatically
+# - udev rule for lcs/ctcm vs. cu3088
+
+# debug: set -x
+
+if [ "${0##*/}" = "reboot" ]; then
+ kill -USR2 1
+ exit
+elif [ "${0##*/}" = "halt" ]; then
+ kill -USR1 1
+ exit
+fi
+
+VERSION=1.2
+
+export TEXTDOMAIN=s390installer
+export TEXTDOMAINDIR=/usr/lib/locale
+
+# helper function to execute command in arguments and print command on stdout
+function debug() {
+ # uncomment the following echo "$*" to enable debug output
+ #echo "$*"
+ $*
+}
+
+# FIXME: maybe change to "$$" for production use, in case it wouldn't be init
+declare -r INITPID="1"
+
+unset testing
+[ "$$" != "$INITPID" ] && testing="1"
+# uncomment the following test="1" to never execute sensitive commands
+#testing="1"
+
+if [ "$RUNKS" = "0" ]; then
+ RUNKS=""
+fi
+
+# ping command to use to test host availability (for gateway & dns servers)
+PINGOPTS="-c 3 -w 30"
+PING="ping $PINGOPTS"
+PING6="ping6 $PINGOPTS"
+
+# helper function to disable commands while running outside the initrd
+function tv() {
+ if [ -z "$testing" ]; then
+ $*
+ else
+ return 0
+ fi
+}
+
+function checkipv6()
+{
+ local ip=$1
+ [ -z "$ip" ] && return 1
+ /bin/ipcalc -c -6 "$ip" >/dev/null 2>&1
+ return $?
+}
+
+function checkipv4()
+{
+ local ip=$1
+ [ -z "$ip" ] && return 1
+ /bin/ipcalc -c -4 "$ip" >/dev/null 2>&1
+ return $?
+}
+
+function doshutdown()
+{
+ echo $"about to exec shutdown"
+ /sbin/umount -a -d -n >/dev/null 2>&1
+ exec /sbin/shutdown
+ exit 0
+}
+
+function doreboot()
+{
+ if [ -e "/sys/firmware/reipl" ]; then
+ read REIPL_TYPE < /sys/firmware/reipl/reipl_type
+ echo "reipl_type=$REIPL_TYPE"
+ pushd /sys/firmware/reipl/$REIPL_TYPE >/dev/null 2>&1
+ for i in *; do
+ echo "$i=`cat $i`"
+ done
+ popd >/dev/null 2>&1
+ fi
+
+ echo $"about to exec shutdown -r"
+ /sbin/umount -a -d -n >/dev/null 2>&1
+ exec /sbin/shutdown -r
+ exit 0
+}
+
+function sysecho () {
+ file=$1
+ shift
+ local i=1
+ while [ $i -le 10 ] ; do
+ if [ ! -f "$file" ]; then
+ sleep 1
+ i=$((i+1))
+ else
+ break
+ fi
+ done
+ [ -f "$file" ] && echo $* > $file
+}
+
+function dasd_settle() {
+ local dasd_status=/sys/bus/ccw/devices/$1/status
+ if [ ! -f $dasd_status ]; then
+ return 1
+ fi
+ local i=1
+ while [ $i -le 30 ] ; do
+ local status
+ read status < $dasd_status
+ case $status in
+ online|unformatted)
+ return 0 ;;
+ *)
+ sleep 0.1
+ i=$((i+1)) ;;
+ esac
+ done
+ return 1
+}
+
+function dasd_settle_all() {
+ for dasdccw in $(cut -d '(' -f 1 /proc/dasd/devices) ; do
+ if ! dasd_settle $dasdccw ; then
+ echo $"Could not access DASD $dasdccw in time"
+ return 1
+ fi
+ done
+ return 0
+}
+
+function startinetd()
+{
+ echo
+ echo $"Starting sshd to allow login over the network."
+ if [ -z "$testing" ]; then
+ echo $"Welcome to the anaconda install environment $VERSION for $S390ARCH" > /etc/issue.net
+ echo $"Welcome to the anaconda install environment $VERSION for $S390ARCH" > /etc/motd
+ echo >> /etc/motd
+ fi # testing
+
+ /usr/sbin/sshd -f /etc/ssh/sshd_config.anaconda
+ if [ -z "$RUNKS" ]; then
+ echo
+ echo $"Connect now to $IPADDR and log in as user 'install' to start the installation."
+ echo $"E.g. using: ssh -x install@$IPADDR"
+ echo $"For VNC or text mode, disable X11 forwarding (recommended) with 'ssh -x'."
+ echo $"For X11, enable X11 forwarding with 'ssh -X'."
+ echo
+ echo $"You may log in as the root user to start an interactive shell."
+ read
+ while : ; do
+ /bin/sh --login
+ [ $? = 0 ] || break
+ done
+ fi
+}
+
+# prints a canonocalized device bus ID for a given devno of any format
+function canonicalize_devno()
+{
+ case ${#1} in
+ 3) echo "0.0.0${1}" ;;
+ 4) echo "0.0.${1}" ;;
+ *) echo "${1}" ;;
+ esac
+ return 0
+}
+
+# read file from CMS and write it to /tmp
+function readcmsfile() # $1=dasdport $2=filename
+{
+ local dev
+ if [ $# -ne 2 ]; then return; fi
+ # precondition: udevd created dasda block device node
+ if ! dasd_cio_free -d $1 ; then
+ echo $"DASD $1 could not be cleared from device blacklist"
+ return 1
+ fi
+ # precondition: dasd_eckd_mod driver incl. dependencies loaded,
+ # dasd_mod must be loaded without setting any DASD online
+ dev=$(canonicalize_devno $1)
+ if ! sysecho /sys/bus/ccw/devices/$dev/online 1; then
+ echo $"DASD $dev could not be set online"
+ return 1
+ fi
+ udevadm settle
+ if ! dasd_settle $dev ; then
+ echo $"Could not access DASD $dev in time"
+ return 1
+ fi
+ udevadm settle
+ if ! cmsfscat -d /dev/dasda -a $2 > /tmp/$2; then
+ echo $"Could not read conf file $2 on CMS DASD $1."
+ fi
+ if ! sysecho /sys/bus/ccw/devices/$dev/online 0; then
+ echo $"DASD $dev could not be set offline again"
+ return 1
+ fi
+ udevadm settle
+ # consequences of no more module unload: loader can no longer
+ # use DASD module option to online DASDs and set other DASD parameters!
+}
+
+# adaption of the same function in init.c (udevd gets started later)
+function createDevices()
+{
+ awk '{ printf("mknod /dev/%s %s %s %s
", $1, $2, $3, $4);
+ printf("chmod %s /dev/%s
", $5, $1);
+ printf("chown %s /dev/%s
", $6, $1);
+ }' <<EOF | sh
+console c 5 1 600 root:root
+null c 1 3 666 root:root
+zero c 1 5 666 root:root
+mem c 1 1 600 root:root
+ptmx c 5 2 666 root:root
+tty c 5 0 666 root:root
+tty0 c 4 0 600 root:tty
+tty1 c 4 1 600 root:tty
+random c 1 8 644 root:root
+urandom c 1 9 644 root:root
+rtc c 10 135 644 root:root
+EOF
+ # tty handling is different from init.c since s390 does not have all
+ for i in 2 3 4 5 6 7 8 9 ; do
+ ln -s console /dev/tty$i
+ done
+ mkdir /dev/pts
+ ln -s /proc/self/fd /dev/fd
+}
+
+# approximately the main() function of init.c
+function init_main() {
+ S390ARCH=$(uname -m)
+ if [ "$S390ARCH" = "s390" ]; then
+ export S390ARCH="S/390"
+ else
+ export S390ARCH="zSeries"
+ fi
+
+ echo
+ echo $"Starting the $S390ARCH initrd to configure networking. Version is $VERSION"
+
+ # set up env vars as we do in init.c
+ if [ $(uname -m) = "s390x" ]; then
+ LD_LIBRARY_PATH=/lib64:/usr/lib64:/usr/X11R6/lib64:/usr/kerberos/lib64:/lib:/usr/lib:/usr/X11R6/lib:/usr/kerberos/lib
+ else
+ LD_LIBRARY_PATH=/lib:/usr/lib:/usr/X11R6/lib:/usr/kerberos/lib
+ fi
+ export LD_LIBRARY_PATH
+
+ PATH="$PATH:/usr/bin:/bin:/sbin:/usr/sbin:/mnt/sysimage/bin:/mnt/sysimage/usr/bin:/mnt/sysimage/usr/sbin:/mnt/sysimage/sbin:/mnt/sysimage/usr/X11R6/bin"
+ export PATH
+ HOME=/
+ export HOME
+ PYTHONPATH=/tmp/updates
+ export PYTHONPATH
+
+ if [ -z "$testing" ]; then
+
+ mount -t proc none /proc
+
+ mount -t tmpfs none /dev
+ createDevices
+ # udevd req'd by udevadm settle (/dev/.udev/queue)
+ # in readcmsfile, dialog_network_table, semantic_check_subchannels.
+ # (important: start udevd at the right time, e.g. after setup of /dev)
+ echo $"Starting udev..."
+ udevd --daemon
+ # debug: udevadm control --log-priority=debug
+
+ udevadm control --env=ANACONDA=1
+
+ mount -t devpts /dev/pts /dev/pts
+ mount -t sysfs none /sys
+
+ # remount root fs rw
+ mount /dev/root / -o remount,rw
+
+ # limit output on 3270 console
+ # (console_loglevel of 4 is just right to not get driver info,
+ # e.g. from qeth, since that would mix up with the user dialog)
+ echo "4 4 1 7" > /proc/sys/kernel/printk
+
+ # make /tmp/ramfs
+ mount -t ramfs none /tmp
+
+ # start rsyslogd after mount of /tmp ramfs since it logs to /tmp/syslog
+ echo $"Starting rsyslogd..."
+ rsyslogd -c 4
+
+ ifconfig lo 127.0.0.1 netmask 255.0.0.0
+ route add -host 127.0.0.1 dev lo
+
+ echo -e "127.0.0.1 localhost.localdomain localhost localhost4 localhost4.localdomain4" > /etc/hosts
+ echo -e "::1 localhost.localdomain localhost localhost6 localhost6.localdomain6" >> /etc/hosts
+
+ /bin/dbus-uuidgen --ensure &
+ [ $? != 0 ] && echo "error on calling /bin/dbus-uuidgen --ensure"
+ /bin/dbus-daemon --system &
+ [ $? != 0 ] && echo "error on calling /bin/dbus-daemon --system"
+
+ fi # testing
+}
+
+# trigger udev to automatically load device drivers
+function udev_setup() {
+ if [ -z "$testing" ]; then
+ # debug: udevadm monitor &
+ udevadm trigger
+ udevadm settle
+ fi # testing
+}
+
+# from here on accesses to sysfs try to follow
+# linux/Documentation/sysfs-rules.txt
+
+### lsznet.raw integration
+
+declare -a nettable
+
+function read_lsznet_output() {
+ count=0
+ local line
+ while read line; do
+ nettable[$count]="$line"
+ count=$((count + 1))
+ # using the more sophisticated process substitution instead of temp file
+ # requires the symlink /dev/fd -> /proc/self/fd => createDevices
+ done < <(/lib/s390-tools/lsznet.raw)
+}
+
+function print_nettable() {
+ local fmtstring="%3s %-14s %-7s %-5s %-4s %-6s %-7s %s
"
+ printf "$fmtstring"
+ "NUM" "CARD" "CU" "CHPID" "TYPE" "DRIVER" "IF" "DEVICES"
+ local i
+ for ((i=0; i < count; i++)); do
+ local item cutype chp chpidtype devdrv devname chlist cardtype
+ read item cutype chp chpidtype devdrv devname chlist cardtype <<< ${nettable[$i]}
+ printf "$fmtstring"
+ $item "$cardtype" $cutype $chp "$chpidtype" $devdrv $devname $chlist
+ done
+}
+
+function clear_screen() {
+ # FIXME: find a way to clear screen despite 3215 line mode terminal
+ echo
+}
+
+function dialog_network_table() {
+ while : ; do
+ echo $"Scanning for available network devices..."
+ # This may take a long time so we show "progress":
+ #( while true; do echo -n "."; sleep 1; done ) &
+ #local childpid=$!
+ read_lsznet_output
+ #kill $childpid
+ #echo
+ echo $"Autodetection found ${count} devices."
+ # count==0: there might still be a blacklist the user wants to clear.
+ # do not flood user with long list if there are many devices
+ if [ "$count" -le 15 ]; then
+ # Show list
+ answer=s
+ else # [ $count -gt 15 ]
+ echo
+ while : ; do
+ echo $"s) show all, m) manual config:"
+ local answer
+ read answer
+ case $answer in
+ s|m) break ;;
+ esac
+ done
+ fi
+ [ "$answer" = "m" ] && break
+ # show network table to select network hardware configuration from
+ if [ "$count" -gt 0 ]; then
+ clear_screen
+ print_nettable
+ echo
+ fi
+ # account for possibly ignored common I/O devices
+ # cio_wc_bytes is NOT local so it can be re-used outside this function
+ cio_wc_bytes=0
+ local cio_wc_filename cio_wc_foo
+ if [ -f /proc/cio_ignore ]; then
+ local cio_wc=$(wc -c /proc/cio_ignore)
+ read cio_wc_bytes cio_wc_filename cio_wc_foo <<< "$cio_wc"
+ if [ "$cio_wc_bytes" != "0" ]; then
+ echo $"Note: There is a device blacklist active! (Clearing might take long)"
+ #cat /proc/cio_ignore | tr '
' ','
+ #echo
+ else
+ if [ "$count" -eq 0 ]; then
+ # count==0 AND no device blacklist => manual mode
+ echo $"Entering manual configuration mode."
+ break
+ fi
+ fi
+ fi
+ # selection dialog
+ while : ; do
+ [ "$count" -gt 0 ] && echo -n $"<num>) use config, "
+ [ "$cio_wc_bytes" != "0" ] && echo -n $"c) clear blacklist, "
+ echo $"m) manual config, r) rescan, s) shell:"
+ local choice
+ read choice
+ [ -z "$choice" ] && continue
+ if [ "$choice" = "s" ]; then
+ echo $"Enter 'exit' at the shell prompt to get back to the installation dialog."
+ /bin/bash
+ continue 2
+ fi
+ [ "$choice" = "m" ] && break
+ [ "$choice" = "r" ] && continue 2
+ [ "$cio_wc_bytes" != "0" -a "$choice" = "c" ] && break
+ [[ "$choice" =~ ^[[:digit:]]+$ ]]
+ case $? in
+ 0)
+ # string matched the pattern
+ [ "$choice" -ge 1 -a "$choice" -le "$count" ] && break
+ ;;
+ 1)
+ # string did not match the pattern
+ continue
+ ;;
+ 2)
+ echo "l.$LINENO: syntax error in regex of match operator =~, code needs to be fixed" 1>&2
+ ;;
+ *)
+ echo "l.$LINENO: unexpected return code of regex match operator =~, code needs to be fixed" 1>&2
+ ;;
+ esac
+ done
+ if [ "$choice" = "c" ]; then
+ echo $"Clearing device blacklist..."
+ cio_ignore -R || echo $"Device blacklist could not be cleared"
+ fi
+ [ "$choice" = "m" ] && break
+ # finally extract config info from selected item
+ # array nettable starts at index zero, user input starts at index one
+ choice=$((choice - 1))
+ local item cutype chp chpidtype devdrv devname chlist cardtype
+ read item cutype chp chpidtype devdrv devname chlist cardtype <<< ${nettable[$choice]}
+ # $NETTYPE happens to be exactly the network driver name
+ if [ "$devdrv" = "ctcm" ]; then
+ NETTYPE="ctc"
+ else
+ NETTYPE=$devdrv
+ fi
+ SUBCHANNELS=$chlist
+ break
+ done
+ echo
+}
+
+declare -r PREFIXFORMAT=[[:xdigit:]]*
+declare -r SSIDFORMAT=[0-3]
+declare -r BUSIDFORMAT=[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]
+declare -r IDFORMAT=$PREFIXFORMAT.$SSIDFORMAT.$BUSIDFORMAT
+declare -r SUBCHANNEL_TYPE_IO=0
+
+. /lib/s390-tools/znetcontrolunits
+
+function cardtype2cleartext() {
+ local cardtype=$1
+ case $cardtype in
+ OSD_10GIG) echo "OSA card in OSD mode, 10 Gigabit Ethernet" ;;
+ OSD_1000) echo "OSA card in OSD mode, Gigabit Ethernet" ;;
+ OSD_100) echo "OSA card in OSD mode, Fast Ethernet" ;;
+ OSD_GbE_LANE) echo "OSA card in OSD mode, Gigabit Ethernet, LAN Emulation" ;;
+ OSD_FE_LANE) echo "OSA card in OSD mode, Fast Ethernet, LAN Emulation" ;;
+ OSD_TR_LANE) echo "OSA card in OSD mode, Token Ring, LAN Emulation" ;;
+ OSD_ATM_LANE) echo "OSA card in OSD mode, ATM, LAN Emulation" ;;
+ OSD_Express) echo "OSA card in OSD mode, unknown link type" ;;
+ HSTR) echo "OSA card in OSD mode, High Speed Token Ring" ;;
+ OSN) echo "OSA for NCP, ESCON/CDLC bridge" ;;
+ HiperSockets) echo "HiperSockets with CHPID type IQD" ;;
+ "GuestLAN QDIO") echo "GuestLAN based on OSA (QDIO)" ;;
+ "GuestLAN Hiper") echo "GuestLAN based on HiperSockets" ;;
+ unknown) echo "other" ;;
+ *) echo "unknown"
+ echo "l.$LINENO: found unknown card_type, code needs to be fixed" 1>&2
+ ;;
+ esac
+}
+
+# returns true iff running under z/VM
+function isVM() {
+ local cpu_version=$(cat /proc/cpuinfo |grep "^processor " | head -n1 | sed 's/.*version = ([[:xdigit:]][[:xdigit:]]).*/1/' | tr '[:lower:]' '[:upper:]')
+ if [ "$cpu_version" = "FF" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# watch out: potential error message as side effect
+function isLayer2Default() {
+ # Read default from sysfs because according to device
+ # drivers book there are differences in the default between
+ # OSA (l2), hipersockets (l3).
+ # This only works here in installer where nobody has overwritten
+ # the default setting with another custom value already!
+ if [ ! -f /sys/devices/${NETTYPE}/$SCH_R_DEVBUSID/layer2 ]; then
+ echo $"Could not read layer mode from sysfs"
+ return 1
+ fi
+ local layer2
+ read layer2 < /sys/devices/${NETTYPE}/$SCH_R_DEVBUSID/layer2
+ if [ "$layer2" = "1" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# returns true iff either LAYER2 has been set to 1 or is the default
+# watch out: potential error message as side effect
+function isLayer2() {
+ case "x$LAYER2" in
+ x0) return 1 ;; # layer 3
+ x1) return 0 ;; # layer 2
+ x) # LAYER2 is unset or empty => qeth driver default applies.
+ isLayer2Default
+ return $?
+ ;;
+ *) echo "l.$LINENO: unknown value "$LAYER2" for LAYER2, code needs to be fixed" 1>&2
+ return 2 ;;
+ esac
+}
+
+# returns true iff qeth device $SCH_R_DEVBUSID
+# is capable of supporting IPv6
+# watch out: potential error message as side effect
+function ipv6_capable() {
+ [ "$NETTYPE" = "qeth" ] || return 1
+ case $cardtype in
+ OSD_10GIG|OSD_1000|OSD_100|OSD_Express|HiperSocket s|"GuestLAN QDIO")
+ return 0 ;;
+ OSD_GbE_LANE|OSD_FE_LANE|OSD_TR_LANE|OSD_ATM_LANE) return 1 ;;
+ HSTR|OSN|unknown) return 1 ;;
+ "GuestLAN Hiper") return 1 ;;
+ *) echo $"Unknown card_type to determine IPv6 support"
+ return 1 ;;
+ esac
+}
+
+# sets device online _and_ retrieves DEVICE at the same time
+function set_device_online() {
+ echo $"Activating network device..."
+ local sysnettype
+ case "${NETTYPE}" in
+ qeth|lcs) sysnettype=${NETTYPE} ;;
+ ctc) sysnettype=ctcm ;;
+ esac
+ if ! [ -f /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/online ]; then
+ echo $"Sysfs path to set device online does not exist."
+ return 1
+ fi
+ if ! sysecho /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/online "1"; then
+ echo $"Could not set device ($SUBCHANNELS) online"
+ return 1
+ fi
+ udevadm settle
+ local i=1
+ while : ; do
+ local online
+ read online < /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/online
+ [ "$online" == "1" ] && break
+ sleep 1
+ i=$((i+1))
+ if [ "$i" -gt 10 ]; then
+ echo $"Could not set device ($SUBCHANNELS) online within timeout"
+ return 1
+ fi
+ done
+ if [ "$NETTYPE" = "lcs" -o "$NETTYPE" = "ctc" ]; then
+ if [ ! -d /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/net ]; then
+ echo $"Device $SUBCHANNELS does not have required sysfs directory 'net'"
+ return 1
+ fi
+ DEVICE=$(ls /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/net/)
+ if [ "$DEVICE" = "" ]; then
+ echo $"Could not get device name for $SUBCHANNELS"
+ return 1
+ fi
+ else # qeth
+ if [ ! -f /sys/devices/qeth/$SCH_R_DEVBUSID/if_name ]; then
+ echo $"Device $SUBCHANNELS does not have required sysfs attribute 'if_name'"
+ return 1
+ fi
+ # (device needs to be online to read if_name from sysfs attribute!)
+ read DEVICE < /sys/devices/qeth/$SCH_R_DEVBUSID/if_name
+ if [ "$DEVICE" = "" ]; then
+ echo $"Could not get device name for $SUBCHANNELS"
+ return 1
+ fi
+ if [ -f /sys/devices/qeth/$SCH_R_DEVBUSID/card_type ]; then
+ read cardtype < /sys/devices/qeth/$SCH_R_DEVBUSID/card_type
+ #debug echo "$cardtype"
+ # device is now online and link type will be known
+ echo -n $"Detected: "
+ cardtype2cleartext "$cardtype"
+ else
+ echo $"Could not read qeth network card type from sysfs."
+ fi
+ fi
+}
+
+# sets device up and blocks until device appears to be up
+function set_device_up() {
+ if [ -z "$DEVICE" ]; then
+ echo $"Could not determine interface name to bring up device $SUBCHANNELS"
+ return 1
+ fi
+ # Device does not come up fast enough to use "ip" to configure, so block.
+ # While OSA come up themselves after setting online,
+ # e.g. HiperSockets won't => set them up explicitly for the following check
+ debug ip link set up $DEVICE
+ local i=1
+ while : ; do
+ local tst=$(ip -o link show up dev $DEVICE)
+ [ -n "$tst" ] && break
+ sleep 1
+ i=$((i+1))
+ if [ "$i" -gt 10 ]; then
+ echo $"Could not bring up device $DEVICE within timeout"
+ return 1
+ fi
+ done
+ return 0
+}
+
+function syntax_check_domainname() {
+ # - match against regex adopted from RFC1035,sec.2.3.1 or RFC1034,sec.3.5
+ # (Internationalized Domain Names in Applications (IDNA) [RFC4690]
+ # have to be entered after encoding by punycode [RFC3492])
+ [[ "$1" =~ ^[[:alpha:]]([[:alnum:]-]{0,61}[[:alnum:]])?(.[[:alpha:]]([[:alnum:]-]{0,61}[[:alnum:]])?)*$ ]]
+ case $? in
+ 0)
+ # string matched the pattern
+ return 0
+ ;;
+ 1)
+ # string did not match the pattern
+ echo "$2"
+ ;;
+ 2)
+ echo "l.$LINENO: syntax error in regex of match operator =~, code needs to be fixed" 1>&2
+ ;;
+ *)
+ echo "l.$LINENO: unexpected return code of regex match operator =~, code needs to be fixed" 1>&2
+ ;;
+ esac
+ return 1
+}
+
+function disable_ipv6_autoconf() {
+ sysctl -w net.ipv6.conf.all.accept_ra=0 > /dev/null
+ sysctl -w net.ipv6.conf.all.accept_redirects=0 > /dev/null
+ sysctl -w net.ipv6.conf.all.autoconf=0 > /dev/null
+ sysctl -w net.ipv6.conf.default.accept_ra=0 > /dev/null
+ sysctl -w net.ipv6.conf.default.accept_redirects=0 > /dev/null
+ sysctl -w net.ipv6.conf.default.autoconf=0 > /dev/null
+}
+
+function configure_ipv6_address() {
+ # device needs to be online
+ # arp flag needs to be on for ipv6 over osa because of ndisc.
+ # happens automatically by the driver. do NOT mess with default setting.
+ #NO#debug ip link set dev $DEVICE arp on
+ if ! debug ip -6 address add $IPADDR/$NETMASK dev $DEVICE; then
+ echo $"Could net set IPv6 address $IPADDR/$NETMASK for device $DEVICE"
+ return 1
+ fi
+ # network route has been set by above "ip address add" already
+ # take care of MTU, which is bundled with ifconfig in the other IPv4 cases
+ if [ -n "$MMTU" ]; then
+ if ! debug ip link set $DEVICE $MMTU; then
+ echo $"Could net set maximum transfer unit ($MMTU) for device $DEVICE"
+ return 1
+ fi
+ fi
+ return 0
+}
+
+function configure_ipv4_address() {
+ # it's IPv4 and we can make use of ipcalc for better usability
+ if ipcalc -bmnp $ipcalc_arg > /tmp/ipcalc.$$.out 2> /dev/null; then
+ . /tmp/ipcalc.$$.out
+ else
+ echo $"Could not calculate network address and broadcast address from"
+ echo $" IPv4 address $IPADDR and netmask $NETMASK"
+ return 1
+ fi
+ rm /tmp/ipcalc.$$.out
+ # device needs to be online
+ if ! debug ifconfig $DEVICE $IPADDR $MMTU netmask $NETMASK broadcast $BROADCAST; then
+ echo $"Could not set IPv4 address $IPADDR for device $DEVICE"
+ echo $" with network mask $NETMASK and broadcast address $BROADCAST"
+ [ -n "$MMTU" ] && echo $" and maximum transfer unit: $MMTU"
+ return 1
+ fi
+ # This network route is already there after ifconfig!
+ #if ! debug route add -net $NETWORK netmask $NETMASK dev $DEVICE; then
+ # echo $"Could not add network route to $NETWORK/$NETMASK on device $DEVICE"
+ # return 1
+ #fi
+ return 0
+}
+
+function handle_mtu() {
+ # don't ask for MTU, but use it if it has been set in the .parm file
+ # don't overwrite MMTU if it has been set for CTC
+ [ -n "$MTU" -a -z "$MMTU" ] && MMTU="mtu $MTU"
+}
+
+function rollback_config() {
+ # each transaction to roll back may fail, if previous setup has not
+ # made progress that far to reach a certain transation
+ # => error output is misleading and should be avoided
+ [ -n "$DEVICE" ] && tv ip -4 route flush default dev $DEVICE
+ [ -n "$DEVICE" ] && tv ip -6 route flush default dev $DEVICE
+ # address flush seems to be effective for all address families
+ [ -n "$DEVICE" ] && ip address flush dev $DEVICE
+ if [ -n "$NETTYPE" ]; then
+ if [ -n "$SCH_R_DEVBUSID" ]; then
+ local sysnettype
+ case "${NETTYPE}" in
+ qeth|lcs) sysnettype=${NETTYPE} ;;
+ ctcm) sysnettype=ctcm ;;
+ esac
+ [ -f /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/online ] &&
+ sysecho /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/online "0"
+ udevadm settle
+ [ -f /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/ungroup ] &&
+ sysecho /sys/devices/${sysnettype}/$SCH_R_DEVBUSID/ungroup "1"
+ udevadm settle
+ fi
+ fi
+ [ -z "$mtu_was_set" ] && unset MTU
+ [ -z "$mmtu_was_set" ] && unset MMTU
+ [ -z "$vswitch_was_set" ] && unset VSWITCH
+ # prevent possible reuse of an old DEVICE on restarting dialog
+ unset DEVICE
+ # set activated DASDs offline again
+ local dasd
+ while read dasd < /proc/dasd/devices; do
+ dasd=${dasd%%(*}
+ sysecho /sys/bus/ccw/devices/$dasd/online 0
+ done
+ udevadm settle
+}
+
+### workflow helper functions
+
+# workflow ideas:
+# - setting/applying single configuration steps right away save us explicit
+# syntactical & semantic checks PLUS we get direct feedback on error
+# - check error level of forked external programs and react on errors
+
+unset reenter
+unset redoitem
+unset interaction_happened
+
+function reenter() {
+ [ -z "$reenter" ] && return 1
+ # reenter menu should only be shown if NOT redoing item
+ if [ -n "$redoitem" ]; then
+ # unset redoitem # wrong => do NOT do this here
+ return 1
+ fi
+ return 0
+}
+
+function reenter_menu() {
+ local oldvalue=$1
+ interaction_happened="yes"
+ # unsetting input here is not sufficient, since reenter_menu
+ # is not called for predefined parameters
+ # which then might get assigned a previous old input of another parameter!
+ #unset input
+ reenter || return 0
+ # don't present reenter menu for empty parameters
+ # (currently ignoring parameters that are allowed to be empty!)
+ # this could be improved by checking if variable has been set/defined
+ #[ -z "$1" ] && return 0
+ while : ; do
+ if [ -n "$helptext" ]; then
+ echo $"0) default is previous "$oldvalue", 1) new value, ?) help"
+ else
+ echo $"0) default is previous "$oldvalue", 1) new value"
+ fi
+ # uncoded alternative: 2) skip parameter
+ local answer
+ read answer
+ [ -z "$answer" ] && return 1
+ case $answer in
+ 0) return 1 ;;
+ 1) # Deciding to enter new value gets user out of reenter-mode
+ # temporarily for this parameter.
+ # To put it differently: redoing does NOT present old values.
+ redoitem="yes"
+ echo -n $"new value: "
+ return 0
+ ;;
+ "?") input="?"
+ return 1
+ ;;
+ esac
+ done
+}
+
+function workflow_item_menu() {
+ local noredo=$1
+ # default is to continue if running kickstart to prevent interaction
+ [ -n "$RUNKS" ] && return 0
+ interaction_happened="yes"
+ while : ; do
+ unset redoitem
+ if [ "$noredo" = "noredo" ]; then
+ echo $"1) continue, 2) restart dialog, 3) halt, 4) shell"
+ else
+ echo $"0) redo this parameter, 1) continue, 2) restart dialog, 3) halt, 4) shell"
+ fi
+ local answer
+ read answer
+ case $answer in
+ 0) [ "$noredo" = "noredo" ] && continue
+ redoitem="yes"
+ continue 2
+ ;;
+ 1) return 0 ;; # can be used to break at caller on ignore
+ 2) reenter="yes"
+ rollback_config
+ continue 3
+ ;;
+ 3) tv doshutdown
+ exit 0
+ ;;
+ 4) echo $"Enter 'exit' at the shell prompt to get back to the installation dialog."
+ /bin/bash
+ if [ "$noredo" != "noredo" ] && [ -n "$question_prefix" ]; then
+ $question_prefix
+ echo
+ fi
+ ;; # stay in workflow item menu
+ esac
+ done
+}
+
+# input variables: PARMNAME, question_prefix, question_choices,
+# "options" ...
+# output variables: $question_prefix, $helptext
+# modifies: the variable named $PARMNAME, $OPTIND
+function ask() {
+ [ $# -lt 3 ] && echo "l.$LINENO: too few arguments (<3), please fix calling code." 1>&2
+ local PARMNAME=$1
+ shift
+ question_prefix=$1
+ shift
+ local question_choices=$1
+ shift
+ local exception
+ local syntax_check
+ unset helptext
+ local handle
+ local finish
+ local optname
+ OPTIND=1
+ while getopts ":e:s:h:c:f:" optname; do
+ case $optname in
+ e) exception=$OPTARG ;;
+ s) syntax_check=$OPTARG ;;
+ h) helptext=$OPTARG ;;
+ c) handle=$OPTARG ;;
+ f) finish=$OPTARG ;;
+ "?") ;; # ignore invalid option
+ :) echo "l.$LINENO: Missing parameter to option -$OPTARG" 1>&2 ;;
+ esac
+ done
+ while : ; do
+ unset input
+ local input
+ # actually ask question if one of the following is true:
+ # - $PARMNAME parameter has not been set yet, e.g. not in parm file
+ # - on 2nd and further attempts, i.e. redoing the parameter
+ # - on having restarted the whole dialog
+ # describing the same from another viewpoint:
+ # - if $PARMNAME has been set, try to check syntax and apply
+ # - on redo, $PARMNAME has been set and reenter is false,
+ # but still ask question again
+ # - on reenter, $PARMNAME might have been set, but still ask question
+ if [ -z "${!PARMNAME}" -o -n "$redoitem" -o -n "$reenter" ]; then
+ # one empty line to separate parameter questions from each other
+ echo
+ $question_prefix
+ if reenter; then
+ echo
+ else
+ $question_choices
+ fi
+ # on reenter, give choice between old value and entering new one
+ reenter_menu ${!PARMNAME} && read input
+ && [ "$input" != "?" ] && eval ${PARMNAME}=$input
+ # escaping the $ in the RHS of the eval statement makes it safe
+ fi
+ if [ -n "$helptext" ] && [ "$input" = "?" ]; then
+ $helptext
+ continue
+ fi
+ # optional: default or exceptional handling
+ [ -n "$exception" ] && $exception
+ if [ -n "$syntax_check" -a -z "$handle" ]; then
+ # some parameters have only syntax check (and deferred config):
+ if $syntax_check; then
+ break
+ else
+ workflow_item_menu && break
+ fi
+ elif [ -n "$syntax_check" -a -n "$handle" ]; then
+ # most common parameters have syntax and configuration:
+ # user might still continue on syntax error
+ $syntax_check || workflow_item_menu
+ # optional: actual configuration
+ if $handle; then
+ # parmname has been configured successfully
+ break
+ else
+ # user might still continue on configuration failure
+ workflow_item_menu && break
+ fi
+ elif [ -n "$finish" ]; then
+ # few parameters need special handling done by their own function:
+ $finish
+ else
+ echo $"Unsupported calling of ask function, please fix calling code"
+ fi
+ done # PARMNAME
+ # disable potential temporary redoing-mode during reenter-mode
+ unset redoitem
+}
+
+### NETTYPE
+
+function syntax_check_nettype() {
+ # - NETTYPE in {qeth,lcs,ctc}
+ [[ "$NETTYPE" =~ (^qeth$)|(^lcs$)|(^ctc$) ]]
+ case $? in
+ 0)
+ # string matched the pattern
+ return 0
+ ;;
+ 1)
+ # string did not match the pattern
+ ;;
+ 2)
+ echo "l.$LINENO: syntax error in regex of match operator =~, code needs to be fixed" 1>&2
+ ;;
+ *)
+ echo "l.$LINENO: unexpected return code of regex match operator =~, code needs to be fixed" 1>&2
+ ;;
+ esac
+ echo $"Incorrect format or value for network type (NETTYPE): $NETTYPE"
+ return 1
+}
+
+function question_prefix_nettype() {
+ echo -n $"Network type"
+}
+
+function question_choices_nettype() {
+ echo $" (qeth, lcs, ctc, ? for help). Default is qeth:"
+}
+
+function helptext_nettype() {
+ echo $" Help text for network type:"
+ echo $" qeth: OSA-Express Fast Ethernet, Gigabit Ethernet (including 1000Base-T),"
+ echo $" High Speed Token Ring, Hipersockets, and ATM (running Ethernet LAN emulation)"
+ echo $" features in QDIO mode."
+ echo $" [default]"
+ echo $" lcs: OSA-2 Ethernet/Token Ring, OSA-Express Fast Ethernet in non-QDIO mode,"
+ echo $" OSA-Express High Speed Token Ring in non-QDIO mode and Gigabit Ethernet"
+ echo $" in non-QDIO mode."
+ echo $" ctc: Deprecated, useful for migration."
+}
+
+function exception_nettype() {
+ # - default is qeth since it should be common
+ if [ -z "$NETTYPE" ]; then
+ NETTYPE=qeth
+ break
+ fi
+}
+
+function finish_nettype() {
+ if syntax_check_nettype; then
+ break
+ else
+ # necessary parts which would otherwise be done by workflow_item_menu
+ interaction_happened="yes"
+ redoitem="yes"
+ fi
+}
+
+function do_nettype() {
+ ask NETTYPE
+ question_prefix_nettype question_choices_nettype
+ -h helptext_nettype -e exception_nettype -f finish_nettype
+}
+
+### CHANDEV
+
+function do_chandev() {
+ echo
+ echo $"The CHANDEV variable isn't used anymore, please update your "
+ echo $".parm or the .conf file to use NETTYPE, SUBCHANNELS, etc. instead."
+ echo
+}
+
+### SUBCHANNELS
+
+function syntax_check_subchannels() {
+ SUBCHANNELS=$(echo $SUBCHANNELS | tr ABCDEF abcdef)
+ # - make subchannel question dependent on NETTYPE (2 vs. 3 subchannels)
+ if [ "$NETTYPE" = "qeth" ]; then
+ # - match against regex, depending on qeth
+ [[ "$SUBCHANNELS" =~ ^[[:xdigit:]]+.[0-3].[[:xdigit:]]{4},[[:xdigit:]]+.[0-3].[[:xdigit:]]{4},[[:xdigit:]]+.[0-3].[[:xdigit:]]{4}$ ]]
+ else
+ # - match against regex, depending on lcs/ctc
+ [[ "$SUBCHANNELS" =~ ^[[:xdigit:]]+.[0-3].[[:xdigit:]]{4},[[:xdigit:]]+.[0-3].[[:xdigit:]]{4}$ ]]
+ fi
+ case $? in
+ 0)
+ # string matched the pattern
+ return 0
+ ;;
+ 1)
+ # string did not match the pattern
+ echo $"Incorrect format for channels (SUBCHANNELS): $SUBCHANNELS"
+ ;;
+ 2)
+ echo "l.$LINENO: syntax error in regex of match operator =~, code needs to be fixed" 1>&2
+ ;;
+ *)
+ echo "l.$LINENO: unexpected return code of regex match operator =~, code needs to be fixed" 1>&2
+ ;;
+ esac
+ return 1
+}
+
+function semantic_check_subchannels() {
+ local subch_count
+ if [ "$NETTYPE" = "qeth" ]; then
+ subch_count=3
+ else
+ subch_count=2
+ fi
+ # done: make subchannel handling more robust by not relying on REMATCH
+ local -a subch_array
+ IFS=,
+ read -a subch_array <<< "indexzero,$SUBCHANNELS"
+ unset IFS
+ local i
+ local all_subch_good=0
+ for ((i=1; i <= $subch_count; i++)); do
+ local devbusid=${subch_array[$i]}
+ # remember first subchannel for potential undo of ccwgroup
+ # (via /sys/devices/qeth/$SCH_R_DEVBUSID/ungroup)
+ [ "$i" -eq 1 ] && SCH_R_DEVBUSID=$devbusid
+ local prefix ssid devno foo
+ IFS=.
+ read prefix ssid devno foo <<< "$devbusid"
+ unset IFS
+ local dev_p=$(echo /sys/devices/css$prefix/$IDFORMAT/$devbusid)
+ # - check for existence of devnos in sysfs
+ if [ ! -d "$dev_p" -a "$cio_wc_bytes" != "0" ]; then
+ # - try to free from /proc/cio_ignore if they don't exist
+ echo $"Device $devbusid not present, trying to clear from blacklist and resense..."
+ if ! znet_cio_free -d $devbusid; then
+ echo $"Device $devbusid could not be cleared from device blacklist"
+ fi
+ fi
+ # reevaluate since globbing might not have worked before device existed
+ dev_p=$(echo /sys/devices/css$prefix/$IDFORMAT/$devbusid)
+ if [ ! -d "$dev_p" ]; then
+ echo $"Device $devbusid does not exist"
+ all_subch_good=1
+ continue
+ fi
+ # devno does exist now
+ local subch_p=${dev_p%/*}
+ local subch=${subch_p##*/}
+ # filter definitely unusable subchannels ...
+ # - check for subchannel type I/O
+ if [ -f $subch_p/type ]; then
+ local type
+ read type < $subch_p/type
+ if [ "$type" != "$SUBCHANNEL_TYPE_IO" ]; then
+ echo $"Channel $subch (device $devbusid) is not of type I/O"
+ all_subch_good=1
+ continue
+ fi
+ fi
+ # - check for correct CU type/model, depending on qeth/lcs/ctc
+ if [ ! -f $dev_p/cutype ]; then
+ echo $"Device $devbusid does not have required sysfs attribute 'cutype'"
+ all_subch_good=1
+ continue
+ fi
+ local cutype
+ read cutype < $dev_p/cutype
+ if search_cu $cutype; then
+ local driver
+ if [ "$NETTYPE" = "ctc" ]; then
+ driver="ctcm"
+ else
+ driver=$NETTYPE
+ fi
+ if [ "${CU_DEVDRV[$cu_idx]}" != "$driver" ]; then
+ echo $"Device $devbusid has control unit type $cutype,"
+ echo $" which does not match your selected network type $NETTYPE"
+ all_subch_good=1
+ continue
+ fi
+ else
+ echo $"Device $devbusid has control unit type $cutype which is unknown"
+ all_subch_good=1
+ continue
+ fi
+ # read CHPIDs information about subchannels
+ if [ ! -f $subch_p/chpids ]; then
+ echo $"Channel $subch (device $devbusid) does not have required sysfs attribute 'chpids'"
+ all_subch_good=1
+ continue
+ fi
+ local chpid_list
+ read chpid_list < $subch_p/chpids
+ local -a chpids
+ read -a chpids <<< "$chpid_list"
+ if [ ${#chpids[@]} -ne 8 ]; then
+ echo $"sysfs reported ${#chpids[@]} CHPIDs instead of expected 8, code needs fix"
+ fi
+ if [ ! -f $subch_p/pimpampom ]; then
+ echo $"Channel $subch (device $devbusid) does not have required sysfs attribute 'pimpampom'"
+ all_subch_good=1
+ continue
+ fi
+ local pim pam pom foo
+ read pim pam pom foo < $subch_p/pimpampom
+ local pimchpidZ=""
+ for ((chp=0; chp < 8; chp++)); do
+ local mask=$((0x80 >> chp))
+ if (( 0x$pim & $mask )); then
+ pimchpidZ=${pimchpidZ}${chpids[chp]}
+ else
+ pimchpidZ=${pimchpidZ}"ZZ"
+ fi
+ done
+ local pimchpids=${pimchpidZ//ZZ/}
+ if [ "x$pimchpids" == "x" ]; then
+ echo $"Channel $subch (device $devbusid) does not have any installed channel path"
+ all_subch_good=1
+ continue
+ fi
+ # compare parts of different subchannels for required matches
+ if [ "$i" -eq 1 ]; then
+ # remember parts of first subchannel for comparison
+ local sch_r_prefix=$prefix
+ local sch_r_ssid=$ssid
+ local sch_r_devno=$devno
+ local sch_r_pimchipidZ=$pimchpidZ
+ local sch_r_cutype=$cutype
+ else
+ local comparison=0
+ # $sch_r_... might be empty if first channel was wrong
+ # => be sure to quote all variable accesses in test statements.
+ # - all subchannels must be of same CU type/model
+ if [ "$cutype" != "$sch_r_cutype" ]; then
+ echo $"Device $devbusid does not have the same control unit type as device $SCH_R_DEVBUSID"
+ comparison=1
+ fi
+ # - all subchannels must have same CHPIDs
+ if [ "$pimchpidZ" != "$sch_r_pimchipidZ" ]; then
+ echo $"Device $devbusid does not have the same CHPIDs as device $SCH_R_DEVBUSID"
+ comparison=1
+ fi
+ # - all subchannels should have same prefix & ssid ?
+ if [ "$prefix" != "$sch_r_prefix"
+ -o "$ssid" != "$sch_r_ssid" ]; then
+ echo $"Device $devbusid does not have the same prefix and subchannel set ID as device $SCH_R_DEVBUSID"
+ comparison=1
+ fi
+ if [ "$i" -eq 2 ]; then
+ local sch_w_devbusid=$devbusid
+ local sch_w_devno=$devno
+ # TODO: not true for CTCM => relax
+ # - write_devbusid == read_devbusid+1
+ if [ $((0x$devno)) -ne $((0x$sch_r_devno + 1)) ]; then
+ echo $"Device bus ID of write channel (dev $devbusid) must be one larger than"
+ echo $" that of read channel (dev $SCH_R_DEVBUSID)"
+ comparison=1
+ fi
+ elif [ "$i" -eq 3 ]; then
+ # check data subchannel unequal to read/write subchannel
+ # (also seems to be handled by ccwgroup kernel subsystem)
+ if [ "$devbusid" = "$sch_w_devbusid"
+ -o "$devbusid" = "$SCH_R_DEVBUSID" ]; then
+ echo $"Device bus ID of data channel (dev $devbusid) must be different to that of"
+ echo $" read channel ($SCH_R_DEVBUSID) and write channel ($sch_w_devbusid)"
+ comparison=1
+ fi
+ fi
+ if [ "$comparison" != 0 ]; then
+ all_subch_good=1
+ continue
+ fi
+ fi
+ # filter potentially good subchannels ...
+ if [ -h $dev_p/group_device ]; then
+ echo $"Device $devbusid is already in a ccwgroup and thus unavailable"
+ all_subch_good=1
+ continue
+ fi
+ if [ ! -f $dev_p/online ]; then
+ echo $"Device $devbusid does not have required sysfs attribute 'online'"
+ all_subch_good=1
+ continue
+ fi
+ local online
+ read online < $dev_p/online
+ if [ "$online" = "1" ]; then
+ echo $"Device $devbusid is already in use and thus unavailable"
+ all_subch_good=1
+ continue
+ fi
+ # - check availability
+ if [ ! -f $dev_p/availability ]; then
+ echo $"Device $devbusid does not have required sysfs attribute 'availability'"
+ all_subch_good=1
+ continue
+ fi
+ local availability
+ read availability < $dev_p/availability
+ if [ "$availability" != "good" ]; then
+ echo $"Device $devbusid is not available but '$availiability'"
+ all_subch_good=1
+ continue
+ fi
+
+ done # for ((i=1; i <= $subch_count; i++))
+ if [ "$all_subch_good" = "0" ]; then
+ return 0
+ fi
+ return 1
+}
+
+function handle_subchannels() {
+ # - try to establish ccwgroup right here and fail out on error
+ local driver
+ if [ "$NETTYPE" = "ctc" ]; then
+ driver="ctcm"
+ else
+ driver=$NETTYPE
+ fi
+ # if necessary,
+ # rebind hybrid devices (3088/08 and 3088/1f) to user specified driver
+ local curdrv
+ curdrv=$(readlink /sys/bus/ccw/devices/$SCH_R_DEVBUSID/driver)
+ curdrv=${curdrv##*/}
+ if [ "$curdrv" = "lcs" -a "$NETTYPE" = "ctc" ]; then
+ sysecho /sys/bus/ccw/drivers/lcs/unbind "$SCH_R_DEVBUSID"
+ sysecho /sys/bus/ccw/drivers/ctcm/bind "$SCH_R_DEVBUSID"
+ fi
+ if [ "$curdrv" = "ctcm" -a "$NETTYPE" = "lcs" ]; then
+ sysecho /sys/bus/ccw/drivers/ctcm/unbind "$SCH_R_DEVBUSID"
+ sysecho /sys/bus/ccw/drivers/lcs/bind "$SCH_R_DEVBUSID"
+ fi
+ local channel2
+ channel2=${SUBCHANNELS##*,}
+ curdrv=$(readlink /sys/bus/ccw/devices/$channel2/driver)
+ curdrv=${curdrv##*/}
+ if [ "$curdrv" = "lcs" -a "$NETTYPE" = "ctc" ]; then
+ sysecho /sys/bus/ccw/drivers/lcs/unbind "$channel2"
+ sysecho /sys/bus/ccw/drivers/ctcm/bind "$channel2"
+ fi
+ if [ "$curdrv" = "ctcm" -a "$NETTYPE" = "lcs" ]; then
+ sysecho /sys/bus/ccw/drivers/ctcm/unbind "$channel2"
+ sysecho /sys/bus/ccw/drivers/lcs/bind "$channel2"
+ fi
+ # create ccwgroup
+ if sysecho /sys/bus/ccwgroup/drivers/${driver}/group "$SUBCHANNELS"; then
+ udevadm settle
+ case "$NETTYPE" in
+ qeth)
+ # Just preliminary card_type info until device goes online!
+ # In fact it seems enough to separate OSA from HiperSockets.
+ if [ -f /sys/devices/qeth/$SCH_R_DEVBUSID/card_type ]; then
+ read cardtype < /sys/devices/qeth/$SCH_R_DEVBUSID/card_type
+ else
+ echo $"Could not read qeth network card type from sysfs."
+ fi
+ ;;
+ ctc|lcs)
+ if [ -f /sys/devices/$driver/$SCH_R_DEVBUSID/type ]; then
+ local type
+ read type < /sys/devices/$driver/$SCH_R_DEVBUSID/type
+ [ "$type" = "CTC/A" ] &&
+ type="channel-to-channel adapter (CTC/A)"
+ echo $"Detected: $type"
+ else
+ echo $"Could not read ctc network card type from sysfs."
+ fi
+ ;;
+ esac
+ return 0
+ else
+ echo $"Channels $SUBCHANNELS could not be grouped"
+ fi
+ return 1
+}
+
+function question_prefix_subchannels() {
+ if [ "$NETTYPE" = "qeth" ]; then
+ echo -n $"Read,write,data channel"
+ else
+ echo -n $"Read,write channel"
+ fi
+}
+
+function question_choices_subchannels() {
+ if [ "$NETTYPE" = "qeth" ]; then
+ echo $" (e.g. 0.0.0300,0.0.0301,0.0.0302 or ? for help)."
+ else
+ echo $" (e.g. 0.0.0600,0.0.0601 or ? for help)"
+ fi
+}
+
+function helptext_subchannels() {
+ if [ "$NETTYPE" = "qeth" ]; then
+ echo $" Help text for qeth channels:"
+ echo $" Enter the device bus ID of your CCW devices."
+ echo $" QETH needs three channels for read, write, and data,"
+ echo $" e.g. 0.0.0300,0.0.0301,0.0.0302"
+ else
+ echo $" Help text for lcs/ctc channels:"
+ echo $" Enter the device bus ID of your CCW devices."
+ echo $" CTC/ESCON and LCS need two channels for read and write,"
+ echo $" e.g. 0.0.0600,0.0.0601 will configure the CTC or ESCON interface"
+ echo $" with the channels 0x600 and 0x601"
+ fi
+}
+
+function finish_subchannels() {
+ syntax_check_subchannels || workflow_item_menu
+ # continuing on syntax error is doomed to fail,
+ # since handle_subchannels relies on the regex-based strict parsing
+ # in syntax_check_subchannels which does not match anything then
+ # news: relaxed by splitting semantic check and actual handling
+ semantic_check_subchannels || workflow_item_menu
+ if handle_subchannels; then
+ break
+ else
+ workflow_item_menu && break
+ fi
+}
+
+function do_subchannels() {
+ ask SUBCHANNELS
+ question_prefix_subchannels question_choices_subchannels
+ -h helptext_subchannels -f finish_subchannels
+}
+
+### PORTNAME (qeth)
+
+function syntax_check_portname() {
+ # - 1-8 characters, we convert it to upper case
+ PORTNAME=$(echo $PORTNAME | tr '[:lower:]' '[:upper:]')
+ local portname_len=${#PORTNAME}
+ if [ "$portname_len" -ge 1 -a "$portname_len" -le 8 ]; then
+ return 0
+ fi
+ echo $"Incorrect string length [1..8] for portname (PORTNAME): $PORTNAME"
+ return 1
+}
+
+function handle_portname() {
+ [ -n "$PORTNAME" ] || return 0
+ # - try to set portname right here w/ error handling
+ if sysecho /sys/devices/${NETTYPE}/$SCH_R_DEVBUSID/portname "$PORTNAME"; then
+ return 0
+ else
+ echo $"Portname '$PORTNAME' could not be configured for $SUBCHANNELS"
+ fi
+ return 1
+}
+
+function hint_portname() {
+ if [ -f /sys/devices/${NETTYPE}/$SCH_R_DEVBUSID/portname ]; then
+ local pname_hint
+ read pname_hint < /sys/devices/${NETTYPE}/$SCH_R_DEVBUSID/portname
+ if [ "$pname_hint" = "no portname required" ]; then
+ echo $" * Your configuration does not require a portname. *"
+ fi
+ fi
+}
+
+function question_prefix_portname(){
+ echo -n $"Portname"
+}
+
+function question_choices_portname(){
+ echo $" (1..8 characters, or ? for help). Default is no portname:"
+}
+
+function helptext_portname(){
+ echo $" Help text for portname:"
+ # updated text describing when portname is obsolete;
+ # taken from:
+ # SA22-7935-09, Open Systems Adapter-Express Customer's
+ # Guide and Reference, 10th ed. May 2008, IBM, p.17f.
+ # SC33-8411-00, Device Drivers, Features, and Commands,
+ # 1st ed. May 2008, IBM, p.116.
+ echo $" Portname of the OSA-Express feature in QDIO mode and z/VM Guest LAN."
+ echo $" This parameter is optional with:"
+ echo $" - z/VM 4.4.0 or z/VM 4.3.0 with APARs VM63308 and PQ73878"
+ echo $" - z800, z900 with >= Driver 3G - EC stream J11204, MCL032 (OSA level 3.33)"
+ echo $" - z890, z990, z9, z10 mainframes"
+ hint_portname
+ echo $" If portname is used, all operating systems sharing port must use same name."
+ echo $" Input empty string if you don't want to enter a portname. [default]"
+}
+
+function exception_portname(){
+ [ -z "$PORTNAME" ] && break
+}
+
+function do_portname() {
+ ask PORTNAME
+ question_prefix_portname question_choices_portname
+ -h helptext_portname
+ -e exception_portname -s syntax_check_portname -c handle_portname
+}
+
+### PORTNO (qeth)
+
+function syntax_check_qeth_portno() {
+ case $PORTNO in
+ 0|1)
+ return 0
+ ;;
+ esac
+ echo $"Incorrect format or value for relative port number (PORTNO): $PORTNO"
+ return 1
+}
+
+function handle_qeth_portno() {
+ if sysecho /sys/devices/qeth/$SCH_R_DEVBUSID/portno "$PORTNO"; then
+ return 0
+ fi
+ echo $"Could not configure relative port number $PORTNO for $SUBCHANNELS"
+ return 1
+}
+
+function question_prefix_portno() {
+ echo -n $"Relative port number for OSA"
+}
+
+function question_choices_portno() {
+ echo $" (0, 1, or ? for help). Default is 0:"
+}
+
+function helptext_portno() {
+ echo $" Help text for relative port number for OSA with 2 ports per CHPID:"
+ echo $" This applies to:"
+ echo $" - OSA-Express3 Gigabit Ethernet on z10 systems"
+ echo $" - OSA-Express ATM on zSeries 800 and 900 systems"
+ echo $" 0 for relative port number 0 [default]"
+ echo $" 1 for relative port number 1"
+ echo $" Input empty string to not modify the default configuration."
+}
+
+function exception_portno() {
+ # Writing portno of e.g. hipersockets device fails.
+ # Therefore, do not configure on empty default value.
+ [ -z "$PORTNO" ] && break
+}
+
+function do_portno() {
+ ask PORTNO
+ question_prefix_portno question_choices_portno
+ -h helptext_portno -e exception_portno
+ -s syntax_check_qeth_portno -c handle_qeth_portno
+}
+
+### LAYER2
+
+function syntax_check_layer2() {
+ # - $LAYER2 in {0,1}
+ case $LAYER2 in
+ 0|1)
+ return 0
+ ;;
+ esac
+ echo $"Incorrect format or value for layer2 mode (LAYER2): $LAYER2"
+ return 1
+}
+
+function handle_layer2() {
+ [ "$NETTYPE" == "qeth" ] || return 0
+ [ -n "$LAYER2" ] || return 0
+ # - try to set layer2 mode right here w/ error handling
+ if sysecho /sys/devices/${NETTYPE}/$SCH_R_DEVBUSID/layer2 "$LAYER2"; then
+ return 0
+ else
+ echo $"Layer2 mode '$LAYER2' could not be configured for $SUBCHANNELS"
+ fi
+ return 1
+}
+
+function question_prefix_layer2() {
+ echo -n $"Layer mode"
+}
+
+function question_choices_layer2() {
+ echo -n $" (0 for layer3, 1 for layer2, or ? for help)."
+ if [ "$isLayer2Default" = "yes" ]; then
+ echo $" Default is 1:"
+ else
+ echo $" Default is 0:"
+ fi
+}
+
+function helptext_layer2() {
+ echo $" Help text for OSA mode of operation: layer 2 vs. layer 3"
+ if [ "$isLayer2Default" = "yes" ]; then
+ echo $" 0 for layer 3 mode (may not work with dhcp, tcpdump, etc.)"
+ echo $" 1 for layer 2 mode [default]"
+ else
+ echo $" 0 for layer 3 mode [default] (may not work with dhcp, tcpdump, etc.)"
+ echo $" 1 for layer 2 mode"
+ fi
+}
+
+function exception_layer2() {
+ if [ -z "$LAYER2" ]; then
+ isLayer2Default && LAYER2=1 || LAYER2=0
+ # do not break, always apply, default may differ from online layer mode
+ #break
+ fi
+}
+
+function do_layer2() {
+ isLayer2Default && isLayer2Default=yes || isLayer2Default=no
+ ask LAYER2
+ question_prefix_layer2 question_choices_layer2
+ -h helptext_layer2 -e exception_layer2
+ -s syntax_check_layer2 -c handle_layer2
+}
+
+### MACADDR
+
+function syntax_check_macaddr() {
+ # - match against regex
+ [[ "$MACADDR" =~ ^[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]$ ]]
+ case $? in
+ 0)
+ # string matched the pattern
+ return 0
+ ;;
+ 1)
+ # string did not match the pattern
+ echo $"Incorrect format for mac address (MACADDR): $MACADDR"
+ ;;
+ 2)
+ echo "l.$LINENO: syntax error in regex of match operator =~, code needs to be fixed" 1>&2
+ ;;
+ *)
+ echo "l.$LINENO: unexpected return code of regex match operator =~, code needs to be fixed" 1>&2
+ ;;
+ esac
+ return 1
+}
+
+function handle_macaddr() {
+ # - try to set macaddr right here w/ error handlg.
+ # device needs to be online
+ if debug ifconfig $DEVICE hw ether $MACADDR; then
+ return 0
+ fi
+ echo $"MAC address $MACADDR could not be configured for"
+ echo $" $SUBCHANNELS (network device $DEVICE)"
+ return 1
+}
+
+function question_prefix_macaddr() {
+ echo -n $"Unique MAC address"
+}
+
+function question_choices_macaddr() {
+ macaddr_default=$(ifconfig $DEVICE | grep 'HWaddr' | sed 's/.*HWaddr ([[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]).*/1/')
+ echo $" (e.g. 02:00:00:00:00:00, ? for help). Default is $macaddr_default:"
+}
+
+function helptext_macaddr() {
+ echo $" Help text for MAC address:"
+ if [ -z "${cardtype//OSD_*/}" ]; then
+ echo $" For real OSA in layer 2 mode, a random MAC address is automatically assigned."
+ else
+ echo $" If connecting to a layer 2 VSWITCH, a MAC address is automatically assigned."
+ fi
+ echo $" You may accept the automatic MAC address with an empty input. [default]"
+ echo $" If the automatic address is not unique, please provide a MAC address."
+ [ -z "${cardtype//OSD_*/}" ] &&
+ echo $" For real OSA, the provided address must be different from that of the OSA."
+ echo $" You may override the automatic MAC address with non-empty input."
+ echo $" An example MAC address would be: 02:00:00:00:00:00"
+}
+
+function exception_macaddr() {
+ if [ -z "$MACADDR" ]; then
+ if [ -z "${cardtype//OSD_*/}" ]; then
+ # keep random default MAC address of real OSA,
+ # so the OSA comes up with the same MAC each time in the future
+ MACADDR=$macaddr_default
+ else
+ # virtual OSA in layer2 is GuestLAN or VSWITCH
+ VSWITCH=1
+ fi
+ break
+ fi
+}
+
+function do_macaddr() {
+ ask MACADDR
+ question_prefix_macaddr question_choices_macaddr
+ -h helptext_macaddr -e exception_macaddr
+ -s syntax_check_macaddr -c handle_macaddr
+}
+
+### CTCPROT
+
+function syntax_check_ctcprot() {
+ case "x$CTCPROT" in
+ x|x0)
+ unset CTCPROT
+ return 0
+ ;;
+ x1|x3)
+ return 0
+ ;;
+ x2)
+ echo $"CTC tty's are not usable for this installation (CTCPROT)"
+ ;;
+ *)
+ echo $"Incorrect format or value for CTC protocol (CTCPROT): $CTCPROT"
+ ;;
+ esac
+ return 1
+}
+
+function handle_ctcprot() {
+ [ -n "$CTCPROT" ] || return 0
+ if sysecho /sys/devices/ctcm/${SCH_R_DEVBUSID}/protocol "$CTCPROT"; then
+ return 0
+ fi
+ echo $"Could not configure CTC protocol $CTCPROT for $SUBCHANNELS"
+ return 1
+}
+
+function question_prefix_ctcprot() {
+ echo -n $"CTC protocol"
+}
+
+function question_choices_ctcprot() {
+ echo $" (0, 1, 3, or ? for help). Default is 0:"
+}
+
+function helptext_ctcprot() {
+ echo $" Help text for CTC protocol:"
+ echo $" Protocol which should be used for the CTC interface"
+ echo $" 0 for compatibility with p.e. VM TCP service machine [default]"
+ echo $" 1 for enhanced package checking for Linux peers"
+ echo $" 3 for compatibility with OS/390 or z/OS peers"
+}
+
+function do_ctcprot() {
+ ask CTCPROT
+ question_prefix_ctcprot question_choices_ctcprot
+ -h helptext_ctcprot -s syntax_check_ctcprot -c handle_ctcprot
+}
+
+### PORTNAME (LCS portno)
+
+function syntax_check_lcs_portno() {
+ [[ "$PORTNAME" =~ ^[[:digit:]]+$ ]]
+ case $? in
+ 0)
+ # string matched the pattern
+ return 0
+ ;;
+ 1)
+ # string did not match the pattern
+ ;;
+ 2)
+ echo "l.$LINENO: syntax error in regex of match operator =~, code needs to be fixed" 1>&2
+ ;;
+ *)
+ echo "l.$LINENO: unexpected return code of regex match operator =~, code needs to be fixed" 1>&2
+ ;;
+ esac
+ echo $"Incorrect format for LCS port number (PORTNAME): $PORTNAME"
+ return 1
+}
+
+function handle_lcs_portno() {
+ [ -n "$PORTNAME" ] || return 0
+ if sysecho /sys/devices/lcs/$SCH_R_DEVBUSID/portno "$PORTNAME"; then
+ return 0
+ fi
+ echo $"Could not configure relative port number $PORTNAME for $SUBCHANNELS"
+ return 1
+}
+
+function question_prefix_lcs_portno() {
+ echo -n $"Relative port number of your LCS device"
+}
+
+function question_choices_lcs_portno() {
+ echo $" (number or ? for help). Default is 0:"
+}
+
+function helptext_lcs_portno() {
+ echo $" Help text for relative port number of LCS device:"
+ echo $" Required for OSA-Express ATM cards only."
+}
+
+function exception_lcs_portno() {
+ [ -z "$PORTNAME" ] && break
+}
+
+function do_lcs_portno() {
+ # LCS portno and QETH portname share the parameter variable PORTNAME.
+ # For compatibility with existing parm files we keep this scheme.
+ ask PORTNAME
+ question_prefix_lcs_portno question_choices_lcs_portno
+ -e exception_lcs_portno
+ -h helptext_lcs_portno -s syntax_check_lcs_portno -c handle_lcs_portno
+}
+
+### HOSTNAME
+
+function syntax_check_hostname() {
+ syntax_check_domainname "$HOSTNAME" "Incorrect format for hostname (HOSTNAME): $HOSTNAME"
+}
+
+function handle_hostname() {
+ if ! hostname $HOSTNAME; then
+ echo $"Could not configure hostname $HOSTNAME"
+ return 1
+ fi
+ return 0
+}
+
+function question_prefix_hostname() {
+ echo -n $"Hostname of your new Linux guest"
+}
+
+function question_choices_hostname() {
+ echo $" (FQDN e.g. s390.redhat.com or ? for help):"
+}
+
+function helptext_hostname() {
+ echo $" Help text for hostname:"
+ echo $" Enter the full qualified domain name of your host."
+}
+
+function do_hostname() {
+ ask HOSTNAME
+ question_prefix_hostname question_choices_hostname
+ -h helptext_hostname -s syntax_check_hostname -c handle_hostname
+}
+
+### IPADDR
+
+function syntax_check_ipaddr() {
+ unset ipv4
+ unset ipv6
+ if checkipv4 $IPADDR; then
+ ipv4="yes"
+ return 0
+ elif [ "$ipv6_capable" = "yes" ] && checkipv6 $IPADDR; then
+ ipv6="yes"
+ return 0
+ fi
+ echo $"Incorrect format for IP address (IPADDR): $IPADDR"
+ return 1
+}
+
+function question_prefix_ipaddr() {
+ echo -n $"IPv4 address"
+ [ "$ipv6_capable" = "yes" ] && echo -n $" / IPv6 addr."
+}
+
+function question_choices_ipaddr() {
+ echo -n $" (e.g. 10.0.0.2"
+ [ "$ipv6_capable" = "yes" ] && echo -n $" / 2001:0DB8::"
+ echo $" or ? for he


All times are GMT. The time now is 01:19 PM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.