[PATCH 6/9] move linuxrc.s390 out of harm's way

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
+#        Oliver Paukstadt <opaukstadt@xxxxxxxxxxxx>
+#        Karsten Hopp <karsten@xxxxxxxxx>
+#        Florian La Roche <laroche@xxxxxxxxxx>
+#        Nils Philippsen <nils@xxxxxxxxx>
+#        Helge Deller <hdeller@xxxxxxxxx>
+#        David Sainty <dsainty@xxxxxxxxxx>
+# Copyright (C) IBM Corp. 2008,2009
+#        Author: Steffen Maier <maier@xxxxxxxxxx>
+#
+#    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\n", $1, $2, $3, $4);
+      printf("chmod %s /dev/%s\n", $5, $1);
+      printf("chown %s /dev/%s\n", $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\tlocalhost.localdomain localhost localhost4 localhost4.localdomain4" > /etc/hosts
+        echo -e     "::1\t\tlocalhost.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\n"
+    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 '\n' ','
+                #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|HiperSockets|"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 help)"
+}
+
+function helptext_ipaddr() {
+    echo $" Help text for IP address:"
+    echo $"  Enter a valid IPv4 address of your new Linux guest (e.g. 10.0.0.2)"
+    if [ "$ipv6_capable" = "yes" ]; then
+        echo $"  or alternatively a valid IPv6 address without CIDR prefix (e.g. 2001:0DB8::)"
+        echo $"  IPv6 is supported on:"
+        echo $"   - Ethernet interfaces of the OSA-Express adapter running in QDIO mode."
+        echo $"   - HiperSockets interfaces"
+        echo $"   - z/VM guest LAN interfaces running in QDIO mode."
+        echo $"  IPv6 is not supported on HiperSockets guest LAN, OSA-Express Token Ring, ATM."
+    fi
+}
+
+function do_ipaddr() {
+    ipv6_capable && ipv6_capable=yes || ipv6_capable=no
+    ask IPADDR \
+        question_prefix_ipaddr question_choices_ipaddr \
+        -h helptext_ipaddr -s syntax_check_ipaddr
+    if [ "$ipv6" ]; then
+       # qeth_l3 would load ipv6 automatically but not qeth_l2
+       modprobe ipv6
+       tv disable_ipv6_autoconf
+    fi
+
+    # no handling/configuring of IPADDR yet, since more parameters needed
+}
+
+### NETMASK (IPv4)
+
+function syntax_check_netmask_v4() {
+    # also support CIDR prefix
+    if [[ "$NETMASK" =~ ^[[:digit:]]+$ ]]; then
+        if [ "$NETMASK" -ge 1 -a "$NETMASK" -le 32 ]; then
+            ipcalc_arg="$IPADDR/$NETMASK"
+            return 0
+        fi
+        echo $"Incorrect value for network prefix [1..32] (NETMASK): $NETMASK"
+        return 1
+    elif checkipv4 $NETMASK; then
+        ipcalc_arg="$IPADDR $NETMASK"
+        return 0
+    fi
+    echo $"Incorrect format or value for network mask (NETMASK): $NETMASK"
+    return 1
+}
+
+function question_prefix_netmask() {
+    echo -n $"IPv4 netmask or CIDR prefix"
+}
+
+function hint_netmask_v4() {
+    # default based on class a/b/c address
+    local a b c d
+    IFS=.
+    read a b c d <<< "$IPADDR"
+    unset IFS
+    local ip=$(( ( a << 24 ) + ( b << 16 ) + ( c << 8 ) + ( d ) ))
+    # <<EOF convince syntax highlighter that above shifts are no here documents
+    if   [ $(( ip & 0x80000000 )) -eq $(( 0x00000000 )) ]; then
+        # class a
+        echo "255.0.0.0"
+    elif [ $(( ip & 0xC0000000 )) -eq $(( 0x80000000 )) ]; then
+        # class b
+        echo "255.255.0.0"
+    elif [ $(( ip & 0xE0000000 )) -eq $(( 0xC0000000 )) ]; then
+        # class c
+        echo "255.255.255.0"
+    else
+        # some other class that should not be used as host address
+        return 1
+    fi
+    return 0
+}
+
+function question_choices_netmask() {
+    echo -n $" (e.g. 255.255.255.0 or 1..32 or ? for help)"
+    local default=$(hint_netmask_v4)
+    if [ -n "$default" ]; then
+        echo $". Default is $default:"
+    else
+        echo $":"
+        echo $"The IP address you entered previously should probably not be used for a host."
+    fi
+}
+
+function helptext_netmask() {
+    echo $" Help text for IPv4 netmask or CIDR prefix:"
+    echo $"  Enter a valid IPv4 netmask or CIDR prefix (e.g. 255.255.255.0 or 1..32)"
+    local default=$(hint_netmask_v4)
+    if [ -n "$default" ]; then
+        echo $"  Default is $default"
+    else
+        echo $"The IP address you entered previously should probably not be used for a host."
+    fi
+}
+
+function exception_netmask() {
+    if [ -z "$NETMASK" ]; then
+        NETMASK=$(hint_netmask_v4)
+    fi
+}
+
+function do_netmask() {
+    ask NETMASK \
+        question_prefix_netmask question_choices_netmask \
+        -h helptext_netmask \
+        -s syntax_check_netmask_v4 -e exception_netmask
+    # no handling/configuring of NETMASK yet, since more parameters needed
+}
+
+### NETWORK
+
+function do_network() {
+    echo
+    echo $"The NETWORK parameter isn't used anymore and will be ignored."
+    echo $" It is sufficient to specify IPADDR and NETMASK."
+    echo
+    unset NETWORK
+}
+
+### BROADCAST
+
+function do_broadcast() {
+    echo
+    echo $"The BROADCAST parameter isn't used anymore and will be ignored."
+    echo $" It is sufficient to specify IPADDR and NETMASK."
+    echo
+    unset BROADCAST
+}
+
+### NETMASK (IPv6)
+
+function syntax_check_prefix_v6() {
+    if [[ "$NETMASK" =~ ^[[:digit:]]+$ ]]; then
+        if [ "$NETMASK" -ge 1 -a "$NETMASK" -le 128 ]; then
+            return 0
+        fi
+    fi
+    echo $"Incorrect value for network prefix [1..128] (NETMASK): $NETMASK"
+    return 1
+}
+
+function question_prefix_netmask_v6() {
+    echo -n $"CIDR prefix for the IPv6 address"
+}
+
+function question_choices_netmask_v6() {
+    echo $" (1..128):"
+}
+
+function do_netmask_v6() {
+    ask NETMASK \
+        question_prefix_netmask_v6 question_choices_netmask_v6 \
+        -s syntax_check_prefix_v6
+    # no handling/configuring of NETMASK yet, since more parameters needed
+}
+
+### GATEWAY (IPv4)
+
+function configure_ipv4_gateway() {
+    # FIXME:
+    # - Strictly speaking we should first check reachability of gateway
+    #   and then configure the gateway route.
+    #   This would require a new intermediate workflow_item step
+    #   so that the user might continue despite unreachable gateway.
+    # done: Only adding default route might add multiple undesired default
+    # routes on redoing the parameter item, so delete default route
+    # before adding a new one.
+    ip -4 route del default dev $DEVICE >& /dev/null
+    [ -z "$GATEWAY" ] && return 0
+    if ! tv route add default gw $GATEWAY dev $DEVICE; then
+        echo $"Could net set default route on device $DEVICE via gateway $GATEWAY"
+        return 1
+    fi
+    # BH FIXME: Workaround for manual MACADDR, need ping to update arp table
+    echo $"Trying to reach gateway $GATEWAY..."
+    if [ "$NETTYPE" = "ctc" ]; then
+        # (virtual) CTC(/A) seems to need some time to get functional
+        local i=1
+        while : ; do
+            $PING $GATEWAY >& /dev/null && break
+            i=$((i+1))
+            if [ "$i" -gt 3 ]; then
+                echo $"Could not reach gateway $GATEWAY within timeout"
+                return 1
+            fi
+        done
+    else
+        if ! $PING $GATEWAY >& /dev/null; then
+            echo $"Could not reach your default gateway $GATEWAY"
+            return 1
+        fi
+    fi
+    return 0
+}
+
+function hint_ipv4_gateway() {
+    # - provide default suggestion based on network,
+    #   for a class C network this would be either .1 or .254 at the end
+    local a b c d
+    IFS=.
+    read a b c d <<< "$NETWORK"
+    unset IFS
+    local ip=$(( ( a << 24 ) + ( b << 16 ) + ( c << 8 ) + ( d ) ))
+    # <<EOF convince syntax highlighter that above shifts are no here documents
+    local lo=$(( ip | 1 ))
+    local lo_a=$(( (lo & 0xFF000000) >> 24 ))
+    local lo_b=$(( (lo & 0x00FF0000) >> 16 ))
+    local lo_c=$(( (lo & 0x0000FF00) >> 8 ))
+    local lo_d=$(( (lo & 0x000000FF) ))
+    local hi=$(( ip | ( (2**(32 - PREFIX)) - 1 ) ))
+    local hi_a=$(( (hi & 0xFF000000) >> 24 ))
+    local hi_b=$(( (hi & 0x00FF0000) >> 16 ))
+    local hi_c=$(( (hi & 0x0000FF00) >> 8 ))
+    local hi_d=$(( (hi & 0x000000FE) ))
+    echo $"  Depending on your network design patterns, the default gateway"
+    echo $"   might be $lo_a.$lo_b.$lo_c.$lo_d or $hi_a.$hi_b.$hi_c.$hi_d"
+}
+
+function question_prefix_gateway() {
+    echo -n $"IPv4 address of your default gateway"
+}
+
+function question_choices_gateway() {
+    echo $" or ? for help:"
+}
+
+function helptext_gateway() {
+    echo $" Help text for IPv4 default gateway:"
+    echo $"  For HiperSockets with internal traffic only you may want to leave this empty"
+    echo $"  and choose continue afterwards to go on without gateway."
+    hint_ipv4_gateway
+}
+
+function finish_gateway() {
+    if ! checkipv4 $GATEWAY; then
+        # above checkipv4 is silent, so make up for syntax error
+        echo $"Incorrect format for IPv4 address of gateway (GATEWAY): $GATEWAY"
+        workflow_item_menu
+    fi
+    if configure_ipv4_gateway; then
+        break
+    else
+        workflow_item_menu && break
+    fi
+}
+
+# FIXME: allow empty/no gateway?
+
+function do_gateway() {
+    ask GATEWAY \
+        question_prefix_gateway question_choices_gateway \
+        -h helptext_gateway -f finish_gateway
+}
+
+### GATEWAY (IPv6)
+
+function configure_ipv6_gateway() {
+    # FIXME:
+    # - Strictly speaking we should first check reachability of gateway
+    #   and then configure the gateway route.
+    #   This would require a new intermediate workflow_item step
+    #   so that the user might continue despite unreachable gateway.
+    # done: Only adding default route might add multiple undesired default
+    # routes on redoing the parameter item, so delete default route
+    # before adding a new one.
+    ip -6 route del default dev $DEVICE >& /dev/null
+    [ -z "$GATEWAY" ] && return 0
+    # IPv6 http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/Linux+IPv6-HOWTO.html#AEN1147
+    #       ip -6 route add ::/0 dev $DEVICE via $GATEWAY
+    # (Could also be learned by autoconfiguration on the link:
+    #  after IP address setup and device up,
+    #   see if default route has been learned
+    #   ip -6 route show | grep ^default
+    #  However, we currently use manual IPv6 configuration only.)
+    if ! debug ip -6 route add ::/0 dev $DEVICE via $GATEWAY; then
+        echo $"Could net set default route on device $DEVICE"
+        echo $" via gateway $GATEWAY"
+        return 1
+    fi
+    # BH FIXME: Workaround for manual MACADDR, need ping to update arp table
+    echo $"Trying to reach gateway $GATEWAY..."
+    if ! $PING6 $GATEWAY >& /dev/null; then
+        echo $"Could not reach your default gateway $GATEWAY"
+        return 1
+    fi
+    return 0
+}
+
+function question_prefix_gateway_v6() {
+    echo -n $"IPv6 address of your default gateway"
+}
+
+function question_choices_gateway_v6() {
+    echo $":"
+}
+
+function helptext_gateway_v6() {
+    echo $" Help text for IPv6 default gateway:"
+    echo $"  For HiperSockets with internal traffic only you may want to leave this empty"
+    echo $"  and choose continue afterwards to go on without gateway."
+}
+
+function finish_gateway_v6() {
+    if ! checkipv6 $GATEWAY; then
+        # above checkipv6 is silent, so make up for syntax error
+        echo $"Incorrect format for IPv6 address of gateway (GATEWAY): $GATEWAY"
+        workflow_item_menu
+    fi
+    if configure_ipv6_gateway; then
+        break
+    else
+        workflow_item_menu && break
+    fi
+}
+
+# FIXME: allow empty/no gateway?
+
+function do_gateway_v6() {
+    ask GATEWAY \
+        question_prefix_gateway_v6 question_choices_gateway_v6 \
+        -h helptext_gateway_v6 -f finish_gateway_v6
+}
+
+### GATEWAY (IPv4, point-to-point)
+
+function configure_ipv4_ptp() {
+    # device needs to be online
+    if debug ifconfig $DEVICE $IPADDR $MMTU pointopoint $GATEWAY; then
+        configure_ipv4_gateway
+        return $?
+    fi
+    echo $"Could not set IPv4 address $IPADDR for device $DEVICE"
+    echo $" to peer $GATEWAY"
+    [ -n "$MMTU" ] && echo $" and maximum transfer unit: $MMTU"
+    return 1
+}
+
+function question_prefix_ptp_gateway() {
+    echo -n $"IPv4 address of your point-to-point partner"
+}
+
+function question_choices_ptp_gateway() {
+    echo $" or ? for help:"
+    # no hinting possible here
+}
+
+function helptext_ptp_gateway() {
+    echo $" Help text for point-to-point partner:"
+    echo $"  IPv4 address of your CTC or ESCON point-to-point partner."
+}
+
+function finish_ptp_gateway() {
+    if checkipv4 $GATEWAY; then
+        if [ "$GATEWAY" = "$IPADDR" ]; then
+            echo $"IPv4 address of partner should probably be different from the guest's address"
+            workflow_item_menu && break
+        else
+            break
+        fi
+    else
+        # above checkipv4 is silent, so make up for syntax error
+        echo $"Incorrect format for IPv4 address of partner (GATEWAY): $GATEWAY"
+        workflow_item_menu && break
+    fi
+    # too early to actually configure gateway
+}
+
+function do_ptp_gateway() {
+    ask GATEWAY \
+        question_prefix_ptp_gateway question_choices_ptp_gateway \
+        -h helptext_ptp_gateway -f finish_ptp_gateway
+}
+
+### DNS
+
+function syntax_check_dns() {
+    if [ -z "$DNS" ]; then
+        echo $"You might encounter problems without a nameserver, especially with FTP installs"
+        return 1
+    fi
+    local dnsitem
+    local allgood="yes"
+    if [ "$ipv6" ]; then
+        while read dnsitem; do
+            if ! checkipv6 $dnsitem; then
+                echo $"Not a valid IPv6 address for DNS server: $dnsitem"
+                allgood="no"
+            fi
+        done < <(echo $DNS | sed 's/,/\n/g')
+    else
+         while read dnsitem; do
+           if ! checkipv4 $dnsitem; then
+                echo $"Not a valid IPv4 address for DNS server: $dnsitem"
+                allgood="no"
+            fi
+         done < <(echo $DNS | sed 's/:/\n/g')
+    fi
+    if [ "$allgood" = "yes" ]; then
+        return 0
+    else
+        return 1
+    fi
+}
+
+function handle_dns() {
+    # - foreach DNS try if server is reachable by one ping
+    [ -z "$DNS" ] && return 0
+    local dnsitem
+    local allgood="yes"
+    echo $"Trying to reach DNS servers..."
+    if [ "$ipv6" ]; then
+        while read dnsitem; do
+            if ! $PING6 $dnsitem >& /dev/null; then
+                echo $"Could not ping DNS server (might still serve DNS requests): $dnsitem"
+                allgood="no"
+                # this should not be a hard failure since some network
+                # environments may prevent pings to DNS servers
+                # => prevent workflow_item_menu in kickstart mode
+            fi
+        done < <(echo $DNS | sed 's/,/\n/g')
+    else
+        while read dnsitem; do
+            # Some network environment may prevent a DNS server from being
+            # reachable by ping, so it would make sense to use nslookup.
+            # However, nslookup fails with "Resolver Error 0 (no error)"
+            # at this stage of the setup progress => not useful
+            if ! $PING $dnsitem >& /dev/null; then
+                echo $"Could not ping DNS server: $dnsitem"
+#                if nslookup $dnsitem $dnsitem >& /dev/null; then
+#                    echo $" but could resolve DNS server with itself: $dnsitem"
+#                else
+#                    echo $"Could not resolve DNS server with itself: $dnsitem"
+#                    allgood="no"
+#                fi
+#            elif ! nslookup $dnsitem $dnsitem >& /dev/null; then
+#                echo $"Could not resolve DNS server with itself: $dnsitem"
+                allgood="no"
+            fi
+        done < <(echo $DNS | sed 's/:/\n/g')
+    fi
+    if [ "$allgood" = "yes" ]; then
+        return 0
+    else
+        return 1
+    fi
+}
+
+function question_prefix_dns() {
+    if [ "$ipv6" ]; then
+        echo -n $"IPv6 addresses of DNS servers"
+    else
+        echo -n $"IPv4 addresses of DNS servers"
+    fi
+}
+
+function question_choices_dns() {
+    if [ "$ipv6" ]; then
+        echo $" (separated by commas ',' or ? for help):"
+    else
+        echo $" (separated by colons ':' or ? for help):"
+    fi
+}
+
+function helptext_dns() {
+    echo $" Help text for DNS servers:"
+    if [ "$ipv6" ]; then
+        echo $"  Enter IPv6 addresses of DNS servers separated by commas ','"
+    else
+        echo $"  Enter IPv4 addresses of DNS servers separated by colons ':'"
+    fi
+    echo $"  Default are no DNS servers at all."
+    echo $"  However, you might encounter problems without a nameserver,"
+    echo $"   especially with FTP installs."
+    if [ "$ipv6" ]; then
+        echo $"  An example with 2 servers would be: 2001:0DB8::42,2001:0DB8::BE:AF"
+    else
+        echo $"  An example with 2 servers would be: 10.0.0.250:10.1.1.1"
+    fi
+}
+
+function do_dns() {
+    ask DNS \
+        question_prefix_dns question_choices_dns \
+        -h helptext_dns -s syntax_check_dns -c handle_dns
+}
+
+### SEARCHDNS
+
+function syntax_check_searchdns() {
+    [ -z "$SEARCHDNS" ] && return 0
+    local dnsitem
+    local allgood="yes"
+    while read dnsitem; do
+        syntax_check_domainname "$dnsitem" $"Not a valid DNS search domain: $dnsitem" || allgood="no"
+    done < <(echo $SEARCHDNS | sed 's/:/\n/g')
+    if [ "$allgood" = "yes" ]; then
+        return 0
+    else
+        return 1
+    fi
+}
+
+function question_prefix_searchdns() {
+    echo -n $"DNS search domains"
+}
+
+function question_choices_searchdns() {
+    echo $" (separated by colons ':' or ? for help):"
+}
+
+function helptext_searchdns() {
+    echo $" Help text for DNS search domains:"
+    echo $"  Enter search domains according to hostname syntax separated by colons."
+    echo $"  Default are no DNS search domains at all."
+    echo $"  An example would be: subdomain.domain.com:domain.com"
+}
+
+function do_searchdns() {
+    ask SEARCHDNS \
+        question_prefix_searchdns question_choices_searchdns \
+        -h helptext_searchdns -s syntax_check_searchdns
+}
+
+### DASD
+
+function parse_dasd() {
+    local handle
+    [ "$1" = "-h" ] && handle=yes || unset handle
+    local dasditem
+    local allgood="yes"
+    local cio_wc=$(wc -c /proc/cio_ignore)
+    read cio_wc_bytes cio_wc_filename cio_wc_foo <<< "$cio_wc"
+    if [ "$handle" = "yes" -a "$cio_wc_bytes" != "0" ]; then
+        echo $"Trying to clear specified DASDs from device blacklist..."
+        mkdir -p /etc/modprobe.d
+        echo "options dasd_mod dasd=$DASD" > /etc/modprobe.d/dasd_mod.conf
+        if ! dasd_cio_free; then
+            echo $"Not all specified DASDs could be detected within timeout."
+            allgood="no"
+        fi
+    fi
+    while read dasditem; do
+        unset range features range lo hi rangegood \
+            attrs devno lodevno hidevno devbusid sys
+        case $dasditem in
+            autodetect)
+                [ -z "$handle" ] && continue
+                cio_wc=$(wc -c /proc/cio_ignore)
+                read cio_wc_bytes cio_wc_filename cio_wc_foo <<< "$cio_wc"
+                # above we only freed the devices specified in $DASD,
+                # so there might still be other DASDs in the blacklist
+                if [ "$cio_wc_bytes" != "0" ]; then
+                    echo $"Note: There is a device blacklist active! Only activating visible DASDs."
+                fi
+                local sys
+                while read sys; do
+                    if ! sysecho $sys/online 1; then
+                        echo $"Could not set DASD ${sys##*/} online"
+                    fi
+                done < <(find /sys/bus/ccw/drivers/dasd-eckd/ -name "*.?.????" 2>/dev/null;\
+                    find /sys/bus/ccw/drivers/dasd-fba/ -name "*.?.????" 2>/dev/null)
+                ;;
+            probeonly|nopav|nofcx)
+                if [ -z "$handle" ]; then
+                    echo $"DASD option $dasditem not supported by installer"
+                fi
+                ;;
+            "") continue ;; # empty range
+            *)  local range features rangegood="yes"
+                IFS='('
+                read range features <<< "$dasditem"
+                unset IFS
+                # parse: dev OR dev'-'dev
+                local lo=${range%%-*}
+                [[ "$lo" =~ (^[[:xdigit:]]+\.[0-3]\.[[:xdigit:]]{4}$)|(^[[:xdigit:]]{3,4}$) ]]
+                case $? in
+                    0)  # string matched the pattern
+                        lo=$(canonicalize_devno $lo) ;;
+                    1)  # string did not match the pattern
+                        rangegood="no"
+                        if [ -z "$handle" ]; then
+                            echo $"Incorrect format for lower bound of DASD range $range: $lo"
+                            allgood="no"
+                        fi
+                        ;;
+                    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
+                if [ "${range//*-*/}" = "" ]; then
+                    local hi=${range##*-}
+                    [[ "$hi" =~ (^[[:xdigit:]]+\.[0-3]\.[[:xdigit:]]{4}$)|(^[[:xdigit:]]{3,4}$) ]]
+                    case $? in
+                        0)  # string matched the pattern
+                            hi=$(canonicalize_devno $hi)
+                            if [ "${lo%.*}" != "${hi%.*}" ]; then
+                                echo $"Prefixes of DASD range $range do not match: ${lo%.*} != ${hi%.*}"
+                                rangegood="no"
+                                allgood="no"
+                            fi
+                            ;;
+                        1)  # string did not match the pattern
+                            rangegood="no"
+                            if [ -z "$handle" ]; then
+                                echo $"Incorrect format for upper bound of DASD range $range: $hi"
+                                allgood="no"
+                            fi
+                            ;;
+                        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
+                fi
+                if [ "${features//*)/}" != "" ]; then
+                    if [ -z "$handle" ]; then
+                        echo $"Missing closing parenthesis at features of DASD range $range: ($features"
+                        allgood="no"
+                    fi
+                fi
+                local attrs=""
+                if [ -n "$features" ]; then
+                    features="${features%)}"
+                    while read feature; do
+                        case $feature in
+                            ro) attrs=$attrs" readonly" ;;
+                            diag) attrs=$attrs" use_diag" ;;
+                            erplog|failfast) attrs=$attrs" "$feature ;;
+                            *) if [ -z "$handle" ]; then
+                                   echo $"Unknown DASD feature for device range $range: $feature"
+                                   allgood="no"
+                               fi
+                               ;;
+                        esac
+                    done < <(echo $features | sed 's/:/\n/g')
+                fi
+                [ "$rangegood" = "yes" ] || continue
+                [ "$handle" = "yes" ] || continue
+                # now apply $attrs and set DASDs $lo to $hi online
+                [ -z "$hi" ] && hi=$lo
+                local devno lodevno=$((0x${lo##*.})) hidevno=$((0x${hi##*.}))
+                local dasdconf="/etc/dasd.conf"
+                for ((devno=$lodevno; $devno <= $hidevno; ++devno)); do
+                    local devbusid=$(printf "%s.%04x" ${lo%.*} $devno)
+                    local sys="/sys/bus/ccw/devices/"$devbusid
+                    echo -n "$devbusid" >> $dasdconf
+                    for attr in $attrs; do
+                        if [ "$attr" = "use_diag" ]; then
+                            # diag discipline cannot be auto-loaded
+                            modprobe dasd_diag_mod
+                        fi
+                        if [ ! -f $sys/$attr ]; then
+                            echo $"DASD $devbusid does not provide attribute $attr"
+                            continue
+                        fi
+                        if ! sysecho $sys/$attr 1; then
+                            echo $"Could not set attribute $attr for DASD $devbusid"
+                        fi
+                        echo -n " $attr=1" >> $dasdconf
+                    done
+                    if [ ! -f $sys/online ]; then
+                        echo $"DASD $devbusid not found"
+                        continue
+                    fi
+                    if ! sysecho $sys/online 1; then
+                        echo $"Could not set DASD $devbusid online"
+                    fi
+                    echo >> $dasdconf
+                done
+                ;;
+        esac
+    done < <(echo $DASD | sed 's/,/\n/g')
+    if [ "$handle" = "yes" ]; then
+        udevadm settle
+        dasd_settle_all || return 1
+        echo $"Activated DASDs:"
+        cat /proc/dasd/devices | sed -e 's/ at ([^)]*) is//' -e 's/ at/,/'
+    fi
+    if [ "$allgood" = "yes" ]; then
+        return 0
+    else
+        return 1
+    fi
+}
+
+function syntax_check_dasd() {
+    parse_dasd
+    return $?
+}
+
+function handle_dasd() {
+    parse_dasd -h
+    return $?
+}
+
+function question_prefix_dasd() {
+    echo -n $"DASD range"
+}
+
+function question_choices_dasd() {
+    echo $" (e.g. 200-203,205 or ? for help). Default is autoprobing:"
+}
+
+function helptext_dasd() {
+    echo $" Help text for DASD range:"
+    echo $"  Comma separated list of ranges of device bus IDs."
+    echo $"  Default is autoprobing (not recommended)."
+    echo $"  Examples would be: 200-203 or 200,201,202,203 or 0.0.0200-0.0.0203,0.0.0205"
+}
+
+function exception_dasd() {
+    [ -z "$DASD" ] && DASD="autodetect"
+}
+
+function do_dasd() {
+    ask DASD \
+        question_prefix_dasd question_choices_dasd \
+        -h helptext_dasd -e exception_dasd -s syntax_check_dasd -c handle_dasd
+}
+
+### FCP
+
+function syntax_check_fcp() {
+    local allgood="yes"
+    local i
+    for i in ${!FCP_*}; do
+        local -a fcp
+        local devno wwpn lun
+        read -a fcp <<< "${!i}"
+        case ${#fcp[@]} in
+            3)
+                devno=${fcp[0]}
+                wwpn=${fcp[1]}
+                lun=${fcp[2]}
+                ;;
+            5)
+                devno=${fcp[0]}
+                wwpn=${fcp[2]}
+                lun=${fcp[4]}
+                echo $"Deprecated number of FCP arguments (5 instead of 3): "
+                echo $" $i=\"${!i}\""
+                echo $" should instead be: "
+                echo $" $i=\"$devno $wwpn $lun\""
+                ;;
+            *)
+                echo $"Unsupported number of FCP arguments (${#fcp[@]} instead of 3) in:"
+                echo $" $i=\"${!i}\""
+                allgood="no"
+                continue
+                ;;
+        esac
+        [[ "$devno" =~ (^[[:xdigit:]]+\.[0-3]\.[[:xdigit:]]{4}$)|(^[[:xdigit:]]{3,4}$) ]]
+        case $? in
+            0)  ;; # string matched the pattern
+            1)  # string did not match the pattern
+                echo $"Incorrect format for FCP device $devno in:"
+                echo $" $i=\"${!i}\""
+                allgood="no"
+                ;;
+            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
+        # zfcp.py:class ZFCPDevice would also accept WWPN without leading 0x
+        [[ "$wwpn" =~ ^0x[[:xdigit:]]{16}$ ]]
+        case $? in
+            0)  ;; # string matched the pattern
+            1)  # string did not match the pattern
+                echo $"Incorrect format for FCP WWPN $wwpn in:"
+                echo $" $i=\"${!i}\""
+                allgood="no"
+                ;;
+            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
+        # zfcp.py:class ZFCPDevice would also accept LUN without leading 0x
+        # zfcp.py:class ZFCPDevice would also accept 16 bit LUN and pads with 0
+        [[ "$lun" =~ ^0x[[:xdigit:]]{8}0{8}$ ]]
+        case $? in
+            0)  ;; # string matched the pattern
+            1)  # string did not match the pattern
+                echo $"Incorrect format for FCP LUN $lun in:"
+                echo $" $i=\"${!i}\""
+                allgood="no"
+                ;;
+            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 [ "$allgood" = "yes" ]; then
+        return 0
+    else
+        return 1
+    fi
+}
+
+###
+
+function show_parms() {
+    # The only issue with this stateless approach to showing parameters based
+    # on their content being non-empty is, that parameters with defaults
+    # such as LAYER2, (PORTNAME,) CTCPROT, PORTNO (,MACADDR) won't be shown
+    # if the user just hit enter, so the parm file would be "incomplete".
+    # However this is not easy to fix in here, since it would require the
+    # inter-parameter dependenies coded below in the main part, e.g. an
+    # empty LAYER2 should only be printed with default value if $NETTYPE=qeth.
+    # For the time being, at least the parameters LAYER2, PORTNAME, and CTCPROT
+    # only get asked on being empty if not running in kickstart mode.
+    cat << EOF
+NETTYPE=$NETTYPE
+IPADDR=$IPADDR
+NETMASK=$NETMASK
+GATEWAY=$GATEWAY
+HOSTNAME=$HOSTNAME
+EOF
+    [ "$SUBCHANNELS" ] && echo "SUBCHANNELS=$SUBCHANNELS"
+    [ "$LAYER2" ] && echo "LAYER2=$LAYER2"
+    [ "$VSWITCH" ] && echo "VSWITCH=$VSWITCH"
+    [ "$MACADDR" ] && echo "MACADDR=$MACADDR"
+    [ "$PORTNAME" ] && echo "PORTNAME=$PORTNAME"
+    [ "$PORTNO" ] && echo "PORTNO=$PORTNO"
+    [ "$PEERID" ] && echo "PEERID=$PEERID"
+    [ "$CTCPROT" ] && echo "CTCPROT=$CTCPROT"
+    if [ -n "$mmtu_was_set" ]; then
+        echo "MMTU=\"$MMTU\""
+    elif [ -n "$mtu_was_set" ]; then
+        echo "MTU=$MTU"
+    fi
+    [ "$DNS" ] && echo "DNS=$DNS"
+    [ "$SEARCHDNS" ] && echo "SEARCHDNS=$SEARCHDNS"
+    [ "$DASD" ] && echo "DASD=$DASD"
+}
+
+function final_check() {
+    # final check && break
+    if [ -z "$interaction_happened" ]; then
+        # if parm file was good enough just continue without interaction
+        break
+        return 0
+    fi
+    while : ; do
+        # optionally consider "continue" as default
+        # but then again the user may inadvertently continue
+        echo
+        echo $"c) continue, p) parm file/configuration, n) network state, r) restart, s) shell"
+        local answer
+        read answer
+        case $answer in
+            c) return 0 ;;
+            p) echo
+                show_parms ;;
+            n) # show interfaces and routing table
+                ifconfig -a
+                if [ "$ipv6" ]; then
+                    #route -n -A inet6
+                    # the following produces more compact output for 80 columns
+                    ip -6 route show | grep -v "^unreachable "
+                else
+                    route -n
+                fi
+                ;;
+            d) # show active DASDs with some useful details
+                echo $"Activated DASDs:"
+                cat /proc/dasd/devices|sed -e 's/ at ([^)]*) is//' -e 's/ at/,/'
+                ;;
+            r) break ;;
+            s) echo $"Enter 'exit' at the shell prompt to get back to the installation dialog."
+                /bin/bash
+                ;;
+    esac
+    done
+    return 1
+}
+
+### MAIN ###
+
+init_main
+udev_setup
+
+# Parse configuration
+if [ -n "$CMSDASD" -a -n "$CMSCONFFILE" ]; then
+    readcmsfile $CMSDASD $CMSCONFFILE
+    source /tmp/$CMSCONFFILE #2>/dev/null
+fi
+
+if [ -r /sys/firmware/ipl/ipl_type ]; then
+    #local ipl_type
+    read ipl_type < /sys/firmware/ipl/ipl_type
+    if [ "$ipl_type" = "fcp" ]; then
+        while : ; do
+            echo $"Your IPL device is set to FCP."
+            echo $"Would you like to perform a CD-ROM/DVD-ROM installation? (y/n)"
+            #local do_cd_install
+            read do_cd_install
+            case $do_cd_install in
+                y|Y|[Yy][Ee][Ss])
+                    # precondition: zfcp driver incl. dependencies loaded
+                    #local CD_DEVICE WWPN LUN
+                    read CD_DEVICE < /sys/firmware/ipl/device
+                    read WWPN < /sys/firmware/ipl/wwpn
+                    read LUN < /sys/firmware/ipl/lun
+                    zfcp_cio_free -d $CD_DEVICE \
+                        || echo $"Device $CD_DEVICE could not be cleared from device blacklist"
+                    sysecho /sys/bus/ccw/drivers/zfcp/$CD_DEVICE/online 1 \
+                        || echo $"Could not set FCP device $CD_DEVICE online"
+                    udevadm settle
+                    # port (WWPN) appears automatically
+                    sysecho /sys/bus/ccw/drivers/zfcp/$CD_DEVICE/$WWPN/unit_add $LUN \
+                        || echo $"Could not add LUN $LUN at WWPN $WWPN on FCP device $CD_DEVICE"
+                    udevadm settle
+                    break
+                    ;;
+                n|N|[Nn][Oo])
+                    break
+                    ;;
+                *)
+                    echo
+                    echo $"*** INVALID ANSWER: $do_cd_install"
+                    echo
+                    unset do_cd_install
+                    ;;
+            esac
+        done
+    fi
+fi
+
+# Perform a network installation
+
+[ -n "$MTU" ] && mtu_was_set=$MTU
+[ -n "$MMTU" ] && mmtu_was_set=$MMTU
+[ -n "$VSWITCH" ] && vswitch_was_set=$VSWITCH
+
+[ -n "$CHANDEV" ] && do_chandev
+[ -n "$NETWORK" ] && do_network
+[ -n "$BROADCAST" ] && do_broadcast
+
+# [ -z "${cardtype//OSD_*/}" ] can be used to check for real OSA
+
+# Check for missing parameters, prompt for them if necessary
+while : ; do
+
+    # do not show list of possible network device configurations, if:
+    # - running unattended install with kickstart
+    # - relevant parameters have already been specified in parm file
+    #   (a possible optimization would be matching those parms to table entry)
+    # - dialog has not been restarted
+    [ -n "$reenter" \
+        -o -z "$RUNKS" -a \( -z "$NETTYPE" -o -z "$SUBCHANNELS" \) ] && \
+        dialog_network_table
+    if isVM; then
+        echo $"* NOTE: To enter default or empty values press enter twice. *"
+    fi
+    do_nettype
+
+    # precondition: driver (qeth/lcs/ctcm) loaded incl. dependencies
+    do_subchannels
+    if [ "$NETTYPE" = "qeth" ]; then
+        [ -z "$reenter" -a -n "$RUNKS" -a -z "$PORTNAME" ] || \
+            [ -n "${cardtype//OSD_*/}" ] || do_portname
+        # See also https://bugzilla.redhat.com/show_bug.cgi?id=439461
+        #
+        # If running in kickstart mode (unattended), we assume no
+        # interaction and the user won't get asked for PORTNO.
+        # Otherwise the user will be asked for PORTNO.
+        # If the user specified PORTNO in parm/conf file, PORTNO gets
+        # respected (or the user will be asked if it was wrong).
+        if [ -f /sys/devices/qeth/$SCH_R_DEVBUSID/portno ]; then
+            # driver support exists since RHEL5.2
+            [ -z "$reenter" -a -n "$RUNKS" -a -z "$PORTNO" ] || \
+                [ -n "${cardtype//OSD_*/}" ] || do_portno
+        fi
+        do_layer2
+        # set device online to know the device name
+        # and to know if it's OSD/HiperSockets/GuestLAN BUT do not
+        # try to ifconfig the device up since that requires
+        # setting the mac address before (if applicable).
+        set_device_online || workflow_item_menu noredo
+        # MAC address handling is not part of
+        # https://bugzilla.redhat.com/show_bug.cgi?id=233376
+        # Instead the additions come from
+        # https://bugzilla.redhat.com/show_bug.cgi?id=248049
+        # The new parms VSWITCH and MACADDR are described in
+        # the RHEL 5.1 release notes.
+        if isLayer2; then
+            if [ -z "$VSWITCH" -o "$VSWITCH" == 0 ]; then
+                do_macaddr
+            fi
+        fi
+    elif [ "$NETTYPE" = "ctc" ]; then
+        [ -z "$reenter" -a -n "$RUNKS" -a -z "$CTCPROT" ] || do_ctcprot
+        set_device_online || workflow_item_menu noredo
+    elif [ "$NETTYPE" = "lcs" ]; then
+        [ -n "$RUNKS" -a -z "$PORTNAME" ] && PORTNAME=0
+        do_lcs_portno
+        set_device_online || workflow_item_menu noredo
+    fi
+
+    # device needs to be up before configuring with ifconfig/ip in
+    # configure_ipv6_address/configure_ipv4_address/configure_ipv4_address
+    set_device_up || workflow_item_menu noredo
+
+    [ "$HOSTNAME" = "(none)" ] && unset HOSTNAME
+    do_hostname
+
+    # Note: The workflow_item_menu does a rollback_config on restart
+    # dialog, i.e. hardware config has been reset and it is impossible to
+    # only restart halfway at IPADDR.
+    do_ipaddr
+    if [ "$ipv6" ]; then
+        # this branch is all IPv6 and at the same time also NETTYPE==qeth
+        do_netmask_v6
+        handle_mtu
+        configure_ipv6_address || workflow_item_menu noredo
+        do_gateway_v6
+    else
+        # Consider IPv4 as default, even for unknown IP versions
+        # due to invalid input for IPADDR ignored by the user previously
+        # (neither ipv6 nor ipv4 is set).
+        # Otherwise we would skip things like NETMASK or GATEWAY
+        # and jump forward to DNS which is probably not what we want.
+        if [ "$NETTYPE" = "qeth" ] || [ "$NETTYPE" = "lcs" ]; then
+            do_netmask
+            handle_mtu
+            configure_ipv4_address || workflow_item_menu noredo
+            do_gateway
+        else  # ctc0
+            if [ -z "$NETMASK" ]; then
+                # If the user did not supply netmask, we add the right one.
+                # Netmask MUST be present,
+                # or pumpSetupInterface() blows routes.
+                NETMASK="255.255.255.255"
+            fi
+            # don't ask for MTU, but use it if set in the parm file
+            # don't overwrite MMTU if it has been set for CTC
+            [ "$NETTYPE" = "ctc" -a -z "$MTU" -a -z "$MMTU" ] && \
+                MMTU="mtu 1500"
+            do_ptp_gateway
+            configure_ipv4_ptp || workflow_item_menu noredo
+        fi
+    fi
+
+    do_dns
+    [ -n "$DNS" ] && do_searchdns
+
+    do_dasd
+
+    echo $"Initial configuration completed."
+    final_check && break
+    rollback_config
+    reenter="yes"
+
+done # outer dialog loop
+
+if [ -z "$testing" ]; then
+
+    # convert to space-separated lists
+    if [ -n "$SEARCHDNS" ]; then
+        SEARCHDNS=$(echo $SEARCHDNS |sed -e 's/:/ /g')
+        for i in "$SEARCHDNS"; do echo "search $i"; done >> /etc/resolv.conf
+    fi
+    if [ -n "$DNS" ]; then
+        if [ "$ipv6" ]; then
+            RESOLVDNS=$(echo $DNS |sed -e 's/,/ /g')
+        else
+            RESOLVDNS=$(echo $DNS |sed -e 's/:/ /g')
+        fi
+        for i in $RESOLVDNS; do echo "nameserver $i"; done >> /etc/resolv.conf
+    fi
+
+    # make sure we have an /etc/hosts file (originally required for telnetd,
+    # which is no longer included)
+    if [ ! -z "$HOSTNAME" -a ! -z "$IPADDR" ]; then
+        echo -e "$IPADDR\t$HOSTNAME $(echo $HOSTNAME | cut -d '.' -f 1)" >> /etc/hosts
+    fi
+
+fi # testing
+
+# syntax check to give user early feedback on parameters provided in parm file
+# (he probably won't notice the logs written by anaconda later on)
+syntax_check_fcp
+# currently we ignore failed syntax checks since FCP parms are non-interactive
+for i in ${!FCP_*}; do
+    echo "${!i}" >> /etc/zfcp.conf
+done
+# cio_ignore handling for FCP should happen when the content of /etc/zfcp.conf
+# will actually be processed which is in anaconda's zfcp.py ZFCP::readConfig()
+
+# TODO/FIXME: also need to pass IPv6 decision to loader/anaconda
+#    [ "$ipv6" ] && echo "IPV6=yes"
+
+# transfer options into install environment
+# loader now uses ifcfg instead of install.cfg to receive our network config
+
+# additionally, loader's readNetInfo needs to know our DEVICE name
+echo $DEVICE > /tmp/s390net
+
+if [ "$ipv6" ]; then
+    DNS1=$(echo $DNS | cut -d ',' -f 1)
+    DNS2=$(echo $DNS | cut -d ',' -f 2)
+else
+    DNS1=$(echo $DNS | cut -d ':' -f 1)
+    DNS2=$(echo $DNS | cut -d ':' -f 2)
+fi
+
+NETSCRIPTS="/etc/sysconfig/network-scripts"
+IFCFGFILE="$NETSCRIPTS/ifcfg-$DEVICE"
+if [ ! -d "$NETSCRIPTS" ]; then
+    mkdir -p $NETSCRIPTS
+fi
+
+# to please NetworkManager on startup in loader before loader reconfigures net
+cat > /etc/sysconfig/network << EOF
+HOSTNAME=$HOSTNAME
+EOF
+if [ "$ipv6" ]; then
+    echo "NETWORKING_IPV6=yes" >> /etc/sysconfig/network
+else
+    echo "NETWORKING=yes" >> /etc/sysconfig/network
+fi
+
+cat > $IFCFGFILE << EOF
+DEVICE=$DEVICE
+ONBOOT=yes
+BOOTPROTO=static
+MTU=$MTU
+SUBCHANNELS=$SUBCHANNELS
+EOF
+if [ "$ipv6" ]; then
+    cat >> $IFCFGFILE << EOF
+IPV6INIT=yes
+IPV6_AUTOCONF=no
+IPV6ADDR=$IPADDR/$NETMASK
+IPV6_DEFAULTGW=$GATEWAY
+EOF
+else
+    cat >> $IFCFGFILE << EOF
+IPADDR=$IPADDR
+NETMASK=$NETMASK
+BROADCAST=$BROADCAST
+GATEWAY=$GATEWAY
+EOF
+fi
+# real DNS config for NetworkManager to generate /etc/resolv.conf
+[ "$DNS1" != "" ] && echo "DNS1=$DNS1" >> $IFCFGFILE
+[ "$DNS2" != "" ] && echo "DNS2=$DNS2" >> $IFCFGFILE
+# just to please loader's readNetInfo && writeEnabledNetInfo
+# which eats DNS1,DNS2,... and generates it themselves based on DNS
+if [ "$ipv6" ]; then
+    [ "$DNS" != "" ] && echo "DNS=\"$DNS\"" >> $IFCFGFILE
+else
+    [ "$DNS" != "" ] && echo "DNS=\"$(echo $DNS|sed -e 's/:/,/g')\"" >> $IFCFGFILE
+fi
+# colons in SEARCHDNS already replaced with spaces above for /etc/resolv.conf
+[ "$SEARCHDNS" != "" ] && echo "DOMAIN=\"$SEARCHDNS\"" >> $IFCFGFILE
+[ "$NETTYPE" != "" ] && echo "NETTYPE=$NETTYPE" >> $IFCFGFILE
+[ "$PEERID" != "" ] && echo "PEERID=$PEERID" >> $IFCFGFILE
+[ "$PORTNAME" != "" ] && echo "PORTNAME=$PORTNAME" >> $IFCFGFILE
+[ "$CTCPROT" != "" ] && echo "CTCPROT=$CTCPROT" >> $IFCFGFILE
+[ "$MACADDR" != "" ] && echo "MACADDR=$MACADDR" >> $IFCFGFILE
+optstr=""
+for option in LAYER2 PORTNO; do
+    [ -z "${!option}" ] && continue
+    [ -n "$optstr" ] && optstr=${optstr}" "
+    optstr=${optstr}$(echo ${option} | tr [[:upper:]] [[:lower:]])"="${!option}
+done
+# write single quotes since network.py removes double quotes but we need quotes
+echo "OPTIONS='$optstr'" >> $IFCFGFILE
+unset option
+unset optstr
+
+if [ -z "$testing" ]; then
+
+    # so that the vars get propagated into the sshd shells
+    mkdir /.ssh
+    cat >> /.ssh/environment <<EOF
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH
+PATH=$PATH
+HOME=$HOME
+PYTHONPATH=$PYTHONPATH
+EOF
+
+    cat >> /etc/profile <<EOF
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH
+PATH=$PATH
+HOME=$HOME
+PYTHONPATH=$PYTHONPATH
+export LD_LIBRARY_PATH PATH HOME PYTHONPATH
+EOF
+
+    if [ -n "$DISPLAY" ]; then
+        echo "export DISPLAY=$DISPLAY" >> /etc/profile
+    fi
+
+    # I'm tired of typing this out...
+    echo "loader" >> /.bash_history
+
+    echo -n $$ > /var/run/init.pid
+
+    # shutdown (halt) on SIGUSR1
+    trap doshutdown SIGUSR1
+    # reboot on SIGUSR2
+    trap doreboot SIGUSR2
+
+    startinetd
+
+    if [ -n "$RUNKS" ]; then
+        /sbin/loader
+    fi
+
+    doshutdown
+
+fi # testing
+
+# ;;; Local Variables: ***
+# ;;; mode: sh ***
+# ;;; end: ***
diff --git a/loader/linuxrc.s390 b/loader/linuxrc.s390
deleted file mode 100644
index 3280498..0000000
--- a/loader/linuxrc.s390
+++ /dev/null
@@ -1,3079 +0,0 @@
-#! /bin/bash
-
-# linuxrc.s390: init process of Red Hat's installer initrd for s390(x)
-# Copyright (C) 2000-2004 by
-#        Bernhard Rosenkraenzer <bero@xxxxxxxxxx>
-#        Oliver Paukstadt <opaukstadt@xxxxxxxxxxxx>
-#        Karsten Hopp <karsten@xxxxxxxxx>
-#        Florian La Roche <laroche@xxxxxxxxxx>
-#        Nils Philippsen <nils@xxxxxxxxx>
-#        Helge Deller <hdeller@xxxxxxxxx>
-#        David Sainty <dsainty@xxxxxxxxxx>
-# Copyright (C) IBM Corp. 2008,2009
-#        Author: Steffen Maier <maier@xxxxxxxxxx>
-#
-#    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\n", $1, $2, $3, $4);
-      printf("chmod %s /dev/%s\n", $5, $1);
-      printf("chown %s /dev/%s\n", $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\tlocalhost.localdomain localhost localhost4 localhost4.localdomain4" > /etc/hosts
-        echo -e     "::1\t\tlocalhost.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\n"
-    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 '\n' ','
-                #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|HiperSockets|"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 help)"
-}
-
-function helptext_ipaddr() {
-    echo $" Help text for IP address:"
-    echo $"  Enter a valid IPv4 address of your new Linux guest (e.g. 10.0.0.2)"
-    if [ "$ipv6_capable" = "yes" ]; then
-        echo $"  or alternatively a valid IPv6 address without CIDR prefix (e.g. 2001:0DB8::)"
-        echo $"  IPv6 is supported on:"
-        echo $"   - Ethernet interfaces of the OSA-Express adapter running in QDIO mode."
-        echo $"   - HiperSockets interfaces"
-        echo $"   - z/VM guest LAN interfaces running in QDIO mode."
-        echo $"  IPv6 is not supported on HiperSockets guest LAN, OSA-Express Token Ring, ATM."
-    fi
-}
-
-function do_ipaddr() {
-    ipv6_capable && ipv6_capable=yes || ipv6_capable=no
-    ask IPADDR \
-        question_prefix_ipaddr question_choices_ipaddr \
-        -h helptext_ipaddr -s syntax_check_ipaddr
-    if [ "$ipv6" ]; then
-       # qeth_l3 would load ipv6 automatically but not qeth_l2
-       modprobe ipv6
-       tv disable_ipv6_autoconf
-    fi
-
-    # no handling/configuring of IPADDR yet, since more parameters needed
-}
-
-### NETMASK (IPv4)
-
-function syntax_check_netmask_v4() {
-    # also support CIDR prefix
-    if [[ "$NETMASK" =~ ^[[:digit:]]+$ ]]; then
-        if [ "$NETMASK" -ge 1 -a "$NETMASK" -le 32 ]; then
-            ipcalc_arg="$IPADDR/$NETMASK"
-            return 0
-        fi
-        echo $"Incorrect value for network prefix [1..32] (NETMASK): $NETMASK"
-        return 1
-    elif checkipv4 $NETMASK; then
-        ipcalc_arg="$IPADDR $NETMASK"
-        return 0
-    fi
-    echo $"Incorrect format or value for network mask (NETMASK): $NETMASK"
-    return 1
-}
-
-function question_prefix_netmask() {
-    echo -n $"IPv4 netmask or CIDR prefix"
-}
-
-function hint_netmask_v4() {
-    # default based on class a/b/c address
-    local a b c d
-    IFS=.
-    read a b c d <<< "$IPADDR"
-    unset IFS
-    local ip=$(( ( a << 24 ) + ( b << 16 ) + ( c << 8 ) + ( d ) ))
-    # <<EOF convince syntax highlighter that above shifts are no here documents
-    if   [ $(( ip & 0x80000000 )) -eq $(( 0x00000000 )) ]; then
-        # class a
-        echo "255.0.0.0"
-    elif [ $(( ip & 0xC0000000 )) -eq $(( 0x80000000 )) ]; then
-        # class b
-        echo "255.255.0.0"
-    elif [ $(( ip & 0xE0000000 )) -eq $(( 0xC0000000 )) ]; then
-        # class c
-        echo "255.255.255.0"
-    else
-        # some other class that should not be used as host address
-        return 1
-    fi
-    return 0
-}
-
-function question_choices_netmask() {
-    echo -n $" (e.g. 255.255.255.0 or 1..32 or ? for help)"
-    local default=$(hint_netmask_v4)
-    if [ -n "$default" ]; then
-        echo $". Default is $default:"
-    else
-        echo $":"
-        echo $"The IP address you entered previously should probably not be used for a host."
-    fi
-}
-
-function helptext_netmask() {
-    echo $" Help text for IPv4 netmask or CIDR prefix:"
-    echo $"  Enter a valid IPv4 netmask or CIDR prefix (e.g. 255.255.255.0 or 1..32)"
-    local default=$(hint_netmask_v4)
-    if [ -n "$default" ]; then
-        echo $"  Default is $default"
-    else
-        echo $"The IP address you entered previously should probably not be used for a host."
-    fi
-}
-
-function exception_netmask() {
-    if [ -z "$NETMASK" ]; then
-        NETMASK=$(hint_netmask_v4)
-    fi
-}
-
-function do_netmask() {
-    ask NETMASK \
-        question_prefix_netmask question_choices_netmask \
-        -h helptext_netmask \
-        -s syntax_check_netmask_v4 -e exception_netmask
-    # no handling/configuring of NETMASK yet, since more parameters needed
-}
-
-### NETWORK
-
-function do_network() {
-    echo
-    echo $"The NETWORK parameter isn't used anymore and will be ignored."
-    echo $" It is sufficient to specify IPADDR and NETMASK."
-    echo
-    unset NETWORK
-}
-
-### BROADCAST
-
-function do_broadcast() {
-    echo
-    echo $"The BROADCAST parameter isn't used anymore and will be ignored."
-    echo $" It is sufficient to specify IPADDR and NETMASK."
-    echo
-    unset BROADCAST
-}
-
-### NETMASK (IPv6)
-
-function syntax_check_prefix_v6() {
-    if [[ "$NETMASK" =~ ^[[:digit:]]+$ ]]; then
-        if [ "$NETMASK" -ge 1 -a "$NETMASK" -le 128 ]; then
-            return 0
-        fi
-    fi
-    echo $"Incorrect value for network prefix [1..128] (NETMASK): $NETMASK"
-    return 1
-}
-
-function question_prefix_netmask_v6() {
-    echo -n $"CIDR prefix for the IPv6 address"
-}
-
-function question_choices_netmask_v6() {
-    echo $" (1..128):"
-}
-
-function do_netmask_v6() {
-    ask NETMASK \
-        question_prefix_netmask_v6 question_choices_netmask_v6 \
-        -s syntax_check_prefix_v6
-    # no handling/configuring of NETMASK yet, since more parameters needed
-}
-
-### GATEWAY (IPv4)
-
-function configure_ipv4_gateway() {
-    # FIXME:
-    # - Strictly speaking we should first check reachability of gateway
-    #   and then configure the gateway route.
-    #   This would require a new intermediate workflow_item step
-    #   so that the user might continue despite unreachable gateway.
-    # done: Only adding default route might add multiple undesired default
-    # routes on redoing the parameter item, so delete default route
-    # before adding a new one.
-    ip -4 route del default dev $DEVICE >& /dev/null
-    [ -z "$GATEWAY" ] && return 0
-    if ! tv route add default gw $GATEWAY dev $DEVICE; then
-        echo $"Could net set default route on device $DEVICE via gateway $GATEWAY"
-        return 1
-    fi
-    # BH FIXME: Workaround for manual MACADDR, need ping to update arp table
-    echo $"Trying to reach gateway $GATEWAY..."
-    if [ "$NETTYPE" = "ctc" ]; then
-        # (virtual) CTC(/A) seems to need some time to get functional
-        local i=1
-        while : ; do
-            $PING $GATEWAY >& /dev/null && break
-            i=$((i+1))
-            if [ "$i" -gt 3 ]; then
-                echo $"Could not reach gateway $GATEWAY within timeout"
-                return 1
-            fi
-        done
-    else
-        if ! $PING $GATEWAY >& /dev/null; then
-            echo $"Could not reach your default gateway $GATEWAY"
-            return 1
-        fi
-    fi
-    return 0
-}
-
-function hint_ipv4_gateway() {
-    # - provide default suggestion based on network,
-    #   for a class C network this would be either .1 or .254 at the end
-    local a b c d
-    IFS=.
-    read a b c d <<< "$NETWORK"
-    unset IFS
-    local ip=$(( ( a << 24 ) + ( b << 16 ) + ( c << 8 ) + ( d ) ))
-    # <<EOF convince syntax highlighter that above shifts are no here documents
-    local lo=$(( ip | 1 ))
-    local lo_a=$(( (lo & 0xFF000000) >> 24 ))
-    local lo_b=$(( (lo & 0x00FF0000) >> 16 ))
-    local lo_c=$(( (lo & 0x0000FF00) >> 8 ))
-    local lo_d=$(( (lo & 0x000000FF) ))
-    local hi=$(( ip | ( (2**(32 - PREFIX)) - 1 ) ))
-    local hi_a=$(( (hi & 0xFF000000) >> 24 ))
-    local hi_b=$(( (hi & 0x00FF0000) >> 16 ))
-    local hi_c=$(( (hi & 0x0000FF00) >> 8 ))
-    local hi_d=$(( (hi & 0x000000FE) ))
-    echo $"  Depending on your network design patterns, the default gateway"
-    echo $"   might be $lo_a.$lo_b.$lo_c.$lo_d or $hi_a.$hi_b.$hi_c.$hi_d"
-}
-
-function question_prefix_gateway() {
-    echo -n $"IPv4 address of your default gateway"
-}
-
-function question_choices_gateway() {
-    echo $" or ? for help:"
-}
-
-function helptext_gateway() {
-    echo $" Help text for IPv4 default gateway:"
-    echo $"  For HiperSockets with internal traffic only you may want to leave this empty"
-    echo $"  and choose continue afterwards to go on without gateway."
-    hint_ipv4_gateway
-}
-
-function finish_gateway() {
-    if ! checkipv4 $GATEWAY; then
-        # above checkipv4 is silent, so make up for syntax error
-        echo $"Incorrect format for IPv4 address of gateway (GATEWAY): $GATEWAY"
-        workflow_item_menu
-    fi
-    if configure_ipv4_gateway; then
-        break
-    else
-        workflow_item_menu && break
-    fi
-}
-
-# FIXME: allow empty/no gateway?
-
-function do_gateway() {
-    ask GATEWAY \
-        question_prefix_gateway question_choices_gateway \
-        -h helptext_gateway -f finish_gateway
-}
-
-### GATEWAY (IPv6)
-
-function configure_ipv6_gateway() {
-    # FIXME:
-    # - Strictly speaking we should first check reachability of gateway
-    #   and then configure the gateway route.
-    #   This would require a new intermediate workflow_item step
-    #   so that the user might continue despite unreachable gateway.
-    # done: Only adding default route might add multiple undesired default
-    # routes on redoing the parameter item, so delete default route
-    # before adding a new one.
-    ip -6 route del default dev $DEVICE >& /dev/null
-    [ -z "$GATEWAY" ] && return 0
-    # IPv6 http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/Linux+IPv6-HOWTO.html#AEN1147
-    #       ip -6 route add ::/0 dev $DEVICE via $GATEWAY
-    # (Could also be learned by autoconfiguration on the link:
-    #  after IP address setup and device up,
-    #   see if default route has been learned
-    #   ip -6 route show | grep ^default
-    #  However, we currently use manual IPv6 configuration only.)
-    if ! debug ip -6 route add ::/0 dev $DEVICE via $GATEWAY; then
-        echo $"Could net set default route on device $DEVICE"
-        echo $" via gateway $GATEWAY"
-        return 1
-    fi
-    # BH FIXME: Workaround for manual MACADDR, need ping to update arp table
-    echo $"Trying to reach gateway $GATEWAY..."
-    if ! $PING6 $GATEWAY >& /dev/null; then
-        echo $"Could not reach your default gateway $GATEWAY"
-        return 1
-    fi
-    return 0
-}
-
-function question_prefix_gateway_v6() {
-    echo -n $"IPv6 address of your default gateway"
-}
-
-function question_choices_gateway_v6() {
-    echo $":"
-}
-
-function helptext_gateway_v6() {
-    echo $" Help text for IPv6 default gateway:"
-    echo $"  For HiperSockets with internal traffic only you may want to leave this empty"
-    echo $"  and choose continue afterwards to go on without gateway."
-}
-
-function finish_gateway_v6() {
-    if ! checkipv6 $GATEWAY; then
-        # above checkipv6 is silent, so make up for syntax error
-        echo $"Incorrect format for IPv6 address of gateway (GATEWAY): $GATEWAY"
-        workflow_item_menu
-    fi
-    if configure_ipv6_gateway; then
-        break
-    else
-        workflow_item_menu && break
-    fi
-}
-
-# FIXME: allow empty/no gateway?
-
-function do_gateway_v6() {
-    ask GATEWAY \
-        question_prefix_gateway_v6 question_choices_gateway_v6 \
-        -h helptext_gateway_v6 -f finish_gateway_v6
-}
-
-### GATEWAY (IPv4, point-to-point)
-
-function configure_ipv4_ptp() {
-    # device needs to be online
-    if debug ifconfig $DEVICE $IPADDR $MMTU pointopoint $GATEWAY; then
-        configure_ipv4_gateway
-        return $?
-    fi
-    echo $"Could not set IPv4 address $IPADDR for device $DEVICE"
-    echo $" to peer $GATEWAY"
-    [ -n "$MMTU" ] && echo $" and maximum transfer unit: $MMTU"
-    return 1
-}
-
-function question_prefix_ptp_gateway() {
-    echo -n $"IPv4 address of your point-to-point partner"
-}
-
-function question_choices_ptp_gateway() {
-    echo $" or ? for help:"
-    # no hinting possible here
-}
-
-function helptext_ptp_gateway() {
-    echo $" Help text for point-to-point partner:"
-    echo $"  IPv4 address of your CTC or ESCON point-to-point partner."
-}
-
-function finish_ptp_gateway() {
-    if checkipv4 $GATEWAY; then
-        if [ "$GATEWAY" = "$IPADDR" ]; then
-            echo $"IPv4 address of partner should probably be different from the guest's address"
-            workflow_item_menu && break
-        else
-            break
-        fi
-    else
-        # above checkipv4 is silent, so make up for syntax error
-        echo $"Incorrect format for IPv4 address of partner (GATEWAY): $GATEWAY"
-        workflow_item_menu && break
-    fi
-    # too early to actually configure gateway
-}
-
-function do_ptp_gateway() {
-    ask GATEWAY \
-        question_prefix_ptp_gateway question_choices_ptp_gateway \
-        -h helptext_ptp_gateway -f finish_ptp_gateway
-}
-
-### DNS
-
-function syntax_check_dns() {
-    if [ -z "$DNS" ]; then
-        echo $"You might encounter problems without a nameserver, especially with FTP installs"
-        return 1
-    fi
-    local dnsitem
-    local allgood="yes"
-    if [ "$ipv6" ]; then
-        while read dnsitem; do
-            if ! checkipv6 $dnsitem; then
-                echo $"Not a valid IPv6 address for DNS server: $dnsitem"
-                allgood="no"
-            fi
-        done < <(echo $DNS | sed 's/,/\n/g')
-    else
-         while read dnsitem; do
-           if ! checkipv4 $dnsitem; then
-                echo $"Not a valid IPv4 address for DNS server: $dnsitem"
-                allgood="no"
-            fi
-         done < <(echo $DNS | sed 's/:/\n/g')
-    fi
-    if [ "$allgood" = "yes" ]; then
-        return 0
-    else
-        return 1
-    fi
-}
-
-function handle_dns() {
-    # - foreach DNS try if server is reachable by one ping
-    [ -z "$DNS" ] && return 0
-    local dnsitem
-    local allgood="yes"
-    echo $"Trying to reach DNS servers..."
-    if [ "$ipv6" ]; then
-        while read dnsitem; do
-            if ! $PING6 $dnsitem >& /dev/null; then
-                echo $"Could not ping DNS server (might still serve DNS requests): $dnsitem"
-                allgood="no"
-                # this should not be a hard failure since some network
-                # environments may prevent pings to DNS servers
-                # => prevent workflow_item_menu in kickstart mode
-            fi
-        done < <(echo $DNS | sed 's/,/\n/g')
-    else
-        while read dnsitem; do
-            # Some network environment may prevent a DNS server from being
-            # reachable by ping, so it would make sense to use nslookup.
-            # However, nslookup fails with "Resolver Error 0 (no error)"
-            # at this stage of the setup progress => not useful
-            if ! $PING $dnsitem >& /dev/null; then
-                echo $"Could not ping DNS server: $dnsitem"
-#                if nslookup $dnsitem $dnsitem >& /dev/null; then
-#                    echo $" but could resolve DNS server with itself: $dnsitem"
-#                else
-#                    echo $"Could not resolve DNS server with itself: $dnsitem"
-#                    allgood="no"
-#                fi
-#            elif ! nslookup $dnsitem $dnsitem >& /dev/null; then
-#                echo $"Could not resolve DNS server with itself: $dnsitem"
-                allgood="no"
-            fi
-        done < <(echo $DNS | sed 's/:/\n/g')
-    fi
-    if [ "$allgood" = "yes" ]; then
-        return 0
-    else
-        return 1
-    fi
-}
-
-function question_prefix_dns() {
-    if [ "$ipv6" ]; then
-        echo -n $"IPv6 addresses of DNS servers"
-    else
-        echo -n $"IPv4 addresses of DNS servers"
-    fi
-}
-
-function question_choices_dns() {
-    if [ "$ipv6" ]; then
-        echo $" (separated by commas ',' or ? for help):"
-    else
-        echo $" (separated by colons ':' or ? for help):"
-    fi
-}
-
-function helptext_dns() {
-    echo $" Help text for DNS servers:"
-    if [ "$ipv6" ]; then
-        echo $"  Enter IPv6 addresses of DNS servers separated by commas ','"
-    else
-        echo $"  Enter IPv4 addresses of DNS servers separated by colons ':'"
-    fi
-    echo $"  Default are no DNS servers at all."
-    echo $"  However, you might encounter problems without a nameserver,"
-    echo $"   especially with FTP installs."
-    if [ "$ipv6" ]; then
-        echo $"  An example with 2 servers would be: 2001:0DB8::42,2001:0DB8::BE:AF"
-    else
-        echo $"  An example with 2 servers would be: 10.0.0.250:10.1.1.1"
-    fi
-}
-
-function do_dns() {
-    ask DNS \
-        question_prefix_dns question_choices_dns \
-        -h helptext_dns -s syntax_check_dns -c handle_dns
-}
-
-### SEARCHDNS
-
-function syntax_check_searchdns() {
-    [ -z "$SEARCHDNS" ] && return 0
-    local dnsitem
-    local allgood="yes"
-    while read dnsitem; do
-        syntax_check_domainname "$dnsitem" $"Not a valid DNS search domain: $dnsitem" || allgood="no"
-    done < <(echo $SEARCHDNS | sed 's/:/\n/g')
-    if [ "$allgood" = "yes" ]; then
-        return 0
-    else
-        return 1
-    fi
-}
-
-function question_prefix_searchdns() {
-    echo -n $"DNS search domains"
-}
-
-function question_choices_searchdns() {
-    echo $" (separated by colons ':' or ? for help):"
-}
-
-function helptext_searchdns() {
-    echo $" Help text for DNS search domains:"
-    echo $"  Enter search domains according to hostname syntax separated by colons."
-    echo $"  Default are no DNS search domains at all."
-    echo $"  An example would be: subdomain.domain.com:domain.com"
-}
-
-function do_searchdns() {
-    ask SEARCHDNS \
-        question_prefix_searchdns question_choices_searchdns \
-        -h helptext_searchdns -s syntax_check_searchdns
-}
-
-### DASD
-
-function parse_dasd() {
-    local handle
-    [ "$1" = "-h" ] && handle=yes || unset handle
-    local dasditem
-    local allgood="yes"
-    local cio_wc=$(wc -c /proc/cio_ignore)
-    read cio_wc_bytes cio_wc_filename cio_wc_foo <<< "$cio_wc"
-    if [ "$handle" = "yes" -a "$cio_wc_bytes" != "0" ]; then
-        echo $"Trying to clear specified DASDs from device blacklist..."
-        mkdir -p /etc/modprobe.d
-        echo "options dasd_mod dasd=$DASD" > /etc/modprobe.d/dasd_mod.conf
-        if ! dasd_cio_free; then
-            echo $"Not all specified DASDs could be detected within timeout."
-            allgood="no"
-        fi
-    fi
-    while read dasditem; do
-        unset range features range lo hi rangegood \
-            attrs devno lodevno hidevno devbusid sys
-        case $dasditem in
-            autodetect)
-                [ -z "$handle" ] && continue
-                cio_wc=$(wc -c /proc/cio_ignore)
-                read cio_wc_bytes cio_wc_filename cio_wc_foo <<< "$cio_wc"
-                # above we only freed the devices specified in $DASD,
-                # so there might still be other DASDs in the blacklist
-                if [ "$cio_wc_bytes" != "0" ]; then
-                    echo $"Note: There is a device blacklist active! Only activating visible DASDs."
-                fi
-                local sys
-                while read sys; do
-                    if ! sysecho $sys/online 1; then
-                        echo $"Could not set DASD ${sys##*/} online"
-                    fi
-                done < <(find /sys/bus/ccw/drivers/dasd-eckd/ -name "*.?.????" 2>/dev/null;\
-                    find /sys/bus/ccw/drivers/dasd-fba/ -name "*.?.????" 2>/dev/null)
-                ;;
-            probeonly|nopav|nofcx)
-                if [ -z "$handle" ]; then
-                    echo $"DASD option $dasditem not supported by installer"
-                fi
-                ;;
-            "") continue ;; # empty range
-            *)  local range features rangegood="yes"
-                IFS='('
-                read range features <<< "$dasditem"
-                unset IFS
-                # parse: dev OR dev'-'dev
-                local lo=${range%%-*}
-                [[ "$lo" =~ (^[[:xdigit:]]+\.[0-3]\.[[:xdigit:]]{4}$)|(^[[:xdigit:]]{3,4}$) ]]
-                case $? in
-                    0)  # string matched the pattern
-                        lo=$(canonicalize_devno $lo) ;;
-                    1)  # string did not match the pattern
-                        rangegood="no"
-                        if [ -z "$handle" ]; then
-                            echo $"Incorrect format for lower bound of DASD range $range: $lo"
-                            allgood="no"
-                        fi
-                        ;;
-                    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
-                if [ "${range//*-*/}" = "" ]; then
-                    local hi=${range##*-}
-                    [[ "$hi" =~ (^[[:xdigit:]]+\.[0-3]\.[[:xdigit:]]{4}$)|(^[[:xdigit:]]{3,4}$) ]]
-                    case $? in
-                        0)  # string matched the pattern
-                            hi=$(canonicalize_devno $hi)
-                            if [ "${lo%.*}" != "${hi%.*}" ]; then
-                                echo $"Prefixes of DASD range $range do not match: ${lo%.*} != ${hi%.*}"
-                                rangegood="no"
-                                allgood="no"
-                            fi
-                            ;;
-                        1)  # string did not match the pattern
-                            rangegood="no"
-                            if [ -z "$handle" ]; then
-                                echo $"Incorrect format for upper bound of DASD range $range: $hi"
-                                allgood="no"
-                            fi
-                            ;;
-                        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
-                fi
-                if [ "${features//*)/}" != "" ]; then
-                    if [ -z "$handle" ]; then
-                        echo $"Missing closing parenthesis at features of DASD range $range: ($features"
-                        allgood="no"
-                    fi
-                fi
-                local attrs=""
-                if [ -n "$features" ]; then
-                    features="${features%)}"
-                    while read feature; do
-                        case $feature in
-                            ro) attrs=$attrs" readonly" ;;
-                            diag) attrs=$attrs" use_diag" ;;
-                            erplog|failfast) attrs=$attrs" "$feature ;;
-                            *) if [ -z "$handle" ]; then
-                                   echo $"Unknown DASD feature for device range $range: $feature"
-                                   allgood="no"
-                               fi
-                               ;;
-                        esac
-                    done < <(echo $features | sed 's/:/\n/g')
-                fi
-                [ "$rangegood" = "yes" ] || continue
-                [ "$handle" = "yes" ] || continue
-                # now apply $attrs and set DASDs $lo to $hi online
-                [ -z "$hi" ] && hi=$lo
-                local devno lodevno=$((0x${lo##*.})) hidevno=$((0x${hi##*.}))
-                local dasdconf="/etc/dasd.conf"
-                for ((devno=$lodevno; $devno <= $hidevno; ++devno)); do
-                    local devbusid=$(printf "%s.%04x" ${lo%.*} $devno)
-                    local sys="/sys/bus/ccw/devices/"$devbusid
-                    echo -n "$devbusid" >> $dasdconf
-                    for attr in $attrs; do
-                        if [ "$attr" = "use_diag" ]; then
-                            # diag discipline cannot be auto-loaded
-                            modprobe dasd_diag_mod
-                        fi
-                        if [ ! -f $sys/$attr ]; then
-                            echo $"DASD $devbusid does not provide attribute $attr"
-                            continue
-                        fi
-                        if ! sysecho $sys/$attr 1; then
-                            echo $"Could not set attribute $attr for DASD $devbusid"
-                        fi
-                        echo -n " $attr=1" >> $dasdconf
-                    done
-                    if [ ! -f $sys/online ]; then
-                        echo $"DASD $devbusid not found"
-                        continue
-                    fi
-                    if ! sysecho $sys/online 1; then
-                        echo $"Could not set DASD $devbusid online"
-                    fi
-                    echo >> $dasdconf
-                done
-                ;;
-        esac
-    done < <(echo $DASD | sed 's/,/\n/g')
-    if [ "$handle" = "yes" ]; then
-        udevadm settle
-        dasd_settle_all || return 1
-        echo $"Activated DASDs:"
-        cat /proc/dasd/devices | sed -e 's/ at ([^)]*) is//' -e 's/ at/,/'
-    fi
-    if [ "$allgood" = "yes" ]; then
-        return 0
-    else
-        return 1
-    fi
-}
-
-function syntax_check_dasd() {
-    parse_dasd
-    return $?
-}
-
-function handle_dasd() {
-    parse_dasd -h
-    return $?
-}
-
-function question_prefix_dasd() {
-    echo -n $"DASD range"
-}
-
-function question_choices_dasd() {
-    echo $" (e.g. 200-203,205 or ? for help). Default is autoprobing:"
-}
-
-function helptext_dasd() {
-    echo $" Help text for DASD range:"
-    echo $"  Comma separated list of ranges of device bus IDs."
-    echo $"  Default is autoprobing (not recommended)."
-    echo $"  Examples would be: 200-203 or 200,201,202,203 or 0.0.0200-0.0.0203,0.0.0205"
-}
-
-function exception_dasd() {
-    [ -z "$DASD" ] && DASD="autodetect"
-}
-
-function do_dasd() {
-    ask DASD \
-        question_prefix_dasd question_choices_dasd \
-        -h helptext_dasd -e exception_dasd -s syntax_check_dasd -c handle_dasd
-}
-
-### FCP
-
-function syntax_check_fcp() {
-    local allgood="yes"
-    local i
-    for i in ${!FCP_*}; do
-        local -a fcp
-        local devno wwpn lun
-        read -a fcp <<< "${!i}"
-        case ${#fcp[@]} in
-            3)
-                devno=${fcp[0]}
-                wwpn=${fcp[1]}
-                lun=${fcp[2]}
-                ;;
-            5)
-                devno=${fcp[0]}
-                wwpn=${fcp[2]}
-                lun=${fcp[4]}
-                echo $"Deprecated number of FCP arguments (5 instead of 3): "
-                echo $" $i=\"${!i}\""
-                echo $" should instead be: "
-                echo $" $i=\"$devno $wwpn $lun\""
-                ;;
-            *)
-                echo $"Unsupported number of FCP arguments (${#fcp[@]} instead of 3) in:"
-                echo $" $i=\"${!i}\""
-                allgood="no"
-                continue
-                ;;
-        esac
-        [[ "$devno" =~ (^[[:xdigit:]]+\.[0-3]\.[[:xdigit:]]{4}$)|(^[[:xdigit:]]{3,4}$) ]]
-        case $? in
-            0)  ;; # string matched the pattern
-            1)  # string did not match the pattern
-                echo $"Incorrect format for FCP device $devno in:"
-                echo $" $i=\"${!i}\""
-                allgood="no"
-                ;;
-            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
-        # zfcp.py:class ZFCPDevice would also accept WWPN without leading 0x
-        [[ "$wwpn" =~ ^0x[[:xdigit:]]{16}$ ]]
-        case $? in
-            0)  ;; # string matched the pattern
-            1)  # string did not match the pattern
-                echo $"Incorrect format for FCP WWPN $wwpn in:"
-                echo $" $i=\"${!i}\""
-                allgood="no"
-                ;;
-            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
-        # zfcp.py:class ZFCPDevice would also accept LUN without leading 0x
-        # zfcp.py:class ZFCPDevice would also accept 16 bit LUN and pads with 0
-        [[ "$lun" =~ ^0x[[:xdigit:]]{8}0{8}$ ]]
-        case $? in
-            0)  ;; # string matched the pattern
-            1)  # string did not match the pattern
-                echo $"Incorrect format for FCP LUN $lun in:"
-                echo $" $i=\"${!i}\""
-                allgood="no"
-                ;;
-            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 [ "$allgood" = "yes" ]; then
-        return 0
-    else
-        return 1
-    fi
-}
-
-###
-
-function show_parms() {
-    # The only issue with this stateless approach to showing parameters based
-    # on their content being non-empty is, that parameters with defaults
-    # such as LAYER2, (PORTNAME,) CTCPROT, PORTNO (,MACADDR) won't be shown
-    # if the user just hit enter, so the parm file would be "incomplete".
-    # However this is not easy to fix in here, since it would require the
-    # inter-parameter dependenies coded below in the main part, e.g. an
-    # empty LAYER2 should only be printed with default value if $NETTYPE=qeth.
-    # For the time being, at least the parameters LAYER2, PORTNAME, and CTCPROT
-    # only get asked on being empty if not running in kickstart mode.
-    cat << EOF
-NETTYPE=$NETTYPE
-IPADDR=$IPADDR
-NETMASK=$NETMASK
-GATEWAY=$GATEWAY
-HOSTNAME=$HOSTNAME
-EOF
-    [ "$SUBCHANNELS" ] && echo "SUBCHANNELS=$SUBCHANNELS"
-    [ "$LAYER2" ] && echo "LAYER2=$LAYER2"
-    [ "$VSWITCH" ] && echo "VSWITCH=$VSWITCH"
-    [ "$MACADDR" ] && echo "MACADDR=$MACADDR"
-    [ "$PORTNAME" ] && echo "PORTNAME=$PORTNAME"
-    [ "$PORTNO" ] && echo "PORTNO=$PORTNO"
-    [ "$PEERID" ] && echo "PEERID=$PEERID"
-    [ "$CTCPROT" ] && echo "CTCPROT=$CTCPROT"
-    if [ -n "$mmtu_was_set" ]; then
-        echo "MMTU=\"$MMTU\""
-    elif [ -n "$mtu_was_set" ]; then
-        echo "MTU=$MTU"
-    fi
-    [ "$DNS" ] && echo "DNS=$DNS"
-    [ "$SEARCHDNS" ] && echo "SEARCHDNS=$SEARCHDNS"
-    [ "$DASD" ] && echo "DASD=$DASD"
-}
-
-function final_check() {
-    # final check && break
-    if [ -z "$interaction_happened" ]; then
-        # if parm file was good enough just continue without interaction
-        break
-        return 0
-    fi
-    while : ; do
-        # optionally consider "continue" as default
-        # but then again the user may inadvertently continue
-        echo
-        echo $"c) continue, p) parm file/configuration, n) network state, r) restart, s) shell"
-        local answer
-        read answer
-        case $answer in
-            c) return 0 ;;
-            p) echo
-                show_parms ;;
-            n) # show interfaces and routing table
-                ifconfig -a
-                if [ "$ipv6" ]; then
-                    #route -n -A inet6
-                    # the following produces more compact output for 80 columns
-                    ip -6 route show | grep -v "^unreachable "
-                else
-                    route -n
-                fi
-                ;;
-            d) # show active DASDs with some useful details
-                echo $"Activated DASDs:"
-                cat /proc/dasd/devices|sed -e 's/ at ([^)]*) is//' -e 's/ at/,/'
-                ;;
-            r) break ;;
-            s) echo $"Enter 'exit' at the shell prompt to get back to the installation dialog."
-                /bin/bash
-                ;;
-    esac
-    done
-    return 1
-}
-
-### MAIN ###
-
-init_main
-udev_setup
-
-# Parse configuration
-if [ -n "$CMSDASD" -a -n "$CMSCONFFILE" ]; then
-    readcmsfile $CMSDASD $CMSCONFFILE
-    source /tmp/$CMSCONFFILE #2>/dev/null
-fi
-
-if [ -r /sys/firmware/ipl/ipl_type ]; then
-    #local ipl_type
-    read ipl_type < /sys/firmware/ipl/ipl_type
-    if [ "$ipl_type" = "fcp" ]; then
-        while : ; do
-            echo $"Your IPL device is set to FCP."
-            echo $"Would you like to perform a CD-ROM/DVD-ROM installation? (y/n)"
-            #local do_cd_install
-            read do_cd_install
-            case $do_cd_install in
-                y|Y|[Yy][Ee][Ss])
-                    # precondition: zfcp driver incl. dependencies loaded
-                    #local CD_DEVICE WWPN LUN
-                    read CD_DEVICE < /sys/firmware/ipl/device
-                    read WWPN < /sys/firmware/ipl/wwpn
-                    read LUN < /sys/firmware/ipl/lun
-                    zfcp_cio_free -d $CD_DEVICE \
-                        || echo $"Device $CD_DEVICE could not be cleared from device blacklist"
-                    sysecho /sys/bus/ccw/drivers/zfcp/$CD_DEVICE/online 1 \
-                        || echo $"Could not set FCP device $CD_DEVICE online"
-                    udevadm settle
-                    # port (WWPN) appears automatically
-                    sysecho /sys/bus/ccw/drivers/zfcp/$CD_DEVICE/$WWPN/unit_add $LUN \
-                        || echo $"Could not add LUN $LUN at WWPN $WWPN on FCP device $CD_DEVICE"
-                    udevadm settle
-                    break
-                    ;;
-                n|N|[Nn][Oo])
-                    break
-                    ;;
-                *)
-                    echo
-                    echo $"*** INVALID ANSWER: $do_cd_install"
-                    echo
-                    unset do_cd_install
-                    ;;
-            esac
-        done
-    fi
-fi
-
-# Perform a network installation
-
-[ -n "$MTU" ] && mtu_was_set=$MTU
-[ -n "$MMTU" ] && mmtu_was_set=$MMTU
-[ -n "$VSWITCH" ] && vswitch_was_set=$VSWITCH
-
-[ -n "$CHANDEV" ] && do_chandev
-[ -n "$NETWORK" ] && do_network
-[ -n "$BROADCAST" ] && do_broadcast
-
-# [ -z "${cardtype//OSD_*/}" ] can be used to check for real OSA
-
-# Check for missing parameters, prompt for them if necessary
-while : ; do
-
-    # do not show list of possible network device configurations, if:
-    # - running unattended install with kickstart
-    # - relevant parameters have already been specified in parm file
-    #   (a possible optimization would be matching those parms to table entry)
-    # - dialog has not been restarted
-    [ -n "$reenter" \
-        -o -z "$RUNKS" -a \( -z "$NETTYPE" -o -z "$SUBCHANNELS" \) ] && \
-        dialog_network_table
-    if isVM; then
-        echo $"* NOTE: To enter default or empty values press enter twice. *"
-    fi
-    do_nettype
-
-    # precondition: driver (qeth/lcs/ctcm) loaded incl. dependencies
-    do_subchannels
-    if [ "$NETTYPE" = "qeth" ]; then
-        [ -z "$reenter" -a -n "$RUNKS" -a -z "$PORTNAME" ] || \
-            [ -n "${cardtype//OSD_*/}" ] || do_portname
-        # See also https://bugzilla.redhat.com/show_bug.cgi?id=439461
-        #
-        # If running in kickstart mode (unattended), we assume no
-        # interaction and the user won't get asked for PORTNO.
-        # Otherwise the user will be asked for PORTNO.
-        # If the user specified PORTNO in parm/conf file, PORTNO gets
-        # respected (or the user will be asked if it was wrong).
-        if [ -f /sys/devices/qeth/$SCH_R_DEVBUSID/portno ]; then
-            # driver support exists since RHEL5.2
-            [ -z "$reenter" -a -n "$RUNKS" -a -z "$PORTNO" ] || \
-                [ -n "${cardtype//OSD_*/}" ] || do_portno
-        fi
-        do_layer2
-        # set device online to know the device name
-        # and to know if it's OSD/HiperSockets/GuestLAN BUT do not
-        # try to ifconfig the device up since that requires
-        # setting the mac address before (if applicable).
-        set_device_online || workflow_item_menu noredo
-        # MAC address handling is not part of
-        # https://bugzilla.redhat.com/show_bug.cgi?id=233376
-        # Instead the additions come from
-        # https://bugzilla.redhat.com/show_bug.cgi?id=248049
-        # The new parms VSWITCH and MACADDR are described in
-        # the RHEL 5.1 release notes.
-        if isLayer2; then
-            if [ -z "$VSWITCH" -o "$VSWITCH" == 0 ]; then
-                do_macaddr
-            fi
-        fi
-    elif [ "$NETTYPE" = "ctc" ]; then
-        [ -z "$reenter" -a -n "$RUNKS" -a -z "$CTCPROT" ] || do_ctcprot
-        set_device_online || workflow_item_menu noredo
-    elif [ "$NETTYPE" = "lcs" ]; then
-        [ -n "$RUNKS" -a -z "$PORTNAME" ] && PORTNAME=0
-        do_lcs_portno
-        set_device_online || workflow_item_menu noredo
-    fi
-
-    # device needs to be up before configuring with ifconfig/ip in
-    # configure_ipv6_address/configure_ipv4_address/configure_ipv4_address
-    set_device_up || workflow_item_menu noredo
-
-    [ "$HOSTNAME" = "(none)" ] && unset HOSTNAME
-    do_hostname
-
-    # Note: The workflow_item_menu does a rollback_config on restart
-    # dialog, i.e. hardware config has been reset and it is impossible to
-    # only restart halfway at IPADDR.
-    do_ipaddr
-    if [ "$ipv6" ]; then
-        # this branch is all IPv6 and at the same time also NETTYPE==qeth
-        do_netmask_v6
-        handle_mtu
-        configure_ipv6_address || workflow_item_menu noredo
-        do_gateway_v6
-    else
-        # Consider IPv4 as default, even for unknown IP versions
-        # due to invalid input for IPADDR ignored by the user previously
-        # (neither ipv6 nor ipv4 is set).
-        # Otherwise we would skip things like NETMASK or GATEWAY
-        # and jump forward to DNS which is probably not what we want.
-        if [ "$NETTYPE" = "qeth" ] || [ "$NETTYPE" = "lcs" ]; then
-            do_netmask
-            handle_mtu
-            configure_ipv4_address || workflow_item_menu noredo
-            do_gateway
-        else  # ctc0
-            if [ -z "$NETMASK" ]; then
-                # If the user did not supply netmask, we add the right one.
-                # Netmask MUST be present,
-                # or pumpSetupInterface() blows routes.
-                NETMASK="255.255.255.255"
-            fi
-            # don't ask for MTU, but use it if set in the parm file
-            # don't overwrite MMTU if it has been set for CTC
-            [ "$NETTYPE" = "ctc" -a -z "$MTU" -a -z "$MMTU" ] && \
-                MMTU="mtu 1500"
-            do_ptp_gateway
-            configure_ipv4_ptp || workflow_item_menu noredo
-        fi
-    fi
-
-    do_dns
-    [ -n "$DNS" ] && do_searchdns
-
-    do_dasd
-
-    echo $"Initial configuration completed."
-    final_check && break
-    rollback_config
-    reenter="yes"
-
-done # outer dialog loop
-
-if [ -z "$testing" ]; then
-
-    # convert to space-separated lists
-    if [ -n "$SEARCHDNS" ]; then
-        SEARCHDNS=$(echo $SEARCHDNS |sed -e 's/:/ /g')
-        for i in "$SEARCHDNS"; do echo "search $i"; done >> /etc/resolv.conf
-    fi
-    if [ -n "$DNS" ]; then
-        if [ "$ipv6" ]; then
-            RESOLVDNS=$(echo $DNS |sed -e 's/,/ /g')
-        else
-            RESOLVDNS=$(echo $DNS |sed -e 's/:/ /g')
-        fi
-        for i in $RESOLVDNS; do echo "nameserver $i"; done >> /etc/resolv.conf
-    fi
-
-    # make sure we have an /etc/hosts file (originally required for telnetd,
-    # which is no longer included)
-    if [ ! -z "$HOSTNAME" -a ! -z "$IPADDR" ]; then
-        echo -e "$IPADDR\t$HOSTNAME $(echo $HOSTNAME | cut -d '.' -f 1)" >> /etc/hosts
-    fi
-
-fi # testing
-
-# syntax check to give user early feedback on parameters provided in parm file
-# (he probably won't notice the logs written by anaconda later on)
-syntax_check_fcp
-# currently we ignore failed syntax checks since FCP parms are non-interactive
-for i in ${!FCP_*}; do
-    echo "${!i}" >> /etc/zfcp.conf
-done
-# cio_ignore handling for FCP should happen when the content of /etc/zfcp.conf
-# will actually be processed which is in anaconda's zfcp.py ZFCP::readConfig()
-
-# TODO/FIXME: also need to pass IPv6 decision to loader/anaconda
-#    [ "$ipv6" ] && echo "IPV6=yes"
-
-# transfer options into install environment
-# loader now uses ifcfg instead of install.cfg to receive our network config
-
-# additionally, loader's readNetInfo needs to know our DEVICE name
-echo $DEVICE > /tmp/s390net
-
-if [ "$ipv6" ]; then
-    DNS1=$(echo $DNS | cut -d ',' -f 1)
-    DNS2=$(echo $DNS | cut -d ',' -f 2)
-else
-    DNS1=$(echo $DNS | cut -d ':' -f 1)
-    DNS2=$(echo $DNS | cut -d ':' -f 2)
-fi
-
-NETSCRIPTS="/etc/sysconfig/network-scripts"
-IFCFGFILE="$NETSCRIPTS/ifcfg-$DEVICE"
-if [ ! -d "$NETSCRIPTS" ]; then
-    mkdir -p $NETSCRIPTS
-fi
-
-# to please NetworkManager on startup in loader before loader reconfigures net
-cat > /etc/sysconfig/network << EOF
-HOSTNAME=$HOSTNAME
-EOF
-if [ "$ipv6" ]; then
-    echo "NETWORKING_IPV6=yes" >> /etc/sysconfig/network
-else
-    echo "NETWORKING=yes" >> /etc/sysconfig/network
-fi
-
-cat > $IFCFGFILE << EOF
-DEVICE=$DEVICE
-ONBOOT=yes
-BOOTPROTO=static
-MTU=$MTU
-SUBCHANNELS=$SUBCHANNELS
-EOF
-if [ "$ipv6" ]; then
-    cat >> $IFCFGFILE << EOF
-IPV6INIT=yes
-IPV6_AUTOCONF=no
-IPV6ADDR=$IPADDR/$NETMASK
-IPV6_DEFAULTGW=$GATEWAY
-EOF
-else
-    cat >> $IFCFGFILE << EOF
-IPADDR=$IPADDR
-NETMASK=$NETMASK
-BROADCAST=$BROADCAST
-GATEWAY=$GATEWAY
-EOF
-fi
-# real DNS config for NetworkManager to generate /etc/resolv.conf
-[ "$DNS1" != "" ] && echo "DNS1=$DNS1" >> $IFCFGFILE
-[ "$DNS2" != "" ] && echo "DNS2=$DNS2" >> $IFCFGFILE
-# just to please loader's readNetInfo && writeEnabledNetInfo
-# which eats DNS1,DNS2,... and generates it themselves based on DNS
-if [ "$ipv6" ]; then
-    [ "$DNS" != "" ] && echo "DNS=\"$DNS\"" >> $IFCFGFILE
-else
-    [ "$DNS" != "" ] && echo "DNS=\"$(echo $DNS|sed -e 's/:/,/g')\"" >> $IFCFGFILE
-fi
-# colons in SEARCHDNS already replaced with spaces above for /etc/resolv.conf
-[ "$SEARCHDNS" != "" ] && echo "DOMAIN=\"$SEARCHDNS\"" >> $IFCFGFILE
-[ "$NETTYPE" != "" ] && echo "NETTYPE=$NETTYPE" >> $IFCFGFILE
-[ "$PEERID" != "" ] && echo "PEERID=$PEERID" >> $IFCFGFILE
-[ "$PORTNAME" != "" ] && echo "PORTNAME=$PORTNAME" >> $IFCFGFILE
-[ "$CTCPROT" != "" ] && echo "CTCPROT=$CTCPROT" >> $IFCFGFILE
-[ "$MACADDR" != "" ] && echo "MACADDR=$MACADDR" >> $IFCFGFILE
-optstr=""
-for option in LAYER2 PORTNO; do
-    [ -z "${!option}" ] && continue
-    [ -n "$optstr" ] && optstr=${optstr}" "
-    optstr=${optstr}$(echo ${option} | tr [[:upper:]] [[:lower:]])"="${!option}
-done
-# write single quotes since network.py removes double quotes but we need quotes
-echo "OPTIONS='$optstr'" >> $IFCFGFILE
-unset option
-unset optstr
-
-if [ -z "$testing" ]; then
-
-    # so that the vars get propagated into the sshd shells
-    mkdir /.ssh
-    cat >> /.ssh/environment <<EOF
-LD_LIBRARY_PATH=$LD_LIBRARY_PATH
-PATH=$PATH
-HOME=$HOME
-PYTHONPATH=$PYTHONPATH
-EOF
-
-    cat >> /etc/profile <<EOF
-LD_LIBRARY_PATH=$LD_LIBRARY_PATH
-PATH=$PATH
-HOME=$HOME
-PYTHONPATH=$PYTHONPATH
-export LD_LIBRARY_PATH PATH HOME PYTHONPATH
-EOF
-
-    if [ -n "$DISPLAY" ]; then
-        echo "export DISPLAY=$DISPLAY" >> /etc/profile
-    fi
-
-    # I'm tired of typing this out...
-    echo "loader" >> /.bash_history
-
-    echo -n $$ > /var/run/init.pid
-
-    # shutdown (halt) on SIGUSR1
-    trap doshutdown SIGUSR1
-    # reboot on SIGUSR2
-    trap doreboot SIGUSR2
-
-    startinetd
-
-    if [ -n "$RUNKS" ]; then
-        /sbin/loader
-    fi
-
-    doshutdown
-
-fi # testing
-
-# ;;; Local Variables: ***
-# ;;; mode: sh ***
-# ;;; end: ***
-- 
1.7.7.6

_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/anaconda-devel-list


[Index of Archives]     [Kickstart]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]
  Powered by Linux