diff -pruN 2.1.5-1/Changelog 2.1.7-2/Changelog
--- 2.1.5-1/Changelog	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/Changelog	2022-05-06 17:37:21.000000000 +0000
@@ -1,3 +1,118 @@
+-> open-iscsi-2.1.6 - open-iscsi-2.1.7
+
+Lee Duncan (48):
+      Remove HEREIS usage from iscsi-gen-initiatorname
+      Fix iscsi-init.service start time
+      test: Rename README to README.orig
+      test: Add new README, update old README and TODO
+      test: Fix bug/spelling error, cleanup messages
+      test: Fix mispelling of MaxBurst
+      test: fix error with verifying mkfs command
+      test: remove the ".setup" file, used for development
+      test: Cleanup README and TODO
+      test: Track time spent calling subprocesses
+      test: Add suggested test setup info to README
+      test: Add missing verbose print, and track more time values
+      test: Track time spent in sleep() more easily/accurately
+      test: fix message mispelling of "umount"
+      test: add item to TODO list
+      test: further improve test suite time display
+      Remove SUSE init.d startup files
+      Cleanup iscsiadm man page
+      Allow name/value args for firmware logins.
+      Update iscsiadm.8 for firmware name/value pairs
+      General Makefile/README cleanup
+      Clean up Makefile build system.
+      Clean up the usage info for iscsid
+      Remove no-longer-used Makefile target for subdir
+      Make DB and ISCSIHOME directories configurable.
+      Build: Cleanup fwparam_ibft and sysdeps subdirs.
+      Add a README for fwparam_ibft subdirectory.
+      Build: cleanup usr Makefile: remove obj files on "clean"
+      Remove unused fwparam_ibft.[ch] files in fwparam_ibft.
+      Build: upate "depend" target to include sysdeps
+      Fix gcc issues with unused params in fwparam
+      Use DESTDIR correctly for HOMEDIR and DBROOT
+      Be smarter about creating iscsiuio.8 man page
+      Build: remove unused Makefile HOMEDIR creation
+      Build: use upper- vs lower-case variable names correctly
+      Build: libopeniscsiusr install should install docs
+      Remove debug messages from libopeniscsiusr/Makefile
+      Build: cleanup libopeniscsiusr/Makefile
+      Build: add libsystemd CFLAGS for building objects
+      Build: remove redundant definition in utils Makefile
+      Build: add RULESDIR to top-level Makefile
+      Create an systemd iBFT rule generator
+      Build: install systemd generator file with svc files
+      Use kernel initiatorname when setting local iname
+      utils: remove errant spaces in script
+      Check for root in iscsi-gen-initiatorname
+      Make fwparam_ibft build more reliable.
+      Fix ibft-rule-generator shell error
+
+Sam James (5):
+      iscsiuio: don't clobber LDFLAGS in configure.ac
+      iscsiuio: respect LDFLAGS fully
+      Makefiles: respect $(CC) fully (don't hardcode GCC); use $(RM)
+      Makefiles: don't hardcode sed, pkg-config
+      libopeniscsiusr: fix version in installed pkgconfig (.pc) file
+
+Wenchao Hao (5):
+      Add conn_xxx() macros to print connection info in more details
+      Make session and connect log readable and helpful to locate problem
+      mgmt: print connection info when write qtask response failed
+      initiator: return ENOMEM if failed to get ev_context in iscsi_send_logout()
+      initiator:print failure reason of iscsi_send_logout() if failed
+
+ryancaicse (1):
+      Fix a missing-unlocking bug
+
+scaleoutSean (1):
+      Fix minor error string typos
+
+
+-> open-iscsi-2.1.5 - open-iscsi-2.1.6
+
+Chris Leech (1):
+      libopeniscsiusr: extend sysfs ignore_error to include EINVAL
+
+Lee Duncan (15):
+      Fix compiler error introduced with recent IPv6 commit.
+      Remove dependences from iscsi-init.service
+      Use "sbindir" for path in systemd service files
+      Updated README a bit
+      Finish ability to have binary location configurable.
+      Fix iscsi-init so that it runs when root writable
+      remove redundant params in Makefile
+      Fixing last parts of sbindir configuration
+      Cosmetic cleanup on recent addition
+      Update the iscsi-gen-initiatorname script: harden and generalize
+      change iscsi-gen-initiatorname option -b => -p
+      Add man page for the iscsi-gen-initiatorname script.
+      Install new man page for iscsi-gen-initiatorname
+      Fix issues discovered by gcc12
+      Fix more issues discovered by gcc12
+
+Mike Christie (4):
+      iscsi sysfs: check state before onlining devs
+      iscsistart: fix login timeout handling
+      iscsid: use infinite timeout if passed in
+      iscsid: add error code for req timeouts
+
+Samy Mahmoudi (1):
+      Improve 'iscsid.conf'
+
+Wenchao Hao (8):
+      iscsiadm: Call log_init() first to fix a segmentation fault
+      iscsi_err: Add iscsid request timed out error messages
+      Fix wrong install_systemd destination path
+      actor: add name to struct actor and init it with function name
+      actor: print thread name in log
+      actor: enhanced: print error log when init a initilized thread
+      initiator_common: make set operational parameter log easy to read
+      iscsid: Check session id before start sync a thread
+
+
 open-iscsi-2.1.4 - open-iscsi-2.1.5
 
 Chris Leech (1):
diff -pruN 2.1.5-1/debian/buildconfig.build-deb 2.1.7-2/debian/buildconfig.build-deb
--- 2.1.5-1/debian/buildconfig.build-deb	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/buildconfig.build-deb	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1 @@
+# empty
diff -pruN 2.1.5-1/debian/buildconfig.build-udeb 2.1.7-2/debian/buildconfig.build-udeb
--- 2.1.5-1/debian/buildconfig.build-udeb	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/buildconfig.build-udeb	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,2 @@
+# disabled libsystemd in d-i
+NO_SYSTEMD=1
diff -pruN 2.1.5-1/debian/buildconfig.common 2.1.7-2/debian/buildconfig.common
--- 2.1.5-1/debian/buildconfig.common	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/buildconfig.common	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1 @@
+# empty
diff -pruN 2.1.5-1/debian/changelog 2.1.7-2/debian/changelog
--- 2.1.5-1/debian/changelog	2021-10-21 16:06:50.000000000 +0000
+++ 2.1.7-2/debian/changelog	2022-07-30 14:23:25.000000000 +0000
@@ -1,3 +1,28 @@
+open-iscsi (2.1.7-2) unstable; urgency=medium
+
+  * [09dfaec] Enable hardening build flags
+  * [c0ce256] d/rules: remove unused DEB_HOST_MULTIARCH
+  * [70574d1] Run separate build for udeb to avoid libsystemd dependency
+    (Closes: #1003366)
+
+ -- Chris Hofstaedtler <zeha@debian.org>  Sat, 30 Jul 2022 14:23:25 +0000
+
+open-iscsi (2.1.7-1) unstable; urgency=medium
+
+  * [3050096] New upstream version 2.1.7 (Closes: #982307, #1016246)
+  * [46fd279] Refresh patches, drop upstream applied ftbfs patch
+  * [cac01da] Help upstream Makefile find sed in /bin
+  * [0202184] Add patches from upstream master to fix build
+  * [f61e6a0] Use dh_auto_install, better suits new upstream build system
+  * [2080bfb] Fix multiarch install location
+  * [4f57eb7] Move udeb files into correct places (like in 2.0.874-7.1)
+  * [75b86ce] Cleanup duplicate override_dh_installsystemd section
+    (Closes: #1004014)
+  * [24f9981] d/copyright: update
+  * [41970e3] Rely on dh_installinitramfs to install triggers
+
+ -- Chris Hofstaedtler <zeha@debian.org>  Fri, 29 Jul 2022 19:59:11 +0000
+
 open-iscsi (2.1.5-1) unstable; urgency=medium
 
   * [150470c] New upstream version 2.1.5
diff -pruN 2.1.5-1/debian/copyright 2.1.7-2/debian/copyright
--- 2.1.5-1/debian/copyright	2021-10-21 15:41:14.000000000 +0000
+++ 2.1.7-2/debian/copyright	2022-07-30 14:23:25.000000000 +0000
@@ -31,7 +31,6 @@ Files: Changelog
        include/list.h
        libopeniscsiusr/*
        sysfs-documentation
-       test/.setup
        test/README
        test/TODO
        test/harness/*
@@ -56,9 +55,9 @@ Files: Changelog
        usr/statics.c
        usr/types.h
        usr/version.h
-       utils/50-iscsi-firmware-login.rules
+       utils/50-iscsi-firmware-login.rules.template
        utils/Makefile
-       utils/iscsi_fw_login
+       utils/iscsi_fw_login.sh.template
        utils/sysdeps/*
 Copyright: 2000, 1 Tim Waugh <twaugh@redhat.com>
            2002-2003, Ardis Technolgies <roman@ardistech.com>
@@ -187,13 +186,13 @@ License: GPL
 Comment: No explicit GPL version specified, using license(s) from:
  GPL-2
 
-Files: utils/fwparam_ibft/prom_parse.tab.c
-       utils/fwparam_ibft/prom_parse.tab.h
+Files: usr/fwparam_ibft/prom_parse.tab.c
+       usr/fwparam_ibft/prom_parse.tab.h
 Copyright: 1984-2015, Free Software Foundation, Inc
 License: GPL-3+ with Bison exception
 
-Files: utils/iscsi-gen-initiatorname
-       utils/iscsi_offload
+Files: utils/iscsi-gen-initiatorname.sh.template
+       utils/iscsi_offload.sh
 Copyright: 2011, Hannes Reinecke, SUSE Labs
 License: GPL
 Comment: No explicit GPL version specified, using license(s) from:
diff -pruN 2.1.5-1/debian/extra/initramfs/hooks/iscsi 2.1.7-2/debian/extra/initramfs/hooks/iscsi
--- 2.1.5-1/debian/extra/initramfs/hooks/iscsi	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/extra/initramfs/hooks/iscsi	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+PREREQ="udev"
+
+prereqs()
+{
+	echo "$PREREQ"
+}
+
+case $1 in
+# get pre-requisites
+prereqs)
+	prereqs
+	exit 0
+	;;
+esac
+
+if [ -r /etc/initramfs-tools/conf.d/open-iscsi ] ; then
+	. /etc/initramfs-tools/conf.d/open-iscsi
+fi
+
+if [ x"$NO_ISCSI_IN_INITRAMFS" = x"yes" ] ; then
+	exit 0
+fi
+
+# Hooks for loading iscsi bits into the initramfs
+. /usr/share/initramfs-tools/hook-functions
+
+copy_exec /sbin/iscsistart /sbin
+cp /etc/iscsi/initiatorname.iscsi $DESTDIR/etc
+if [ -r /etc/iscsi/iscsi.initramfs ] ; then
+	cp /etc/iscsi/iscsi.initramfs $DESTDIR/etc
+fi
+
+for x in crc32c libcrc32c ib_iser iscsi_tcp libiscsi scsi_transport_iscsi iscsi_ibft; do
+	manual_add_modules ${x}
+done
+for x in cxgb3i cxgb4i; do
+	manual_add_modules ${x}
+done
+
diff -pruN 2.1.5-1/debian/extra/initramfs/hooks/iscsiuio 2.1.7-2/debian/extra/initramfs/hooks/iscsiuio
--- 2.1.5-1/debian/extra/initramfs/hooks/iscsiuio	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/extra/initramfs/hooks/iscsiuio	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+PREREQ="udev iscsi"
+
+prereqs()
+{
+	echo "$PREREQ"
+}
+
+case $1 in
+# get pre-requisites
+prereqs)
+	prereqs
+	exit 0
+	;;
+esac
+
+if [ -r /etc/initramfs-tools/conf.d/open-iscsi ] ; then
+	. /etc/initramfs-tools/conf.d/open-iscsi
+fi
+
+if [ x"$NO_ISCSI_IN_INITRAMFS" = x"yes" ] ; then
+	exit 0
+fi
+
+# Hooks for loading iscsi bits into the initramfs
+. /usr/share/initramfs-tools/hook-functions
+
+copy_exec /sbin/iscsiuio
+# iscsiuio needs libgcc_s library, so add it and its dependencies.
+LIBC_DIR=$(ldd /sbin/iscsiuio | sed -nr 's#.* => (/lib.*)/libc\.so\.[0-9.-]+ \(0x[[:xdigit:]]+\)$#\1#p')
+find -L "$LIBC_DIR" -maxdepth 1 -name 'libgcc_s.*' -type f | while read so; do
+	copy_exec "$so"
+done
+manual_add_modules bnx2i
diff -pruN 2.1.5-1/debian/extra/initramfs/local-bottom/iscsi 2.1.7-2/debian/extra/initramfs/local-bottom/iscsi
--- 2.1.5-1/debian/extra/initramfs/local-bottom/iscsi	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/extra/initramfs/local-bottom/iscsi	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,30 @@
+#!/bin/sh
+# If iscsiuio is present in the initramfs, and it was started by us,
+# stop it again so the system iscsiuio can take over later.
+if [ -x /sbin/iscsiuio ] && [ -e /run/initramfs/iscsiuio.pid ] ; then
+	start-stop-daemon --stop --quiet --retry=TERM/10/KILL/5 \
+		--pidfile /run/initramfs/iscsiuio.pid \
+		--name iscsiuio --exec /sbin/iscsiuio || :
+fi
+
+# Remove the interface file if no disks are present
+if [ -f /run/initramfs/open-iscsi.interface ] ; then
+	found=0
+	for disk in /dev/disk/by-path/*-iscsi-*; do
+		if [ ! -e "$disk" ] ; then
+			# If we have no matches, we stil go through the for loop once with
+			# the pattern as a string
+			continue
+		fi
+		if ! readlink -f "$disk" > /dev/null ; then
+			continue
+		fi
+		found=1
+		break;
+	done
+	if [ $found = 0 ] ; then
+		rm /run/initramfs/open-iscsi.interface
+	fi
+fi
+
+exit 0
diff -pruN 2.1.5-1/debian/extra/initramfs/local-top/iscsi 2.1.7-2/debian/extra/initramfs/local-top/iscsi
--- 2.1.5-1/debian/extra/initramfs/local-top/iscsi	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/extra/initramfs/local-top/iscsi	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,384 @@
+#!/bin/sh
+
+PREREQ=""
+
+prereqs()
+{
+	echo "$PREREQ"
+}
+
+case $1 in
+# get pre-requisites
+prereqs)
+	prereqs
+	exit 0
+	;;
+esac
+
+parse_root_param ()
+{
+	target="$1"
+	auth="$2"
+	OLDIFS="$IFS"
+	IFS=":"
+	set -- $target
+	IFS="$OLDIFS"
+
+	tmp_ISCSI_TARGET_IP="$1"
+	if [ -n "$2" ] ; then
+		if [ x"$2" != x"6" ] ; then
+			echo "Warning: unsupported protocol specified for iSCSI root parameter, assuming 6 (TCP)" >&2
+		fi
+	fi
+	tmp_ISCSI_TARGET_PORT="$3"
+	tmp_ISCSI_ROOT_LUN="$4"
+	tmp_ISCSI_TARGET_NAME="$5"
+	shift 5
+	while [ -n "$1" ] ; do
+		tmp_ISCSI_TARGET_NAME="${tmp_ISCSI_TARGET_NAME}:$1"
+		shift
+	done
+
+	if [ -z "$tmp_ISCSI_TARGET_IP" ] || [ -z "$tmp_ISCSI_TARGET_NAME" ] ; then
+		echo "Warning: empty iSCSI IP / target name currently not supported for root=iscsi:, ignoring parameter" >&2
+		return
+	fi
+
+	OLDIFS="$IFS"
+	IFS=":"
+	set -- $auth
+	IFS="$OLDIFS"
+
+	tmp_ISCSI_USERNAME=""
+	tmp_ISCSI_PASSWORD=""
+	tmp_ISCSI_IN_USERNAME=""
+	tmp_ISCSI_IN_PASSWORD=""
+
+	if [ $# -gt 4 ] ; then
+		echo "Warning: invalid authentication for root=iscsi:, ignoring" >&2
+		return
+	fi
+
+	if [ $# -gt 0 ] ; then
+		tmp_ISCSI_USERNAME="$1"
+		tmp_ISCSI_PASSWORD="$2"
+		if [ $# -gt 2 ] ; then
+			tmp_ISCSI_IN_USERNAME="$3"
+			tmp_ISCSI_IN_PASSWORD="$4"
+		fi
+	fi
+
+	ISCSI_TARGET_IP="$tmp_ISCSI_TARGET_IP"
+	ISCSI_TARGET_PORT="$tmp_ISCSI_TARGET_PORT"
+	ISCSI_TARGET_NAME="$tmp_ISCSI_TARGET_NAME"
+	ISCSI_ROOT_LUN="$tmp_ISCSI_ROOT_LUN"
+	if [ -n "$tmp_ISCSI_USERNAME" ] ; then
+		ISCSI_USERNAME="$tmp_ISCSI_USERNAME"
+		ISCSI_PASSWORD="$tmp_ISCSI_PASSWORD"
+	fi
+	if [ -n "$tmp_ISCSI_IN_USERNAME" ] ; then
+		ISCSI_IN_USERNAME="$tmp_ISCSI_IN_USERNAME"
+		ISCSI_IN_PASSWORD="$tmp_ISCSI_IN_PASSWORD"
+	fi
+	ISCSI_HAD_ROOT=yes
+}
+
+do_iscsi_login ()
+{
+	# Bring in the main config
+	. /conf/initramfs.conf
+	for conf in conf/conf.d/*; do
+		[ -f ${conf} ] && . ${conf}
+	done
+	. /scripts/functions
+
+	udevadm settle
+	IBFT_DHCP_DEVICE=""
+
+	if [ -n "$ISCSI_AUTO" ] ; then
+		# try to auto-configure network interface based
+		# on firmware values
+		modprobe iscsi_ibft
+		iscsistart -N
+
+		# write out /run/net-$IFACE.conf based on what
+		# was in the firmware
+		iscsistart -f | while read k eq v; do
+			case "${k} ${eq} ${v}" in
+			("# BEGIN RECORD"*)
+				DEVICE=""
+				PROTO="none"
+				IPV4ADDR=""
+				IPV4NETMASK=""
+				IPV4GATEWAY=""
+				IPV4DNS0=""
+				IPV4DNS1=""
+				UPTIME="0"
+				DHCPLEASETIME="0"
+				DOMAINSEARCH=""
+				continue
+				;;
+			("# END RECORD"*)
+				if [ -n "$DEVICE" ] ; then
+				{
+					echo "DEVICE='${DEVICE}'"
+					echo "PROTO='${PROTO}'"
+					echo "IPV4ADDR='${IPV4ADDR}'"
+					echo "IPV4BROADCAST=''"
+					echo "IPV4NETMASK='${IPV4NETMASK}'"
+					echo "IPV4GATEWAY='${IPV4GATEWAY}'"
+					echo "IPV4DNS0='${IPV4DNS0}'"
+					echo "IPV4DNS1='${IPV4DNS1}'"
+					echo "HOSTNAME=''"
+					echo "DNSDOMAIN=''"
+					echo "NISDOMAIN=''"
+					echo "ROOTSERVER=''"
+					echo "ROOTPATH=''"
+					echo "UPTIME='${UPTIME}'"
+					echo "DHCPLEASETIME='${DHCPLEASETIME}'"
+					echo "DOMAINSEARCH=''"
+				} > "/run/net-${DEVICE}.conf.ibft"
+				if [ "$PROTO" != "dhcp" -a "$DHCPLEASETIME" = "0" ]; then
+					# this is static ibft configuration.
+					mv "/run/net-${DEVICE}.conf.ibft" "/run/net-${DEVICE}.conf"
+				else
+					IBFT_DHCP_DEVICE="$DEVICE"
+				fi
+				echo "${DEVICE}" > /run/initramfs/open-iscsi.interface
+				# iscsistart -N doesn't set the default gateway. Therefore,
+				# we need to add it ourselves. However, the ip command is
+				# only available if we use busybox in the initramfs (it's
+				# in open-iscsi's Recommends), so check for that.
+				if [ -n "${IPV4GATEWAY}" ] && which ip >/dev/null 2>&1 ; then
+					ip route add default via "${IPV4GATEWAY}"
+				fi
+				fi
+				continue
+				;;
+			esac
+			if [ "${eq}" != "=" ] ; then
+				continue
+			fi
+			case "${k}" in
+				iface.ipaddress)     IPV4ADDR="${v}" ;;
+				iface.subnet_mask)   IPV4NETMASK="${v}" ;;
+				iface.gateway)       IPV4GATEWAY="${v}" ;;
+				iface.primary_dns)   IPV4DNS0="${v}" ;;
+				iface.secondary_dns) IPV4DNS1="${v}" ;;
+				iface.net_ifacename) DEVICE="${v}" ;;
+				iface.bootproto)
+					case "${v}" in
+						DHCP)	PROTO="dhcp"   ;;
+						STATIC)	PROTO="static" ;;
+						*)	PROTO="${v}"   ;;
+					esac
+					;;
+			esac
+		done
+	fi
+
+	# run configure_networking even if we have iscsi_auto, because there
+	# could be other network interfaces that need to be configured
+	# also, if we set up DHCP iBFT, we need ipconfig to run so it creates
+	# a proper /run/net-${DEVICE}.conf file that includes the DNS search
+	# domain, which we don't get in our iBFT data (see LP: #1806777)
+	configure_networking
+
+	if [ -n "$IBFT_DHCP_DEVICE" ]; then
+		if ! [ -e "/run/net-${DEVICE}.conf" ] ; then
+			echo "WARN: ipconfig dhcp failed, using iSCSI iBFT config - DNS search domain may be missing at runtime" >&2
+			# We have DHCP iBFT, but ipconfig DHCP failed;
+			# so we should fallback to just using the iBFT config,
+			# though that will not include the DNS search domain
+			mv "/run/net-${DEVICE}.conf.ibft" "/run/net-${DEVICE}.conf"
+			# need to re-run configure_networking to process conf file
+			configure_networking
+		fi
+	fi
+
+	# Save network device we configured via configure_networking, but only
+	# if we didn't already get one from autoconfiguration (then we always
+	# prefer that).
+	if ! [ -e /run/initramfs/open-iscsi.interface ] ; then
+		if [ -z "${DEVICE}" ] || ! [ -e "/run/net-${DEVICE}.conf" ] ; then
+			for i in /run/net-*.conf ; do
+				[ -e "${i}" ] && { . "${i}" ; break ; }
+			done
+		fi
+		if [ -n "${DEVICE}" ] ; then
+			echo "${DEVICE}" > /run/initramfs/open-iscsi.interface
+                else
+			for i in /run/net6-*.conf; do
+				[ -e "${i}" ] && { . "${i}" ; break ; }
+			done
+		fi
+		if [ -z "${DEVICE}" ] && [ -n "${DEVICE6}" ] ; then
+			echo "${DEVICE6}" > /run/initramfs/open-iscsi.interface
+		fi
+	fi
+
+	modprobe iscsi_tcp
+	modprobe crc32c
+
+	# If iscsiuio is present in the initramfs, start it, in case UIO
+	# offloading is required.
+	if [ -x /sbin/iscsiuio ] ; then
+		start-stop-daemon --start --quiet --pidfile /run/initramfs/iscsiuio.pid \
+				  --startas /sbin/iscsiuio --name iscsiuio \
+				  --exec /sbin/iscsiuio -- --pid=/run/initramfs/iscsiuio.pid || :
+	fi
+
+	if [ -z $ISCSI_AUTO ]; then
+		if [ -z $ISCSI_INITIATOR ]; then
+			. /etc/initiatorname.iscsi
+			ISCSI_INITIATOR=$InitiatorName
+		fi
+
+		if [ -z $ISCSI_TARGET_PORT ]; then
+			ISCSI_TARGET_PORT=3260
+		fi
+
+		if [ -z $ISCSI_TARGET_GROUP ]; then
+			ISCSI_TARGET_GROUP=1
+		fi
+
+		iscsistart -i $ISCSI_INITIATOR -t $ISCSI_TARGET_NAME	\
+			   -g $ISCSI_TARGET_GROUP -a $ISCSI_TARGET_IP	\
+			   -p $ISCSI_TARGET_PORT \
+			   ${ISCSI_USERNAME:+-u "$ISCSI_USERNAME"}	\
+			   ${ISCSI_PASSWORD:+-w "$ISCSI_PASSWORD"}	\
+			   ${ISCSI_IN_USERNAME:+-U "$ISCSI_IN_USERNAME"}\
+			   ${ISCSI_IN_PASSWORD:+-W "$ISCSI_IN_PASSWORD"}
+	else
+		modprobe iscsi_ibft
+		iscsistart -b
+	fi
+
+	if [ -z $ISCSI_TARGET_PORT ]; then
+		ISCSI_TARGET_PORT=3260
+	fi
+
+	if [ -z $ISCSI_TARGET_GROUP ]; then
+		ISCSI_TARGET_GROUP=1
+	fi
+
+	for i in $ISCSI_TARGET_IP; do
+	iscsistart -i $ISCSI_INITIATOR -t $ISCSI_TARGET_NAME	\
+		   -g $ISCSI_TARGET_GROUP -a $i \
+		   -p $ISCSI_TARGET_PORT \
+		   ${ISCSI_USERNAME:+-u "$ISCSI_USERNAME"}	\
+		   ${ISCSI_PASSWORD:+-w "$ISCSI_PASSWORD"}	\
+		   ${ISCSI_IN_USERNAME:+-U "$ISCSI_IN_USERNAME"}\
+		   ${ISCSI_IN_PASSWORD:+-W "$ISCSI_IN_PASSWORD"}
+	done
+}
+
+parse_iscsi_ops ()
+{
+	[ -r /etc/iscsi.initramfs ] && . /etc/iscsi.initramfs
+
+	for x in $(cat /proc/cmdline); do
+		case ${x} in
+		iscsi_auto)
+			ISCSI_AUTO=true
+			;;
+        	iscsi_initiator=*)
+                	ISCSI_INITIATOR="${x#iscsi_initiator=}"
+                	;;
+        	iscsi_target_name=*)
+                	ISCSI_TARGET_NAME="${x#iscsi_target_name=}"
+                	;;
+        	iscsi_target_ip=*)
+                	ISCSI_TARGET_IP="${x#iscsi_target_ip=}"
+                	;;
+        	iscsi_target_port=*)
+                	ISCSI_TARGET_PORT="${x#iscsi_target_port=}"
+                	;;
+		iscsi_target_group=*)
+			ISCSI_TARGET_GROUP="${x#iscsi_target_group=}"
+			;;
+		iscsi_username=*)
+			ISCSI_USERNAME="${x#iscsi_username=}"
+			;;
+		iscsi_password=*)
+			ISCSI_PASSWORD="${x#iscsi_password=}"
+			;;
+		iscsi_in_username=*)
+			ISCSI_IN_USERNAME="${x#iscsi_in_username=}"
+			;;
+		iscsi_in_password=*)
+			ISCSI_IN_PASSWORD="${x#iscsi_in_password=}"
+			;;
+		root=iscsi:*@*)
+			x="${x##root=iscsi:}"
+			parse_root_param "${x#*@}" "${x%%@*}"
+			;;
+		root=iscsi:*)
+			parse_root_param "${x##root=iscsi:}" ""
+			;;
+		esac
+	done
+}
+
+if [ ! -x /sbin/iscsistart ]; then
+	exit 0
+fi
+
+parse_iscsi_ops
+
+if ( [ -z $ISCSI_TARGET_NAME ] || [ -z $ISCSI_TARGET_IP ] ) && [ -z $ISCSI_AUTO ]; then
+	exit 0
+fi
+
+do_iscsi_login
+
+udevadm settle
+
+# The second check is to allow us to use multiple root= parameters. That way
+# one may specify root=iscsi:... root=UUID=... to mount partitions on an iSCSI
+# disk. (The latter value will overwrite the former for purposes of the main
+# initramfs scripts, but our loop that scans /proc/cmdline will still detect
+# the former and set proper parameters.
+if [ -n "$ISCSI_HAD_ROOT" ] && [ x"${ROOT##iscsi:}" != x"${ROOT}" ] ; then
+	if [ -z "$ISCSI_ROOT_LUN" ] ; then
+		ISCSI_ROOT_LUN=0
+	fi
+	found=0
+	# FIXME: RFC 4173 defines the LUN field to be more complicated and that
+	#        the same LUN may have multiple representations.
+	for disk in /dev/disk/by-path/*-iscsi-*-"${ISCSI_ROOT_LUN}" ; do
+		# Resolve device name, as the colons in the by-path name will
+		# cause mount to think that this is a NFS share, which we don't
+		# want.
+		if ! disk="$(readlink -f "$disk")" ; then
+			continue
+		fi
+
+		# Try to load file system type module (ignore errors), otherwise
+		# this won't succeed.
+		if fstype=$(get_fstype "$disk") ; then
+			modprobe "$fstype" || :
+			ROOTFSTYPE="$fstype"
+		fi
+
+		# Try to mount read-only and see if it's the right filesystem.
+		# If so, record the device name but umount again, because we
+		# want to be able to do an fsck on it.
+		if mount -r -t "${ROOTFSTYPE:-auto}" ${ROOTFLAGS} "${disk}" ${rootmnt} ; then
+			if [ -d ${rootmnt}/proc ] ; then
+				# This will be sourced by init after this hook has run.
+				echo "export ROOT=$disk" >> /conf/param.conf
+				if [ -n "$ROOTFSTYPE" ] && [ x"$ROOTFSTYPE" != x"auto" ] ; then
+					echo "export ROOTFSTYPE=$ROOTFSTYPE" >> /conf/param.conf
+				fi
+				found=1
+			fi
+			umount ${rootmnt}
+			if [ $found -eq 1 ] ; then
+				break
+			fi
+		fi
+	done
+fi
+
+exit 0
diff -pruN 2.1.5-1/debian/extra/initramfs.hook 2.1.7-2/debian/extra/initramfs.hook
--- 2.1.5-1/debian/extra/initramfs.hook	2021-10-21 15:41:14.000000000 +0000
+++ 2.1.7-2/debian/extra/initramfs.hook	1970-01-01 00:00:00.000000000 +0000
@@ -1,41 +0,0 @@
-#!/bin/sh
-
-PREREQ="udev"
-
-prereqs()
-{
-	echo "$PREREQ"
-}
-
-case $1 in
-# get pre-requisites
-prereqs)
-	prereqs
-	exit 0
-	;;
-esac
-
-if [ -r /etc/initramfs-tools/conf.d/open-iscsi ] ; then
-	. /etc/initramfs-tools/conf.d/open-iscsi
-fi
-
-if [ x"$NO_ISCSI_IN_INITRAMFS" = x"yes" ] ; then
-	exit 0
-fi
-
-# Hooks for loading iscsi bits into the initramfs
-. /usr/share/initramfs-tools/hook-functions
-
-copy_exec /sbin/iscsistart /sbin
-cp /etc/iscsi/initiatorname.iscsi $DESTDIR/etc
-if [ -r /etc/iscsi/iscsi.initramfs ] ; then
-	cp /etc/iscsi/iscsi.initramfs $DESTDIR/etc
-fi
-
-for x in crc32c libcrc32c ib_iser iscsi_tcp libiscsi scsi_transport_iscsi iscsi_ibft; do
-	manual_add_modules ${x}
-done
-for x in cxgb3i cxgb4i; do
-	manual_add_modules ${x}
-done
-
diff -pruN 2.1.5-1/debian/extra/initramfs.local-bottom 2.1.7-2/debian/extra/initramfs.local-bottom
--- 2.1.5-1/debian/extra/initramfs.local-bottom	2021-10-21 15:41:14.000000000 +0000
+++ 2.1.7-2/debian/extra/initramfs.local-bottom	1970-01-01 00:00:00.000000000 +0000
@@ -1,30 +0,0 @@
-#!/bin/sh
-# If iscsiuio is present in the initramfs, and it was started by us,
-# stop it again so the system iscsiuio can take over later.
-if [ -x /sbin/iscsiuio ] && [ -e /run/initramfs/iscsiuio.pid ] ; then
-	start-stop-daemon --stop --quiet --retry=TERM/10/KILL/5 \
-		--pidfile /run/initramfs/iscsiuio.pid \
-		--name iscsiuio --exec /sbin/iscsiuio || :
-fi
-
-# Remove the interface file if no disks are present
-if [ -f /run/initramfs/open-iscsi.interface ] ; then
-	found=0
-	for disk in /dev/disk/by-path/*-iscsi-*; do
-		if [ ! -e "$disk" ] ; then
-			# If we have no matches, we stil go through the for loop once with
-			# the pattern as a string
-			continue
-		fi
-		if ! readlink -f "$disk" > /dev/null ; then
-			continue
-		fi
-		found=1
-		break;
-	done
-	if [ $found = 0 ] ; then
-		rm /run/initramfs/open-iscsi.interface
-	fi
-fi
-
-exit 0
diff -pruN 2.1.5-1/debian/extra/initramfs.local-top 2.1.7-2/debian/extra/initramfs.local-top
--- 2.1.5-1/debian/extra/initramfs.local-top	2021-10-21 15:41:14.000000000 +0000
+++ 2.1.7-2/debian/extra/initramfs.local-top	1970-01-01 00:00:00.000000000 +0000
@@ -1,384 +0,0 @@
-#!/bin/sh
-
-PREREQ=""
-
-prereqs()
-{
-	echo "$PREREQ"
-}
-
-case $1 in
-# get pre-requisites
-prereqs)
-	prereqs
-	exit 0
-	;;
-esac
-
-parse_root_param ()
-{
-	target="$1"
-	auth="$2"
-	OLDIFS="$IFS"
-	IFS=":"
-	set -- $target
-	IFS="$OLDIFS"
-
-	tmp_ISCSI_TARGET_IP="$1"
-	if [ -n "$2" ] ; then
-		if [ x"$2" != x"6" ] ; then
-			echo "Warning: unsupported protocol specified for iSCSI root parameter, assuming 6 (TCP)" >&2
-		fi
-	fi
-	tmp_ISCSI_TARGET_PORT="$3"
-	tmp_ISCSI_ROOT_LUN="$4"
-	tmp_ISCSI_TARGET_NAME="$5"
-	shift 5
-	while [ -n "$1" ] ; do
-		tmp_ISCSI_TARGET_NAME="${tmp_ISCSI_TARGET_NAME}:$1"
-		shift
-	done
-
-	if [ -z "$tmp_ISCSI_TARGET_IP" ] || [ -z "$tmp_ISCSI_TARGET_NAME" ] ; then
-		echo "Warning: empty iSCSI IP / target name currently not supported for root=iscsi:, ignoring parameter" >&2
-		return
-	fi
-
-	OLDIFS="$IFS"
-	IFS=":"
-	set -- $auth
-	IFS="$OLDIFS"
-
-	tmp_ISCSI_USERNAME=""
-	tmp_ISCSI_PASSWORD=""
-	tmp_ISCSI_IN_USERNAME=""
-	tmp_ISCSI_IN_PASSWORD=""
-
-	if [ $# -gt 4 ] ; then
-		echo "Warning: invalid authentication for root=iscsi:, ignoring" >&2
-		return
-	fi
-
-	if [ $# -gt 0 ] ; then
-		tmp_ISCSI_USERNAME="$1"
-		tmp_ISCSI_PASSWORD="$2"
-		if [ $# -gt 2 ] ; then
-			tmp_ISCSI_IN_USERNAME="$3"
-			tmp_ISCSI_IN_PASSWORD="$4"
-		fi
-	fi
-
-	ISCSI_TARGET_IP="$tmp_ISCSI_TARGET_IP"
-	ISCSI_TARGET_PORT="$tmp_ISCSI_TARGET_PORT"
-	ISCSI_TARGET_NAME="$tmp_ISCSI_TARGET_NAME"
-	ISCSI_ROOT_LUN="$tmp_ISCSI_ROOT_LUN"
-	if [ -n "$tmp_ISCSI_USERNAME" ] ; then
-		ISCSI_USERNAME="$tmp_ISCSI_USERNAME"
-		ISCSI_PASSWORD="$tmp_ISCSI_PASSWORD"
-	fi
-	if [ -n "$tmp_ISCSI_IN_USERNAME" ] ; then
-		ISCSI_IN_USERNAME="$tmp_ISCSI_IN_USERNAME"
-		ISCSI_IN_PASSWORD="$tmp_ISCSI_IN_PASSWORD"
-	fi
-	ISCSI_HAD_ROOT=yes
-}
-
-do_iscsi_login ()
-{
-	# Bring in the main config
-	. /conf/initramfs.conf
-	for conf in conf/conf.d/*; do
-		[ -f ${conf} ] && . ${conf}
-	done
-	. /scripts/functions
-
-	udevadm settle
-	IBFT_DHCP_DEVICE=""
-
-	if [ -n "$ISCSI_AUTO" ] ; then
-		# try to auto-configure network interface based
-		# on firmware values
-		modprobe iscsi_ibft
-		iscsistart -N
-
-		# write out /run/net-$IFACE.conf based on what
-		# was in the firmware
-		iscsistart -f | while read k eq v; do
-			case "${k} ${eq} ${v}" in
-			("# BEGIN RECORD"*)
-				DEVICE=""
-				PROTO="none"
-				IPV4ADDR=""
-				IPV4NETMASK=""
-				IPV4GATEWAY=""
-				IPV4DNS0=""
-				IPV4DNS1=""
-				UPTIME="0"
-				DHCPLEASETIME="0"
-				DOMAINSEARCH=""
-				continue
-				;;
-			("# END RECORD"*)
-				if [ -n "$DEVICE" ] ; then
-				{
-					echo "DEVICE='${DEVICE}'"
-					echo "PROTO='${PROTO}'"
-					echo "IPV4ADDR='${IPV4ADDR}'"
-					echo "IPV4BROADCAST=''"
-					echo "IPV4NETMASK='${IPV4NETMASK}'"
-					echo "IPV4GATEWAY='${IPV4GATEWAY}'"
-					echo "IPV4DNS0='${IPV4DNS0}'"
-					echo "IPV4DNS1='${IPV4DNS1}'"
-					echo "HOSTNAME=''"
-					echo "DNSDOMAIN=''"
-					echo "NISDOMAIN=''"
-					echo "ROOTSERVER=''"
-					echo "ROOTPATH=''"
-					echo "UPTIME='${UPTIME}'"
-					echo "DHCPLEASETIME='${DHCPLEASETIME}'"
-					echo "DOMAINSEARCH=''"
-				} > "/run/net-${DEVICE}.conf.ibft"
-				if [ "$PROTO" != "dhcp" -a "$DHCPLEASETIME" = "0" ]; then
-					# this is static ibft configuration.
-					mv "/run/net-${DEVICE}.conf.ibft" "/run/net-${DEVICE}.conf"
-				else
-					IBFT_DHCP_DEVICE="$DEVICE"
-				fi
-				echo "${DEVICE}" > /run/initramfs/open-iscsi.interface
-				# iscsistart -N doesn't set the default gateway. Therefore,
-				# we need to add it ourselves. However, the ip command is
-				# only available if we use busybox in the initramfs (it's
-				# in open-iscsi's Recommends), so check for that.
-				if [ -n "${IPV4GATEWAY}" ] && which ip >/dev/null 2>&1 ; then
-					ip route add default via "${IPV4GATEWAY}"
-				fi
-				fi
-				continue
-				;;
-			esac
-			if [ "${eq}" != "=" ] ; then
-				continue
-			fi
-			case "${k}" in
-				iface.ipaddress)     IPV4ADDR="${v}" ;;
-				iface.subnet_mask)   IPV4NETMASK="${v}" ;;
-				iface.gateway)       IPV4GATEWAY="${v}" ;;
-				iface.primary_dns)   IPV4DNS0="${v}" ;;
-				iface.secondary_dns) IPV4DNS1="${v}" ;;
-				iface.net_ifacename) DEVICE="${v}" ;;
-				iface.bootproto)
-					case "${v}" in
-						DHCP)	PROTO="dhcp"   ;;
-						STATIC)	PROTO="static" ;;
-						*)	PROTO="${v}"   ;;
-					esac
-					;;
-			esac
-		done
-	fi
-
-	# run configure_networking even if we have iscsi_auto, because there
-	# could be other network interfaces that need to be configured
-	# also, if we set up DHCP iBFT, we need ipconfig to run so it creates
-	# a proper /run/net-${DEVICE}.conf file that includes the DNS search
-	# domain, which we don't get in our iBFT data (see LP: #1806777)
-	configure_networking
-
-	if [ -n "$IBFT_DHCP_DEVICE" ]; then
-		if ! [ -e "/run/net-${DEVICE}.conf" ] ; then
-			echo "WARN: ipconfig dhcp failed, using iSCSI iBFT config - DNS search domain may be missing at runtime" >&2
-			# We have DHCP iBFT, but ipconfig DHCP failed;
-			# so we should fallback to just using the iBFT config,
-			# though that will not include the DNS search domain
-			mv "/run/net-${DEVICE}.conf.ibft" "/run/net-${DEVICE}.conf"
-			# need to re-run configure_networking to process conf file
-			configure_networking
-		fi
-	fi
-
-	# Save network device we configured via configure_networking, but only
-	# if we didn't already get one from autoconfiguration (then we always
-	# prefer that).
-	if ! [ -e /run/initramfs/open-iscsi.interface ] ; then
-		if [ -z "${DEVICE}" ] || ! [ -e "/run/net-${DEVICE}.conf" ] ; then
-			for i in /run/net-*.conf ; do
-				[ -e "${i}" ] && { . "${i}" ; break ; }
-			done
-		fi
-		if [ -n "${DEVICE}" ] ; then
-			echo "${DEVICE}" > /run/initramfs/open-iscsi.interface
-                else
-			for i in /run/net6-*.conf; do
-				[ -e "${i}" ] && { . "${i}" ; break ; }
-			done
-		fi
-		if [ -z "${DEVICE}" ] && [ -n "${DEVICE6}" ] ; then
-			echo "${DEVICE6}" > /run/initramfs/open-iscsi.interface
-		fi
-	fi
-
-	modprobe iscsi_tcp
-	modprobe crc32c
-
-	# If iscsiuio is present in the initramfs, start it, in case UIO
-	# offloading is required.
-	if [ -x /sbin/iscsiuio ] ; then
-		start-stop-daemon --start --quiet --pidfile /run/initramfs/iscsiuio.pid \
-				  --startas /sbin/iscsiuio --name iscsiuio \
-				  --exec /sbin/iscsiuio -- --pid=/run/initramfs/iscsiuio.pid || :
-	fi
-
-	if [ -z $ISCSI_AUTO ]; then
-		if [ -z $ISCSI_INITIATOR ]; then
-			. /etc/initiatorname.iscsi
-			ISCSI_INITIATOR=$InitiatorName
-		fi
-
-		if [ -z $ISCSI_TARGET_PORT ]; then
-			ISCSI_TARGET_PORT=3260
-		fi
-
-		if [ -z $ISCSI_TARGET_GROUP ]; then
-			ISCSI_TARGET_GROUP=1
-		fi
-
-		iscsistart -i $ISCSI_INITIATOR -t $ISCSI_TARGET_NAME	\
-			   -g $ISCSI_TARGET_GROUP -a $ISCSI_TARGET_IP	\
-			   -p $ISCSI_TARGET_PORT \
-			   ${ISCSI_USERNAME:+-u "$ISCSI_USERNAME"}	\
-			   ${ISCSI_PASSWORD:+-w "$ISCSI_PASSWORD"}	\
-			   ${ISCSI_IN_USERNAME:+-U "$ISCSI_IN_USERNAME"}\
-			   ${ISCSI_IN_PASSWORD:+-W "$ISCSI_IN_PASSWORD"}
-	else
-		modprobe iscsi_ibft
-		iscsistart -b
-	fi
-
-	if [ -z $ISCSI_TARGET_PORT ]; then
-		ISCSI_TARGET_PORT=3260
-	fi
-
-	if [ -z $ISCSI_TARGET_GROUP ]; then
-		ISCSI_TARGET_GROUP=1
-	fi
-
-	for i in $ISCSI_TARGET_IP; do
-	iscsistart -i $ISCSI_INITIATOR -t $ISCSI_TARGET_NAME	\
-		   -g $ISCSI_TARGET_GROUP -a $i \
-		   -p $ISCSI_TARGET_PORT \
-		   ${ISCSI_USERNAME:+-u "$ISCSI_USERNAME"}	\
-		   ${ISCSI_PASSWORD:+-w "$ISCSI_PASSWORD"}	\
-		   ${ISCSI_IN_USERNAME:+-U "$ISCSI_IN_USERNAME"}\
-		   ${ISCSI_IN_PASSWORD:+-W "$ISCSI_IN_PASSWORD"}
-	done
-}
-
-parse_iscsi_ops ()
-{
-	[ -r /etc/iscsi.initramfs ] && . /etc/iscsi.initramfs
-
-	for x in $(cat /proc/cmdline); do
-		case ${x} in
-		iscsi_auto)
-			ISCSI_AUTO=true
-			;;
-        	iscsi_initiator=*)
-                	ISCSI_INITIATOR="${x#iscsi_initiator=}"
-                	;;
-        	iscsi_target_name=*)
-                	ISCSI_TARGET_NAME="${x#iscsi_target_name=}"
-                	;;
-        	iscsi_target_ip=*)
-                	ISCSI_TARGET_IP="${x#iscsi_target_ip=}"
-                	;;
-        	iscsi_target_port=*)
-                	ISCSI_TARGET_PORT="${x#iscsi_target_port=}"
-                	;;
-		iscsi_target_group=*)
-			ISCSI_TARGET_GROUP="${x#iscsi_target_group=}"
-			;;
-		iscsi_username=*)
-			ISCSI_USERNAME="${x#iscsi_username=}"
-			;;
-		iscsi_password=*)
-			ISCSI_PASSWORD="${x#iscsi_password=}"
-			;;
-		iscsi_in_username=*)
-			ISCSI_IN_USERNAME="${x#iscsi_in_username=}"
-			;;
-		iscsi_in_password=*)
-			ISCSI_IN_PASSWORD="${x#iscsi_in_password=}"
-			;;
-		root=iscsi:*@*)
-			x="${x##root=iscsi:}"
-			parse_root_param "${x#*@}" "${x%%@*}"
-			;;
-		root=iscsi:*)
-			parse_root_param "${x##root=iscsi:}" ""
-			;;
-		esac
-	done
-}
-
-if [ ! -x /sbin/iscsistart ]; then
-	exit 0
-fi
-
-parse_iscsi_ops
-
-if ( [ -z $ISCSI_TARGET_NAME ] || [ -z $ISCSI_TARGET_IP ] ) && [ -z $ISCSI_AUTO ]; then
-	exit 0
-fi
-
-do_iscsi_login
-
-udevadm settle
-
-# The second check is to allow us to use multiple root= parameters. That way
-# one may specify root=iscsi:... root=UUID=... to mount partitions on an iSCSI
-# disk. (The latter value will overwrite the former for purposes of the main
-# initramfs scripts, but our loop that scans /proc/cmdline will still detect
-# the former and set proper parameters.
-if [ -n "$ISCSI_HAD_ROOT" ] && [ x"${ROOT##iscsi:}" != x"${ROOT}" ] ; then
-	if [ -z "$ISCSI_ROOT_LUN" ] ; then
-		ISCSI_ROOT_LUN=0
-	fi
-	found=0
-	# FIXME: RFC 4173 defines the LUN field to be more complicated and that
-	#        the same LUN may have multiple representations.
-	for disk in /dev/disk/by-path/*-iscsi-*-"${ISCSI_ROOT_LUN}" ; do
-		# Resolve device name, as the colons in the by-path name will
-		# cause mount to think that this is a NFS share, which we don't
-		# want.
-		if ! disk="$(readlink -f "$disk")" ; then
-			continue
-		fi
-
-		# Try to load file system type module (ignore errors), otherwise
-		# this won't succeed.
-		if fstype=$(get_fstype "$disk") ; then
-			modprobe "$fstype" || :
-			ROOTFSTYPE="$fstype"
-		fi
-
-		# Try to mount read-only and see if it's the right filesystem.
-		# If so, record the device name but umount again, because we
-		# want to be able to do an fsck on it.
-		if mount -r -t "${ROOTFSTYPE:-auto}" ${ROOTFLAGS} "${disk}" ${rootmnt} ; then
-			if [ -d ${rootmnt}/proc ] ; then
-				# This will be sourced by init after this hook has run.
-				echo "export ROOT=$disk" >> /conf/param.conf
-				if [ -n "$ROOTFSTYPE" ] && [ x"$ROOTFSTYPE" != x"auto" ] ; then
-					echo "export ROOTFSTYPE=$ROOTFSTYPE" >> /conf/param.conf
-				fi
-				found=1
-			fi
-			umount ${rootmnt}
-			if [ $found -eq 1 ] ; then
-				break
-			fi
-		fi
-	done
-fi
-
-exit 0
diff -pruN 2.1.5-1/debian/extra/iscsiuio.initramfs.hook 2.1.7-2/debian/extra/iscsiuio.initramfs.hook
--- 2.1.5-1/debian/extra/iscsiuio.initramfs.hook	2021-09-03 15:10:39.000000000 +0000
+++ 2.1.7-2/debian/extra/iscsiuio.initramfs.hook	1970-01-01 00:00:00.000000000 +0000
@@ -1,35 +0,0 @@
-#!/bin/sh
-
-PREREQ="udev iscsi"
-
-prereqs()
-{
-	echo "$PREREQ"
-}
-
-case $1 in
-# get pre-requisites
-prereqs)
-	prereqs
-	exit 0
-	;;
-esac
-
-if [ -r /etc/initramfs-tools/conf.d/open-iscsi ] ; then
-	. /etc/initramfs-tools/conf.d/open-iscsi
-fi
-
-if [ x"$NO_ISCSI_IN_INITRAMFS" = x"yes" ] ; then
-	exit 0
-fi
-
-# Hooks for loading iscsi bits into the initramfs
-. /usr/share/initramfs-tools/hook-functions
-
-copy_exec /sbin/iscsiuio
-# iscsiuio needs libgcc_s library, so add it and its dependencies.
-LIBC_DIR=$(ldd /sbin/iscsiuio | sed -nr 's#.* => (/lib.*)/libc\.so\.[0-9.-]+ \(0x[[:xdigit:]]+\)$#\1#p')
-find -L "$LIBC_DIR" -maxdepth 1 -name 'libgcc_s.*' -type f | while read so; do
-	copy_exec "$so"
-done
-manual_add_modules bnx2i
diff -pruN 2.1.5-1/debian/extra/udeb/finish-install.d/10open-iscsi 2.1.7-2/debian/extra/udeb/finish-install.d/10open-iscsi
--- 2.1.5-1/debian/extra/udeb/finish-install.d/10open-iscsi	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/extra/udeb/finish-install.d/10open-iscsi	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,24 @@
+#! /bin/sh
+
+set -e
+
+got_iscsi=
+for f in /etc/iscsi/*; do
+	# Ignore iscsid.conf, as that will always be present, even if
+	# iSCSI is not used. (See Debian bug #863435.)
+	if [ x"$f" = x"/etc/iscsi/iscsid.conf" ] ; then
+		continue
+	fi
+	[ -e "$f" ] || continue
+	got_iscsi=1
+	break
+done
+
+if [ "$got_iscsi" ]; then
+	# Copy the configuration to the target...
+	cp -a /etc/iscsi /target/etc/
+	if [ -x /target/usr/sbin/update-initramfs ] ; then
+		echo "iSCSI detected, refreshing initramfs"
+		/bin/in-target update-initramfs -k all -u
+	fi
+fi
diff -pruN 2.1.5-1/debian/extra/udeb/iscsi-start 2.1.7-2/debian/extra/udeb/iscsi-start
--- 2.1.5-1/debian/extra/udeb/iscsi-start	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/extra/udeb/iscsi-start	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,20 @@
+#! /bin/sh
+
+# This is basically a version of the init script without dependencies on lsb
+# and without all the sanity checks. The installer is a clean environment, so
+# we don't need all of that.
+
+if ! [ -f /etc/iscsi/initiatorname.iscsi ]; then
+	# Generate a unique InitiatorName and save it
+	INAME=`iscsi-iname -p iqn.1993-08.org.debian:01`
+	echo "## DO NOT EDIT OR REMOVE THIS FILE!" > /etc/iscsi/initiatorname.iscsi
+	echo "## If you remove this file, the iSCSI daemon will not start." >> /etc/iscsi/initiatorname.iscsi
+	echo "## If you change the InitiatorName, existing access control lists" >> /etc/iscsi/initiatorname.iscsi
+	echo "## may reject this initiator.  The InitiatorName must be unique">> /etc/iscsi/initiatorname.iscsi
+	echo "## for each iSCSI initiator.  Do NOT duplicate iSCSI InitiatorNames." >> /etc/iscsi/initiatorname.iscsi
+	printf "InitiatorName=$INAME\n"  >> /etc/iscsi/initiatorname.iscsi
+	chmod 600 /etc/iscsi/initiatorname.iscsi
+fi
+
+modprobe -q iscsi_tcp 2>/dev/null >&2
+/sbin/iscsid
diff -pruN 2.1.5-1/debian/extra/udev/70-iscsi-network-interface.rules 2.1.7-2/debian/extra/udev/70-iscsi-network-interface.rules
--- 2.1.5-1/debian/extra/udev/70-iscsi-network-interface.rules	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/extra/udev/70-iscsi-network-interface.rules	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,3 @@
+# run before 80-networking.rules to run before ifupdown
+SUBSYSTEM=="net", ACTION=="add", RUN+="/lib/open-iscsi/net-interface-handler start"
+SUBSYSTEM=="net", ACTION=="remove", RUN+="/lib/open-iscsi/net-interface-handler stop"
diff -pruN 2.1.5-1/debian/extra/udev/70-open-iscsi.rules 2.1.7-2/debian/extra/udev/70-open-iscsi.rules
--- 2.1.5-1/debian/extra/udev/70-open-iscsi.rules	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/extra/udev/70-open-iscsi.rules	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,3 @@
+# When iscsi disks are present, iscsid.service should be running. LP: #1802354
+# ID_PATH looks like ip-<ipv4-dotted-quad>:<port>-iscsi-<target>-lun-<lun>
+SUBSYSTEM=="block", ACTION=="add", ENV{ID_PATH}=="*-iscsi-*", ENV{SYSTEMD_WANTS}+="iscsid.service"
diff -pruN 2.1.5-1/debian/iscsi-network-interface.rules 2.1.7-2/debian/iscsi-network-interface.rules
--- 2.1.5-1/debian/iscsi-network-interface.rules	2021-10-21 15:41:14.000000000 +0000
+++ 2.1.7-2/debian/iscsi-network-interface.rules	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-# run before 80-networking.rules to run before ifupdown
-SUBSYSTEM=="net", ACTION=="add", RUN+="/lib/open-iscsi/net-interface-handler start"
-SUBSYSTEM=="net", ACTION=="remove", RUN+="/lib/open-iscsi/net-interface-handler stop"
diff -pruN 2.1.5-1/debian/iscsiuio.install 2.1.7-2/debian/iscsiuio.install
--- 2.1.5-1/debian/iscsiuio.install	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/iscsiuio.install	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,2 @@
+debian/extra/initramfs/hooks/iscsiuio usr/share/initramfs-tools/hooks/
+usr/sbin/iscsiuio sbin/
diff -pruN 2.1.5-1/debian/iscsiuio.manpages 2.1.7-2/debian/iscsiuio.manpages
--- 2.1.5-1/debian/iscsiuio.manpages	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/iscsiuio.manpages	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1 @@
+usr/share/man/man8/iscsiuio.8.gz
diff -pruN 2.1.5-1/debian/iscsiuio.triggers 2.1.7-2/debian/iscsiuio.triggers
--- 2.1.5-1/debian/iscsiuio.triggers	2021-09-03 15:10:39.000000000 +0000
+++ 2.1.7-2/debian/iscsiuio.triggers	1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-activate update-initramfs
diff -pruN 2.1.5-1/debian/libopeniscsiusr-dev.install 2.1.7-2/debian/libopeniscsiusr-dev.install
--- 2.1.5-1/debian/libopeniscsiusr-dev.install	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/libopeniscsiusr-dev.install	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1 @@
+usr/include
diff -pruN 2.1.5-1/debian/libopeniscsiusr-dev.manpages 2.1.7-2/debian/libopeniscsiusr-dev.manpages
--- 2.1.5-1/debian/libopeniscsiusr-dev.manpages	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/libopeniscsiusr-dev.manpages	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,57 @@
+usr/share/man/man3/iscsi_iface_name_get.3.gz
+usr/share/man/man3/iscsi_ifaces_get.3.gz
+usr/share/man/man3/iscsi_session_username_in_get.3.gz
+usr/share/man/man3/iscsi_is_default_iface.3.gz
+usr/share/man/man3/iscsi_session_lu_reset_tmo_get.3.gz
+usr/share/man/man3/iscsi_iface_dump_config.3.gz
+usr/share/man/man3/iscsi_iface_port_speed_get.3.gz
+usr/share/man/man3/iscsi_iface_free.3.gz
+usr/share/man/man3/libopeniscsiusr.h.3.gz
+usr/share/man/man3/iscsi_session_persistent_address_get.3.gz
+usr/share/man/man3/iscsi_iface_transport_name_get.3.gz
+usr/share/man/man3/iscsi_iface_netdev_get.3.gz
+usr/share/man/man3/iscsi_node_tpgt_get.3.gz
+usr/share/man/man3/iscsi_session_recovery_tmo_get.3.gz
+usr/share/man/man3/iscsi_node_conn_port_get.3.gz
+usr/share/man/man3/iscsi_context_log_func_set.3.gz
+usr/share/man/man3/iscsi_iface_hwaddress_get.3.gz
+usr/share/man/man3/iscsi_node_iface_name_get.3.gz
+usr/share/man/man3/iscsi_node_dump_config.3.gz
+usr/share/man/man3/iscsi_sessions_free.3.gz
+usr/share/man/man3/iscsi_session_port_get.3.gz
+usr/share/man/man3/iscsi_default_iface_setup.3.gz
+usr/share/man/man3/iscsi_session_tpgt_get.3.gz
+usr/share/man/man3/iscsi_session_sid_get.3.gz
+usr/share/man/man3/iscsi_context_free.3.gz
+usr/share/man/man3/iscsi_context_userdata_get.3.gz
+usr/share/man/man3/iscsi_sessions_get.3.gz
+usr/share/man/man3/iscsi_iface_ipaddress_get.3.gz
+usr/share/man/man3/iscsi_session_free.3.gz
+usr/share/man/man3/iscsi_node_conn_is_ipv6.3.gz
+usr/share/man/man3/iscsi_iface_iname_get.3.gz
+usr/share/man/man3/iscsi_context_log_priority_get.3.gz
+usr/share/man/man3/iscsi_node_conn_address_get.3.gz
+usr/share/man/man3/iscsi_session_tgt_reset_tmo_get.3.gz
+usr/share/man/man3/iscsi_log_priority_str.3.gz
+usr/share/man/man3/iscsi_strerror.3.gz
+usr/share/man/man3/iscsi_context_new.3.gz
+usr/share/man/man3/iscsi_ifaces_free.3.gz
+usr/share/man/man3/iscsi_session_target_name_get.3.gz
+usr/share/man/man3/iscsi_node_portal_get.3.gz
+usr/share/man/man3/iscsi_session_get.3.gz
+usr/share/man/man3/iscsi_session_username_get.3.gz
+usr/share/man/man3/iscsi_nodes_get.3.gz
+usr/share/man/man3/iscsi_session_password_get.3.gz
+usr/share/man/man3/iscsi_node_print_config.3.gz
+usr/share/man/man3/iscsi_session_persistent_port_get.3.gz
+usr/share/man/man3/iscsi_context_userdata_set.3.gz
+usr/share/man/man3/iscsi_session_iface_get.3.gz
+usr/share/man/man3/iscsi_nodes_free.3.gz
+usr/share/man/man3/iscsi_session_abort_tmo_get.3.gz
+usr/share/man/man3/iscsi_context_log_priority_set.3.gz
+usr/share/man/man3/iscsi_node_target_name_get.3.gz
+usr/share/man/man3/iscsi_iface_print_config.3.gz
+usr/share/man/man3/iscsi_iface_port_state_get.3.gz
+usr/share/man/man3/iscsi_session_password_in_get.3.gz
+usr/share/man/man3/iscsi_iface_get.3.gz
+usr/share/man/man3/iscsi_session_address_get.3.gz
diff -pruN 2.1.5-1/debian/libopeniscsiusr.install 2.1.7-2/debian/libopeniscsiusr.install
--- 2.1.5-1/debian/libopeniscsiusr.install	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/libopeniscsiusr.install	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1 @@
+usr/lib/${DEB_HOST_MULTIARCH}/libopeniscsiusr*.so.*
diff -pruN 2.1.5-1/debian/not-installed 2.1.7-2/debian/not-installed
--- 2.1.5-1/debian/not-installed	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/not-installed	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,17 @@
+etc/iscsi/ifaces/iface.example
+etc/iscsi/initiatorname.iscsi
+etc/logrotate.d/iscsiuiolog
+etc/udev/rules.d/50-iscsi-firmware-login.rules
+sbin/iscsi-gen-initiatorname
+sbin/iscsi_fw_login
+sbin/iscsi_offload
+usr/lib/systemd/system-generators/ibft-rule-generator
+usr/lib/systemd/system/iscsi-init.service
+usr/lib/systemd/system/iscsi.service
+usr/lib/systemd/system/iscsid.service
+usr/lib/systemd/system/iscsiuio.service
+usr/lib/systemd/system/iscsiuio.socket
+usr/lib/${DEB_HOST_MULTIARCH}/libopeniscsiusr.so
+usr/lib/${DEB_HOST_MULTIARCH}/pkgconfig/libopeniscsiusr.pc
+usr/sbin/brcm_iscsiuio
+usr/share/man/man8/iscsi_fw_login.8
diff -pruN 2.1.5-1/debian/open-iscsi.install 2.1.7-2/debian/open-iscsi.install
--- 2.1.5-1/debian/open-iscsi.install	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/open-iscsi.install	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,18 @@
+etc/iscsi/iscsid.conf
+debian/extra/umountiscsi.sh lib/open-iscsi/
+debian/extra/logout-all.sh lib/open-iscsi/
+debian/extra/startup-checks.sh lib/open-iscsi/
+debian/extra/activate-storage.sh lib/open-iscsi/
+debian/extra/net-interface-handler lib/open-iscsi/
+debian/iscsid.service lib/systemd/system/
+usr/lib/systemd/system/iscsid.socket lib/systemd/system/
+debian/extra/udev/* lib/udev/rules.d/
+debian/open-iscsi.finalrd usr/share/finalrd/
+debian/extra/initramfs/hooks/iscsi usr/share/initramfs-tools/hooks/
+debian/extra/initramfs/local-top/iscsi usr/share/initramfs-tools/scripts/local-top/
+debian/extra/initramfs/local-bottom/iscsi usr/share/initramfs-tools/scripts/local-bottom/
+sbin/iscsiadm
+sbin/iscsid
+sbin/iscsi_discovery
+sbin/iscsi-iname
+sbin/iscsistart
diff -pruN 2.1.5-1/debian/open-iscsi.links 2.1.7-2/debian/open-iscsi.links
--- 2.1.5-1/debian/open-iscsi.links	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/open-iscsi.links	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1 @@
+sbin/iscsiadm usr/bin/iscsiadm
diff -pruN 2.1.5-1/debian/open-iscsi.manpages 2.1.7-2/debian/open-iscsi.manpages
--- 2.1.5-1/debian/open-iscsi.manpages	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/open-iscsi.manpages	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,6 @@
+usr/share/man/man8/iscsid.8
+usr/share/man/man8/iscsistart.8
+usr/share/man/man8/iscsi-gen-initiatorname.8
+usr/share/man/man8/iscsiadm.8
+usr/share/man/man8/iscsi_discovery.8
+usr/share/man/man8/iscsi-iname.8
diff -pruN 2.1.5-1/debian/open-iscsi.rules 2.1.7-2/debian/open-iscsi.rules
--- 2.1.5-1/debian/open-iscsi.rules	2021-09-03 15:10:39.000000000 +0000
+++ 2.1.7-2/debian/open-iscsi.rules	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-# When iscsi disks are present, iscsid.service should be running. LP: #1802354
-# ID_PATH looks like ip-<ipv4-dotted-quad>:<port>-iscsi-<target>-lun-<lun>
-SUBSYSTEM=="block", ACTION=="add", ENV{ID_PATH}=="*-iscsi-*", ENV{SYSTEMD_WANTS}+="iscsid.service"
diff -pruN 2.1.5-1/debian/open-iscsi.triggers 2.1.7-2/debian/open-iscsi.triggers
--- 2.1.5-1/debian/open-iscsi.triggers	2021-09-03 15:10:39.000000000 +0000
+++ 2.1.7-2/debian/open-iscsi.triggers	1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-activate update-initramfs
diff -pruN 2.1.5-1/debian/open-iscsi-udeb.finish-install 2.1.7-2/debian/open-iscsi-udeb.finish-install
--- 2.1.5-1/debian/open-iscsi-udeb.finish-install	2021-09-03 15:10:39.000000000 +0000
+++ 2.1.7-2/debian/open-iscsi-udeb.finish-install	1970-01-01 00:00:00.000000000 +0000
@@ -1,24 +0,0 @@
-#! /bin/sh
-
-set -e
-
-got_iscsi=
-for f in /etc/iscsi/*; do
-	# Ignore iscsid.conf, as that will always be present, even if
-	# iSCSI is not used. (See Debian bug #863435.)
-	if [ x"$f" = x"/etc/iscsi/iscsid.conf" ] ; then
-		continue
-	fi
-	[ -e "$f" ] || continue
-	got_iscsi=1
-	break
-done
-
-if [ "$got_iscsi" ]; then
-	# Copy the configuration to the target...
-	cp -a /etc/iscsi /target/etc/
-	if [ -x /target/usr/sbin/update-initramfs ] ; then
-		echo "iSCSI detected, refreshing initramfs"
-		/bin/in-target update-initramfs -k all -u
-	fi
-fi
diff -pruN 2.1.5-1/debian/open-iscsi-udeb.install 2.1.7-2/debian/open-iscsi-udeb.install
--- 2.1.5-1/debian/open-iscsi-udeb.install	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/open-iscsi-udeb.install	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,10 @@
+debian/tmp-udeb/etc/iscsi/iscsid.conf etc/iscsi/
+debian/tmp-udeb/sbin/iscsiadm sbin/
+debian/tmp-udeb/sbin/iscsid sbin/
+debian/tmp-udeb/sbin/iscsi_discovery sbin/
+debian/tmp-udeb/sbin/iscsi-iname sbin/
+debian/tmp-udeb/sbin/iscsistart sbin/
+debian/extra/udeb/iscsi-start sbin/
+debian/extra/udeb/finish-install.d/10open-iscsi usr/lib/finish-install.d/
+# Ship shared libraries along with the executable in a single udeb
+debian/tmp-udeb/usr/lib/${DEB_HOST_MULTIARCH}/libopeniscsiusr*.so.* usr/lib/${DEB_HOST_MULTIARCH}/
diff -pruN 2.1.5-1/debian/open-iscsi-udeb.start 2.1.7-2/debian/open-iscsi-udeb.start
--- 2.1.5-1/debian/open-iscsi-udeb.start	2021-09-03 15:10:39.000000000 +0000
+++ 2.1.7-2/debian/open-iscsi-udeb.start	1970-01-01 00:00:00.000000000 +0000
@@ -1,20 +0,0 @@
-#! /bin/sh
-
-# This is basically a version of the init script without dependencies on lsb
-# and without all the sanity checks. The installer is a clean environment, so
-# we don't need all of that.
-
-if ! [ -f /etc/iscsi/initiatorname.iscsi ]; then
-	# Generate a unique InitiatorName and save it
-	INAME=`iscsi-iname -p iqn.1993-08.org.debian:01`
-	echo "## DO NOT EDIT OR REMOVE THIS FILE!" > /etc/iscsi/initiatorname.iscsi
-	echo "## If you remove this file, the iSCSI daemon will not start." >> /etc/iscsi/initiatorname.iscsi
-	echo "## If you change the InitiatorName, existing access control lists" >> /etc/iscsi/initiatorname.iscsi
-	echo "## may reject this initiator.  The InitiatorName must be unique">> /etc/iscsi/initiatorname.iscsi
-	echo "## for each iSCSI initiator.  Do NOT duplicate iSCSI InitiatorNames." >> /etc/iscsi/initiatorname.iscsi
-	printf "InitiatorName=$INAME\n"  >> /etc/iscsi/initiatorname.iscsi
-	chmod 600 /etc/iscsi/initiatorname.iscsi
-fi
-
-modprobe -q iscsi_tcp 2>/dev/null >&2
-/sbin/iscsid
diff -pruN 2.1.5-1/debian/patches/fix-ftbfs-strcpy-destination-size.patch 2.1.7-2/debian/patches/fix-ftbfs-strcpy-destination-size.patch
--- 2.1.5-1/debian/patches/fix-ftbfs-strcpy-destination-size.patch	2021-10-21 16:03:47.000000000 +0000
+++ 2.1.7-2/debian/patches/fix-ftbfs-strcpy-destination-size.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,12 +0,0 @@
-See: https://github.com/open-iscsi/open-iscsi/commit/424d5967e94f6adf4c0669d390779af8da0bef20
---- a/libopeniscsiusr/idbm.c
-+++ b/libopeniscsiusr/idbm.c
-@@ -996,7 +996,7 @@
- 
- 	/* use the interface name passed in, if any */
- 	if (iface_name)
--		strncpy((*node).iface.name, iface_name, ISCSI_MAX_IFACE_LEN);
-+		strncpy((*node).iface.name, iface_name, ISCSI_MAX_IFACE_LEN-1);
- 
- 	/*
- 	 * Note: because we do not add the iface.iscsi_ifacename to
diff -pruN 2.1.5-1/debian/patches/lp1755858-default-iscsid_conf-to-iscsid_socket.patch 2.1.7-2/debian/patches/lp1755858-default-iscsid_conf-to-iscsid_socket.patch
--- 2.1.5-1/debian/patches/lp1755858-default-iscsid_conf-to-iscsid_socket.patch	2021-10-21 15:41:14.000000000 +0000
+++ 2.1.7-2/debian/patches/lp1755858-default-iscsid_conf-to-iscsid_socket.patch	2022-07-30 14:23:25.000000000 +0000
@@ -12,15 +12,16 @@ Bug-Ubuntu: https://bugs.launchpad.net/b
 Reviewed-by: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
 Last-Update: 2020-08-13
 
---- a/etc/iscsid.conf
-+++ b/etc/iscsid.conf
-@@ -18,8 +18,8 @@
- # maintainers. If you leave the iscsid daemon running all
- # the time then leave this attribute commented out.
- #
--# Default for Fedora and RHEL. (uncomment to activate).
+Index: open-iscsi/etc/iscsid.conf
+===================================================================
+--- open-iscsi.orig/etc/iscsid.conf
++++ open-iscsi/etc/iscsid.conf
+@@ -22,7 +22,7 @@
  # iscsid.startup = /bin/systemctl start iscsid.socket iscsiuio.socket
+ #
+ # Default for Debian and Ubuntu. Uncomment to activate.
+-# iscsid.startup = /bin/systemctl start iscsid.socket
 +iscsid.startup = /bin/systemctl start iscsid.socket
  #
- # Default if you are not using systemd (uncomment to activate)
+ # Default if you are not using systemd. Uncomment to activate.
  # iscsid.startup = /usr/bin/service start iscsid
diff -pruN 2.1.5-1/debian/patches/multiarch-path.patch 2.1.7-2/debian/patches/multiarch-path.patch
--- 2.1.5-1/debian/patches/multiarch-path.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/patches/multiarch-path.patch	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,18 @@
+Index: open-iscsi/libopeniscsiusr/Makefile
+===================================================================
+--- open-iscsi.orig/libopeniscsiusr/Makefile
++++ open-iscsi/libopeniscsiusr/Makefile
+@@ -17,11 +17,8 @@ SBINDIR ?= $(exec_prefix)/sbin
+ DBROOT ?= $(etcdir)/iscsi
+ 
+ ifndef LIB_DIR
+-	ifeq ($(shell test -d /lib64 && echo 1),1)
+-		LIB_DIR=$(prefix)/lib64
+-	else
+-		LIB_DIR=$(prefix)/lib
+-	endif
++	DEB_HOST_MULTIARCH  ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
++	LIB_DIR=$(prefix)/lib/$(DEB_HOST_MULTIARCH)
+ endif
+ 
+ INCLUDE_DIR ?= $(prefix)/include
diff -pruN 2.1.5-1/debian/patches/non-usrmerge-sed.patch 2.1.7-2/debian/patches/non-usrmerge-sed.patch
--- 2.1.5-1/debian/patches/non-usrmerge-sed.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/patches/non-usrmerge-sed.patch	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,52 @@
+Index: open-iscsi/doc/Makefile
+===================================================================
+--- open-iscsi.orig/doc/Makefile
++++ open-iscsi/doc/Makefile
+@@ -7,7 +7,7 @@ ifeq ($(TOPDIR),)
+ 	TOPDIR = ..
+ endif
+ 
+-SED = /usr/bin/sed
++SED = sed
+ INSTALL = install
+ 
+ DESTDIR ?=
+Index: open-iscsi/etc/Makefile
+===================================================================
+--- open-iscsi.orig/etc/Makefile
++++ open-iscsi/etc/Makefile
+@@ -19,7 +19,7 @@ initddir ?= $(etcdir)/init.d
+ 
+ HOMEDIR ?= $(etcdir)/iscsi
+ 
+-SED = /usr/bin/sed
++SED = sed
+ INSTALL = install
+ 
+ SYSTEMD_SOURCE_FILES	= iscsid.socket iscsiuio.socket
+Index: open-iscsi/libopeniscsiusr/Makefile
+===================================================================
+--- open-iscsi.orig/libopeniscsiusr/Makefile
++++ open-iscsi/libopeniscsiusr/Makefile
+@@ -29,7 +29,7 @@ PKGCONF_DIR ?= $(LIB_DIR)/pkgconfig
+ MAN_DIR = $(prefix)/share/man
+ 
+ PKG_CONFIG ?= /usr/bin/pkg-config
+-SED ?= /usr/bin/sed
++SED ?= sed
+ 
+ LIBISCSI_USR_DIR=$(TOPDIR)/libopeniscsiusr
+ 
+Index: open-iscsi/utils/Makefile
+===================================================================
+--- open-iscsi.orig/utils/Makefile
++++ open-iscsi/utils/Makefile
+@@ -7,7 +7,7 @@
+ # from the top-level make file.
+ #
+ 
+-SED = /usr/bin/sed
++SED = sed
+ INSTALL = install
+ CHMOD = chmod
+ 
diff -pruN 2.1.5-1/debian/patches/series 2.1.7-2/debian/patches/series
--- 2.1.5-1/debian/patches/series	2021-10-21 16:03:47.000000000 +0000
+++ 2.1.7-2/debian/patches/series	2022-07-30 14:23:25.000000000 +0000
@@ -1,2 +1,5 @@
 lp1755858-default-iscsid_conf-to-iscsid_socket.patch
-fix-ftbfs-strcpy-destination-size.patch
+non-usrmerge-sed.patch
+multiarch-path.patch
+upstream/341.patch
+upstream/354.patch
diff -pruN 2.1.5-1/debian/patches/upstream/341.patch 2.1.7-2/debian/patches/upstream/341.patch
--- 2.1.5-1/debian/patches/upstream/341.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/patches/upstream/341.patch	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,44 @@
+From 790ee9c43cf3143a9cdb45dc6d12648ce784f474 Mon Sep 17 00:00:00 2001
+From: Sam James <sam@gentoo.org>
+Date: Thu, 14 Apr 2022 02:13:03 +0100
+Subject: [PATCH] iscsiuio: fix LDADD
+
+- We don't want to use _LIBS here, we're building a library, not an executable.
+- We want LDADD for the whole lot (not a mix of LDFLAGS/LIBS/LDADD),
+but put the objects/libraries (.a files) first so that -l* works correctly.
+
+Closes: https://github.com/open-iscsi/open-iscsi/issues/337
+Fixes: 9fbd6009cd917f1152a367fa7e5ae3993133c1e4
+Signed-off-by: Sam James <sam@gentoo.org>
+---
+ iscsiuio/src/unix/Makefile.am | 17 +++++++----------
+ 1 file changed, 7 insertions(+), 10 deletions(-)
+
+diff --git a/iscsiuio/src/unix/Makefile.am b/iscsiuio/src/unix/Makefile.am
+index 8a943714..4c10711b 100644
+--- a/iscsiuio/src/unix/Makefile.am
++++ b/iscsiuio/src/unix/Makefile.am
+@@ -27,16 +27,13 @@ iscsiuio_CFLAGS = 	$(AM_CFLAGS)		\
+ 			$(LIBNL_CFLAGS)		\
+ 			-DBYTE_ORDER=@ENDIAN@
+ 
+-iscsiuio_LIBS = 	$(AM_LIBS)		\
+-			-ldl			\
+-			-rdynamic		\
+-			$(LIBNL_LIBS)		\
+-			-lpthread
+-
+-iscsiuio_LDADD  = 	$(AM_LDADD) \
+-			${top_srcdir}/src/uip/lib_iscsi_uip.a	\
+-			${top_srcdir}/src/apps/dhcpc/lib_apps_dhcpc.a\
++iscsiuio_LDADD = 	${top_srcdir}/src/uip/lib_iscsi_uip.a   		\
++			${top_srcdir}/src/apps/dhcpc/lib_apps_dhcpc.a   	\
+ 			${top_srcdir}/src/apps/brcm-iscsi/lib_apps_brcm_iscsi.a \
+-			${top_srcdir}/src/unix/libs/lib_iscsiuio_hw_cnic.a
++			${top_srcdir}/src/unix/libs/lib_iscsiuio_hw_cnic.a	\
++			$(AM_LDADD)						\
++			-ldl							\
++			$(LIBNL_LIBS)						\
++			-lpthread
+ 
+ iscsiuio_YFLAGS = -d
diff -pruN 2.1.5-1/debian/patches/upstream/354.patch 2.1.7-2/debian/patches/upstream/354.patch
--- 2.1.5-1/debian/patches/upstream/354.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/debian/patches/upstream/354.patch	2022-07-30 14:23:25.000000000 +0000
@@ -0,0 +1,28 @@
+From dda3eeb61ab5134da02ea916d7be10434dc18b94 Mon Sep 17 00:00:00 2001
+From: Christian Hesse <mail@eworm.de>
+Date: Thu, 7 Jul 2022 10:32:07 +0200
+Subject: [PATCH] etc: install system unit with without executable bit
+
+All systemd unit files are expected to be not executable, so install
+with correct permissions.
+---
+ etc/Makefile | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/etc/Makefile b/etc/Makefile
+index 6a03c327..c47c180e 100644
+--- a/etc/Makefile
++++ b/etc/Makefile
+@@ -81,10 +81,10 @@ install_systemd_service_files: $(DESTDIR)$(systemddir)/system $(SYSTEMD_DEST_SVC
+ install_systemd_generator_files: $(DESTDIR)$(systemddir)/system-generators $(SYSTEMD_DEST_GEN_FILES)
+ 
+ $(SYSTEMD_DEST_SVC_FILES): $(DESTDIR)$(systemddir)/system/%: systemd/%
+-	$(INSTALL) $? $@
++	$(INSTALL) -m 644 $? $@
+ 
+ $(SYSTEMD_DEST_GEN_FILES): $(DESTDIR)$(systemddir)/system-generators/%: systemd/%
+-	$(INSTALL) $? $@
++	$(INSTALL) -m 755 $? $@
+ 
+ install_iname: $(DESTDIR)$(HOMEDIR) $(ISCSI_INAME)
+ 	if [ ! -f $(INAME_DEST_FILE) ]; then \
diff -pruN 2.1.5-1/debian/rules 2.1.7-2/debian/rules
--- 2.1.5-1/debian/rules	2021-10-21 16:03:19.000000000 +0000
+++ 2.1.7-2/debian/rules	2022-07-30 14:23:25.000000000 +0000
@@ -1,86 +1,61 @@
 #!/usr/bin/make -f
 # export DH_VERBOSE = 1
 
-DEB_HOST_MULTIARCH  ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
-
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
 DPKG_EXPORT_BUILDFLAGS = 1
 include /usr/share/dpkg/buildflags.mk
-
 include /usr/share/dpkg/pkg-info.mk
-export KBUILD_BUILD_TIMESTAMP = @$(SOURCE_DATE_EPOCH)
+export KBUILD_BUILD_TIMESTAMP = "@$(SOURCE_DATE_EPOCH)"
 
 UDEB := $(filter open-iscsi-udeb,$(shell dh_listpackages))
 
-# Fix gcc10 warnings as errors while upstream doesn't catch up
-export DEB_CFLAGS_PREPEND=-Wno-error=zero-length-bounds -Wno-error=format-overflow= -Wno-error=format-truncation= -Wno-error=maybe-uninitialized
-export DEB_CXXFLAGS_PREPEND=${DEB_CFLAGS_PREPEND}
+ifneq ($(UDEB),)
+TREENAMES = build-deb build-udeb
+else
+TREENAMES = build-deb
+endif
 
 %:
 	dh $@
 
-override_dh_update_autotools_config:
-override_autoreconf:
+execute_before_dh_clean:
+	for treename in $(TREENAMES); do \
+		rm -rf debian/$$treename ;\
+	done
+	rm -rf debian/tmp-udeb
+
+execute_before_dh_auto_configure:
+	# no out of tree build support, prepare two source trees
+	for treename in $(TREENAMES); do \
+		mkdir debian/$$treename ;\
+		cp -r -t debian/$$treename $$(find . -mindepth 1 -maxdepth 1 \! -name debian \! -name .git) ;\
+	done
+
 override_dh_auto_configure:
+	for treename in $(TREENAMES); do \
+		cat debian/buildconfig.common debian/buildconfig.$$treename Makefile > debian/$$treename/Makefile ;\
+		CFLAGS="$(CPPFLAGS) $(CFLAGS)" dh_auto_configure --sourcedirectory=debian/$$treename ;\
+		CFLAGS="$(CPPFLAGS) $(CFLAGS)" dh_auto_configure --sourcedirectory=debian/$$treename/iscsiuio ;\
+	done
 
 override_dh_auto_build:
-	@# Let debhelper pass configure flags.
-	dh_auto_configure --sourcedirectory=iscsiuio
-
-	CFLAGS="$(CPPFLAGS) $(CFLAGS)" dh_auto_build
+	for treename in $(TREENAMES); do \
+		CFLAGS="$(CPPFLAGS) $(CFLAGS)" NO_SYSTEMD=$$NO_SYSTEMD dh_auto_build --sourcedirectory=debian/$$treename ;\
+	done
 
 override_dh_auto_install:
-
-	@# libopeniscsiusr
-	dh_install -p libopeniscsiusr libopeniscsiusr/libopeniscsiusr*.so.* usr/lib/${DEB_HOST_MULTIARCH}
-
-	@# libopeniscsi-dev
-	dh_install -p libopeniscsiusr-dev libopeniscsiusr/libopeniscsiusr/ usr/include/
-
-	@# open-iscsi
-	dh_install -p open-iscsi usr/iscsid sbin/
-	dh_install -p open-iscsi usr/iscsistart sbin/
-	dh_install -p open-iscsi usr/iscsiadm sbin/
-	dh_install -p open-iscsi utils/iscsi_discovery sbin/
-	dh_install -p open-iscsi utils/iscsi-iname sbin/
-	dh_install -p open-iscsi etc/iscsid.conf etc/iscsi/
-	dh_install -p open-iscsi debian/extra/umountiscsi.sh lib/open-iscsi/
-	dh_install -p open-iscsi debian/extra/logout-all.sh lib/open-iscsi/
-	dh_install -p open-iscsi debian/extra/startup-checks.sh lib/open-iscsi/
-	dh_install -p open-iscsi debian/extra/activate-storage.sh lib/open-iscsi/
-	dh_install -p open-iscsi debian/extra/net-interface-handler lib/open-iscsi/
-	dh_install -p open-iscsi debian/open-iscsi.finalrd usr/share/finalrd/
-	dh_install -p open-iscsi etc/systemd/iscsid.socket lib/systemd/system/
-	dh_install -p open-iscsi debian/iscsid.service lib/systemd/system/
-	mkdir -p debian/open-iscsi/usr/bin
-	ln -s /sbin/iscsiadm debian/open-iscsi/usr/bin/iscsiadm
-	mkdir -p debian/open-iscsi/usr/share/initramfs-tools/hooks
-	mkdir -p debian/open-iscsi/usr/share/initramfs-tools/scripts/local-top/
-	mkdir -p debian/open-iscsi/usr/share/initramfs-tools/scripts/local-bottom/
-	cp -p debian/extra/initramfs.hook debian/open-iscsi/usr/share/initramfs-tools/hooks/iscsi
-	cp -p debian/extra/initramfs.local-top debian/open-iscsi/usr/share/initramfs-tools/scripts/local-top/iscsi
-	cp -p debian/extra/initramfs.local-bottom debian/open-iscsi/usr/share/initramfs-tools/scripts/local-bottom/iscsi
-	mkdir -p debian/open-iscsi/lib/udev/rules.d/
-	cp -p debian/open-iscsi.rules debian/open-iscsi/lib/udev/rules.d/70-open-iscsi.rules
-	cp -p debian/iscsi-network-interface.rules debian/open-iscsi/lib/udev/rules.d/70-iscsi-network-interface.rules
-
-	@# iscsiuio
-	dh_install -p iscsiuio iscsiuio/src/unix/iscsiuio /sbin
-	mkdir -p debian/iscsiuio/usr/share/initramfs-tools/hooks
-	cp -p debian/extra/iscsiuio.initramfs.hook debian/iscsiuio/usr/share/initramfs-tools/hooks/iscsiuio
-
+	# workaround upstream makefile parallelism problem
+	dh_auto_install --no-parallel --sourcedirectory=debian/build-deb
 ifneq ($(UDEB),)
-	@# open-iscsi-udeb
-	dh_install -p open-iscsi-udeb usr/iscsid sbin/
-	dh_install -p open-iscsi-udeb usr/iscsistart sbin/
-	dh_install -p open-iscsi-udeb usr/iscsiadm sbin/
-	dh_install -p open-iscsi-udeb utils/iscsi_discovery sbin/
-	dh_install -p open-iscsi-udeb utils/iscsi-iname sbin/
-	dh_install -p open-iscsi-udeb etc/iscsid.conf etc/iscsi/
-	dh_install -p open-iscsi-udeb debian/open-iscsi-udeb.start sbin/iscsi-start
-	dh_install -p open-iscsi-udeb debian/open-iscsi-udeb.finish-install usr/lib/finish-install.d/10open-iscsi
+	dh_auto_install --no-parallel --sourcedirectory=debian/build-udeb --destdir=$(CURDIR)/debian/tmp-udeb
+endif
 
-	# Ship shared libraries along with the executable in a single udeb
-	dh_install -p open-iscsi-udeb libopeniscsiusr/libopeniscsiusr*.so.* usr/lib/${DEB_HOST_MULTIARCH}
+ifneq ($(UDEB),)
+execute_after_dh_install:
+	if strings debian/open-iscsi-udeb/sbin/iscsid | grep libsystemd.so ; then \
+		echo ERROR: udeb linked to libsystemd ;\
+		exit 1 ;\
+	fi
 endif
 
 override_dh_installinit:
@@ -89,25 +64,14 @@ override_dh_installinit:
 	dh_installinit -p iscsiuio --no-start --no-enable --no-stop-on-upgrade
 
 override_dh_installsystemd:
-	dh_installsystemd -p open-iscsi --name=iscsid --no-enable iscsid.service
-	dh_installsystemd -p open-iscsi --name=iscsid --no-enable iscsid.socket
-	dh_installsystemd -p open-iscsi --no-enable open-iscsi.service
-	dh_installsystemd -p iscsiuio --no-enable
-
-override_dh_installsystemd:
 	dh_installsystemd -p open-iscsi --no-restart-on-upgrade iscsid.socket
 	dh_installsystemd -p open-iscsi --no-restart-on-upgrade open-iscsi.service
 	dh_installsystemd -p iscsiuio --no-restart-on-upgrade iscsiuio.service
 
-override_dh_installman:
-	dh_installman -p open-iscsi ./doc/*
-	dh_installman -p libopeniscsiusr-dev ./libopeniscsiusr/docs/man/*
-	dh_installman -p iscsiuio iscsiuio/docs/*
-
 override_dh_installdocs:
 	dh_installdocs -p open-iscsi README sysfs-documentation THANKS
 	dh_installdocs -p iscsiuio iscsiuio/RELEASE.TXT iscsiuio/README
-	dh_installdocs -p libopeniscsiusr ./libopeniscsiusr/docs/doc-preclean.pl ./libopeniscsiusr/docs/kernel-doc ./libopeniscsiusr/docs/libopeniscsiusr.h.3 ./libopeniscsiusr/docs/split-man.pl
+	dh_installdocs -p libopeniscsiusr
 	dh_installdocs -p libopeniscsiusr-dev
 
 override_dh_makeshlibs:
diff -pruN 2.1.5-1/doc/.gitignore 2.1.7-2/doc/.gitignore
--- 2.1.5-1/doc/.gitignore	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/doc/.gitignore	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,3 @@
+iscsi-gen-initiatorname.8
+iscsiadm.8
+iscsid.8
diff -pruN 2.1.5-1/doc/iscsiadm.8 2.1.7-2/doc/iscsiadm.8
--- 2.1.5-1/doc/iscsiadm.8	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/doc/iscsiadm.8	1970-01-01 00:00:00.000000000 +0000
@@ -1,695 +0,0 @@
-.TH ISCSIADM 8 "Nov 2020" "" "Linux Administrator's Manual"
-.SH NAME
-iscsiadm \- open-iscsi administration utility
-.SH SYNOPSIS
-.B iscsiadm
-.B \-m discoverydb
-.RB [ \-hV ]
-.RB [ \-d
-.IR debug_level ]
-.RB [ \-P
-.IR printlevel ]
-.RB [ \-I
-.I iface
-.BI \-t\  type\  \-p\  ip:port
-.RB [ \-lD ]
-] | [
-.RB [ \-p
-.I ip:port
-.B \-t
-.IR type ]
-.RB [ \-o
-.IR operation ]
-.RB [ \-n
-.IR name ]
-.RB [ \-v
-.IR value ]
-.RB [ \-lD ]
-]
-.PP
-.B iscsiadm
-.B \-m discovery
-.RB [ \-hV ]
-.RB [ \-d
-.IR debug_level ]
-.RB [ \-P
-.IR printlevel ]
-.RB [ \-I
-.IR iface ]
-.RB [ \-t
-.IR  type ]
-.RB [ \-p
-.IR ip:port ]
-.RB [ \-l ]
-.PP
-.B iscsiadm
-.B \-m node
-.RB [ \-hV ]
-.RB [ \-d
-.IR debug_level ]
-.RB [ \-P
-.IR printlevel ]
-.RB [ \-L
-.IR all,manual,automatic,onboot ]
-.RB [ \-W ]
-.RB [ \-U
-.IR all,manual,automatic,onboot ]
-.RB [ \-S ]
-[
-.RB [ \-T
-.IB targetname\  \-p\  ip:port\  \-I
-.IR iface ]
-.RB [ \-l | \-u | \-R | \-s ]
-]
-[
-.RB [ \-o
-.IR operation ]
-.RB [ \-n
-.IR name ]
-.RB [ \-v
-.IR value ]
-.RB [ \-p
-.IR ip:port ]
-]
-.PP
-.B iscsiadm
-.B \-m session
-.RB [ \-hV ]
-.RB [ \-d
-.IR debug_level ]
-.RB [ \-P
-.IR printlevel ]
-.RB [ \-r
-.IR sessionid | sysfsdir
-.RB [ \-R ]
-.RB [ \-u | \-s | \-o
-.IR new ]
-]
-.PP
-.B iscsiadm
-.B \-m iface
-.RB [ \-hV ]
-.RB [ \-d
-.IR debug_level ]
-.RB [ \-P
-.IR printlevel ]
-.RB [ \-I
-.IR ifacename\  |
-.B \-H
-.IR hostno|MAC ]
-[
-.RB [ \-o
-.IR operation ]
-.RB [ \-n
-.IR name ]
-.RB [ \-v
-.IR value ]
-]
-[
-.BI \-C\  ping
-.RB [ \-a
-.IR ip ]
-.RB [ \-b
-.IR packetsize ]
-.RB [ \-c
-.IR count ]
-.RB [ \-i
-.IR interval ]
-]
-.PP
-.B iscsiadm
-.B \-m fw
-.RB [ \-d
-.IR debug_level ]
-.RB [ \-l ]
-.RB [ \-W ]
-.PP
-.B iscsiadm
-.B \-m host
-.RB [ \-P
-.IR printlevel ]
-.RB [ \-H
-.IR hostno|MAC ]
-[
-.RB [ \-C
-.I chap
-.RB [ \-x
-.IR chap_tbl_idx ]
-] |
-.RB [ \-C
-.I flashnode
-.RB [ \-A
-.IR portal_type ]
-.RB [ \-x
-.IR flashnode_idx ]
-] |
-.RB [ \-C
-.IR stats ]
-]
-[
-.RB [ \-o
-.IR operation ]
-.RB [ \-n
-.IR name ]
-.RB [ \-v
-.IR value ]
-]
-.PP
-.B iscsiadm
-.B \-k  priority
-.SH DESCRIPTION
-The iscsiadm utility is a command-line tool allowing discovery and login
-to iSCSI targets, as well as access and management of the open-iscsi
-database.
-.PP
-Open-iscsi does not use the term node as defined by the iSCSI RFC,
-where a node is a single iSCSI initiator or target. Open-iscsi uses the
-term node to refer to a portal on a target.
-.PP
-For session mode, a session id (sid) is used. The sid of a session can be
-found by running iscsiadm \-m session \-P 1. The session id and sysfs
-path are not currently persistent and is partially determined by when the
-session is setup.
-.PP
-Note that many of the node and discovery operations require that the iSCSI
-daemon (iscsid) be running.
-.SH OPTIONS
-.TP
-\fB\-a\fR, \fB\-\-ip=\fIipaddr\fP
-\fIipaddr\fR can be IPv4 or IPv6.
-.IP
-This option is only valid for ping submode.
-.TP
-\fB\-A\fR, \fB\-\-portal_type=\fI[ipv4|ipv6]\fR
-Specify the portal type for the new flash node entry to be created.
-.IP
-This option is only valid for flashnode submode of host mode and only with \fInew\fR operation.
-.TP
-\fB\-b\fR, \fB\-\-packetsize=\fIpacketsize\fP
-Specify the ping \fIpacketsize\fR.
-.IP
-This option is only valid for ping submode.
-.TP
-\fB\-c\fR, \fB\-\-count=\fIcount\fP
-\fIcount\fR specify number of ping iterations.
-.IP
-This option is only valid for ping submode.
-.TP
-\fB\-C\fR, \fB\-\-submode=\fIop\fP
-Specify the submode for mode. op must be name of submode.
-.IP
-Currently iscsiadm support ping as submode for iface. For example:
-.IP
-iscsiadm \-m iface \-I ifacename \-C ping \-a ipaddr \-b packetsize \-c count \-i interval
-.IP
-For host, it supports chap , flashnode and stats as submodes. For example:
-.IP
-iscsiadm \-m host \-H hostno \-C chap \-x chap_tbl_idx \-o operation
-.IP
-iscsiadm \-m host \-H hostno \-C flashnode \-x flashnode_idx \-o operation
-.IP
-iscsiadm \-m host \-H hostno \-C stats
-.TP
-\fB\-d\fR, \fB\-\-debug=\fIdebug_level\fP
-print debugging information. Valid values for debug_level are 0 to 8.
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-display help text and exit
-.TP
-\fB\-H\fR, \fB\-\-host=\fI[hostno|MAC]\fR
-The host argument specifies the SCSI host to use for the operation. It can be
-the scsi host number assigned to the host by the kernel's scsi layer, or the
-MAC address of a scsi host.
-.TP
-\fB\-i\fR, \fB\-\-interval=\fIinterval\fP
-\fIinterval\fP specify delay between two ping iterations.
-.IP
-This option is only valid for ping submode.
-.TP
-\fB\-I\fR, \fB\-\-interface=\fI[iface]\fR
-The interface argument specifies the iSCSI interface to use for the operation.
-iSCSI interfaces (iface) are defined in /etc/iscsi/ifaces. For hardware
-iSCSI (qla4xxx) the iface config must have the hardware address
-(iface.hwaddress = port's MAC address)
-and the driver/transport_name (iface.transport_name). The iface's name is
-then the filename of the iface config. For software iSCSI, the iface config
-must have either the hardware address (iface.hwaddress), or the network
-layer's interface name (iface.net_ifacename), and it must have the
-driver/transport_name
-.IP
-The available drivers/iscsi_transports are tcp (software iSCSI over TCP/IP),
-\fIiser\fR (software iSCSI over InfiniBand),
-\fIqla4xxx\fR (Qlogic 4XXXX and 82XXX HBAs),
-\fIcxgb3i\fR and \fIcxgb4i\fR (Chelsio T3 and T4 adapters),
-\fIbnx2i\fR (QLogic Netextreme II adapters),
-\fIbe2iscsi\fR (Emulex 10G adapter),
-\fIqedi\fR (QLogic QEDI 25/40/100Gb adapter), and
-\fIocs\fR (Emulex One Connect storage).
-Some of these are considered experimental, as they are not fully tested.
-.IP
-The hwaddress is the MAC address or for software iSCSI it may be the special
-value \fIdefault\fR which directs the initiator to not bind the session to a
-specific hardware resource and instead allow the network or InfiniBand layer
-to decide what to do. There is no need to create an iface config with the default
-behavior. If you do not specify an iface, then the default behavior is used.
-.IP
-As mentioned above there is a special iface name \fIdefault\fR. There are
-others which do not bind the session to a specific card, but instead bind
-the session to the transport:
-\fIiser\fR,
-\fIcxgb3i\fR,
-\fIcxgb4i\fR, and
-\fIbnx2i\fR.
-.IP
-In discovery mode multiple interfaces can be specified by passing in multiple
-\-I/\-\-interface instances. For example:
-.IP
-\fBsh#\fR iscsiadm \-m discoverydb \-t st \-p ip:port \-I iface0 \-I iface2 \-\-discover
-.IP
-Will direct iscsiadm to setup the node db to create records which will create
-sessions through the two intefaces passed in.
-.IP
-In node mode, only a single interface is supported in each call to iscsiadm.
-.IP
-This option is valid for discovery, node and iface mode.
-.TP
-\fB\-k\fR, \fB\-\-killiscsid=\fI[priority]\fR
-Currently priority must be zero. This will immediately stop all iscsid
-operations and shutdown iscsid. It does not logout any sessions. Running
-this command is the same as doing \fIkillall iscsid\fR. Neither should
-normally be used, because if iscsid is doing error recovery or if there
-is an error while iscsid is not running, the system may not be able to recover.
-This command and iscsid's SIGTERM handling are experimental.
-.TP
-\fB\-D\fR, \fB\-\-discover\fR
-Discover targets using the discovery record with the  \fIrecid\fR matching
-the the discovery type and portal passed in. If there is no matching record,
-it will be created using the iscsid.conf discovery settings.
-This must be passed in \fIdiscoverydb\fR mode to instruct iscsiadm to perform
-discovery.
-.IP
-This option is only valid for SendTargets discovery mode.
-.TP
-\fB\-l\fR, \fB\-\-login\fR
-For node and fw mode, login to a specified record. For discovery mode, login to
-all discovered targets.
-.IP
-This option is only valid for discovery and node modes.
-.TP
-\fB\-L\fR, \fB\-\-loginall=\fI[all|manual|automatic|onboot]\fR
-For node mode, login all sessions with the node or conn startup values passed
-in or all running session, except ones marked onboot, if all is passed in.
-.IP
-This option is only valid for node mode (it is valid but not functional
-for session mode).
-.TP
-\fB\-W\fR, \fB\-\-\-no_wait\fR
-In node, discovery, or firmware mode,
-do not wait for a response from the targets.
-This means that success will be returned if the command is able to
-send the login requests, whether or not they succeed. In this case, it will
-be up to the caller to poll for success (i.e. session creation).
-.TP
-\fB\-m\fR, \fB\-\-mode \fIop\fR
-specify the mode. \fIop\fR
-must be one of \fIdiscovery\fR, \fIdiscoverydb\fR, \fInode\fR, \fIfw\fR,
-\fIhost\fR \fIiface\fR or \fIsession\fR.
-.IP
-If no other options are specified: for \fIdiscovery\fR, \fIdiscoverydb\fR and
-\fInode\fR, all of their respective records are displayed; for \fIsession\fR,
-all active sessions and connections are displayed; for \fIfw\fR, all boot
-firmware values are displayed; for \fIhost\fR, all iSCSI hosts are displayed;
-and for \fIiface\fR, all ifaces setup in /etc/iscsi/ifaces are displayed.
-.TP
-\fB\-n\fR, \fB\-\-name=\fIname\fR
-In node mode, specify a field \fIname\fR in a record. In flashnode submode
-of host mode, specify name of the flash node parameter.
-.IP
-For use with the \fIupdate\fR operator.
-.TP
-\fB\-o\fR, \fB\-\-op=\fIop\fR
-Specifies a database operator \fIop\fR. \fIop\fR must be one of
-\fInew\fR, \fIdelete\fR, \fIupdate\fR, \fIshow\fR or \fInonpersistent\fR.
-.IP
-For iface mode, \fIapply\fR and \fIapplyall\fR  are also applicable.
-.IP
-For flashnode submode of host mode, \fIlogin\fR and \fIlogout\fR are also applicable.
-.IP
-This option is valid for all modes except fw. Delete should not be used
-on a running session. If it is iscsiadm will stop the session and then delete the
-record.
-.IP
-\fInew\fR creates a new database record for a given object. In node mode, the
-\fIrecid\fR is the target name and portal (IP:port). In iface mode, the \fIrecid\fR
-is the iface name. In discovery mode, the \fIrecid\fR is the portal and
-discovery type.
-.IP
-In session mode, the \fInew\fR operation logs in a new session using
-the same node database and iface information as the specified session.
-.IP
-In discovery mode, if the \fIrecid\fR and new operation is passed in,
-but the \fI--discover\fR argument is not, then iscsiadm will only create a
-discovery record (it will not perform discovery). If the \fI--discover\fR
-argument is passed in with the portal and discovery type, then iscsiadm
-will create the discovery record if needed, and it will create records
-for portals returned by the target that do not yet have a node DB record.
-.IP
-\fIdelete\fR deletes a specified \fIrecid\fR. In discovery mode, if
-iscsiadm is performing discovery it will delete records for portals that
-are no longer returned.
-.IP
-\fIupdate\fR will update the \fIrecid\fR with \fIname\fR to the specified
-\fIvalue\fR. In discovery mode, if iscsiadm is performing discovery the
-\fIrecid\fR, \fIname\fR  and \fIvalue\fR arguments are not needed. The
-update operation will operate on the portals returned by the target,
-and will update the node records with info from the config file and
-command line.
-.IP
-\fIshow\fR is the default behaviour for node, discovery and iface mode. It is
-also used when there are no commands passed into session mode and a running
-sid is passed in.
-\fIname\fR and \fIvalue\fR are currently ignored when used with \fIshow\fR.
-.IP
-\fInonpersistent\fR instructs iscsiadm to not manipulate the node DB.
-.IP
-\fIapply\fR will cause the network settings to take effect on the specified iface.
-.IP
-\fIapplyall\fR will cause the network settings to take effect on all the
-ifaces whose MAC address or host number matches that of the specific host.
-.IP
-\fIlogin\fR will log into the specified flash node entry.
-.IP
-\fIlogout\fR does the logout from the given flash node entry.
-.TP
-\fB\-p\fR, \fB\-\-portal=\fIip[:port]\fR
-Use target portal with ip-address \fIip\fR and \fIport\fR. If port is not passed
-in the default \fIport\fR value is 3260.
-.IP
-IPv6 addresses can be specified as [ddd.ddd.ddd.ddd]:port or
-ddd.ddd.ddd.ddd.
-.IP
-Hostnames can also be used for the ip argument.
-.IP
-This option is only valid for discovery, or for node operations with
-the \fInew\fR operator.
-.IP
-This should be used along with \-\-target in node mode, to specify what
-the open-iscsi docs refer to as a node or node record. Note: open-iscsi's
-use of the word node, does not match the iSCSI RFC's iSCSI Node term.
-.TP
-\fB\-P\fR,  \fB\-\-print=\fIprintlevel\fR
-If in node mode print nodes in tree format. If in session mode print
-sessions in tree format. If in discovery mode print the nodes in
-tree format.
-.TP
-\fB\-T\fR, \fB\-\-targetname=\fItargetname\fR
-Use target \fItargetname\fR.
-.IP
-This should be used along with \-\-portal in node mode, to specify what
-the open-iscsi docs refer to as a node or node record. Note: open-iscsi's
-use of the word node, does not match the iSCSI RFC's iSCSI Node term.
-.TP
-\fB\-r\fR,  \fB\-\-sid=\fIsid | sysfsdir\fR
-Use session ID \fIsid\fR. The sid of a session can be found from running
-iscsiadm in session mode with the \-\-info argument.
-.IP
-Instead of sid, a sysfs path containing the session can be used.
-For example using one of the following:
-/sys/devices/platform/hostH/sessionS/targetH:B:I/H:B:I:L,
-/sys/devices/platform/hostH/sessionS/targetH:B:I, or
-/sys/devices/platform/hostH/sessionS, for the sysfsdir argument would
-result in the session with sid S to be used.
-.IP
-\fIsid | sysfsdir\fR is only required for session mode.
-.TP
-\fB\-R\fR,  \fB\-\-rescan\fR
-In session mode, if sid is also passed in rescan the session. If no sid has
-been passed in  rescan all running sessions.
-.IP
-In node mode, rescan a session running through the target, portal, iface
-tuple passed in.
-.TP
-\fB\-s\fR, \fB\-\-stats\fR
-Display session statistics.
-This option when used with host mode, displays host statistics.
-.TP
-\fB\-S\fR, \fB\-\-show\fR
-When displaying records, do not hide masked values, such as the CHAP
-secret (password).
-.IP
-This option is only valid for node and session mode.
-.TP
-\fB\-t\fR, \fB\-\-type=\fItype\fR
-\fItype\fR must be \fIsendtargets\fR (or abbreviated as \fIst\fR),
-\fIslp\fR, \fIisns\fR or \fIfw\fR. Currently only sendtargets, fw, and
-iSNS is supported, see the DISCOVERY TYPES section.
-.IP
-This option is only valid for discovery mode.
-.TP
-\fB\-u\fR, \fB\-\-logout\fR
-logout for a specified record.
-.IP
-This option is only valid for node and session mode.
-.TP
-\fB\-U\fR, \fB\-\-logoutall=\fI[all,manual,automatic|onboot]\fR
-logout all sessions with the node or conn startup values passed in or all
-running session, except ones marked onboot, if all is passed in.
-.IP
-This option is only valid for node mode (it is valid but not functional
-for session mode).
-.TP
-\fB\-v\fR, \fB\-\-value=\fIvalue\fR
-Specify a \fIvalue\fR for use with the \fIupdate\fR operator.
-.IP
-This option is only valid for node mode and flashnode submode of host mode.
-.TP
-\fB\-V\fR, \fB\-\-version\fR
-display version and exit
-.TP
-\fB\-x\fR, \fB\-\-index=\fIindex\fR
-Specify the \fIindex\fR of the entity to operate on.
-.IP
-This option is only valid for chap and flashnode submodes of host mode.
-.SH DISCOVERY TYPES
-iSCSI defines 3 discovery types: SendTargets, SLP, and iSNS.
-.PP
-A special discovery type called
-.I fw
-(for firmware) is also supported, for discoverying firmware interfaces,
-and populating the interface database in the process.
-.TP
-.B
-SendTargets
-A native iSCSI protocol which allows each iSCSI
-target to send a list of available targets to the initiator.
-.TP
-.B
-SLP
-Optionally an iSCSI target can use the Service Location Protocol (SLP)
-to announce the available targets. The initiator can either implement
-SLP queries directly or can use a separate tool to acquire the
-information about available targets.
-.TP
-.B
-iSNS
-iSNS (Internet Storage Name Service) records information about storage
-volumes within a larger network. To utilize iSNS, pass the address and
-optionally the port of the iSNS server to do discovery to.
-.TP
-.B
-fw
-Firmware mode.
-Several NICs and systems contain a mini iSCSI initiator which can be used
-for boot. To get the values used for boot the fw option can be used.
-Doing fw discovery, does not store persistent records in the node or
-discovery DB, because the values are stored in the system's or NIC's
-resource.
-.IP
-Performing fw discovery will print the portals, like with other discovery
-methods. To see other settings like CHAP values and initiator settings,
-like you would in node mode, run \fIiscsiadm \-m fw\fR.
-.P
-Note that the SLP implementation is under development and currently
-is not supported.
-.SH EXIT STATUS
-On success 0 is returned. On error one of the return codes below will
-be returned.
-.PP
-Commands that operate on multiple objects (sessions, records, etc),
-iscsiadm/iscsistart will return the first error that is encountered.
-iscsiadm/iscsistart will attempt to execute the operation on the objects it
-can. If no objects are found ISCSI_ERR_NO_OBJS_FOUND is returned.
-.TP
-.B
-0
-ISCSI_SUCCESS - command executed successfully.
-.TP
-.B
-1
-ISCSI_ERR - generic error code.
-.TP
-.B
-2
-ISCSI_ERR_SESS_NOT_FOUND - session could not be found.
-.TP
-.B
-3
-ISCSI_ERR_NOMEM - could not allocate resource for operation.
-.TP
-.B
-4
-ISCSI_ERR_TRANS - connect problem caused operation to fail.
-.TP
-.B
-5
-ISCSI_ERR_LOGIN - generic iSCSI login failure.
-.TP
-.B
-6
-ISCSI_ERR_IDBM - error accessing/managing iSCSI DB.
-.TP
-.B
-7
-ISCSI_ERR_INVAL - invalid argument.
-.TP
-.B
-8
-ISCSI_ERR_TRANS_TIMEOUT - connection timer exired while trying to connect.
-.TP
-.B
-9
-ISCSI_ERR_INTERNAL - generic internal iscsid/kernel failure.
-.TP
-.B
-10
-ISCSI_ERR_LOGOUT - iSCSI logout failed.
-.TP
-.B
-11
-ISCSI_ERR_PDU_TIMEOUT - iSCSI PDU timedout.
-.TP
-.B
-12
-ISCSI_ERR_TRANS_NOT_FOUND - iSCSI transport module not loaded in kernel or iscsid.
-.TP
-.B
-13
-ISCSI_ERR_ACCESS - did not have proper OS permissions to access iscsid or execute iscsiadm command.
-.TP
-.B
-14
-ISCSI_ERR_TRANS_CAPS - transport module did not support operation.
-.TP
-.B
-15
-ISCSI_ERR_SESS_EXISTS - session is logged in.
-.TP
-.B
-16
-ISCSI_ERR_INVALID_MGMT_REQ - invalid IPC MGMT request.
-.TP
-.B
-17
-ISCSI_ERR_ISNS_UNAVAILABLE - iSNS service is not supported.
-.TP
-.B
-18
-ISCSI_ERR_ISCSID_COMM_ERR - a read/write to iscsid failed.
-.TP
-.B
-19
-ISCSI_ERR_FATAL_LOGIN - fatal iSCSI login error.
-.TP
-.B
-20
-ISCSI_ERR_ISCSID_NOTCONN - could not connect to iscsid.
-.TP
-.B
-21
-ISCSI_ERR_NO_OBJS_FOUND - no records/targets/sessions/portals found to execute operation on.
-.TP
-.B
-22
-ISCSI_ERR_SYSFS_LOOKUP - could not lookup object in sysfs.
-.TP
-.B
-23
-ISCSI_ERR_HOST_NOT_FOUND - could not lookup host.
-.TP
-.B
-24
-ISCSI_ERR_LOGIN_AUTH_FAILED - login failed due to authorization failure.
-.TP
-.B
-25
-ISCSI_ERR_ISNS_QUERY - iSNS query failure.
-.TP
-.B
-26
-ISCSI_ERR_ISNS_REG_FAILED - iSNS registration/deregistration failed.
-.TP
-.B
-27
-ISCSI_ERR_OP_NOT_SUPP - operation not support
-.TP
-.B
-28
-ISCSI_ERR_BUSY - device or resource in use
-.TP
-.B
-29
-ISCSI_ERR_AGAIN - operation failed, but retrying later may succeed
-.TP
-.B
-30
-ISCSI_ERR_UNKNOWN_DISCOVERY_TYPE - unknown discovery type
-.TP
-.B
-31
-ISCSI_ERR_CHILD_TERMINATED - child process terminated
-.TP
-.B
-32
-ISCSI_ERR_SESSION_NOT_CONNECTED - session likely not connected
-.SH EXAMPLES
-Discover targets at a given IP address:
-.IP
-\fBsh#\fR iscsiadm \-\-mode discoverydb \-\-type sendtargets \-\-portal 192.168.1.10 \-\-discover
-.PP
-Login, must use a node record id found by the discovery:
-.IP
-\fBsh#\fR iscsiadm \-\-mode node \-\-targetname iqn.2001-05.com.doe:test \-\-portal 192.168.1.1:3260 \-\-login
-.PP
-Logout:
-.IP
-\fBsh#\fR iscsiadm \-\-mode node \-\-targetname iqn.2001-05.com.doe:test \-\-portal 192.168.1.1:3260 \-\-logout
-.PP
-List node records:
-.IP
-\fBsh#\fR iscsiadm \-\-mode node
-.PP
-Display all data for a given node record:
-.IP
-\fBsh#\fR iscsiadm \-\-mode node \-\-targetname iqn.2001-05.com.doe:test \-\-portal 192.168.1.1:3260
-.SH FILES
-.TP
-/etc/iscsi/iscsid.conf
-The configuration file read by \fBiscsid\fR and \fBiscsiadm\fR on startup.
-.TP
-/etc/iscsi/initiatorname.iscsi
-The file containing the iSCSI InitiatorName and InitiatorAlias read by
-\fBiscsid\fR and \fBiscsiadm\fR on startup.
-.TP
-/etc/iscsi/nodes/
-This directory contains the nodes with their targets.
-.TP
-/etc/iscsi/send_targets
-This directory contains the portals.
-.SH "SEE ALSO"
-.BR iscsid (8)
-.SH AUTHORS
-Open-iSCSI project <http://www.open-iscsi.com/>
-.br
-Alex Aizman <itn780@yahoo.com>
-.br
-Dmitry Yusupov <dmitry_yus@yahoo.com>
diff -pruN 2.1.5-1/doc/iscsiadm.8.template 2.1.7-2/doc/iscsiadm.8.template
--- 2.1.5-1/doc/iscsiadm.8.template	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/doc/iscsiadm.8.template	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,718 @@
+.TH ISCSIADM 8 "Mar 2022" "" "Linux Administrator's Manual"
+.SH NAME
+iscsiadm \- open-iscsi administration utility
+.SH SYNOPSIS
+.B iscsiadm
+.B \-m discoverydb
+.RB [ \-hV ]
+.RB [ \-d
+.IR debug_level ]
+.RB [ \-P
+.IR printlevel ]
+.RB [ \-I
+.I iface
+.BI \-t\  type\  \-p\  ip:port
+.RB [ \-lD ]
+] | [
+.RB [ \-p
+.I ip:port
+.B \-t
+.IR type ]
+.RB [ \-o
+.IR operation ]
+.RB [ \-n
+.IR name ]
+.RB [ \-v
+.IR value ]
+.RB [ \-lD ]
+]
+.PP
+.B iscsiadm
+.B \-m discovery
+.RB [ \-hV ]
+.RB [ \-d
+.IR debug_level ]
+.RB [ \-P
+.IR printlevel ]
+.RB [ \-I
+.IR iface ]
+.RB [ \-t
+.IR type ]
+.RB [ \-p
+.IR ip:port ]
+.RB [ \-l ]
+.PP
+.B iscsiadm
+.B \-m node
+.RB [ \-hV ]
+.RB [ \-d
+.IR debug_level ]
+.RB [ \-P
+.IR printlevel ]
+.RB [ \-L
+.IR all,manual,automatic,onboot ]
+.RB [ \-W ]
+.RB [ \-U
+.IR all,manual,automatic,onboot ]
+.RB [ \-S ]
+[
+.RB [ \-T
+.IB targetname\  \-p\  ip:port\  \-I
+.IR iface ]
+.RB [ \-l | \-u | \-R | \-s ]
+]
+[
+.RB [ \-o
+.IR operation ]
+.RB [ \-n
+.IR name ]
+.RB [ \-v
+.IR value ]
+.RB [ \-p
+.IR ip:port ]
+]
+.PP
+.B iscsiadm
+.B \-m session
+.RB [ \-hV ]
+.RB [ \-d
+.IR debug_level ]
+.RB [ \-P
+.IR printlevel ]
+.RB [ \-r
+.IR sessionid | sysfsdir
+.RB [ \-R ]
+.RB [ \-u | \-s | \-o
+.IR new ]
+]
+.PP
+.B iscsiadm
+.B \-m iface
+.RB [ \-hV ]
+.RB [ \-d
+.IR debug_level ]
+.RB [ \-P
+.IR printlevel ]
+.RB [ \-I
+.IR ifacename\  |
+.B \-H
+.IR hostno|MAC ]
+[
+.RB [ \-o
+.IR operation ]
+.RB [ \-n
+.IR name ]
+.RB [ \-v
+.IR value ]
+]
+[
+.BI \-C\  ping
+.RB [ \-a
+.IR ip ]
+.RB [ \-b
+.IR packetsize ]
+.RB [ \-c
+.IR count ]
+.RB [ \-i
+.IR interval ]
+]
+.PP
+.B iscsiadm
+.B \-m fw
+.RB [ \-d
+.IR debug_level ]
+.RB [ \-l ]
+.RB [ \-W ]
+.RB [ \-n
+.IR name ]
+.RB [ \-v
+.IR value ]
+.PP
+.B iscsiadm
+.B \-m host
+.RB [ \-P
+.IR printlevel ]
+.RB [ \-H
+.IR hostno|MAC ]
+[
+.RB [ \-C
+.I chap
+.RB [ \-x
+.IR chap_tbl_idx ]
+] |
+.RB [ \-C
+.I flashnode
+.RB [ \-A
+.IR portal_type ]
+.RB [ \-x
+.IR flashnode_idx ]
+] |
+.RB [ \-C
+.IR stats ]
+]
+[
+.RB [ \-o
+.IR operation ]
+.RB [ \-n
+.IR name ]
+.RB [ \-v
+.IR value ]
+]
+.PP
+.B iscsiadm
+.B \-k priority
+.SH DESCRIPTION
+The iscsiadm utility is a command-line tool allowing discovery and login
+to iSCSI targets, as well as access and management of the open-iscsi
+database.
+.PP
+Open-iscsi does not use the term \fInode\fR as defined by the iSCSI RFC,
+where a node is a single iSCSI initiator or target. Open-iscsi uses the
+term \fInode\fR to refer to a portal on a target.
+.PP
+For \fIsession\fR mode, a session id (\fIsid\fR) is used. The \fIsid\fR of a session can be
+found by running \fIiscsiadm \-m session \-P 1\fR. The session id and sysfs
+path are not currently persistent and is partially determined by when the
+session is setup.
+.SH NOTES
+.PP
+Many of the node and discovery operations require that the iSCSI
+daemon (iscsid) be running. If running on a system that uses systemd,
+the daemon may start up automatically, if enabled, when needed.
+.PP
+Open-iscsi has two groups of files it needs to store or get access to,
+while running: the \fBHOMEDIR\fR and the \fBDBROOT\fR. The following
+describes them:
+.TP
+.B Home Directory
+The \fIhome directory\fR for open-iscsi is @HOMEDIR@. This is
+where it keeps it's configuration file (\fIiscsid.conf\fR) and it's
+initiator name file (\fIinitiatorname.iscsi\fR).
+.TP
+.B Database Root Directory
+The \fIdatabase root directory\fR for open-iscsi is @DBROOT@. This
+is where it keeps its flat database files, such as it's list of \fInode\fRs
+(see below).
+.SH OPTIONS
+.TP
+\fB\-a\fR, \fB\-\-ip=\fIipaddr\fP
+\fIipaddr\fR can be IPv4 or IPv6.
+.IP
+This option is only valid for \fIping\fR submode.
+.TP
+\fB\-A\fR, \fB\-\-portal_type=\fI[ipv4|ipv6]\fR
+Specify the portal type for the new flash node entry to be created.
+.IP
+This option is only valid for \fIflashnode\fR submode of \fIhost\fR mode and only with \fInew\fR operation.
+.TP
+\fB\-b\fR, \fB\-\-packetsize=\fIpacketsize\fP
+Specify the ping \fIpacketsize\fR.
+.IP
+This option is only valid for \fIping\fR submode.
+.TP
+\fB\-c\fR, \fB\-\-count=\fIcount\fP
+\fIcount\fR specifies the number of ping iterations.
+.IP
+This option is only valid for \fIping\fR submode.
+.TP
+\fB\-C\fR, \fB\-\-submode=\fIop\fP
+Specify the submode for mode. \fIop\fR must be name of submode.
+.IP
+Currently iscsiadm supports \fIping\fR as a submode for \fIiface\fR. For example:
+.IP
+iscsiadm \-m iface \-I ifacename \-C ping \-a ipaddr \-b packetsize \-c count \-i interval
+.IP
+For \fIhost\fR, it supports \fIchap\fR, \fIflashnode\fR and \fIstats\fR as submodes. For example:
+.IP
+iscsiadm \-m host \-H hostno \-C chap \-x chap_tbl_idx \-o operation
+.IP
+iscsiadm \-m host \-H hostno \-C flashnode \-x flashnode_idx \-o operation
+.IP
+iscsiadm \-m host \-H hostno \-C stats
+.TP
+\fB\-d\fR, \fB\-\-debug=\fIdebug_level\fP
+print debugging information. Valid values for \fIdebug_level\fR are 0 to 8.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+display help text and exit
+.TP
+\fB\-H\fR, \fB\-\-host=\fI[hostno|MAC]\fR
+The \fIhost\fR argument specifies the SCSI host to use for the operation. It can be
+the scsi host number assigned to the host by the kernel's scsi layer, or the
+MAC address of a scsi host.
+.TP
+\fB\-i\fR, \fB\-\-interval=\fIinterval\fP
+\fIinterval\fP specifies the delay between two ping iterations.
+.IP
+This option is only valid for \fIping\fR submode.
+.TP
+\fB\-I\fR, \fB\-\-interface=\fI[iface]\fR
+The \fIinterface\fR argument specifies the iSCSI interface to use for the operation.
+iSCSI interfaces (\fIiface\fR) are defined in @DBROOT@/ifaces. For hardware
+iSCSI (e.g. qla4xxx) the \fIiface\fR configuration must have the hardware address
+(\fIiface.hwaddress\fR = port's MAC address)
+and the driver/transport_name (\fIiface.transport_name\fR). The \fIiface\fR's name is
+then the filename of the iface configuration. For software iSCSI, the iface configuration
+must have either the hardware address (\fIiface.hwaddress\fR), or the network
+layer's interface name (\fIiface.net_ifacename\fR), and it must have the
+driver/transport_name.
+.IP
+The available drivers/iscsi_transports are \fItcp\fR (software iSCSI over TCP/IP),
+\fIiser\fR (software iSCSI over InfiniBand),
+\fIqla4xxx\fR (Qlogic 4XXXX and 82XXX HBAs),
+\fIcxgb3i\fR and \fIcxgb4i\fR (Chelsio T3 and T4 adapters),
+\fIbnx2i\fR (QLogic Netextreme II adapters),
+\fIbe2iscsi\fR (Emulex 10G adapter),
+\fIqedi\fR (QLogic QEDI 25/40/100Gb adapter), and
+\fIocs\fR (Emulex One Connect storage).
+Some of these are considered experimental, as they are not fully tested.
+.IP
+The \fIhwaddress\fR is the MAC address or for software iSCSI it may be the special
+value \fIdefault\fR which directs the initiator to not bind the session to a
+specific hardware resource and instead allow the network or InfiniBand layer
+to decide what to do. There is no need to create an iface configuration with the default
+behavior. If you do not specify an \fIiface\fR, then the default behavior is used.
+.IP
+As mentioned above there is a special iface name \fIdefault\fR. There are
+others which do not bind the session to a specific card, but instead bind
+the session to the transport:
+\fIiser\fR,
+\fIcxgb3i\fR,
+\fIcxgb4i\fR, and
+\fIbnx2i\fR.
+.IP
+In \fIdiscovery\fR mode multiple interfaces can be specified by passing in
+multiple \fI\-I/\-\-interface\fR instances. For example:
+.IP
+\fBsh#\fR iscsiadm \-m discoverydb \-t st \-p ip:port \-I iface0 \-I iface2 \-\-discover
+.IP
+Will direct iscsiadm to setup the node db to create records which will create
+sessions through the two interfaces passed in.
+.IP
+In \fInode\fR mode, only a single interface is supported in each call to iscsiadm.
+.IP
+This option is valid for \fIdiscovery\fR, \fInode\fR and \fIiface\fR modes.
+.TP
+\fB\-k\fR, \fB\-\-killiscsid=\fI[priority]\fR
+Currently \fIpriority\fR must be zero. This will immediately stop all iscsid
+operations and shutdown iscsid. It does not logout any sessions. Running
+this command is the same as doing \fIkillall iscsid\fR. Neither should
+normally be used, because if iscsid is doing error recovery or if there
+is an error while iscsid is not running, the system may not be able to recover.
+This command and iscsid's SIGTERM handling are experimental.
+.TP
+\fB\-D\fR, \fB\-\-discover\fR
+Discover targets using the discovery record with the \fIrecid\fR matching
+the the discovery type and portal passed in. If there is no matching record,
+it will be created using the iscsid.conf discovery settings.
+This must be passed in to \fIdiscoverydb\fR mode to instruct iscsiadm to perform
+discovery.
+.IP
+This option is only valid for \fISendTargets\fR discovery mode.
+.TP
+\fB\-l\fR, \fB\-\-login\fR
+For \fInode\fR and \fIfw\fR modes, login to a specified record. For \fIdiscovery\fR mode,
+login to all discovered targets.
+.IP
+This option is only valid for \fIdiscovery\fR, \fInode\fR, and \fIfw\fR modes.
+For \fIfw\fR mode only, \fIname\fR and \fIvalue\fR pairs can optionally be passed in,
+so that those values get used for the sessions created. In this case, no \fIop\fR
+is needed, since \fIupdate\fR is assumed.
+.TP
+\fB\-L\fR, \fB\-\-loginall=\fI[all|manual|automatic|onboot]\fR
+For \fInode\fR mode, login to all sessions with the node or conn startup values passed
+in or all running session, except ones marked \fIonboot\fR, if \fIall\fR is passed in.
+.IP
+This option is only valid for \fInode\fR mode (it is valid but not functional
+for \fIsession\fR mode).
+.TP
+\fB\-W\fR, \fB\-\-\-no_wait\fR
+In \fInode\fR, \fIdiscovery\fR, or \fIfw\fR (firmware) mode,
+do not wait for a response from the target(s).
+This means that success will be returned if the command is able to
+send the login requests, whether or not they succeed. In this case, it will
+be up to the caller to poll for success (i.e. session creation).
+.TP
+\fB\-m\fR, \fB\-\-mode \fIop\fR
+specify the mode. \fIop\fR
+must be one of \fIdiscovery\fR, \fIdiscoverydb\fR, \fInode\fR, \fIfw\fR,
+\fIhost\fR, \fIiface\fR or \fIsession\fR.
+.IP
+If no other options are specified: for \fIdiscovery\fR, \fIdiscoverydb\fR and
+\fInode\fR mode, all of their respective records are displayed; for \fIsession\fR mode,
+all active sessions and connections are displayed; for \fIfw\fR mode, all boot
+firmware values are displayed; for \fIhost\fR mode, all iSCSI hosts are displayed;
+and for \fIiface\fR mode, all interfaces setup in @DBROOT@/ifaces are displayed.
+.TP
+\fB\-n\fR, \fB\-\-name=\fIname\fR
+In \fInode\fR mode, specify a field \fIname\fR in a record. In \fIflashnode\fR submode
+of \fIhost\fR mode, specify name of the flash node parameter.
+.IP
+For use with the \fIupdate\fR operator.
+.TP
+\fB\-o\fR, \fB\-\-op=\fIop\fR
+Specifies a database operator \fIop\fR. \fIop\fR must be one of
+\fInew\fR, \fIdelete\fR, \fIupdate\fR, \fIshow\fR or \fInonpersistent\fR.
+.IP
+For \fIiface\fR mode, \fIapply\fR and \fIapplyall\fR are also applicable.
+.IP
+For \fIflashnode\fR submode of \fIhost\fR mode, \fIlogin\fR and \fIlogout\fR are also applicable.
+.IP
+This option is valid for all modes except \fIfw\fR. Delete should not be used
+on a running session. If it is iscsiadm will stop the session and then delete the
+record.
+.IP
+An \fIop\fR of \fInew\fR creates a new database record for a given object. In \fInode\fR mode, the
+\fIrecid\fR is the target name and portal (IP:port). In \fIiface\fR mode, the \fIrecid\fR
+is the iface name. In \fIdiscovery\fR mode, the \fIrecid\fR is the portal and
+discovery type.
+.IP
+In \fIsession\fR mode, the \fInew\fR operation logs in a new session using
+the same node database and iface information as the specified session.
+.IP
+In \fIdiscovery\fR mode, if the \fIrecid\fR and \fInew\fR operation is passed in,
+but the \fI\-\-discover\fR argument is not passed in, then iscsiadm will only create a
+discovery record (it will not perform discovery). If the \fI\-\-discover\fR
+argument is passed in with the portal and discovery type, then iscsiadm
+will create the discovery record if needed, and it will create records
+for portals returned by the target that do not yet have a node DB record.
+.IP
+Setting \fIop\fR to \fIdelete\fR deletes the specified \fIrecid\fR. In \fIdiscovery\fR mode, if
+iscsiadm is performing discovery, it will delete records for portals that
+are no longer returned.
+.IP
+Setting \fIop\fR to \fIupdate\fR will update the \fIrecid\fR with \fIname\fR to the specified
+\fIvalue\fR. In discovery mode, if iscsiadm is performing discovery the
+\fIrecid\fR, \fIname\fR and \fIvalue\fR arguments are not needed. The
+update operation will operate on the portals returned by the target,
+and will update the node records with information from the configuration file and
+command line.
+.IP
+The \fIop\fR value of \fIshow\fR is the default behaviour for \fInode\fR,
+\fIdiscovery\fR and \fIiface\fR mode. It is
+also used when there are no commands passed into \fIsession\fR mode and a
+running \fIsid\fR is passed in.
+If \fIname\fR and \fIvalue\fR are passed in, they are currently ignored in \fIshow\fR mode.
+.IP
+An \fIop\fR value of \fInonpersistent\fR instructs iscsiadm to not manipulate the node DB.
+.IP
+An \fIop\fR value of \fIapply\fR will cause the network settings to take effect on the specified iface.
+.IP
+An \fIop\fR value of \fIapplyall\fR will cause the network settings to take effect on all the
+ifaces whose MAC address or host number matches that of the specific host.
+.IP
+An \fIop\fR value of \fIlogin\fR will log into the specified flash node entry.
+.IP
+An \fIop\fR value of \fIlogout\fR does the logout from the given flash node entry.
+.TP
+\fB\-p\fR, \fB\-\-portal=\fIip[:port]\fR
+Use target portal with IP address \fIip\fR and port \fIport\fR. If \fIport\fI is not passed
+in the default value of 3260 is used.
+.IP
+IPv6 addresses can be specified as \fI[ddd.ddd.ddd.ddd]:port\fI or \fIddd.ddd.ddd.ddd\fR.
+.IP
+Hostnames can also be used for the \fIip\fI argument.
+.IP
+This option is only valid for \fIdiscovery\fR, or for \fInode\fR operations with
+the \fInew\fR operator.
+.IP
+This should be used along with \fI\-\-target\fR in \fInode\fR mode, to specify what
+the open-iscsi documents refer to as a node or node record. Note: open-iscsi's
+use of the word node, does not match the iSCSI RFC's iSCSI Node term.
+.TP
+\fB\-P\fR, \fB\-\-print=\fIprintlevel\fR
+If in \fInode\fR mode print nodes in tree format. If in \fIsession\fR mode print
+sessions in tree format. If in \fIdiscovery\fR mode print the nodes in
+tree format.
+.TP
+\fB\-T\fR, \fB\-\-targetname=\fItargetname\fR
+Use target \fItargetname\fR.
+.IP
+This should be used along with \fI\-\-portal\fR in \fInode\fR mode, to specify what
+the open-iscsi documents refer to as a node or node record. Note: open-iscsi's
+use of the word node, does not match the iSCSI RFC's iSCSI Node term.
+.TP
+\fB\-r\fR, \fB\-\-sid=\fIsid | sysfsdir\fR
+Use session ID \fIsid\fR. The session ID of a session can be found from running
+iscsiadm in session mode with the \fI\-\-info\fR argument.
+.IP
+Instead of a session ID, a sysfs path containing the session can be used.
+For example using one of the following:
+/sys/devices/platform/hostH/sessionS/targetH:B:I/H:B:I:L,
+/sys/devices/platform/hostH/sessionS/targetH:B:I, or
+/sys/devices/platform/hostH/sessionS, for the \fIsysfsdir\fR argument would
+result in the session with session ID \fIS\fR to be used.
+.IP
+\fIsid | sysfsdir\fR is only required for \fIsession\fR mode.
+.TP
+\fB\-R\fR, \fB\-\-rescan\fR
+In \fIsession\fR mode, if \fIsid\fR is also passed in, rescan the session.
+If no \fIsid\fR has been passed in rescan all running sessions.
+.IP
+In \fInode\fR mode, rescan a session running through the target, portal, iface
+tuple passed in.
+.TP
+\fB\-s\fR, \fB\-\-stats\fR
+Display session statistics.
+This option when used with \fIhost\fR mode, displays host statistics.
+.TP
+\fB\-S\fR, \fB\-\-show\fR
+When displaying records, do not hide masked values, such as the CHAP
+secret (password).
+.IP
+This option is only valid for \fInode\fR and \fIsession\fR mode.
+.TP
+\fB\-t\fR, \fB\-\-type=\fItype\fR
+\fItype\fR must be \fIsendtargets\fR (or abbreviated as \fIst\fR),
+\fIslp\fR, \fIisns\fR or \fIfw\fR. Currently only \fIsendtargets\fR, \fIfw\fR, and
+\fIiSNS\fR are supported, see the \fBDISCOVERY TYPES\fR section.
+.IP
+This option is only valid for \fIdiscovery\fR mode.
+.TP
+\fB\-u\fR, \fB\-\-logout\fR
+Logout for the specified record.
+.IP
+This option is only valid for \fInode\fR and \fIsession\fR mode.
+.TP
+\fB\-U\fR, \fB\-\-logoutall=\fI[all,manual,automatic|onboot]\fR
+Logout of all sessions with the node or conn startup values passed in or all
+running sessions, except ones marked \fIonboot\fR, if \fIall\fR is passed in.
+.IP
+This option is only valid for \fInode\fR mode (it is valid but not functional
+for \fIsession\fR mode).
+.TP
+\fB\-v\fR, \fB\-\-value=\fIvalue\fR
+Specify a \fIvalue\fR for use with the \fIupdate\fR operator, or for firmware login mode.
+.IP
+This option is only valid for \fInode\fR mode and \fIflashnode\fR submode of \fIhost\fR mode.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Display version and exit.
+.TP
+\fB\-x\fR, \fB\-\-index=\fIindex\fR
+Specify the \fIindex\fR of the entity to operate on.
+.IP
+This option is only valid for \fIchap\fR and \fIflashnode\fR submodes of \fIhost\fR mode.
+.SH DISCOVERY TYPES
+iSCSI defines 3 discovery types: \fISendTargets\fR, \fISLP\fR, and \fIiSNS\fR.
+.PP
+A special discovery type called
+.I fw
+(for firmware) is also supported, for discovering firmware interfaces,
+and populating the interface database in the process.
+.TP
+.B
+SendTargets
+A native iSCSI protocol which allows each iSCSI
+target to send a list of available targets to the initiator.
+.TP
+.B
+SLP
+Optionally an iSCSI target can use the Service Location Protocol (SLP)
+to announce the available targets. The initiator can either implement
+SLP queries directly or can use a separate tool to acquire the
+information about available targets.
+.TP
+.B
+iSNS
+iSNS (Internet Storage Name Service) records information about storage
+volumes within a larger network. To utilize iSNS, pass the address and
+optionally the port of the iSNS server to do discovery to.
+.TP
+.B
+fw
+Firmware mode.
+Several NICs and systems contain a mini iSCSI initiator which can be used
+for boot. To get the values used for boot the \fIfw\fR option can be used.
+Doing \fIfw\fR discovery does not store persistent records in the node or
+discovery DB, because the values are stored in the system's or NIC's
+resource.
+.IP
+Performing \fIfw\fR discovery will print the portals, like with other discovery
+methods. To see other settings like CHAP values and initiator settings,
+like you would in \fInode\fR mode, run \fIiscsiadm \-m fw\fR.
+.P
+Note that the \fISLP\fR implementation is under development and currently
+is not supported.
+.SH EXIT STATUS
+On success 0 is returned. On error one of the return codes below will
+be returned.
+.PP
+Commands that operate on multiple objects (sessions, records, etc),
+iscsiadm/iscsistart will return the first error that is encountered.
+iscsiadm/iscsistart will attempt to execute the operation on the objects it
+can. If no objects are found ISCSI_ERR_NO_OBJS_FOUND is returned.
+.TP
+.B
+0
+ISCSI_SUCCESS - command executed successfully.
+.TP
+.B
+1
+ISCSI_ERR - generic error code.
+.TP
+.B
+2
+ISCSI_ERR_SESS_NOT_FOUND - session could not be found.
+.TP
+.B
+3
+ISCSI_ERR_NOMEM - could not allocate resource for operation.
+.TP
+.B
+4
+ISCSI_ERR_TRANS - connect problem caused operation to fail.
+.TP
+.B
+5
+ISCSI_ERR_LOGIN - generic iSCSI login failure.
+.TP
+.B
+6
+ISCSI_ERR_IDBM - error accessing/managing iSCSI DB.
+.TP
+.B
+7
+ISCSI_ERR_INVAL - invalid argument.
+.TP
+.B
+8
+ISCSI_ERR_TRANS_TIMEOUT - connection timer expired while trying to connect.
+.TP
+.B
+9
+ISCSI_ERR_INTERNAL - generic internal iscsid/kernel failure.
+.TP
+.B
+10
+ISCSI_ERR_LOGOUT - iSCSI logout failed.
+.TP
+.B
+11
+ISCSI_ERR_PDU_TIMEOUT - iSCSI PDU timed out.
+.TP
+.B
+12
+ISCSI_ERR_TRANS_NOT_FOUND - iSCSI transport module not loaded in kernel or iscsid.
+.TP
+.B
+13
+ISCSI_ERR_ACCESS - did not have proper OS permissions to access iscsid or execute iscsiadm command.
+.TP
+.B
+14
+ISCSI_ERR_TRANS_CAPS - transport module did not support operation.
+.TP
+.B
+15
+ISCSI_ERR_SESS_EXISTS - session is logged in.
+.TP
+.B
+16
+ISCSI_ERR_INVALID_MGMT_REQ - invalid IPC MGMT request.
+.TP
+.B
+17
+ISCSI_ERR_ISNS_UNAVAILABLE - iSNS service is not supported.
+.TP
+.B
+18
+ISCSI_ERR_ISCSID_COMM_ERR - a read/write to iscsid failed.
+.TP
+.B
+19
+ISCSI_ERR_FATAL_LOGIN - fatal iSCSI login error.
+.TP
+.B
+20
+ISCSI_ERR_ISCSID_NOTCONN - could not connect to iscsid.
+.TP
+.B
+21
+ISCSI_ERR_NO_OBJS_FOUND - no records/targets/sessions/portals found to execute operation on.
+.TP
+.B
+22
+ISCSI_ERR_SYSFS_LOOKUP - could not lookup object in sysfs.
+.TP
+.B
+23
+ISCSI_ERR_HOST_NOT_FOUND - could not lookup host.
+.TP
+.B
+24
+ISCSI_ERR_LOGIN_AUTH_FAILED - login failed due to authorization failure.
+.TP
+.B
+25
+ISCSI_ERR_ISNS_QUERY - iSNS query failure.
+.TP
+.B
+26
+ISCSI_ERR_ISNS_REG_FAILED - iSNS registration/deregistration failed.
+.TP
+.B
+27
+ISCSI_ERR_OP_NOT_SUPP - operation not support
+.TP
+.B
+28
+ISCSI_ERR_BUSY - device or resource in use
+.TP
+.B
+29
+ISCSI_ERR_AGAIN - operation failed, but retrying later may succeed
+.TP
+.B
+30
+ISCSI_ERR_UNKNOWN_DISCOVERY_TYPE - unknown discovery type
+.TP
+.B
+31
+ISCSI_ERR_CHILD_TERMINATED - child process terminated
+.TP
+.B
+32
+ISCSI_ERR_SESSION_NOT_CONNECTED - session likely not connected
+.SH EXAMPLES
+Discover targets at a given IP address:
+.IP
+\fBsh#\fR iscsiadm \-\-mode discoverydb \-\-type sendtargets \-\-portal 192.168.1.10 \-\-discover
+.PP
+Login, must use a node record id found by the discovery:
+.IP
+\fBsh#\fR iscsiadm \-\-mode node \-\-targetname iqn.2001-05.com.doe:test \-\-portal 192.168.1.1:3260 \-\-login
+.PP
+Logout:
+.IP
+\fBsh#\fR iscsiadm \-\-mode node \-\-targetname iqn.2001-05.com.doe:test \-\-portal 192.168.1.1:3260 \-\-logout
+.PP
+List node records:
+.IP
+\fBsh#\fR iscsiadm \-\-mode node
+.PP
+Display all data for a given node record:
+.IP
+\fBsh#\fR iscsiadm \-\-mode node \-\-targetname iqn.2001-05.com.doe:test \-\-portal 192.168.1.1:3260
+.SH FILES
+.TP
+@HOMEDIR@/iscsid.conf
+The configuration file read by \fBiscsid\fR and \fBiscsiadm\fR on startup.
+.TP
+@HOMEDIR@/initiatorname.iscsi
+The file containing the iSCSI InitiatorName and InitiatorAlias read by
+\fBiscsid\fR and \fBiscsiadm\fR on startup.
+.TP
+@DBROOT@/nodes/
+This directory contains the nodes with their targets.
+.TP
+@DBROOT@/send_targets
+This directory contains the portals.
+.SH "SEE ALSO"
+.BR iscsid (8)
+.SH AUTHORS
+Open-iSCSI project <http://www.open-iscsi.com/>
+.br
+Alex Aizman <itn780@yahoo.com>
+.br
+Dmitry Yusupov <dmitry_yus@yahoo.com>
diff -pruN 2.1.5-1/doc/iscsid.8 2.1.7-2/doc/iscsid.8
--- 2.1.5-1/doc/iscsid.8	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/doc/iscsid.8	1970-01-01 00:00:00.000000000 +0000
@@ -1,84 +0,0 @@
-.TH ISCSID 8 "July 2005" "" "Linux Administrator's Manual"
-.SH NAME
-iscsid \- Open-iSCSI daemon
-.SH SYNOPSIS
-.BI iscsid
-[OPTION]
-.SH "DESCRIPTION"
-The
-.B iscsid
-implements the control path of iSCSI protocol, plus some management
-facilities. For example, the daemon could be configured to automatically 
-re-start discovery at startup, based on the contents of persistent 
-iSCSI database.
-.SH OPTIONS
-.TP
-.BI [-c|--config=]\fIconfig\-file\fP
-Read configuration from \fIconfig\-file\fR rather than the default
-\fI/etc/iscsi/iscsid.conf\fR file.
-.TP
-.BI [-i|--initiatorname=]\fIiname\-file\fP
-Read initiator name from \fIiname\-file\fR rather than the default
-\fI/etc/iscsi/initiatorname.iscsi\fR file.
-.TP
-.BI [-f|--foreground]
-run
-.B iscsid
-in the foreground. Implies
-.BR --no-pid-file .
-.TP
-.BI [-d|--debug=] debug_level
-print debugging information. Valid values for debug_level are 0 to 8.
-.TP
-.BI [-u|--uid=] uid
-run under user ID \fIuid\fR (default is the current user ID).
-.TP
-.BI [-g|--gid=] gid
-run under user group ID \fIgid\fR (default is the current user group ID).
-.TP
-.BI [-n|--no-pid-file]
-do not write a process ID file. Conflicts with the
-.BI --pid=
-option.
-.TP
-.BI [-p|--pid=] pid\-file
-write process ID to \fIpid\-file\fR rather than the default
-\fI/run/iscsid.pid\fR. Conflicts with the 
-.BI --no-pid-file
-option. 
-.TP
-.BI [-h|--help]
-display this help and exit
-.TP
-.BI [-v|--version]
-display version and exit.
-
-.SH FILES
-.TP
-/etc/iscsi/iscsid.conf
-The configuration file read by
-.B iscsid
-and
-.B iscsiadm
-on startup.
-.TP
-/etc/iscsi/initiatorname.iscsi
-The file containing the iSCSI initiatorname
-and initiatoralias read by
-.B iscsid
-and
-.B iscsiadm
-on startup.
-.TP
-/etc/iscsi/nodes
-Open-iSCSI persistent configuration database
-
-.SH "SEE ALSO"
-.BR iscsiadm (8)
-
-.SH AUTHORS
-Open-iSCSI project <http://www.open-iscsi.com/>
-.br
-Alex Aizman <itn780@yahoo.com>
-.br
-Dmitry Yusupov <dmitry_yus@yahoo.com>
diff -pruN 2.1.5-1/doc/iscsid.8.template 2.1.7-2/doc/iscsid.8.template
--- 2.1.5-1/doc/iscsid.8.template	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/doc/iscsid.8.template	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,84 @@
+.TH ISCSID 8 "July 2005" "" "Linux Administrator's Manual"
+.SH NAME
+iscsid \- Open-iSCSI daemon
+.SH SYNOPSIS
+.BI iscsid
+[OPTION]
+.SH "DESCRIPTION"
+The
+.B iscsid
+implements the control path of iSCSI protocol, plus some management
+facilities. For example, the daemon could be configured to automatically 
+re-start discovery at startup, based on the contents of persistent 
+iSCSI database.
+.SH OPTIONS
+.TP
+.BI [-c|--config=]\fIconfig\-file\fP
+Read configuration from \fIconfig\-file\fR rather than the default
+\fI@HOMEDIR@/iscsid.conf\fR file.
+.TP
+.BI [-i|--initiatorname=]\fIiname\-file\fP
+Read initiator name from \fIiname\-file\fR rather than the default
+\fI@HOMEDIR@/initiatorname.iscsi\fR file.
+.TP
+.BI [-f|--foreground]
+run
+.B iscsid
+in the foreground. Implies
+.BR --no-pid-file .
+.TP
+.BI [-d|--debug=] debug_level
+print debugging information. Valid values for debug_level are 0 to 8.
+.TP
+.BI [-u|--uid=] uid
+run under user ID \fIuid\fR (default is the current user ID).
+.TP
+.BI [-g|--gid=] gid
+run under user group ID \fIgid\fR (default is the current user group ID).
+.TP
+.BI [-n|--no-pid-file]
+do not write a process ID file. Conflicts with the
+.BI --pid=
+option.
+.TP
+.BI [-p|--pid=] pid\-file
+write process ID to \fIpid\-file\fR rather than the default
+\fI/run/iscsid.pid\fR. Conflicts with the 
+.BI --no-pid-file
+option. 
+.TP
+.BI [-h|--help]
+display this help and exit
+.TP
+.BI [-v|--version]
+display version and exit.
+
+.SH FILES
+.TP
+@HOMEDIR@/iscsid.conf
+The configuration file read by
+.B iscsid
+and
+.B iscsiadm
+on startup.
+.TP
+@HOMEDIR@/initiatorname.iscsi
+The file containing the iSCSI initiatorname
+and initiatoralias read by
+.B iscsid
+and
+.B iscsiadm
+on startup.
+.TP
+@DBROOT@/nodes
+Open-iSCSI persistent configuration database
+
+.SH "SEE ALSO"
+.BR iscsiadm (8)
+
+.SH AUTHORS
+Open-iSCSI project <http://www.open-iscsi.com/>
+.br
+Alex Aizman <itn780@yahoo.com>
+.br
+Dmitry Yusupov <dmitry_yus@yahoo.com>
diff -pruN 2.1.5-1/doc/iscsi-gen-initiatorname.8.template 2.1.7-2/doc/iscsi-gen-initiatorname.8.template
--- 2.1.5-1/doc/iscsi-gen-initiatorname.8.template	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/doc/iscsi-gen-initiatorname.8.template	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,51 @@
+.TH ISCSI_GEN_INITIATORNAME 8 "APR 2022" "" "Linux Administrator's Manual"
+.SH NAME
+iscsi-gen-initiatorname \- smart iSCSI initiator name generation tool
+.SH SYNOPSIS
+.BI iscsi-gen-initiatorname
+[OPTIONS]
+.SH "DESCRIPTION"
+.B iscsi-gen-initiatorname
+generates an iSCSI Initiator Name in the
+.I initiatorname.iscsi
+file. It is an error to try to overwrite an existing Initiator Name,
+unless the \fB-f\fP (\fIforce\fR) option is supplied.
+.P
+The Initiator Name will be taken from the kernel command line,
+if present (from the \fIrd.initiatorname\fR parameter), else from
+the iBFT subsystem (if present in \fIsysfs\fR), else it will be
+generated using the \fBiscsi-iname\fR command.
+.P
+It is an error if both the kernel command-line Initiator Name
+and the iBFT Initiator Name are both set, and they are different.
+it is also an error to try to write over an Initiator Name file
+if it read-only, or to create one if its directory is not writable.
+.P
+You
+.B must
+be
+.I root
+to run this command.
+.SH OPTIONS
+.TP
+.BI [-h]
+Display a help message and exit.
+.TP
+.BI [-f]
+Force overwrite of existing initiator name, if present.
+.TP
+.BI [-p] \fIIQN-PREFIX\fP
+Use \fIIQN-PREFIX\fP as the prefix to the IQN generated,
+instead of the default of \fBiqn.1996-04.de.suse:01\fP.
+.SH FILES
+.TP
+@HOMEDIR@/initiatorname.iscsi
+The file containing the initiator name. Do not edit manually.
+.SH "SEE ALSO"
+.BR iscsi-iname (8)
+.SH AUTHORS
+Open-iSCSI project <http://www.open-iscsi.com/>
+.br
+Hannes Reinecke <hare@suse.de>
+.br
+Lee Duncan <lduncan@suse.com>
diff -pruN 2.1.5-1/doc/Makefile 2.1.7-2/doc/Makefile
--- 2.1.5-1/doc/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/doc/Makefile	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,51 @@
+# This Makefile will work only with GNU make.
+#
+# Make file for the doc sub-directory
+#
+
+ifeq ($(TOPDIR),)
+	TOPDIR = ..
+endif
+
+SED = /usr/bin/sed
+INSTALL = install
+
+DESTDIR ?=
+etcdir = /etc
+DBROOT ?= $(etcdir)/iscsi
+HOMEDIR ?= $(etcdir)/iscsi
+
+prefix ?= /usr
+mandir ?= $(prefix)/share/man
+
+MAN8DIR = $(DESTDIR)$(mandir)/man8
+
+MANPAGES_SOURCES	= iscsi_discovery.8 \
+			  iscsi_fw_login.8 \
+			  iscsi-iname.8 \
+			  iscsistart.8
+MANPAGES_TEMPLATES	= iscsid.8.template \
+			  iscsiadm.8.template \
+			  iscsi-gen-initiatorname.8
+MANPAGES_GENERATED	= $(MANPAGES_TEMPLATES:.template=)
+MANPAGES_DEST		= $(addprefix $(MAN8DIR)/,$(MANPAGES_GENERATED)) \
+			  $(addprefix $(MAN8DIR)/,$(MANPAGES_SOURCES))
+
+all: $(MANPAGES_GENERATED)
+
+install: install_doc
+
+install_doc: $(MAN8DIR) $(MANPAGES_DEST)
+
+$(MANPAGES_GENERATED): %.8: %.8.template
+	$(SED) -e 's:@HOMEDIR@:$(HOMEDIR):' -e 's:@DBROOT@:$(DBROOT):' $? > $@
+
+$(MANPAGES_DEST): $(MAN8DIR)/%: %
+	$(INSTALL) -m 644 $? $@
+
+
+$(MAN8DIR):
+	[ -d $@ ] || $(INSTALL) -d $@
+
+clean:
+	$(RM) $(MANPAGES_GENERATED)
diff -pruN 2.1.5-1/etc/initd/boot.suse 2.1.7-2/etc/initd/boot.suse
--- 2.1.5-1/etc/initd/boot.suse	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/etc/initd/boot.suse	1970-01-01 00:00:00.000000000 +0000
@@ -1,77 +0,0 @@
-#!/bin/bash
-#
-# /etc/init.d/iscsi
-#
-### BEGIN INIT INFO
-# Provides:          iscsiboot
-# Required-Start:
-# Should-Start:      boot.multipath
-# Required-Stop:
-# Should-Stop:
-# Default-Start:     B
-# Default-Stop:      
-# Short-Description: iSCSI initiator daemon root-fs support
-# Description:       Starts the iSCSI initiator daemon if the
-#                    root-filesystem is on an iSCSI device
-#               
-### END INIT INFO
-
-ISCSIADM=/sbin/iscsiadm
-CONFIG_FILE=/etc/iscsid.conf
-DAEMON=/sbin/iscsid
-ARGS="-c $CONFIG_FILE"
-
-# Source LSB init functions
-. /etc/rc.status
-
-#
-# This service is run right after booting. So all targets activated
-# during mkinitrd run should not be removed when the open-iscsi
-# service is stopped.
-#
-iscsi_mark_root_nodes()
-{
-    $ISCSIADM -m session 2> /dev/null | while read t num i target ; do
-	ip=${i%%:*}
-	STARTUP=`$ISCSIADM -m node -p $ip -T $target 2> /dev/null | grep "node.conn\[0\].startup" | cut -d' ' -f3`
-	if [ "$STARTUP" -a "$STARTUP" != "onboot" ] ; then
-	    $ISCSIADM -m node -p $ip -T $target -o update -n node.conn[0].startup -v onboot
-	fi
-    done
-}
-
-# Reset status of this service
-rc_reset
-
-# We only need to start this for root on iSCSI
-if ! grep -q iscsi_tcp /proc/modules ; then
-    rc_failed 6
-    rc_exit
-fi
-
-case "$1" in
-    start)
-	echo -n "Starting iSCSI initiator for the root device: "
-	startproc $DAEMON $ARGS
-	rc_status -v
-	iscsi_mark_root_nodes
-	;;
-    stop|restart|reload)
-	rc_failed 0
-	;;
-    status)
-	echo -n "Checking for iSCSI initiator service: "
-	if checkproc $DAEMON ; then
-	    rc_status -v
-	else
-	    rc_failed 3
-	    rc_status -v
-	fi
-	;;
-    *)
-	echo "Usage: $0 {start|stop|status|restart|reload}"
-	exit 1
-	;;
-esac
-rc_exit
-
diff -pruN 2.1.5-1/etc/initd/initd.suse 2.1.7-2/etc/initd/initd.suse
--- 2.1.5-1/etc/initd/initd.suse	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/etc/initd/initd.suse	1970-01-01 00:00:00.000000000 +0000
@@ -1,465 +0,0 @@
-#!/bin/bash
-#
-# /etc/init.d/iscsi
-#
-### BEGIN INIT INFO
-# Provides:          iscsi
-# Required-Start:    $network
-# Should-Start:      iscsitarget multipathd
-# Required-Stop:     $network
-# Should-Stop:       multipathd
-# Default-Start:     3 5
-# Default-Stop:      
-# Short-Description: iSCSI initiator daemon
-# Description:       The iSCSI initator is used to create and
-#                    manage iSCSI connections to an iSCSI Target.
-#
-### END INIT INFO
-
-CONFIG_FILE=/etc/iscsi/iscsid.conf
-DAEMON=/sbin/iscsid
-ISCSIADM=/sbin/iscsiadm
-BRCM_ISCSIUIO=/sbin/brcm_iscsiuio
-ARGS="-c $CONFIG_FILE -n"
-
-# Source LSB init functions
-. /etc/rc.status
-
-# Reset status of this service
-rc_reset
-
-DM_MAJOR=$(sed -n 's/\(.*\) device-mapper/\1/p' /proc/devices)
-
-iscsi_login_all_nodes()
-{
-	echo -n "Setting up iSCSI targets: "
-	$ISCSIADM -m node --loginall=automatic 2> /dev/null
-	if [ $? == 21 ] ; then
-	    rc_failed 6
-	fi
-	rc_status -v
-}
-
-#
-# Try to load all required modules prior to startup
-#
-iscsi_load_transport_modules()
-{
-    loaded=$(sed -n "/^iscsi_tcp/p" /proc/modules)
-    if [ -z "$loaded" ] ; then
-	modprobe iscsi_tcp
-	if [ $? = 0 ] ; then
-	    echo -n " tcp"
-	fi
-    fi
-
-    for iface in /etc/iscsi/ifaces/*; do
-	[ -f "$iface" ] || continue
-	[ "$iface" = "iface.example" ] && continue
-	# Check if the iface has been configured
-	result=$(sed '/#.*/D;/iface.iscsi_ifacename/D;/iface.hwaddress/D;/iface.transport_name/D' $iface)
-	if [ "$result" ] ; then
-	    mod=$(sed -n 's/iface.transport_name *= *\(.*\)/\1/p' $iface)
-	    loaded=$(sed -n "/^$mod/p" /proc/modules)
-	    if [ -z "$loaded" ] ; then
-		modprobe $mod
-		if [ $? = 0 ] ; then
-		    echo -n " $mod"
-		fi
-	    fi
-	fi
-    done
-}
-
-#
-# Set a temporary startmode for ifdown
-#
-iscsi_modify_if_startmode()
-{
-    local ifname=$1
-    local tmp_ifcfg=/dev/.sysconfig/network/if-$ifname
-
-    if [ -e "$tmp_ifcfg" ] ; then
-	. $tmp_ifcfg
-	if [ "$startmode" ] ; then
-	    return
-	fi
-    fi
-    : disabling shutdown on $ifname
-    echo "startmode=nfsroot" >> $tmp_ifcfg
-}
-
-iscsi_get_ifacename_from_session()
-{
-    local session=$1
-    local ifacename
-
-    ifacename=$(iscsiadm -m session -r ${session##.*/session} 2> /dev/null | \
-	sed -n 's/iface.iscsi_ifacename = \(.*\)/\1/p')
-    if [ -z "$ifacename" ] ; then
-	# Check for iBFT
-	ifacename=$(iscsiadm -m fw 2> /dev/null)
-	if [ -n "$ifacename" ] ; then
-	    ifacename="fw"
-	fi
-    fi
-    echo $ifacename
-}
-
-iscsi_get_hwaddress_from_iface()
-{
-    local iface=$1
-    local hwaddress
-
-    hwaddress=$(iscsiadm -m iface -I "$iface" 2> /dev/null | sed -n 's/iface.hwaddress = \(.*\)/\1/p')
-    [ "$hwaddress" = "<empty>" ] && hwaddress=
-
-    echo $hwaddress
-}
-
-iscsi_get_ifname_from_iface()
-{
-    local iface=$1
-    local ifname
-
-    ifname=$(iscsiadm -m iface -I "$iface" 2> /dev/null | sed -n 's/iface.net_ifacename = \(.*\)/\1/p')
-    [ "$ifname" = "<empty>" ] && ifname=
-
-    echo $ifname
-}
-
-iscsi_get_ipaddr_from_iface()
-{
-    local iface=$1
-    local ipaddr
-
-    ipaddr=$(iscsiadm -m iface -I "$iface" 2> /dev/null | sed -n 's/iface.ipaddress = \(.*\)/\1/p')
-    [ "$ipaddr" = "<empty>" ] && ipaddr=
-
-    echo $ipaddr
-}
-
-iscsi_get_ifname_from_firmware()
-{
-    local hwaddress
-
-    hwaddress=$(iscsiadm -m fw 2> /dev/null | sed -n 's/iface.net_ifacename = \(.*\)/\1/p')
-
-    echo $hwaddress
-}
-
-#
-# cxgb3i is using the HWAddress to select
-# the correct interface
-#
-iscsi_get_ifname_from_hwaddress()
-{
-    local hwaddress=$1
-
-    for if in /sys/class/net/*; do
-	[ -e "$if" ] || continue
-	read mac < $if/address
-	[ "$mac" = "$hwaddress" ] || continue
-	echo ${if##*/}
-	break
-    done
-}
-
-iscsi_get_ifname_from_ipaddr()
-{
-    local ipaddr=$1
-    local ifname
-
-    ifname=$(ip addr show to $ipaddr | sed -n 's/[0-9]*: \([^ :]*\): .*/\1/p')
-    return $ifname
-}
-
-#
-# Handle 'default' interface:
-# It is basically impossible to determine via which
-# interface the iSCSI traffic will flow, so we take
-# the easy option and ignore _all_ active interfaces
-# during shutdown
-#
-iscsi_modify_all_interfaces()
-{
-    ip link show up | sed -n '/.*LOOPBACK.*/d;s/[0-9]*: \(.*\): .*/\1/p' | while read ifname; do
-	iscsi_modify_if_startmode $ifname
-    done
-}
-
-#
-# Check iface setting and disable
-# affected network interfaces
-#
-iscsi_check_interface()
-{
-    local session=$1
-    local i h n
-
-    i=$(iscsi_get_ifacename_from_session $session)
-    [ -z "$i" ] && continue
-    if [ "$i" = "default" ] ; then
-	iscsi_modify_all_interfaces
-    elif [ "$i" = "fw" ] ; then
-	n=$(iscsi_get_ifname_from_firmware)
-    else
-	n=$(iscsi_get_ifname_from_iface $i)
-	if [ -z "$n" ] ; then
-	    h=$(iscsi_get_hwaddress_from_iface $i)
-	    if [ -n "$h" ] ; then
-		n=$(iscsi_get_ifname_from_hwaddress $h)
-	    fi
-	fi
-	if [ -z "$n" ] ; then
-	    h=$(iscsi_get_ipaddr_from_iface $i)
-	    if [ -n "$h" ] ; then
-		n=$(iscsi_get_ifname_from_ipaddr $h)
-	    fi
-	fi
-    fi
-    if [ "$n" ] ; then
-	iscsi_modify_if_startmode $n
-    fi
-}
-
-#
-# Check if device 'dev' is mounted
-# Returns the mount point on success
-#
-iscsi_check_if_mounted()
-{
-    local dev=$1
-    local d m t o x p
-
-    cat /proc/mounts | sed -ne '/^\/dev\/.*/p' | while read d m t o x; do 
-	if [ -L "$d" ] ; then
-	    d=$(readlink -f $d)
-	fi
-	[ -b "$d" ] || continue
-
-	b=$(ls -l $d | sed -n 's/.* \([0-9]*\), \([0-9]*\) .*/\1:\2/p')
-	p=$(cd -P /sys/dev/block/$b ; echo $PWD)
-
-	if [ -z "$p" ] ; then
-	    d=${d##/dev}
-	    p="/sys/block${d%%[0-9]*}"
-	fi
-
-	[ ! -d ${p} ] && continue
-
-	if [ -e $p/partition ] ; then
-	    p=$(cd -P $p/../; echo $PWD)
-	fi
-	if [ "$dev" = "${p##*/}" ] ; then
-	    echo $m
-	fi
-    done
-}
-
-#
-# Unwind block device stack
-# 
-# Stops unwinding if either no more 'holders'
-# are found or if a device is mounted
-# 
-# Unmounts top-level device and deconfigures
-# all devices down the stack
-#
-# Root fs is not unmounted
-#
-iscsi_unwind_stack()
-{
-    local p=$1
-    local d=${p##*/}
-    local u
-    local m
-
-    if [ ! -d ${p} ] ; then
-	return;
-    fi
-
-    m=$(iscsi_check_if_mounted $d)
-    if [ -z "$m" ] ; then
-	for s in $p/holders/* ; do
-	    [ -e $s ] || continue
-	    p=$(cd -P $s; echo $PWD)
-	    u=$(iscsi_unwind_stack $p)
-	    if [ "$u" ] ; then
-		echo -n "$u "
-	    fi
-	done
-    else
-	if [ "$m" = "/" ] ; then
-	    echo -n "$d "
-	    return 1
-	fi
-	if ! umount $m ; then
-	    echo -n "$d "
-	    return 1
-	fi
-    fi
-
-    if [ "${d#dm-}" != "$d" ] ; then
-	if ! dmsetup remove -j $DM_MAJOR -m ${d#dm-} 2> /dev/null ; then
-	    echo -n "$d "
-	    return 1
-	fi
-    fi
-
-    if [ "${d#md}" != "$d" ] ; then
-	if ! mdadm --manage /dev/$d --stop 2> /dev/null ; then
-	    echo -n "$d "
-	    return 1
-	fi
-    fi
-    return 0
-}
-
-#
-# Return all targets for a given session
-#
-iscsi_get_target()
-{
-    local session=$1
-    local d
-
-    for d in $session/device/target* ; do
-	[ -e "$d" ] || continue
-	echo "$d"
-    done
-}
-
-#
-# Checks all devices presented by a target
-# and tries to umount them.
-# Skip unmounting for the root fs.
-# Stops on the first device which could not be unmounted
-# and returns the mount device of that device.
-#
-iscsi_check_target()
-{
-    local t=$1
-    local d b m
-
-    for d in $t/* ; do
-	[ -d $d/block ] || continue
-	for b in $d/block/sd* ; do
-	    [ -d "$b" ] || continue
-	    m=$(iscsi_unwind_stack $b)
-	    if [ -n "$m" ] ; then
-		echo $m
-		return 1
-	    fi
-	done
-    done
-}
-
-#
-# Check all sessions for mounted devices
-# and shutdown the session if the affected
-# devices could be umounted cleanly.
-# If umount fails disable shutdown on all
-# affected network interfaces
-#
-iscsi_stop_sessions()
-{
-    local t m s i
-
-    i=0
-    for session in /sys/class/iscsi_session/session* ; do
-	[ -e "$session" ] || continue;
-	[ -e $session/device ] || continue
-	t=$(iscsi_get_target $session)
-	m=$(iscsi_check_target $t)
-	s=${session##*/session}
-	if [ -z "$m" ] ; then
-	    iscsiadm -m session -r ${s} -u
-	    i=$(( $i + 1 ))
-	else
-	    iscsi_check_interface $s
-	fi
-    done
-    echo $i
-}
-
-iscsi_list_all_nodes()
-{
-    # Check for active sessions
-    if $ISCSIADM -m session > /dev/null; then
-	return 0
-    fi
-    echo "Active connections:"
-    $ISCSIADM -m session | while read proto num PORTAL TARGET ; do
-	PORTAL=${PORTAL%,*}
-	echo -e "\t$TARGET at $PORTAL"
-    done
-}
-
-case "$1" in
-    start)
-	if checkproc $DAEMON ; then
-	    RETVAL=0
-	else
-	    echo -n "Starting iSCSI initiator service: "
-	    iscsi_load_transport_modules
-	    if grep -q bnx2i /proc/modules && [ -x $BRCM_ISCSIUIO ] ; then
-		startproc $BRCM_ISCSIUIO
-	    fi
-	    startproc $DAEMON $ARGS
-	    RETVAL=$?
-	    rc_status -v
-	fi
-	if [ "$RETVAL" == "0" ]; then
-	    iscsi_login_all_nodes
-	fi
-	;;
-    stop)
-	n=$(iscsi_stop_sessions)
-	echo -n "Stopping iSCSI initiator service: "
-	if [ "$n" ] && [ "$n" != "0" ] ; then
-	    m=$(iscsiadm -m session 2> /dev/null)
-	    if [ -z "$m" ] ; then
-		killproc -KILL $DAEMON
-		RETVAL=$?
-		if grep -q bnx2i /proc/modules && [ -x $BRCM_ISCSIUIO ]; then
-		    killproc -KILL $BRCM_ISCSIUIO
-		fi
- 		RETVAL=$?
-	    else
-		RETVAL=1
-	    fi
-	    rc_failed $RETVAL
-	    rc_status -v
-	else
-	    # umounting failed, leave initiator running
-	    rc_status -s
-	fi
-	;;
-    status)
-	echo -n "Checking for iSCSI initiator service: "
-	if checkproc $DAEMON ; then
-	    rc_status -v
-	    iscsi_list_all_nodes
-	else
-	    rc_failed 3
-	    rc_status -v
-	fi
-	;;
-    restart|reload)
-	$0 stop
-	RETVAL=$?
-	if [ "$RETVAL" != "0" ]; then
-		echo "Stopping iSCSI initiator service failed, not starting"
-		exit $RETVAL
-	fi
-	sleep 1
-	$0 start
-	;;
-    *)
-	echo "Usage: $0 {start|stop|status|restart|reload}"
-	exit 1
-	;;
-esac
-rc_exit
-
diff -pruN 2.1.5-1/etc/iscsid.conf 2.1.7-2/etc/iscsid.conf
--- 2.1.5-1/etc/iscsid.conf	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/etc/iscsid.conf	2022-05-06 17:37:21.000000000 +0000
@@ -18,10 +18,13 @@
 # maintainers. If you leave the iscsid daemon running all
 # the time then leave this attribute commented out.
 #
-# Default for Fedora and RHEL. (uncomment to activate).
+# Default for Fedora and RHEL. Uncomment to activate.
 # iscsid.startup = /bin/systemctl start iscsid.socket iscsiuio.socket
 #
-# Default if you are not using systemd (uncomment to activate)
+# Default for Debian and Ubuntu. Uncomment to activate.
+# iscsid.startup = /bin/systemctl start iscsid.socket
+#
+# Default if you are not using systemd. Uncomment to activate.
 # iscsid.startup = /usr/bin/service start iscsid
 
 # Check for active mounts on devices reachable through a session
@@ -38,10 +41,10 @@
 # Startup settings
 #*****************
 
-# To request that the iscsi initd scripts startup a session set to "automatic".
+# To request that the iscsi service scripts startup a session, use "automatic":
 # node.startup = automatic
 #
-# To manually startup the session set to "manual". The default is manual.
+# To manually startup the session, use "manual". The default is manual.
 node.startup = manual
 
 # For "automatic" startup nodes, setting this to "Yes" will try logins on each
@@ -57,9 +60,10 @@ node.leading_login = No
 # to CHAP. The default is None.
 #node.session.auth.authmethod = CHAP
 
-# To configure which CHAP algorithms to enable set
-# node.session.auth.chap_algs to a comma seperated list.
-# The algorithms should be listen with most prefered first.
+# To configure which CHAP algorithms to enable, set
+# node.session.auth.chap_algs to a comma separated list.
+# The algorithms should be listed in order of decreasing
+# preference — in particular, with the most preferred algorithm first.
 # Valid values are MD5, SHA1, SHA256, and SHA3-256.
 # The default is MD5.
 #node.session.auth.chap_algs = SHA3-256,SHA256,SHA1,MD5
@@ -74,7 +78,7 @@ node.leading_login = No
 #node.session.auth.username_in = username_in
 #node.session.auth.password_in = password_in
 
-# To enable CHAP authentication for a discovery session to the target
+# To enable CHAP authentication for a discovery session to the target,
 # set discovery.sendtargets.auth.authmethod to CHAP. The default is None.
 #discovery.sendtargets.auth.authmethod = CHAP
 
@@ -114,31 +118,36 @@ node.conn[0].timeo.login_timeout = 15
 node.conn[0].timeo.logout_timeout = 15
 
 # Time interval to wait for on connection before sending a ping.
+# The value is in seconds and the default is 5 seconds.
 node.conn[0].timeo.noop_out_interval = 5
 
 # To specify the time to wait for a Nop-out response before failing
 # the connection, edit this line. Failing the connection will
 # cause IO to be failed back to the SCSI layer. If using dm-multipath
 # this will cause the IO to be failed to the multipath layer.
+# The value is in seconds and the default is 5 seconds.
 node.conn[0].timeo.noop_out_timeout = 5
 
-# To specify the time to wait for abort response before
-# failing the operation and trying a logical unit reset edit the line.
+# To specify the time to wait for an abort response before
+# failing the operation and trying a logical unit reset, edit the line.
 # The value is in seconds and the default is 15 seconds.
 node.session.err_timeo.abort_timeout = 15
 
 # To specify the time to wait for a logical unit response
-# before failing the operation and trying session re-establishment
+# before failing the operation and trying session re-establishment,
 # edit the line.
 # The value is in seconds and the default is 30 seconds.
 node.session.err_timeo.lu_reset_timeout = 30
 
 # To specify the time to wait for a target response
-# before failing the operation and trying session re-establishment
+# before failing the operation and trying session re-establishment,
 # edit the line.
 # The value is in seconds and the default is 30 seconds.
 node.session.err_timeo.tgt_reset_timeout = 30
 
+# The value is in seconds and the default is 60 seconds.
+node.session.err_timeo.host_reset_timeout = 60
+
 
 #******
 # Retry
@@ -146,7 +155,7 @@ node.session.err_timeo.tgt_reset_timeout
 
 # To specify the number of times iscsid should retry a login
 # if the login attempt fails due to the node.conn[0].timeo.login_timeout
-# expiring modify the following line. Note that if the login fails
+# expiring, modify the following line. Note that if the login fails
 # quickly (before node.conn[0].timeo.login_timeout fires) because the network
 # layer or the target returns an error, iscsid may retry the login more than
 # node.session.initial_login_retry_max times.
@@ -160,8 +169,7 @@ node.session.err_timeo.tgt_reset_timeout
 # The default node.session.initial_login_retry_max is 8 and
 # node.conn[0].timeo.login_timeout is 15 so we have:
 #
-# node.conn[0].timeo.login_timeout * node.session.initial_login_retry_max =
-#								120 seconds
+# node.conn[0].timeo.login_timeout * node.session.initial_login_retry_max = 120s
 #
 # Valid values are any integer value. This only
 # affects the initial login. Setting it to a high value can slow
@@ -174,12 +182,12 @@ node.session.initial_login_retry_max = 8
 # session and device queue depth
 ################################
 
-# To control how many commands the session will queue set
+# To control how many commands the session will queue, set
 # node.session.cmds_max to an integer between 2 and 2048 that is also
 # a power of 2. The default is 128.
 node.session.cmds_max = 128
 
-# To control the device's queue depth set node.session.queue_depth
+# To control the device's queue depth, set node.session.queue_depth
 # to a value between 1 and 1024. The default is 32.
 node.session.queue_depth = 32
 
@@ -187,9 +195,9 @@ node.session.queue_depth = 32
 # MISC SYSTEM PERFORMANCE SETTINGS
 ##################################
 
-# For software iscsi (iscsi_tcp) and iser (ib_iser) each session
+# For software iscsi (iscsi_tcp) and iser (ib_iser), each session
 # has a thread used to transmit or queue data to the hardware. For
-# cxgb3i you will get a thread per host.
+# cxgb3i, you will get a thread per host.
 #
 # Setting the thread's priority to a lower value can lead to higher throughput
 # and lower latencies. The lowest value is -20. Setting the priority to
@@ -197,8 +205,8 @@ node.session.queue_depth = 32
 # the iscsi or scsi threads dominate the use of the CPU then you may want
 # to set this value higher.
 #
-# Note: For cxgb3i you must set all sessions to the same value, or the
-# behavior is not defined.
+# Note: For cxgb3i, you must set all sessions to the same value.
+# Otherwise the behavior is not defined.
 #
 # The default value is -20. The setting must be between -20 and 20.
 node.session.xmit_thread_priority = -20
@@ -228,28 +236,28 @@ node.session.iscsi.InitialR2T = No
 # To enable immediate data (i.e., the initiator sends unsolicited data
 # with the iSCSI command packet), uncomment the following line:
 #
-# The default is Yes
+# The default is Yes.
 node.session.iscsi.ImmediateData = Yes
 
 # To specify the maximum number of unsolicited data bytes the initiator
 # can send in an iSCSI PDU to a target, edit the following line.
 #
 # The value is the number of bytes in the range of 512 to (2^24-1) and
-# the default is 262144
+# the default is 262144.
 node.session.iscsi.FirstBurstLength = 262144
 
 # To specify the maximum SCSI payload that the initiator will negotiate
 # with the target for, edit the following line.
 #
 # The value is the number of bytes in the range of 512 to (2^24-1) and
-# the defauls it 16776192
+# the defauls it 16776192.
 node.session.iscsi.MaxBurstLength = 16776192
 
 # To specify the maximum number of data bytes the initiator can receive
 # in an iSCSI PDU from a target, edit the following line.
 #
 # The value is the number of bytes in the range of 512 to (2^24-1) and
-# the default is 262144
+# the default is 262144.
 node.conn[0].iscsi.MaxRecvDataSegmentLength = 262144
 
 # To specify the maximum number of data bytes the initiator will send
@@ -266,12 +274,12 @@ node.conn[0].iscsi.MaxXmitDataSegmentLen
 # following line.
 #
 # The value is the number of bytes in the range of 512 to (2^24-1) and
-# the default is 32768
-# 
+# the default is 32768.
 discovery.sendtargets.iscsi.MaxRecvDataSegmentLength = 32768
 
 # To allow the targets to control the setting of the digest checking,
-# with the initiator requesting a preference of enabling the checking, uncomment# one or both of the following lines:
+# with the initiator requesting a preference of enabling the checking,
+# uncomment one or both of the following lines:
 #node.conn[0].iscsi.HeaderDigest = CRC32C,None
 #node.conn[0].iscsi.DataDigest = CRC32C,None
 #
@@ -295,41 +303,40 @@ discovery.sendtargets.iscsi.MaxRecvDataS
 #
 
 # For multipath configurations, you may want more than one session to be
-# created on each iface record.  If node.session.nr_sessions is greater
+# created on each iface record. If node.session.nr_sessions is greater
 # than 1, performing a 'login' for that node will ensure that the
 # appropriate number of sessions is created.
 node.session.nr_sessions = 1
 
-# When iscsid starts up it recovers existing sessions, if possible.
+# When iscsid starts up, it recovers existing sessions (if possible).
 # If the target for a session has gone away when this occurs, the
 # iscsid daemon normally tries to reestablish each session,
 # in succession, in the background, by trying again every two
-# seconds, until all sessions are restored. This configuration
+# seconds until all sessions are restored. This configuration
 # variable can limits the number of retries for each session.
 # For example, setting reopen_max=150 would mean that each session
 # recovery was limited to about five minutes.
-# 
 node.session.reopen_max = 0
 
 #************
 # Workarounds
 #************
 
-# Some targets like IET prefer after an initiator has sent a task
-# management function like an ABORT TASK or LOGICAL UNIT RESET, that
-# it does not respond to PDUs like R2Ts. To enable this behavior uncomment
-# the following line (The default behavior is Yes):
+# Some targets like IET prefer that an initiator does not respond to PDUs like
+# R2Ts after it has sent a task management function like an ABORT TASK or a
+# LOGICAL UNIT RESET. To adopt this behavior, uncomment the following line.
+# The default is Yes.
 node.session.iscsi.FastAbort = Yes
 
-# Some targets like Equalogic prefer that after an initiator has sent
-# a task management function like an ABORT TASK or LOGICAL UNIT RESET, that
-# it continue to respond to R2Ts. To enable this uncomment this line
+# Some targets like Equalogic prefer that an initiator continue to respond to
+# R2Ts after it has sent a task management function like an ABORT TASK or a
+# LOGICAL UNIT RESET. To adopt this behavior, uncomment the following line.
 # node.session.iscsi.FastAbort = No
 
-# To prevent doing automatic scans that would add unwanted luns to the system
+# To prevent doing automatic scans that would add unwanted luns to the system,
 # we can disable them and have sessions only do manually requested scans.
 # Automatic scans are performed on startup, on login, and on AEN/AER reception
-# on devices supporting it.  For HW drivers all sessions will use the value
-# defined in the configuration file.  This configuration option is independent
-# of scsi_mod scan parameter. (The default behavior is auto):
+# on devices supporting it. For HW drivers, all sessions will use the value
+# defined in the configuration file. This configuration option is independent
+# of the scsi_mod.scan parameter. The default is auto.
 node.session.scan = auto
diff -pruN 2.1.5-1/etc/Makefile 2.1.7-2/etc/Makefile
--- 2.1.5-1/etc/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/etc/Makefile	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,111 @@
+#
+# gnu Makefile for the etc subdirectory, including
+# 	initd and systemd subdirectories
+#
+
+ifeq ($(TOPDIR),)
+	TOPDIR = ..
+endif
+
+prefix = /usr
+DESTDIR ?=
+SBINDIR ?= /sbin
+
+ISCSI_INAME ?= $(TOPDIR)/utils/iscsi-iname
+
+systemddir ?= $(prefix)/lib/systemd
+etcdir = /etc
+initddir ?= $(etcdir)/init.d
+
+HOMEDIR ?= $(etcdir)/iscsi
+
+SED = /usr/bin/sed
+INSTALL = install
+
+SYSTEMD_SOURCE_FILES	= iscsid.socket iscsiuio.socket
+SYSTEMD_SOURCES		= $(addprefix systemd/,$(SYSTEMD_SOURCE_FILES))
+SYSTEMD_TEMPLATE_FILES	= iscsi-init.service.template \
+			  iscsid.service.template \
+			  iscsi.service.template \
+			  iscsiuio.service.template
+SYSTEMD_TEMPLATES	= $(addprefix systemd/,$(SYSTEMD_TEMPLATE_FILES))
+SYSTEMD_RULES_FILES	= ibft-rule-generator
+SYSTEMD_RULES_SOURCES	= $(addprefix systemd/,$(SYSTEMD_RULES_FILES))
+SYSTEMD_GENERATED_SERVICE_FILES	= $(SYSTEMD_TEMPLATES:.template=)
+SYSTEMD_DEST_SVC_FILES	= $(addprefix $(DESTDIR)$(systemddir)/system/,$(SYSTEMD_SOURCE_FILES)) \
+			  $(addprefix $(DESTDIR)$(systemddir)/system/,$(notdir $(SYSTEMD_GENERATED_SERVICE_FILES)))
+SYSTEMD_DEST_GEN_FILES	= $(addprefix $(DESTDIR)$(systemddir)/system-generators/,$(notdir $(SYSTEMD_RULES_SOURCES)))
+IFACE_FILES		= iface.example
+IFACE_DEST_FILES	= $(addprefix $(DESTDIR)$(DBROOT)/ifaces/,$(IFACE_FILES))
+ETC_FILES		= iscsid.conf
+ETC_DEST_FILES		= $(addprefix $(DESTDIR)$(HOMEDIR)/,$(ETC_FILES))
+
+INAME_DEST_FILE		= $(DESTDIR)$(HOMEDIR)/initiatorname.iscsi
+
+all: $(SYSTEMD_SOURCES) $(SYSTEMD_GENERATED_SERVICE_FILES)
+
+$(SYSTEMD_GENERATED_SERVICE_FILES): systemd/%.service: systemd/%.service.template
+	$(SED) -e 's:@SBINDIR@:$(SBINDIR):' $? > $@
+
+install: install_systemd install_iface install_etc
+
+install_iface: $(DESTDIR)$(DBROOT)/ifaces $(IFACE_DEST_FILES)
+
+$(IFACE_DEST_FILES): $(DESTDIR)$(DBROOT)/ifaces/%: %
+	$(INSTALL) -m 644 $? $@
+
+install_etc: $(DESTDIR)$(HOMEDIR) $(ETC_DEST_FILES)
+
+$(ETC_DEST_FILES): $(DESTDIR)$(HOMEDIR)/%: %
+	$(INSTALL) -m 644 $? $@
+
+install_initd_distro = $(INSTALL) -m 755 $(1) $(DESTDIR)$(initddir)/open-iscsi/
+
+install_initd: $(DESTDIR)$(initddir)/open-iscsi
+	@if [ -f /etc/debian_version ]; then \
+		$(call install_initd_distro,initd/initd.redhat) ; \
+	elif [ -f /etc/redhat-release ]; then \
+		$(call install_initd_distro,initd/initd.debian) ; \
+	fi
+
+install_initd_redhat: $(DESTDIR)$(initddir)/open-iscsi
+	$(call install_initd_distro,initd/initd.redhat)
+
+install_initd_debian: $(DESTDIR)$(initddir)/open-iscsi
+	$(call install_initd_distro,initd/initd.debian)
+
+install_systemd: install_systemd_service_files install_systemd_generator_files
+
+install_systemd_service_files: $(DESTDIR)$(systemddir)/system $(SYSTEMD_DEST_SVC_FILES)
+
+install_systemd_generator_files: $(DESTDIR)$(systemddir)/system-generators $(SYSTEMD_DEST_GEN_FILES)
+
+$(SYSTEMD_DEST_SVC_FILES): $(DESTDIR)$(systemddir)/system/%: systemd/%
+	$(INSTALL) $? $@
+
+$(SYSTEMD_DEST_GEN_FILES): $(DESTDIR)$(systemddir)/system-generators/%: systemd/%
+	$(INSTALL) $? $@
+
+install_iname: $(DESTDIR)$(HOMEDIR) $(ISCSI_INAME)
+	if [ ! -f $(INAME_DEST_FILE) ]; then \
+		INAME="`$(ISCSI_INAME)`" ; \
+		echo "InitiatorName=$$INAME" > $(INAME_DEST_FILE) ; \
+		echo "***************************************************" ; \
+		echo "Setting InitiatorName to $$INAME" ; \
+		echo "To override edit $(INAME_DEST_FILE)" ; \
+		echo "***************************************************" ; \
+	fi
+
+$(ISCSI_INAME):
+	$(MAKE) $(MFLAGS) -c $(TOPDIR)/utils $(notdir $@)
+
+# make needed directories
+$(DESTDIR)$(systemddir)/system $(DESTDIR)$(systemddir)/system-generators $(DESTDIR)$(HOMEDIR) \
+		$(DESTDIR)$(DBROOT)/ifaces $(DESTDIR)$(initddir)/open-iscsi:
+	[ -d $@ ] || $(INSTALL) -d -m 775 $@
+
+clean:
+	$(RM) $(SYSTEMD_GENERATED_SERVICE_FILES)
+
+.PHONY: all clean install install_iface install_initd install_initd_redhat \
+	install_initd_debian install_systemd
diff -pruN 2.1.5-1/etc/systemd/.gitignore 2.1.7-2/etc/systemd/.gitignore
--- 2.1.5-1/etc/systemd/.gitignore	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/etc/systemd/.gitignore	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,4 @@
+iscsi-init.service
+iscsi.service
+iscsid.service
+iscsiuio.service
diff -pruN 2.1.5-1/etc/systemd/ibft-rule-generator 2.1.7-2/etc/systemd/ibft-rule-generator
--- 2.1.5-1/etc/systemd/ibft-rule-generator	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/etc/systemd/ibft-rule-generator	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+# Systemd rule generator for ibft interfaces
+#
+# Copyright (c) 2022 Hannes Reinecke, SUSE Labs
+# This script is licensed under the GPL.
+#
+# When booted with 'ip=ibft' dracut will rename the
+# interface to 'ibft*'. After systemd has started
+# it'll try to rename the interface yet again with
+# a persistent name.
+# But as the ibft interface is already renamed _and_
+# in use, the second renaming will fail and udev
+# will complain.
+# So add a dummy rule which signals udev the correct name
+#
+# Interface renaming happes at 80-net-setup-link.rules,
+# so we need to hook in before that.
+#
+IBFT_RULE_DIR=/run/udev/rules.d
+IBFT_RULES=${IBFT_RULE_DIR}/79-ibft.rules
+
+# ensure we have a rules directory and no rules file
+if [ -d ${IBFT_RULE_DIR} ] ; then
+    rm -f ${IBFT_RULES} 2> /dev/null
+else
+    mkdir -p ${IBFT_RULE_DIR}
+fi
+
+# create an iBFT udev rule for each iBFT NIC found
+for d in /sys/firmware/ibft/ethernet* ; do
+    [ -d "$d" ] || break
+    num="${d##*/ethernet}"
+    read mac < $d/mac
+    printf 'SUBSYSTEM=="net", KERNEL=="ibft*", ACTION=="add", DRIVERS=="?*", ATTR{address}=="%s", ATTR{type}=="1", NAME="ibft%s"\n' "$mac" "$num" >> $IBFT_RULES
+done
diff -pruN 2.1.5-1/etc/systemd/iscsid.service 2.1.7-2/etc/systemd/iscsid.service
--- 2.1.5-1/etc/systemd/iscsid.service	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/etc/systemd/iscsid.service	1970-01-01 00:00:00.000000000 +0000
@@ -1,19 +0,0 @@
-[Unit]
-Description=Open-iSCSI
-Documentation=man:iscsid(8) man:iscsiuio(8) man:iscsiadm(8)
-DefaultDependencies=no
-After=network-online.target iscsiuio.service iscsi-init.service
-Before=remote-fs-pre.target
-Wants=remote-fs-pre.target
-Requires=iscsi-init.service
-
-[Service]
-Type=notify
-NotifyAccess=main
-ExecStart=/sbin/iscsid -f
-KillMode=mixed
-Restart=on-failure
-
-[Install]
-WantedBy=multi-user.target
-Also=iscsid.socket
diff -pruN 2.1.5-1/etc/systemd/iscsid.service.template 2.1.7-2/etc/systemd/iscsid.service.template
--- 2.1.5-1/etc/systemd/iscsid.service.template	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/etc/systemd/iscsid.service.template	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,19 @@
+[Unit]
+Description=Open-iSCSI
+Documentation=man:iscsid(8) man:iscsiuio(8) man:iscsiadm(8)
+DefaultDependencies=no
+After=network-online.target iscsiuio.service iscsi-init.service
+Before=remote-fs-pre.target
+Wants=remote-fs-pre.target
+Requires=iscsi-init.service
+
+[Service]
+Type=notify
+NotifyAccess=main
+ExecStart=@SBINDIR@/iscsid -f
+KillMode=mixed
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
+Also=iscsid.socket
diff -pruN 2.1.5-1/etc/systemd/iscsi-init.service 2.1.7-2/etc/systemd/iscsi-init.service
--- 2.1.5-1/etc/systemd/iscsi-init.service	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/etc/systemd/iscsi-init.service	1970-01-01 00:00:00.000000000 +0000
@@ -1,8 +0,0 @@
-[Unit]
-Description=One time configuration for iscsi.service
-ConditionPathExists=!/etc/iscsi/initiatorname.iscsi
-
-[Service]
-Type=oneshot
-RemainAfterExit=no
-ExecStart=/usr/bin/sh -c 'echo "InitiatorName=`/usr/sbin/iscsi-iname`" > /etc/iscsi/initiatorname.iscsi'
diff -pruN 2.1.5-1/etc/systemd/iscsi-init.service.template 2.1.7-2/etc/systemd/iscsi-init.service.template
--- 2.1.5-1/etc/systemd/iscsi-init.service.template	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/etc/systemd/iscsi-init.service.template	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,19 @@
+[Unit]
+Description=One time configuration for iscsi.service
+ConditionPathExists=!/etc/iscsi/initiatorname.iscsi
+DefaultDependencies=no
+RequiresMountsFor=/etc/iscsi
+# systemd-remount-fs.service is optionally pulled in by
+# local-fs.target, don't start it here (no Wants=) but if
+# it's running wait for it to finish
+After=systemd-remount-fs.service
+
+[Install]
+# this ensures we are in the same transaction with
+# systemd-remount-fs.service
+WantedBy=systemd-remount-fs.service
+
+[Service]
+Type=oneshot
+RemainAfterExit=no
+ExecStart=/usr/bin/sh -c 'echo "InitiatorName=`@SBINDIR@/iscsi-iname`" > /etc/iscsi/initiatorname.iscsi'
diff -pruN 2.1.5-1/etc/systemd/iscsi.service 2.1.7-2/etc/systemd/iscsi.service
--- 2.1.5-1/etc/systemd/iscsi.service	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/etc/systemd/iscsi.service	1970-01-01 00:00:00.000000000 +0000
@@ -1,18 +0,0 @@
-[Unit]
-Description=Login and scanning of iSCSI devices
-Documentation=man:iscsiadm(8) man:iscsid(8)
-Before=remote-fs.target
-After=network-online.target iscsid.service
-Requires=iscsid.socket iscsi-init.service
-Wants=network-online.target
-
-[Service]
-Type=oneshot
-ExecStart=/sbin/iscsiadm -m node --loginall=automatic -W
-ExecStop=/sbin/iscsiadm -m node --logoutall=automatic
-ExecStop=/sbin/iscsiadm -m node --logoutall=manual
-SuccessExitStatus=21 15
-RemainAfterExit=true
-
-[Install]
-WantedBy=remote-fs.target
diff -pruN 2.1.5-1/etc/systemd/iscsi.service.template 2.1.7-2/etc/systemd/iscsi.service.template
--- 2.1.5-1/etc/systemd/iscsi.service.template	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/etc/systemd/iscsi.service.template	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,18 @@
+[Unit]
+Description=Login and scanning of iSCSI devices
+Documentation=man:iscsiadm(8) man:iscsid(8)
+Before=remote-fs.target
+After=network-online.target iscsid.service
+Requires=iscsid.socket iscsi-init.service
+Wants=network-online.target
+
+[Service]
+Type=oneshot
+ExecStart=@SBINDIR@/iscsiadm -m node --loginall=automatic -W
+ExecStop=@SBINDIR@/iscsiadm -m node --logoutall=automatic
+ExecStop=@SBINDIR@/iscsiadm -m node --logoutall=manual
+SuccessExitStatus=21 15
+RemainAfterExit=true
+
+[Install]
+WantedBy=remote-fs.target
diff -pruN 2.1.5-1/etc/systemd/iscsiuio.service 2.1.7-2/etc/systemd/iscsiuio.service
--- 2.1.5-1/etc/systemd/iscsiuio.service	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/etc/systemd/iscsiuio.service	1970-01-01 00:00:00.000000000 +0000
@@ -1,20 +0,0 @@
-[Unit]
-Description=iSCSI UserSpace I/O driver
-Documentation=man:iscsiuio(8)
-DefaultDependencies=no
-Conflicts=shutdown.target
-Requires=iscsid.service
-BindTo=iscsid.service
-After=network.target
-Before=remote-fs-pre.target iscsid.service
-Wants=remote-fs-pre.target
-
-[Service]
-Type=notify
-NotifyAccess=main
-ExecStart=/sbin/iscsiuio -f
-KillMode=mixed
-Restart=on-failure
-
-[Install]
-WantedBy=multi-user.target
diff -pruN 2.1.5-1/etc/systemd/iscsiuio.service.template 2.1.7-2/etc/systemd/iscsiuio.service.template
--- 2.1.5-1/etc/systemd/iscsiuio.service.template	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/etc/systemd/iscsiuio.service.template	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,20 @@
+[Unit]
+Description=iSCSI UserSpace I/O driver
+Documentation=man:iscsiuio(8)
+DefaultDependencies=no
+Conflicts=shutdown.target
+Requires=iscsid.service
+BindTo=iscsid.service
+After=network.target
+Before=remote-fs-pre.target iscsid.service
+Wants=remote-fs-pre.target
+
+[Service]
+Type=notify
+NotifyAccess=main
+ExecStart=@SBINDIR@/iscsiuio -f
+KillMode=mixed
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff -pruN 2.1.5-1/include/iscsi_err.h 2.1.7-2/include/iscsi_err.h
--- 2.1.5-1/include/iscsi_err.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/include/iscsi_err.h	2022-05-06 17:37:21.000000000 +0000
@@ -70,6 +70,8 @@ enum iscsi_error_list {
 	ISCSI_ERR_CHILD_TERMINATED	= 31,
 	/* session likely not connected */
 	ISCSI_ERR_SESSION_NOT_CONNECTED = 32,
+	/* iscsid request timed out */
+	ISCSI_ERR_REQ_TIMEDOUT = 33,
 
 	/* Always last. Indicates end of error code space */
 	ISCSI_MAX_ERR_VAL,
diff -pruN 2.1.5-1/include/iscsi_net_util.h 2.1.7-2/include/iscsi_net_util.h
--- 2.1.5-1/include/iscsi_net_util.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/include/iscsi_net_util.h	2022-05-06 17:37:21.000000000 +0000
@@ -2,7 +2,12 @@
 #define __ISCSI_NET_UTIL_h__
 
 #define ISCSI_HWADDRESS_BUF_SIZE 18
-#define ISCSIUIO_PATH "/sbin/iscsiuio"
+
+#ifndef SBINDIR
+#define SBINDIR	"/sbin"
+#endif
+
+#define ISCSIUIO_PATH SBINDIR"/iscsiuio"
 
 extern int net_get_transport_name_from_netdev(char *netdev, char *transport);
 extern int net_get_netdev_from_hwaddress(char *hwaddress, char *netdev);
diff -pruN 2.1.5-1/iscsiuio/configure.ac 2.1.7-2/iscsiuio/configure.ac
--- 2.1.5-1/iscsiuio/configure.ac	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/iscsiuio/configure.ac	2022-05-06 17:37:21.000000000 +0000
@@ -72,7 +72,7 @@ AC_ARG_WITH([systemd],
      *)   AC_MSG_ERROR([bad value $withval for --with-systemd]) ;;
      esac],[with_libsystemd=auto])
 AS_IF([test "$with_libsystemd" != no],[
-    PKG_CHECK_MODULES([LIBSYSTEMD],[libsystemd],[LDFLAGS=$LIBSYSTEMD_LIBS],[
+    PKG_CHECK_MODULES([LIBSYSTEMD],[libsystemd],[LIBS="${LIBS} $LIBSYSTEMD_LIBS"],[
         if test "$with_libsystemd" = yes; then
             AC_MSG_ERROR([could not find libsystemd using pkg-config])
 	else
diff -pruN 2.1.5-1/iscsiuio/.gitignore 2.1.7-2/iscsiuio/.gitignore
--- 2.1.5-1/iscsiuio/.gitignore	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/iscsiuio/.gitignore	2022-05-06 17:37:21.000000000 +0000
@@ -23,3 +23,5 @@ libtool
 ltmain.sh
 missing
 
+# generated man page
+iscsiuio.8.gz
diff -pruN 2.1.5-1/iscsiuio/Makefile.am 2.1.7-2/iscsiuio/Makefile.am
--- 2.1.5-1/iscsiuio/Makefile.am	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/iscsiuio/Makefile.am	2022-05-06 17:37:21.000000000 +0000
@@ -17,10 +17,14 @@ logdir = /etc/logrotate.d
 install-am: all-am
 	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install-man install-log install-brcm
 
-install-man:
-	cat docs/iscsiuio.8 | GZIP=$(GZIP_ENV) gzip -c > iscsiuio.8.gz
+install-man: $(DESTDIR)$(mandir)/man8/iscsiuio.8.gz
+
+iscsiuio.8.gz: docs/iscsiuio.8
+	gzip $(GZIP_ENV) -c < $? > $@
+
+$(DESTDIR)$(mandir)/man8/iscsiuio.8.gz: iscsiuio.8.gz
 	$(INSTALL) -d $(DESTDIR)$(mandir)/man8/
-	$(INSTALL_DATA) iscsiuio.8.gz $(DESTDIR)$(mandir)/man8/
+	$(INSTALL_DATA) $? $(DESTDIR)$(mandir)/man8/
 
 install-log:
 	$(INSTALL) -d $(DESTDIR)$(logdir)/
diff -pruN 2.1.5-1/iscsiuio/src/unix/Makefile.am 2.1.7-2/iscsiuio/src/unix/Makefile.am
--- 2.1.5-1/iscsiuio/src/unix/Makefile.am	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/iscsiuio/src/unix/Makefile.am	2022-05-06 17:37:21.000000000 +0000
@@ -27,13 +27,14 @@ iscsiuio_CFLAGS = 	$(AM_CFLAGS)		\
 			$(LIBNL_CFLAGS)		\
 			-DBYTE_ORDER=@ENDIAN@
 
-iscsiuio_LDFLAGS= 	$(AM_LDADD)		\
+iscsiuio_LIBS = 	$(AM_LIBS)		\
 			-ldl			\
 			-rdynamic		\
 			$(LIBNL_LIBS)		\
 			-lpthread
 
-iscsiuio_LDADD  = 	${top_srcdir}/src/uip/lib_iscsi_uip.a	\
+iscsiuio_LDADD  = 	$(AM_LDADD) \
+			${top_srcdir}/src/uip/lib_iscsi_uip.a	\
 			${top_srcdir}/src/apps/dhcpc/lib_apps_dhcpc.a\
 			${top_srcdir}/src/apps/brcm-iscsi/lib_apps_brcm_iscsi.a \
 			${top_srcdir}/src/unix/libs/lib_iscsiuio_hw_cnic.a
diff -pruN 2.1.5-1/iscsiuio/src/unix/nic_utils.c 2.1.7-2/iscsiuio/src/unix/nic_utils.c
--- 2.1.5-1/iscsiuio/src/unix/nic_utils.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/iscsiuio/src/unix/nic_utils.c	2022-05-06 17:37:21.000000000 +0000
@@ -1042,9 +1042,9 @@ void prepare_nic_thread(nic_t *nic)
 		LOG_INFO("Created nic thread: %s", nic->log_name);
 	}
 
-	pthread_mutex_unlock(&nic->nic_mutex);
 
 error:
+	pthread_mutex_unlock(&nic->nic_mutex);
 	return;
 }
 
diff -pruN 2.1.5-1/libopeniscsiusr/idbm.c 2.1.7-2/libopeniscsiusr/idbm.c
--- 2.1.5-1/libopeniscsiusr/idbm.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/libopeniscsiusr/idbm.c	2022-05-06 17:37:21.000000000 +0000
@@ -996,7 +996,7 @@ static void _idbm_node_rec_link(struct i
 
 	/* use the interface name passed in, if any */
 	if (iface_name)
-		strncpy((*node).iface.name, iface_name, ISCSI_MAX_IFACE_LEN);
+		strncpy((*node).iface.name, iface_name, ISCSI_MAX_IFACE_LEN-1);
 
 	/*
 	 * Note: because we do not add the iface.iscsi_ifacename to
diff -pruN 2.1.5-1/libopeniscsiusr/idbm.h 2.1.7-2/libopeniscsiusr/idbm.h
--- 2.1.5-1/libopeniscsiusr/idbm.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/libopeniscsiusr/idbm.h	2022-05-06 17:37:21.000000000 +0000
@@ -30,8 +30,12 @@
 
 #include "libopeniscsiusr/libopeniscsiusr_common.h"
 
-#define ISCSI_CONFIG_ROOT	"/etc/iscsi/"
-#define IFACE_CONFIG_DIR	ISCSI_CONFIG_ROOT"ifaces"
+#ifndef ISCSI_DB_ROOT
+#define ISCSI_DB_ROOT "/etc/iscsi"
+#endif
+
+#define	IFACE_CONFIG_DIR	ISCSI_DB_ROOT"/ifaces"
+
 #define AUTH_STR_MAX_LEN	256
 #define BOOT_NAME_MAXLEN	256
 #define IDBM_DUMP_SIZE		8192
diff -pruN 2.1.5-1/libopeniscsiusr/iface.c 2.1.7-2/libopeniscsiusr/iface.c
--- 2.1.5-1/libopeniscsiusr/iface.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/libopeniscsiusr/iface.c	2022-05-06 17:37:21.000000000 +0000
@@ -44,7 +44,10 @@
 #include "idbm.h"
 #include "default.h"
 
-#define ISCSIUIO_PATH		"/sbin/iscsiuio"
+#ifndef SBINDIR
+#define SBINDIR "/sbin"
+#endif
+#define ISCSIUIO_PATH SBINDIR "/iscsiuio"
 
 struct _iscsi_net_drv {
 	const char *net_driver_name;		// Ethernet driver.
diff -pruN 2.1.5-1/libopeniscsiusr/Makefile 2.1.7-2/libopeniscsiusr/Makefile
--- 2.1.5-1/libopeniscsiusr/Makefile	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/libopeniscsiusr/Makefile	2022-05-06 17:37:21.000000000 +0000
@@ -11,6 +11,10 @@ endif
 DESTDIR ?=
 prefix ?= /usr
 INSTALL ?= install
+exec_prefix =
+etcdir = /etc
+SBINDIR ?= $(exec_prefix)/sbin
+DBROOT ?= $(etcdir)/iscsi
 
 ifndef LIB_DIR
 	ifeq ($(shell test -d /lib64 && echo 1),1)
@@ -22,8 +26,10 @@ endif
 
 INCLUDE_DIR ?= $(prefix)/include
 PKGCONF_DIR ?= $(LIB_DIR)/pkgconfig
+MAN_DIR = $(prefix)/share/man
 
-PKG_CONFIG = /usr/bin/pkg-config
+PKG_CONFIG ?= /usr/bin/pkg-config
+SED ?= /usr/bin/sed
 
 LIBISCSI_USR_DIR=$(TOPDIR)/libopeniscsiusr
 
@@ -47,6 +53,8 @@ OBJS = context.o misc.o session.o sysfs.
 CFLAGS ?= -O2 -g
 CFLAGS += -Wall -Werror -Wextra -fvisibility=hidden -fPIC
 CFLAGS += $(shell $(PKG_CONFIG) --cflags libkmod)
+CFLAGS += -DSBINDIR=\"$(SBINDIR)\"
+CFLAGS += -DISCSI_DB_ROOT=\"$(DBROOT)\"
 
 LDFLAGS += $(shell $(PKG_CONFIG) --libs libkmod)
 
@@ -55,7 +63,6 @@ LIBADD =
 all: $(LIBS) $(LIBS_MAJOR) $(TESTS) doc
 
 $(LIBS): $(OBJS)
-	@echo CFLAGS= $(CFLAGS)
 	$(CC) $(CFLAGS) -shared -Wl,-soname=$@ -o $@ $(OBJS) $(LDFLAGS) $(LIBADD)
 	ln -sf $@ $(DEVLIB)
 
@@ -74,15 +81,23 @@ check: $(LIBS) $(TESTS)
 	sudo env LD_LIBRARY_PATH=$(LIBISCSI_USR_DIR) TESTS="$(TESTS)" \
 		tests/runtest.sh || exit 1;
 
-install: $(LIBS) $(LIBS_MAJOR)
-	$(INSTALL) -d $(DESTDIR)/$(LIB_DIR)/
-	$(INSTALL) -d $(DESTDIR)/$(INCLUDE_DIR)/
+install: install_libs install_docs install_pkg_files
+
+install_libs: $(LIBS) $(LIBS_MAJOR)
+	$(INSTALL) -d $(DESTDIR)$(LIB_DIR)/
+	$(INSTALL) -d $(DESTDIR)$(INCLUDE_DIR)/
 	$(INSTALL) $(LIBS) $(DESTDIR)$(LIB_DIR)/
-	ln -sf $(LIBS) $(DESTDIR)/$(LIB_DIR)/$(DEVLIB)
-	ln -sf $(LIBS) $(DESTDIR)/$(LIB_DIR)/$(LIBS_MAJOR)
-	$(INSTALL) $(HEADERS) $(DESTDIR)$(INCLUDE_DIR)/
+	ln -sf $(LIBS) $(DESTDIR)$(LIB_DIR)/$(DEVLIB)
+	ln -sf $(LIBS) $(DESTDIR)$(LIB_DIR)/$(LIBS_MAJOR)
+	$(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INCLUDE_DIR)/
+
+install_docs: doc
+	$(INSTALL) -d $(DESTDIR)$(MAN_DIR)/man3
+	$(INSTALL) -m 644 docs/man/*.gz $(DESTDIR)$(MAN_DIR)/man3/
+
+install_pkg_files:
 	$(INSTALL) -m 644 -D $(PKGFILE).in $(DESTDIR)$(PKGCONF_DIR)/$(PKGFILE)
-	perl -i -pe 's|__VERSION__|$(LIBNVME_VERSION)|g' \
+	perl -i -pe 's|__VERSION__|$(LIBISCSI_USR_VERSION)|g' \
 		$(DESTDIR)$(PKGCONF_DIR)/$(PKGFILE)
 	perl -i -pe 's|__LIB_DIR__|$(LIB_DIR)|g' \
 		$(DESTDIR)$(PKGCONF_DIR)/$(PKGFILE)
@@ -101,7 +116,7 @@ docs/man/$(EXTRA_MAN_FILES).gz: $(HEADER
 	    perl docs/doc-preclean.pl > "$(TEMPFILE)"
 	perl docs/kernel-doc -man "$(TEMPFILE)" | \
 	    perl docs/split-man.pl docs/man
-	-rm -f "$(TEMPFILE)"
+	-$(RM) "$(TEMPFILE)"
 	@for file in docs/man/*.3; do \
 		gzip -f $$file; \
 	done
diff -pruN 2.1.5-1/libopeniscsiusr/node.h 2.1.7-2/libopeniscsiusr/node.h
--- 2.1.5-1/libopeniscsiusr/node.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/libopeniscsiusr/node.h	2022-05-06 17:37:21.000000000 +0000
@@ -44,7 +44,7 @@ struct iscsi_node {
 	char					portal[NI_MAXHOST * 2];
 };
 
-#define NODE_CONFIG_DIR		ISCSI_CONFIG_ROOT"nodes"
+#define NODE_CONFIG_DIR		ISCSI_DB_ROOT"/nodes"
 
 /* Might be public in the future */
 __DLL_LOCAL void iscsi_node_free(struct iscsi_node *node);
diff -pruN 2.1.5-1/libopeniscsiusr/sysfs.c 2.1.7-2/libopeniscsiusr/sysfs.c
--- 2.1.5-1/libopeniscsiusr/sysfs.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/libopeniscsiusr/sysfs.c	2022-05-06 17:37:21.000000000 +0000
@@ -240,7 +240,7 @@ static int iscsi_sysfs_prop_get_ll(struc
 
 	errno_save = sysfs_read_file(file_path, buff, _INT32_STR_MAX_LEN);
 	if (errno_save != 0) {
-		if (errno_save == ENOENT) {
+		if (errno_save == ENOENT || errno_save == EINVAL) {
 			if (! ignore_error) {
 				rc = LIBISCSI_ERR_SYSFS_LOOKUP;
 				_error(ctx, "Failed to read '%s': "
diff -pruN 2.1.5-1/libopeniscsiusr/version.h 2.1.7-2/libopeniscsiusr/version.h
--- 2.1.5-1/libopeniscsiusr/version.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/libopeniscsiusr/version.h	2022-05-06 17:37:21.000000000 +0000
@@ -25,6 +25,6 @@
  * This may not be the same value as the kernel versions because
  * some other maintainer could merge a patch without going through us
  */
-#define ISCSI_VERSION_STR	"2.1.5"
+#define ISCSI_VERSION_STR	"2.1.7"
 
 #endif  /* End of __ISCSI_OPEN_USR_VERSION_H__ */
diff -pruN 2.1.5-1/Makefile 2.1.7-2/Makefile
--- 2.1.5-1/Makefile	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/Makefile	2022-05-06 17:37:21.000000000 +0000
@@ -7,32 +7,19 @@
 DESTDIR ?=
 
 prefix = /usr
-exec_prefix = /
-sbindir = $(exec_prefix)/sbin
-bindir = $(exec_prefix)/bin
+exec_prefix =
 mandir = $(prefix)/share/man
 etcdir = /etc
-initddir = $(etcdir)/init.d
-rulesdir = $(etcdir)/udev/rules.d
-systemddir = $(prefix)/lib/systemd/system
-
-MANPAGES = doc/iscsid.8 doc/iscsiadm.8 doc/iscsi_discovery.8 \
-		iscsiuio/docs/iscsiuio.8 doc/iscsi_fw_login.8 doc/iscsi-iname.8 \
-		doc/iscsistart.8
-PROGRAMS = usr/iscsid usr/iscsiadm utils/iscsi-iname iscsiuio/src/unix/iscsiuio \
-		   usr/iscsistart
-SCRIPTS = utils/iscsi_discovery utils/iscsi_fw_login utils/iscsi_offload \
-		  utils/iscsi-gen-initiatorname
-INSTALL = install
-ETCFILES = etc/iscsid.conf
-IFACEFILES = etc/iface.example
-RULESFILES = utils/50-iscsi-firmware-login.rules
-SYSTEMDFILES = etc/systemd/iscsi.service \
-			   etc/systemd/iscsi-init.service \
-			   etc/systemd/iscsid.service etc/systemd/iscsid.socket \
-			   etc/systemd/iscsiuio.service etc/systemd/iscsiuio.socket
 
-export DESTDIR prefix INSTALL
+SBINDIR = $(exec_prefix)/sbin
+HOMEDIR = $(etcdir)/iscsi
+DBROOT = $(etcdir)/iscsi
+RULESDIR = $(etcdir)/udev/rules.d
+
+INSTALL = /usr/bin/install
+
+# pass these on to sub-Makefiles
+export DESTDIR prefix INSTALL SBINDIR HOMEDIR DBROOT RULESDIR
 
 # Compatibility: parse old OPTFLAGS argument
 ifdef OPTFLAGS
@@ -59,13 +46,17 @@ endif
 
 all: user
 
+make_utils:
+	$(MAKE) $(MFLAGS) -C utils
+
 user: iscsiuio/Makefile
-	$(MAKE) -C libopeniscsiusr
-	$(MAKE) -C utils/sysdeps
-	$(MAKE) -C utils/fwparam_ibft
-	$(MAKE) -C usr
-	$(MAKE) -C utils
-	$(MAKE) -C iscsiuio
+	$(MAKE) $(MFLAGS) -C libopeniscsiusr
+	$(MAKE) $(MFLAGS) -C utils/sysdeps
+	$(MAKE) $(MFLAGS) -C usr
+	$(MAKE) $(MFLAGS) -C utils
+	$(MAKE) $(MFLAGS) -C etc
+	$(MAKE) $(MFLAGS) -C iscsiuio
+	$(MAKE) $(MFLAGS) -C doc
 	@echo
 	@echo "Compilation complete                 Output file"
 	@echo "-----------------------------------  ----------------"
@@ -78,105 +69,62 @@ user: iscsiuio/Makefile
 	@echo "Read README file for detailed information."
 
 iscsiuio/Makefile: iscsiuio/configure iscsiuio/Makefile.in
-	cd iscsiuio; ./configure $(WITHOUT_ARG)
+	cd iscsiuio; ./configure $(WITHOUT_ARG) --sbindir=$(SBINDIR)
 
-iscsiuio/configure iscsiuio/Makefile.in: iscsiuio/configure.ac iscsiuio/Makefile.am
+iscsiuio/configure: iscsiuio/configure.ac iscsiuio/Makefile.am
 	cd iscsiuio; autoreconf --install
 
 force: ;
 
 clean:
-	$(MAKE) -C utils/sysdeps clean
-	$(MAKE) -C utils/fwparam_ibft clean
-	$(MAKE) -C utils clean
-	$(MAKE) -C usr clean
-	$(MAKE) -C libopeniscsiusr clean
-	[ ! -f iscsiuio/Makefile ] || $(MAKE) -C iscsiuio clean
-	[ ! -f iscsiuio/Makefile ] || $(MAKE) -C iscsiuio distclean
+	$(MAKE) $(MFLAGS) -C utils/sysdeps clean
+	$(MAKE) $(MFLAGS) -C utils clean
+	$(MAKE) $(MFLAGS) -C usr clean
+	$(MAKE) $(MFLAGS) -C etc clean
+	$(MAKE) $(MFLAGS) -C libopeniscsiusr clean
+	[ ! -f iscsiuio/Makefile ] || $(MAKE) $(MFLAGS) -C iscsiuio clean
+	[ ! -f iscsiuio/Makefile ] || $(MAKE) $(MFLAGS) -C iscsiuio distclean
 
 # this is for safety
 # now -jXXX will still be safe
 # note that make may still execute the blocks in parallel
 .NOTPARALLEL: install_user install_programs install_initd \
-	install_initd_suse install_initd_redhat install_initd_debian \
-	install_etc install_iface install_doc install_iname
+	install_initd_redhat install_initd_debian \
+	install_doc install_iname install_etc install_etc_all
+
+install: install_programs install_doc \
+	install_systemd install_iname install_libopeniscsiusr \
+	install_iscsiuio install_etc_all
 
-install: install_programs install_doc install_etc \
-	install_initd install_iname install_iface install_libopeniscsiusr
+install_iscsiuio:
+	$(MAKE) $(MFLAGS) -C iscsiuio install
 
-install_user: install_programs install_doc install_etc \
-	install_initd install_iname install_iface
+install_user: install_programs install_doc install_systemd install_iname
 
 install_udev_rules:
-	$(INSTALL) -d $(DESTDIR)$(rulesdir)
-	$(INSTALL) -m 644 $(RULESFILES) $(DESTDIR)/$(rulesdir)
+	$(MAKE) $(MFLAGS) -C utils $@
+
+install_programs:
+	$(MAKE) $(MFLAGS) -C utils install
+	$(MAKE) $(MFLAGS) -C usr install
+
+install_initd install_initd_redhat install_initd_debian install_iface install_systemd install_etc install_iname:
+	$(MAKE) $(MFLAGS) -C etc $@
+
+install_etc_all:
+	$(MAKE) $(MFLAGS) -C etc install
 
-install_systemd:
-	$(INSTALL) -d $(DESTDIR)$(systemddir)
-	$(INSTALL) -m 644 $(SYSTEMDFILES) $(DESTDIR)/$(systemddir)
-
-install_programs:  $(PROGRAMS) $(SCRIPTS)
-	$(INSTALL) -d $(DESTDIR)$(sbindir)
-	$(INSTALL) -m 755 $^ $(DESTDIR)$(sbindir)
-
-# ugh, auto-detection is evil
-# Gentoo maintains their own init.d stuff
-install_initd:
-	if [ -f /etc/debian_version ]; then \
-		$(MAKE) install_initd_debian ; \
-	elif [ -f /etc/redhat-release ]; then \
-		$(MAKE) install_initd_redhat ; \
-	elif [ -f /etc/SuSE-release ]; then \
-		$(MAKE) install_initd_suse ; \
-	fi
-
-# these are external targets to allow bypassing distribution detection
-install_initd_suse:
-	$(INSTALL) -d $(DESTDIR)$(initddir)
-	$(INSTALL) -m 755 etc/initd/initd.suse \
-		$(DESTDIR)$(initddir)/open-iscsi
-	$(INSTALL) -m 755 etc/initd/boot.suse \
-		$(DESTDIR)$(initddir)/boot.open-iscsi
-
-install_initd_redhat:
-	$(INSTALL) -d $(DESTDIR)$(initddir)
-	$(INSTALL) -m 755 etc/initd/initd.redhat \
-		$(DESTDIR)$(initddir)/open-iscsi
-
-install_initd_debian:
-	$(INSTALL) -d $(DESTDIR)$(initddir)
-	$(INSTALL) -m 755 etc/initd/initd.debian \
-		$(DESTDIR)$(initddir)/open-iscsi
-
-install_iface: $(IFACEFILES)
-	$(INSTALL) -d $(DESTDIR)$(etcdir)/iscsi/ifaces
-	$(INSTALL) -m 644 $^ $(DESTDIR)$(etcdir)/iscsi/ifaces
-
-install_etc: $(ETCFILES)
-	if [ ! -f $(DESTDIR)/etc/iscsi/iscsid.conf ]; then \
-		$(INSTALL) -d $(DESTDIR)$(etcdir)/iscsi ; \
-		$(INSTALL) -m 644 $^ $(DESTDIR)$(etcdir)/iscsi ; \
-	fi
-
-install_doc: $(MANPAGES)
-	$(INSTALL) -d $(DESTDIR)$(mandir)/man8
-	$(INSTALL) -m 644 $^ $(DESTDIR)$(mandir)/man8
-
-install_iname:
-	if [ ! -f $(DESTDIR)/etc/iscsi/initiatorname.iscsi ]; then \
-		echo "InitiatorName=`$(DESTDIR)/sbin/iscsi-iname`" > $(DESTDIR)/etc/iscsi/initiatorname.iscsi ; \
-		echo "***************************************************" ; \
-		echo "Setting InitiatorName to `cat $(DESTDIR)/etc/iscsi/initiatorname.iscsi`" ; \
-		echo "To override edit $(DESTDIR)/etc/iscsi/initiatorname.iscsi" ; \
-		echo "***************************************************" ; \
-	fi
+install_doc:
+	$(MAKE) $(MFLAGS) -C doc $@
 
 install_libopeniscsiusr:
-	$(MAKE) -C libopeniscsiusr install
+	$(MAKE) $(MFLAGS) -C libopeniscsiusr install
 
 depend:
-	for dir in usr utils utils/fwparam_ibft; do \
-		$(MAKE) -C $$dir $@; \
+	for dir in usr utils utils/fwparam_ibft utils/sysdeps; do \
+		$(MAKE) $(MFLAGS) -C $$dir $@; \
 	done
 
-# vim: ft=make tw=72 sw=4 ts=4:
+.PHONY: all user install force clean install_user install_udev_rules install_systemd \
+	install_programs install_initrd install_initrd_redhat install_initrd_debian \
+	install_doc install_iname install_libopeniscsiusr install_etc install_ec_all
diff -pruN 2.1.5-1/README 2.1.7-2/README
--- 2.1.5-1/README	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/README	2022-05-06 17:37:21.000000000 +0000
@@ -4,7 +4,7 @@
 
 =================================================================
 
-                                                   Sep 29, 2016
+                                                   Mar 30, 2022
 Contents
 ========
 
@@ -73,7 +73,7 @@ Linux operating system with kernel versi
 2.6.15 are partially supported. Known issues with 2.6.14 - .15 support:
 
 - If the device is using a write back cache, during session logout
-the cache sync command will fail.
+  the cache sync command will fail.
 - iscsiadm's -P 3 option will not print out scsi devices.
 - iscsid will not automatically online devices.
 
@@ -100,53 +100,31 @@ By default the kernel's iSCSI modules wi
 	make
 	make install
 
-will install the iSCSI tools iscsiadm and iscsid to /sbin.
-
-For 2.6.14 - 2.6.34 the modules in the kernel dir can be built and installed
-by running:
-
-	make kernel
-
-When building those modules the kernel source found at
-	/lib/modules/`uname -r`/build
-
-will be used to compile the open-iscsi modules. To specify a different
-kernel to build against, use:
-	make kernel KSRC=<kernel-src>
-
-or to use cross-compilation:
-	make kernel KSRC=<kernel-src> KARCH="ARCH=um"
-
-To compile on SUSE Linux you'll have to use
-
-	make kernel KSRC=/usr/src/linux \
-	     KBUILD_OUTPUT=/usr/src/linux-obj/<arch>/<config>
-
-where <config> is the kernel configuration to use (eg. 'smp').
-
-To install the kernel modules that were built, run:
-
-	make install_kernel
-
-This will copy iscsi_tcp.ko, libiscsi_tcp.ko, libiscsi.ko and
-scsi_transport_iscsi.ko to
-	/lib/modules/`uname -r`/kernel/drivers/scsi/
-overwriting existing iscsi modules.
-
-For Debian, be sure to install the linux-headers package that
-corresponds to your kernel in order to compile the kernel modules
-('aptitude install linux-headers-`uname -r`').  You may also wish to
-run 'make -C kernel/ dpkg_divert' before installing kernel modules if
-you run a Debian-provided kernel.  This will use dpkg-divert(8) to
-move the packaged kernel modules out of the way, and ensure that
-future kernel upgrades will not overwrite them.
-
-Also, please be aware that the compatibility patches that enable these
-iscsi modules to run on kernels older than 2.6.25 will not update the
-ib_iser module; you may get warnings related to mismatched symbols on
-this driver, in which case you'll be unable to load ib_iser and
-open-iscsi simultaneously.
-
+will install the iSCSI tools iscsiadm and iscsid to /sbin, by default,
+though that location can be overridden by passing in "SBINDIR", e.g. to
+install in /usr/bin instead of /sbin:
+
+	make SBINDIR="/usr/sbin"
+
+The default home directory for open-iscsi is /etc/iscsi. This
+directory is used for the open-iscsi database, and for the initiator
+name file initiatorname.iscsi and for the configuration file iscsid.conf.
+You can override these with two "make" parameters "HOMEDIR", for the
+initiator name and configuration files, and "DBROOT" for the open-iscsi
+databases. Both of these default to "/etc/iscsi". For example, the following
+would location the database file under /usr/lib/iscsi and leave the
+configuration and initiator name files in /etc/iscsi:
+
+	make DBROOT=/var/lib/iscsi
+
+To build and install iscsiuio, use something like:
+
+	cd iscsiuio
+	touch AUTHORS NEWS
+	autoreconf --install
+	./configure [--sbindir="/usr/sbin"]
+	make
+	make install
 
 4. Open-iSCSI daemon
 ====================
@@ -159,15 +137,18 @@ iSCSI database (see next section).
 For help, run:
 	iscsid --help
 
-The output will be similar to the following.
+The output will be similar to the following (assuming a default install):
 
 Usage: iscsid [OPTION]
 
   -c, --config=[path]     Execute in the config file (/etc/iscsi/iscsid.conf).
+  -i, --initiatorname=[path]     read initiatorname from file (/etc/iscsi/initiatorname.iscsi).
   -f, --foreground        run iscsid in the foreground
   -d, --debug debuglevel  print debugging information
   -u, --uid=uid           run as uid, default is current user
   -g, --gid=gid           run as gid, default is current user group
+  -n, --no-pid-file       do not use a pid file
+  -p, --pid=pidfile       use pid file (default /run/iscsid.pid).
   -h, --help              display this help and exit
   -v, --version           display version and exit
 
@@ -178,7 +159,8 @@ Usage: iscsid [OPTION]
 Open-iSCSI persistent configuration is stored in a number of
 directories under a configuration root directory, using a flat-file
 format. This configuration root directory is /etc/iscsi by default,
-but may also commonly be in /var/lib/iscsi.
+but may also commonly be in /var/lib/iscsi (see "DBROOT" in the Make
+options discussed earlier).
 
 Configuration is contained in directories for:
 
@@ -216,13 +198,13 @@ For help, run:
 
 The output will be similar to the following.
 
-iscsiadm -m discoverydb [ -hV ] [ -d debug_level ] [-P printlevel] [ -t type -p ip:port -I ifaceN ... [ -Dl ] ] | [ [ -p ip:port -t type] [ -o operation ] [ -n name ] [ -v value ] [ -lD ] ] 
-iscsiadm -m discovery [ -hV ] [ -d debug_level ] [-P printlevel] [ -t type -p ip:port -I ifaceN ... [ -l ] ] | [ [ -p ip:port ] [ -l | -D ] ] 
-iscsiadm -m node [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -L all,manual,automatic ] [ -W ] [ -U all,manual,automatic ] [ -S ] [ [ -T targetname -p ip:port -I ifaceN ] [ -l | -u | -R | -s] ] [ [ -o  operation  ] [ -n name ] [ -v value ] ]
-iscsiadm -m session [ -hV ] [ -d debug_level ] [ -P  printlevel] [ -r sessionid | sysfsdir [ -R | -u | -s ] [ -o operation ] [ -n name ] [ -v value ] ]
-iscsiadm -m iface [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -I ifacename | -H hostno|MAC ] [ [ -o  operation  ] [ -n name ] [ -v value ] ] [ -C ping [ -a ip ] [ -b packetsize ] [ -c count ] [ -i interval ] ]
-iscsiadm -m fw [ -d debug_level ] [ -l ]
-iscsiadm -m host [ -P printlevel ] [ -H hostno|MAC ] [ [ -C chap [ -x chap_tbl_idx ] ] | [ -C flashnode [ -A portal_type ] [ -x flashnode_idx ] ] | [ -C stats ] ] [ [ -o operation ] [ -n name ] [ -v value ] ] 
+iscsiadm -m discoverydb [-hV] [-d debug_level] [-P printlevel] [-t type -p ip:port -I ifaceN ... [-Dl]] | [[-p ip:port -t type] [-o operation] [-n name] [-v value] [-lD]]
+iscsiadm -m discovery [-hV] [-d debug_level] [-P printlevel] [-t type -p ip:port -I ifaceN ... [-l]] | [[-p ip:port] [-l | -D]] [-W]
+iscsiadm -m node [-hV] [-d debug_level] [-P printlevel] [-L all,manual,automatic,onboot] [-W] [-U all,manual,automatic,onboot] [-S] [[-T targetname -p ip:port -I ifaceN] [-l | -u | -R | -s]] [[-o operation ] [-n name] [-v value]]
+iscsiadm -m session [-hV] [-d debug_level] [-P printlevel] [-r sessionid | sysfsdir [-R | -u | -s] [-o operation] [-n name] [-v value]]
+iscsiadm -m iface [-hV] [-d debug_level] [-P printlevel] [-I ifacename | -H hostno|MAC] [[-o operation ] [-n name] [-v value]] [-C ping [-a ip] [-b packetsize] [-c count] [-i interval]]
+iscsiadm -m fw [-d debug_level] [-l] [-W] [[-n name] [-v value]]
+iscsiadm -m host [-P printlevel] [-H hostno|MAC] [[-C chap [-x chap_tbl_idx]] | [-C flashnode [-A portal_type] [-x flashnode_idx]] | [-C stats]] [[-o operation] [-n name] [-v value]]
 iscsiadm -k priority
 
 
@@ -1127,10 +1109,12 @@ Host mode with stats submode
 6. Configuration
 ================
 
-The default configuration file is /etc/iscsi/iscsid.conf. This file contains
-only configuration that could be overwritten by iSCSI Discovery,
-or manualy updated via iscsiadm utility. Its OK if this file does not
-exist, in which case compiled-in default configuration will take place
+The default configuration file is /etc/iscsi/iscsid.conf, but the
+directory is configurable with the top-level make option "homedir".
+The remainder of this document will assume the /etc/iscsi directory.
+This file contains only configuration that could be overwritten by iSCSI
+discovery, or manualy updated via iscsiadm utility. Its OK if this file
+does not exist, in which case compiled-in default configuration will take place
 for newer discovered Target nodes.
 
 See the man page and the example file for the current syntax.
@@ -1198,7 +1182,7 @@ After that, start iSCSI as a daemon proc
 
 or alternatively, start it with debug enabled, in a seperate window,
 which will force it into "foreground" mode:
-	iscsid -d 8 
+	iscsid -d 8
 
 
 7.1.2.2 Logging into Targets
diff -pruN 2.1.5-1/test/harness/tests.py 2.1.7-2/test/harness/tests.py
--- 2.1.5-1/test/harness/tests.py	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/test/harness/tests.py	2022-05-06 17:37:21.000000000 +0000
@@ -5,12 +5,41 @@ tests -- the actual TestCase (just one)
 import sys
 import os
 import unittest
+import time
 
 from . import util
 from .util import Global
 from .iscsi import IscsiData
 
 
+def s2dt(s):
+    # seconds to "HH:MM:SS.sss"
+    s_orig = s
+    hrs = s / 3600
+    s -= (int(hrs) * 3600)
+    mins = s / 60
+    s -= (int(mins) * 60)
+    a_str="%02d:%02d:%06.3f" % (hrs, mins, s)
+    dprint("s2dt: %f -> %s" % (s_orig, a_str))
+    return a_str
+
+
+def print_time_values():
+    # print out global exec time values
+    util.vprint('')
+    util.vprint('Times spent running sub-programs:')
+    ttl_time = 0.0
+    for s in Global.timing.keys():
+        v = Global.timing[s]
+        r = s2dt(v)
+        ttl_time += v
+        util.vprint('  %10s = %s' % (s, r))
+    util.vprint('    =======================')
+    util.vprint('  %10s = %s' % ('Total', s2dt(ttl_time)))
+    util.vprint('')
+    util.vprint('Total test-run time: %s' % (s2dt(Global.total_time)))
+
+
 class TestRegression(unittest.TestCase):
     """
     Regression testing
@@ -18,7 +47,7 @@ class TestRegression(unittest.TestCase):
 
     @classmethod
     def setUpClass(cls):
-        util.verify_needed_commands_exist(['parted', 'fio', 'mkfs', 'bonnie++', 'sgdisk', 'iscsiadm'])
+        util.verify_needed_commands_exist(['parted', 'fio', Global.MKFSCMD[0], 'bonnie++', 'sgdisk', 'iscsiadm'])
         util.vprint('*** Starting %s' % cls.__name__)
         # XXX validate that target exists?
         # an array of first burts, max burst, and max recv values, for testing
@@ -38,6 +67,7 @@ class TestRegression(unittest.TestCase):
                             [4096, 4096, 32768],
                             [4096, 4096, 65536],
                             [4096, 4096, 131072]]
+        cls.time_start = time.perf_counter()
 
     def setUp(self):
         if Global.debug or Global.verbosity > 1:
@@ -57,11 +87,11 @@ class TestRegression(unittest.TestCase):
         """Test Initial Request to Transmit on, but Immediate Data off"""
         i = 1
         for v in self.param_values:
-            with self.subTest('Testing FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v), i=i):
+            with self.subTest('Testing FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v), i=i):
                 if i not in Global.subtest_list:
-                    util.vprint('Skipping subtest %d: FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v) % i)
+                    util.vprint('Skipping subtest %d: FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v) % i)
                 else:
-                    util.vprint('Running subtest %d: FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v) % i)
+                    util.vprint('Running subtest %d: FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v) % i)
                     self.iscsi_logout()
                     iscsi_data = IscsiData('No', 'Yes', 'None', 'None', v[0], v[1], v[2])
                     iscsi_data.update_cfg(Global.target, Global.ipnr)
@@ -72,10 +102,11 @@ class TestRegression(unittest.TestCase):
         """Test Initial Request to Transmit off, Immediate Data on"""
         i = 1
         for v in self.param_values:
-            with self.subTest('Testing FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v), i=i):
+            with self.subTest('Testing FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v), i=i):
                 if i not in Global.subtest_list:
-                    util.vprint('Skipping subtest %d: FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v) % i)
+                    util.vprint('Skipping subtest %d: FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v) % i)
                 else:
+                    util.vprint('Running subtest %d: FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v) % i)
                     self.iscsi_logout()
                     iscsi_data = IscsiData('Yes', 'No', 'None', 'None', v[0], v[1], v[2])
                     iscsi_data.update_cfg(Global.target, Global.ipnr)
@@ -86,11 +117,11 @@ class TestRegression(unittest.TestCase):
         """Test Initial Request to Transmit and Immediate Data on"""
         i = 1
         for v in self.param_values:
-            with self.subTest('Testing FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v), i=i):
+            with self.subTest('Testing FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v), i=i):
                 if i not in Global.subtest_list:
-                    util.vprint('Skipping subtest %d: FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v) % i)
+                    util.vprint('Skipping subtest %d: FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v) % i)
                 else:
-                    util.vprint('Running subtest %d: FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v) % i)
+                    util.vprint('Running subtest %d: FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v) % i)
                     self.iscsi_logout()
                     iscsi_data = IscsiData('Yes', 'Yes', 'None', 'None', v[0], v[1], v[2])
                     iscsi_data.update_cfg(Global.target, Global.ipnr)
@@ -101,11 +132,11 @@ class TestRegression(unittest.TestCase):
         """Test Initial Request to Transmit and Immediate Data off"""
         i = 1
         for v in self.param_values:
-            with self.subTest('Testing FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v), i=i):
+            with self.subTest('Testing FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v), i=i):
                 if i not in Global.subtest_list:
-                    util.vprint('Skipping subtest %d: FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v) % i)
+                    util.vprint('Skipping subtest %d: FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v) % i)
                 else:
-                    util.vprint('Running subtest %d: FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v) % i)
+                    util.vprint('Running subtest %d: FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v) % i)
                     self.iscsi_logout()
                     iscsi_data = IscsiData('No', 'No', 'None', 'None', v[0], v[1], v[2])
                     iscsi_data.update_cfg(Global.target, Global.ipnr)
@@ -116,11 +147,11 @@ class TestRegression(unittest.TestCase):
         """Test With Header Digest"""
         i = 1
         for v in self.param_values:
-            with self.subTest('Testing FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v), i=i):
+            with self.subTest('Testing FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v), i=i):
                 if i not in Global.subtest_list:
-                    util.vprint('Skipping subtest %d: FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v) % i)
+                    util.vprint('Skipping subtest %d: FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v) % i)
                 else:
-                    util.vprint('Running subtest %d: FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v) % i)
+                    util.vprint('Running subtest %d: FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v) % i)
                     self.iscsi_logout()
                     iscsi_data = IscsiData('No', 'Yes', 'CRC32C', 'None', v[0], v[1], v[2])
                     iscsi_data.update_cfg(Global.target, Global.ipnr)
@@ -131,11 +162,11 @@ class TestRegression(unittest.TestCase):
         """Test With Header Digest"""
         i = 1
         for v in self.param_values:
-            with self.subTest('Testing FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v), i=i):
+            with self.subTest('Testing FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v), i=i):
                 if i not in Global.subtest_list:
-                    util.vprint('Skipping subtest %d: FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v) % i)
+                    util.vprint('Skipping subtest %d: FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v) % i)
                 else:
-                    util.vprint('Running subtest %d: FirstBurst={} MaxBurts={} MaxRecv={}'.format(*v) % i)
+                    util.vprint('Running subtest %d: FirstBurst={} MaxBurst={} MaxRecv={}'.format(*v) % i)
                     self.iscsi_logout()
                     iscsi_data = IscsiData('No', 'Yes', 'CRC32C', 'CRC32C', v[0], v[1], v[2])
                     iscsi_data.update_cfg(Global.target, Global.ipnr)
@@ -151,12 +182,18 @@ class TestRegression(unittest.TestCase):
         # wait a few seconds for the device to show up
         if not util.wait_for_path(Global.device):
             self.fail('%s: does not exist after login' % Global.device)
-        (res, reason) = util.run_fio()
-        self.assertEqual(res, 0, reason)
+        # run parted to partition the disc with one whole disk partition
         (res, reason) = util.run_parted()
         self.assertEqual(res, 0, reason)
+        # run fio to test file IO
+        (res, reason) = util.run_fio()
+        self.assertEqual(res, 0, reason)
+        # wait a bit for cache to flush
+        util.sleep_some(1)
+        # make a filesystem
         (res, reason) = util.run_mkfs()
         self.assertEqual(res, 0, reason)
+        # run bonnie++ to test the filesystem IO
         (res, reason) = util.run_bonnie()
         self.assertEqual(res, 0, reason)
 
@@ -170,4 +207,5 @@ class TestRegression(unittest.TestCase):
                       '-T', Global.target,
                       '-p', Global.ipnr,
                       '--logout'])
-
+        Global.total_time = time.perf_counter() - cls.time_start
+        print_time_values()
diff -pruN 2.1.5-1/test/harness/util.py 2.1.7-2/test/harness/util.py
--- 2.1.5-1/test/harness/util.py	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/test/harness/util.py	2022-05-06 17:37:21.000000000 +0000
@@ -42,6 +42,9 @@ class Global:
     # XXX we should really look how many subtests there are, but there's
     # no good way to detect that.
     subtest_list = [i+1 for i in range(16)]
+    # for timing
+    timing = dict.fromkeys(['fio', 'sgdisk', 'dd', 'bonnie', 'mkfs', 'sleep'], 0.0)
+    total_time = 0.0
 
 
 def dprint(*args):
@@ -261,7 +264,7 @@ def run_fio():
     Return zero for success.
     Return non-zero for failure and a failure reason.
 
-    Uses Globals: device, blocksize
+    Uses Globals: partition, blocksize
     """
     if Global.blocksize is not None:
         dprint('Found a block size passed in: %s' % Global.blocksize)
@@ -272,37 +275,41 @@ def run_fio():
                 '16k', '32k', '75536', '128k', '1000000']
     # for each block size, do a read test, then a write test
     for bs in blocksizes:
-        vprint('Running "fio" read test: 8 threads, bs=%s' % bs)
+        vprint('Running "fio" read/write/verify tests with 8/8/1 threads, bs=%s' % bs)
         # only support direct IO with aligned reads
         if bs.endswith('k'):
             direct=1
         else:
             direct=0
+        ts = time.perf_counter()
         res = run_cmd(['fio', '--name=read-test', '--readwrite=randread',
             '--runtime=2s', '--numjobs=8', '--blocksize=%s' % bs, 
-            '--direct=%d' % direct, '--filename=%s' % Global.device])
+            '--offset=256k',
+            '--direct=%d' % direct, '--filename=%s' % Global.partition])
         if res != 0:
             return (res, 'fio failed')
-        vprint('Running "fio" write test: 8 threads, bs=%s' % bs)
         res = run_cmd(['fio', '--name=write-test', '--readwrite=randwrite',
             '--runtime=2s', '--numjobs=8', '--blocksize=%s' % bs, 
-            '--direct=%d' % direct, '--filename=%s' % Global.device])
+            '--offset=256k',
+            '--direct=%d' % direct, '--filename=%s' % Global.partition])
         if res != 0:
             return (res, 'fio failed')
-        vprint('Running "fio" verify test: 1 thread, bs=%s' % bs)
         res = run_cmd(['fio', '--name=verify-test', '--readwrite=randwrite',
             '--runtime=2s', '--numjobs=1', '--blocksize=%s' % bs, 
-            '--direct=%d' % direct, '--filename=%s' % Global.device,
+            '--direct=%d' % direct, '--filename=%s' % Global.partition,
+            '--offset=256k',
             '--verify=md5', '--verify_state_save=0'])
         if res != 0:
             return (res, 'fio failed')
+        te = time.perf_counter()
+        Global.timing['fio'] += te - ts
     return (0, 'Success')
 
 def wait_for_path(path, present=True, amt=10):
     """Wait until a path exists or is gone"""
     dprint("Looking for path=%s, present=%s" % (path, present))
     for i in range(amt):
-        time.sleep(1)
+        sleep_some(1)
         if os.path.exists(path) == present:
             dprint("We are Happy :) present=%s, cnt=%d" % (present, i))
             return True
@@ -318,13 +325,27 @@ def wipe_disc():
     """
     # zero out the label and parition table
     vprint('Running "sgdisk" and "dd" to wipe disc label, partitions, and filesystem')
-    time.sleep(1)
-    res = run_cmd(['sgdisk', '-Z', Global.device])
+    sleep_some(1)
+    ts = time.perf_counter()
+    res = run_cmd(['sgdisk', '--clear', Global.device])
+    te = time.perf_counter()
+    Global.timing['sgdisk'] += te -ts
     if res != 0:
-        return (res, '%s: could not zero out label: %d' % (Global.device, res))
+        if res == 4:
+            dprint("Oh oh -- 'clear' failed! trying one more time ...")
+        ts = time.perf_counter()
+        res = run_cmd(['sgdisk', '--clear', Global.device])
+        te = time.perf_counter()
+        if res != 0:
+            return (res, '%s: could not zero out label after two tries: %d' % \
+                    (Global.device, res))
+        Global.timing['sgdisk'] += te - ts
+    ts = time.perf_counter()
     res = run_cmd(['dd', 'if=/dev/zero', 'of=%s' % Global.device, 'bs=256k', 'count=20', 'oflag=direct'])
+    te = time.perf_counter()
     if res != 0:
         return (res, '%s: could not zero out filesystem: %d' % (Global.device, res))
+    Global.timing['dd'] += te - ts
     return (0, 'Success')
     
 def run_parted():
@@ -339,7 +360,7 @@ def run_parted():
     """
     (res, reason) = wipe_disc()
     if res != 0:
-        return (res, resason)
+        return (res, reason)
     # ensure our partition file is not there, to be safe
     if not wait_for_path(Global.partition, present=False, amt=30):
         return (1, '%s: Partition already exists?' % Global.partition)
@@ -359,25 +380,39 @@ def run_parted():
 
 def run_mkfs():
     vprint('Running "mkfs" to to create filesystem')
+    ts = time.perf_counter()
     res = run_cmd(Global.MKFSCMD + [ Global.partition ] )
+    te = time.perf_counter()
     if res != 0:
         return (res, '%s: mkfs failed (%d)' % (Global.partition, res))
+    Global.timing['mkfs'] += te - ts
     return (0, 'Success')
 
 def run_bonnie():
     # make a temp dir and mount the device there
     with tempfile.TemporaryDirectory() as tmp_dir:
-        vprint('Mounting the filesystem')
+        vprint('Running "mount" to mount the filesystem')
         res = run_cmd(['mount'] + Global.MOUNTOPTIONS + [Global.partition, tmp_dir])
         if res != 0:
             return (res, '%s: mount failed (%d)' % (Global.partition, res))
         # run bonnie++ on the new directory
         vprint('Running "bonnie++" on the filesystem')
+        ts = time.perf_counter()
         res = run_cmd(['bonnie++'] + Global.BONNIEPARAMS + ['-d', tmp_dir])
+        te = time.perf_counter()
         if res != 0:
             return (res, '%s: umount failed (%d)' % (tmp_dir, res))
+        Global.timing['bonnie'] += te - ts
         # unmount the device and remove the temp dir
+        vprint('Running "umount" to unmount the filesystem')
         res = run_cmd(['umount', tmp_dir])
         if res != 0:
             return (res, '%s: umount failed (%d)' % (tmp_dir, res))
     return (0, 'Success')
+
+def sleep_some(s):
+    # sleep s seconds
+    ts = time.perf_counter()
+    time.sleep(s)
+    te = time.perf_counter()
+    Global.timing['sleep'] += te - ts
diff -pruN 2.1.5-1/test/README 2.1.7-2/test/README
--- 2.1.5-1/test/README	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/test/README	2022-05-06 17:37:21.000000000 +0000
@@ -1,93 +1,239 @@
-From the original test/README:
 ---------------------------------------------------------------------------
-This directory contains regression suite.
 
-I would appreciate if developer will run it at least once after
-modifications done before commit or mailing list submit.
+======
+README
+======
+
+--------------------
+Setting up the tests
+--------------------
+
+  This is the README for the updated "test" open-iscsi subdirectory.
+
+  Note that these tests are *not* performance tests. So no
+  attempt is made to track or display how long each test takes,
+  so it is not currently possible to track any improvement
+  nor degredation in IO performance. Please feel free to
+  add tests to measure performance, if you wish.
+
+  The tests here are based on the python unittest package. Please use
+  the included "test-open-iscsi.py" python script to run the tests.
+  You can run:
+
+    # ./test-open-iscsi.py --help
+
+  to get a list of options for this script. You will need the following
+  packages or commands to run these tests:
+
+  * fio
+  * bonie++
+  * mkfs.FSTYPE (e.g. mkfs.ext3)
+  * sgdisk
+  * dd
+  * parted
+  * mount/umount
+  * iscsiadm (with the iscsid daemon or service running) [of course]
+
+
+-----------------
+Running the tests
+-----------------
+
+  You will also need to know the IQN (name) of an accesable iscsi target,
+  set up with appropriate access controls so that you can log into it,
+  as well as the IP address where you can access this
+  target, and you will need to know which SCSI disk will show in in
+  /dev for this target (e.g. "/dev/sdc", if you already have a "/dev/sda"
+  and a "/dev/sdb"). You will need to pass in this information to the
+  python script to test. For example, to run all tests on my test
+  system (as root, of course):
+
+    # ./test-open-iscsi.py -v -f \
+        -t iqn.2003-01.org.linux-iscsi.linux-o2br.x8664:sn.2296be998e2c \
+	-i 192.168.20.168 \
+	-D /dev/sdc
+
+  This can take quite a while to run -- hours -- unless you limit
+  the tests to a subset of the whole suite.
+
+  The data on your target iSCSI disc will be wiped, so don't use a target
+  that has data you wish to save. As far as the size of the target, I
+  set up a 10G block-based iscsi target. Having a larger target makes
+  the test run take longer, though. I believe 1G or even 100M might work?
+
+  Instead of running all the tests, one can instead run a subtest, since
+  the unittest package supports this. To get a list of the tests, run:
+
+    # ./test-open-iscsi.py -l
+    test_HdrDigest_on_DataDigest_off (harness.tests.TestRegression)
+    test_HdrDigest_on_DataDigest_on (harness.tests.TestRegression)
+    test_InitialR2T_off_ImmediateData_off (harness.tests.TestRegression)
+    test_InitialR2T_off_ImmediateData_on (harness.tests.TestRegression)
+    test_InitialR2T_on_ImmediateData_off (harness.tests.TestRegression)
+    test_InitialR2T_on_ImmediateData_on (harness.tests.TestRegression)
+
+  I believe the names are self-explanitory. (If not, submit a pull
+  request or let me know.)
+
+  There are 6 test groups, all coming from one test script file (in
+  harness/tests.py), and that are in the the TestRegression python class.
+
+  [In the future, one can add more tests to this class, and other
+  classes to test things besides regression (like functionality,
+  bug-fix detection, etc).]
+
+  See below for an exapmle of how you might use this option.
+
+  One can also specify the list of subtests (by number) for each test,
+  further reducing test executing amount and time, if one wishes, using
+  the "-l/--list" option. Each subtest specifies a different
+  combination of FirstBurst, MaxBurstLength, and MaxRecv for the IO test.
+  Here's a list of the subest values:
+
+    Subtest   [FirstBurstLength, MaxBurstLength, MaxRecvDataSegmentLength]
+        1	    4096	     4096	     4096
+        2	    8192	     4096	     4096
+        3	   16384	     4096	     4096
+        4	   32768	     4096	     4096
+        5	   65536	     4096	     4096
+        6	  131972	     4096	     4096
+        7	    4096	     8192	     4096
+        8	    4096	    16384	     4096
+        9	    4096	    32768	     4096
+       10	    4096	    65536	     4096
+       11	    4096	   131072	     4096
+       12	    4096	     4096	     8192
+       13	    4096	     4096	    16384
+       14	    4096	     4096	    32768
+       15	    4096	     4096	    65536
+       16	    4096	     4096	   131072
+
+  So to run subtest 7 through 11 of test_InitialR2T_off_ImmediateData_off:
+
+    # ... (fill in)									<< TODO XXX
+
+  Lastly, one can reduce the number of tests run (and hence the length of
+  time spent testing) by specifying the block size to test with during
+  IO testing. By default the script uses an array of block sizes:
+
+	[512,1k,2k,4k,8k,16k,32k,75536,128k,1000000]
+
+  For example, to run a test for block size 4k, all subtest 12, for
+  the test_HdrDigest_on_DataDigest_on test:
+
+    # ./test-open-iscsi.py -v -f \
+        -t iqn.2003-01.org.linux-iscsi.linux-o2br.x8664:sn.2296be998e2c \
+	-i 192.168.20.168 \
+	-D /dev/sdc \
+	-B 4k \
+	-s 12 \
+	TestRegression.test_HdrDigest_on_DataDigest_on
+
+
+------------------
+Test Descriptsions
+------------------
+
+  The "regression" test sequence was laid out in regression.sh (the
+  previous test script, still around for reference). I am not sure
+  why we still call it a regression test, when it does not in fact
+  check for any regression in performance. Instead, it tests
+  functionality.
+
+  Each iscsi test has the following default values
+  (called "IscsiData()" in the test suite). These correspond to
+  the default values usually found in open-iscsi:
+
+    Immediate Data		= on
+    Initial Request to Transmit	= off
+    Header Digest		= 'None,CRC32C' (i.e. off by default)
+    Data Digest			= 'None,CRC32C' (i.e. off by default)
+    First Burst Length		= 256k
+    Max Burst Length		= (16 Meg - 1k)
+    Max Receive Data Length	= 128k
+    Max Request to Transmit	= 1
+
+  but one or more of these values can be overwritten for each test.
+
+  The current test suite is laid out like this:
+
+    test_HdrDigest_on_DataDigest_off (harness.tests.TestRegression)
+
+	This tests the Header Digest functionality, by itself.
+
+    test_HdrDigest_on_DataDigest_on (harness.tests.TestRegression)
+
+	This one tests both the Header and Data Digest functionality,
+	together
+
+    test_InitialR2T_off_ImmediateData_off (harness.tests.TestRegression)
+
+	Test both Initial Rquest to Transmit and Imediate data off
+
+    test_InitialR2T_off_ImmediateData_on (harness.tests.TestRegression)
+
+	Test with Initial Request to Transmit off but Imeediate Data
+	on. (This is the default configuration)
+
+    test_InitialR2T_on_ImmediateData_off (harness.tests.TestRegression)
+
+	Test Initial Request to Transmit on but Imediate Data off
+
+    test_InitialR2T_on_ImmediateData_on (harness.tests.TestRegression)
+
+	Test with both Initial Request to Transmit and Immediate Data
+	on.
+
+  For each test run (from this list above), we perform the following tests:
+
+    - Use "iscsiadm" to log into the iscsi target and wait for the
+      device to show up
+    - Run "fio" on the raw disc device
+	This is done 16 times, one for each subtest (see above)
+	  Each of these 16 tests has 10 different block sizes used
+	  (see above)
+	  fio actually does (for each block size):
+	  - fio read test (8 threads)
+	  - fio write test (8 threads)
+	  - fio verify test (1 thread)
+    - Run "parted" to partition
+	This actually first runs "sgdisk" then "dd" to wipe the disc,
+	then runs "parted" make a label then partition it, then
+	waits for the partition to show up.
+    - Run "mkfs" to create a filesystem (EXT3 by default)
+    - Run "bonnie++" on the created filesystem
+
+  For the math-friendly out there, I believe this adds up to about
+  960 tests (10x16x6). By far the slowest part of the tests seems
+  to be wiping the discs clean of a label or partitions. Perhaps this
+  can be sped up?
+
+  The following things can be overridden in the environment, if you
+  wish, by setting the appropriate environment variable before running
+  the test script:
+
+    env. var.		default			meaning
+    ---------		-------			-------
+    FSTYPE		"ext3"			filesystem type to create
+    MOUNTOPTIONS	"-t FSTYPE"		"-t FSTYPE" is added to whatever
+						options you pass in, if any
+    MKFSCMD		"mkfs.FSTYPE"		which mkfs command to call
+    MKFSOPTS		<none>			options too add to mkfs call,
+						if any
+    BONNIEPARAMS	"-r0 -n10:0:0 -s16 -uroot -f -q"
+						params used when running bonnie++
+
+-----------------------------------
+Suggestions for running these tests
+-----------------------------------
+
+  I suggest the following values for setting up these tests:
+
+  - Set up a smaller target -- maybe 100M -- which makes tests run faster
+  - Ensure that noop_out_* values are 0 (NOPs off) for your target
+  - Use the local system for your target, to avoid network/switch delays
+  - If there are failures, check dmesg for possible error messages
+  - If you use targetcli for your target, disable NOP-INs on the
+    target ACL attributes
 
-./regression.sh script expects next binaries and data files exists
-in current directory:
-
-	- regression.dat
-	- iscsiadm
-	- bonnie++ (source: http://www.open-iscsi.org/bits/bonnie++.tar.gz)
-	- disktest (source: http://www.open-iscsi.org/bits/disktest.tar.gz)
-
-Thanks!
-Dmitry
 ---------------------------------------------------------------------------
-Call:
-
-> # ./regression.sh -f/--format <device>
-
-to run "mkfs" on the device and exit, or
-
-> # ./regression.sh <targetname> <ipnumber#> <device> [test#[:#]] [bsize]
-
-Where:
-	<targetname>	?
-	<ipnumber#>	?
-	<device>	the device on which to test (e.g. /dev/sd?)
-	test#[:#]	test(s) to run, i.e. single or range (default: all)
-	bsize		disktest block size (default: a range of 10 sizes)
-			special value "bonnie" => skip disktest
-
-And env var "SKIP_WARNING" skips a big warning about writing on the device?
-
----------------------------------------------------------------------------
-
-The problem is that these tests have not been run for a while, and,
-additionally, disktest seems to be extinct and unfindable.
-
-I plan to get these tests working, and consider these the steps I plan
-to take:
-
-* understand the current tests
-  - particularly, what disktest and bonnie++ are doing
-
-* try to replace disktest and/or bonnie++, if needed
-  - there are a lot of good disk test packages these days
-
-* replace the shell code with PyTest code, to make it
-  easier to use
-
-Lee Duncan -- 2/13/2020
-
-Analysis of disktest usage:
-
-	options used:					fio option for this?
-	=======================================		==================================
-							--name=test (or whatever)
-	-T2		-- run 2 seconds		--runtime=2
-	-K8		-- run with 8 threads		--numjobs=8
-	-B<bs>		-- set block xfer size		--blocksize=<bs> (default 4k?)
-	-ID		-- use direct IO		--direct=1
-	<dev>		-- use device			--filename=<dev>
-
-	in read mode:
-	-r		-- read mode			--readwrite=randread
-
-	in write mode:
-	-w		-- write mode			--readwrite=randwrite
-	-E 16		-- compare 16 bytes		--verify=md5? (lots of options)
-
-It looks like the "fio" program may address these needs?
-
-e.g. running
-
-with file "test.fio":
-> [test]
-> rw=randread
-> bs=8k
-> filename=/dev/sdb
-> direct=1
-> numjobs=4
-> runtime=60s
-
-run:
-
-> # fio test.fio
-
-The output is interactive? But results are ridiculously verbose,
-but include a nice summary line or two that could be used as a
-go/no-go?
diff -pruN 2.1.5-1/test/README.orig 2.1.7-2/test/README.orig
--- 2.1.5-1/test/README.orig	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/test/README.orig	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,104 @@
+---------------------------------------------------------------------------
+A Note from current open-iscsi maintainer Lee Duncan:
+
+README.orig:
+  This is the old README for the "test" subdirectory, directed
+  at being able to use the "regressioin..sh" shell script. But
+  I no longer maintain the shell script, much preferring the
+  python unittest package. Please see the new README file
+  for how to use that package. (2/2022)
+---------------------------------------------------------------------------
+
+From the original test/README:
+---------------------------------------------------------------------------
+This directory contains regression suite.
+
+I would appreciate if developer will run it at least once after
+modifications done before commit or mailing list submit.
+
+./regression.sh script expects next binaries and data files exists
+in current directory:
+
+	- regression.dat
+	- iscsiadm
+	- bonnie++ (source: http://www.open-iscsi.org/bits/bonnie++.tar.gz)
+	- disktest (source: http://www.open-iscsi.org/bits/disktest.tar.gz)
+
+Thanks!
+Dmitry
+---------------------------------------------------------------------------
+Call:
+
+> # ./regression.sh -f/--format <device>
+
+to run "mkfs" on the device and exit, or
+
+> # ./regression.sh <targetname> <ipnumber#> <device> [test#[:#]] [bsize]
+
+Where:
+	<targetname>	?
+	<ipnumber#>	?
+	<device>	the device on which to test (e.g. /dev/sd?)
+	test#[:#]	test(s) to run, i.e. single or range (default: all)
+	bsize		disktest block size (default: a range of 10 sizes)
+			special value "bonnie" => skip disktest
+
+And env var "SKIP_WARNING" skips a big warning about writing on the device?
+
+---------------------------------------------------------------------------
+
+The problem is that these tests have not been run for a while, and,
+additionally, disktest seems to be extinct and unfindable.
+
+I plan to get these tests working, and consider these the steps I plan
+to take:
+
+* understand the current tests
+  - particularly, what disktest and bonnie++ are doing
+
+* try to replace disktest and/or bonnie++, if needed
+  - there are a lot of good disk test packages these days
+
+* replace the shell code with PyTest code, to make it
+  easier to use
+
+Lee Duncan -- 2/13/2020
+
+Analysis of disktest usage:
+
+	options used:					fio option for this?
+	=======================================		==================================
+							--name=test (or whatever)
+	-T2		-- run 2 seconds		--runtime=2
+	-K8		-- run with 8 threads		--numjobs=8
+	-B<bs>		-- set block xfer size		--blocksize=<bs> (default 4k?)
+	-ID		-- use direct IO		--direct=1
+	<dev>		-- use device			--filename=<dev>
+
+	in read mode:
+	-r		-- read mode			--readwrite=randread
+
+	in write mode:
+	-w		-- write mode			--readwrite=randwrite
+	-E 16		-- compare 16 bytes		--verify=md5? (lots of options)
+
+It looks like the "fio" program may address these needs?
+
+e.g. running
+
+with file "test.fio":
+> [test]
+> rw=randread
+> bs=8k
+> filename=/dev/sdb
+> direct=1
+> numjobs=4
+> runtime=60s
+
+run:
+
+> # fio test.fio
+
+The output is interactive? But results are ridiculously verbose,
+but include a nice summary line or two that could be used as a
+go/no-go?
diff -pruN 2.1.5-1/test/.setup 2.1.7-2/test/.setup
--- 2.1.5-1/test/.setup	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/test/.setup	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-target="iqn.2003-01.org.linux-iscsi.linux-dell.x8664:sn.ae8d5828b4b4"
-ipnr="192.168.20.3:3260"
-dev="/dev/sdb"
diff -pruN 2.1.5-1/test/TODO 2.1.7-2/test/TODO
--- 2.1.5-1/test/TODO	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/test/TODO	2022-05-06 17:37:21.000000000 +0000
@@ -2,14 +2,6 @@
 # Things to do for testing
 #
 
-* get current tests running
-  * this will mean replacing disktest with something
-    (like fio?)
-
-  PASS -- no need to spend time getting disktest working
-  when (1) it's hard to find, and (2) it's going to be
-  replaced anyway.
-
 * ensure user is root? -- easy to do
 
 * have tests create their own target using targetcli and
@@ -21,9 +13,6 @@
   that to be done already. Either way, we may still need
   to know the IQN of our target and the host where it lives.
 
-  PASS -- we still would have to know two things (IQN and
-  IP:Port). See next item.
-
 * Have tests figure out the device path, so it doesn't have
   to be passed in. Passing it in requires the called to
   login to the remote iscsi target and look at the path
@@ -58,11 +47,18 @@
 
 * Add back in the "big warning" from regression.sh?
 
-* Add info to the README about how to run the python tests
-
-* Leave the regression test around, for now? It doesn't run,
-  so maybe it should just be removed?
+* Find a faster way to zero the disc than using sgdisk and
+  dd. Running both of these on a 10G disc can take minutes.
 
-* Add in option to specify which subtests (of 16) are run
-  for each test case. Would make it much faster for testing
-  and go/no-go testing?
+* Come up with some common subsets of tests that can be run
+  when needed, since running all the tests takes forever. Maybe
+  a "short", "medium", and "long" option, so the caller doesn't
+  have to remember the arcane command-line options?
+
+* keep track of our session id (when we have one), so that
+  we can log out of just our session more easily
+
+* do a better job of tracking time spent exec-ing other
+  programs -- maybe have the run_cmd() function do it
+  automatically, using a dict, based on the argv[0]
+  command being run?
diff -pruN 2.1.5-1/usr/actor.c 2.1.7-2/usr/actor.c
--- 2.1.5-1/usr/actor.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/actor.c	2022-05-06 17:37:21.000000000 +0000
@@ -43,8 +43,12 @@ actor_time_left(actor_t *thread, time_t
 	((int64_t)(b) - (int64_t)(a) < 0)
 
 void
-actor_init(actor_t *thread, void (*callback)(void *), void *data)
+__actor_init(actor_t *thread, void (*callback)(void *), void *data)
 {
+	if (thread->state != ACTOR_INVALID)
+		log_error("bug:thread %p:%s has already been initialized",
+			  thread, thread->name);
+
 	INIT_LIST_HEAD(&thread->list);
 	thread->state = ACTOR_NOTSCHEDULED;
 	thread->callback = callback;
@@ -54,7 +58,8 @@ actor_init(actor_t *thread, void (*callb
 void
 actor_delete(actor_t *thread)
 {
-	log_debug(7, "thread %08lx delete: state %d", (long)thread,
+	log_debug(7, "thread %p:%s delete: state %d",
+			thread, thread->name,
 			thread->state);
 	switch(thread->state) {
 	case ACTOR_WAITING:
@@ -62,7 +67,8 @@ actor_delete(actor_t *thread)
 		/* priority: low */
 		/* fallthrough */
 	case ACTOR_SCHEDULED:
-		log_debug(1, "deleting a scheduled/waiting thread!");
+		log_debug(1, "deleting a scheduled/waiting thread %p:%s!",
+			 thread, thread->name);
 		list_del_init(&thread->list);
 		if (list_empty(&pend_list)) {
 			log_debug(7, "nothing left on pend_list, deactivating alarm");
@@ -93,10 +99,10 @@ actor_insert_on_pend_list(actor_t *threa
 	/* insert new entry in sort order */
 	list_for_each_entry(next_thread, &pend_list, list) {
 		if (time_after(next_thread->ttschedule, thread->ttschedule)) {
-			log_debug(7, "next thread %p due %lld", next_thread,
-			  (long long)next_thread->ttschedule);
-			log_debug(7, "new thread %p is before (%lld), inserting", thread,
-			  (long long)thread->ttschedule);
+			log_debug(7, "next thread %p:%s due %lld", next_thread,
+			  next_thread->name, (long long)next_thread->ttschedule);
+			log_debug(7, "new thread %p:%s is before (%lld), inserting",
+			  thread, next_thread->name, (long long)thread->ttschedule);
 
 			/* insert new thread before the next thread */
 			__list_add(&thread->list, next_thread->list.prev, &next_thread->list);
@@ -105,14 +111,14 @@ actor_insert_on_pend_list(actor_t *threa
 	}
 
 	if (orig_head) {
-		log_debug(7, "last thread %p due %lld", next_thread,
-			  (long long)next_thread->ttschedule);
-		log_debug(7, "new thread %p is after (%lld), inserting at tail", thread,
-			  (long long)thread->ttschedule);
+		log_debug(7, "last thread %p:%s due %lld", next_thread,
+			  next_thread->name, (long long)next_thread->ttschedule);
+		log_debug(7, "new thread %p:%s is after (%lld), inserting at tail",
+			  thread, thread->name, (long long)thread->ttschedule);
 	}
 	else
-		log_debug(7, "new thread %p due %lld is first item on pend_list", thread,
-			  (long long)thread->ttschedule);
+		log_debug(7, "new thread %p:%s due %lld is first item on pend_list",
+			  thread, thread->name, (long long)thread->ttschedule);
 
 	/* Not before any existing entries */
 	list_add_tail(&thread->list, &pend_list);
@@ -140,12 +146,13 @@ actor_schedule_private(actor_t *thread,
 
 	current_time = tv.tv_sec;
 
-	log_debug(7, "thread %p schedule: delay %u state %d",
-		thread, delay_secs, thread->state);
+	log_debug(7, "thread %p:%s schedule: delay %u state %d",
+		thread, thread->name, delay_secs, thread->state);
 
 	switch(thread->state) {
 	case ACTOR_WAITING:
-		log_error("rescheduling a waiting thread!");
+		log_error("rescheduling a waiting thread %p:%s !",
+			  thread, thread->name);
 		list_del(&thread->list);
 		/* fall-through */
 	case ACTOR_NOTSCHEDULED:
@@ -168,8 +175,9 @@ actor_schedule_private(actor_t *thread,
 		// don't do anything
 		break;
 	case ACTOR_INVALID:
-		log_error("BUG: Trying to schedule a thread that has not been "
-			  "setup. Ignoring sched.");
+		log_error("BUG: Trying to schedule a thread %p"
+			  "that has not been setup. Ignoring sched.",
+			  thread);
 		break;
 	}
 
@@ -188,10 +196,10 @@ actor_schedule(actor_t *thread)
 }
 
 void
-actor_timer(actor_t *thread, uint32_t timeout_secs, void (*callback)(void *),
+__actor_timer(actor_t *thread, uint32_t timeout_secs, void (*callback)(void *),
 	    void *data)
 {
-	actor_init(thread, callback, data);
+	__actor_init(thread, callback, data);
 	actor_schedule_private(thread, timeout_secs, 0);
 }
 
@@ -238,8 +246,8 @@ actor_poll(void)
 	list_for_each_entry_safe(thread, tmp, &pend_list, list) {
 		uint64_t time_left = actor_time_left(thread, current_time);
 		if (time_left) {
-			log_debug(7, "thread %08lx due %" PRIu64 ", wait %" PRIu64 " more",
-				  (long)thread,
+			log_debug(7, "thread %p:%s due %" PRIu64 ", wait %" PRIu64 " more",
+				  thread, thread->name,
 				  (uint64_t)thread->ttschedule, time_left);
 
 			alarm(time_left);
@@ -249,17 +257,17 @@ actor_poll(void)
 		/* This entry can be run now */
 		list_del_init(&thread->list);
 
-		log_debug(2, "thread %08lx was scheduled for "
+		log_debug(2, "thread %p:%s was scheduled for "
 			  "%" PRIu64 ", curtime %" PRIu64 " q_forw %p "
 			  "&pend_list %p",
-			  (long)thread, (uint64_t)thread->ttschedule,
+			  thread, thread->name, (uint64_t)thread->ttschedule,
 			  current_time, pend_list.next, &pend_list);
 
 		list_add_tail(&thread->list, &ready_list);
 		assert(thread->state == ACTOR_WAITING);
 		thread->state = ACTOR_SCHEDULED;
-		log_debug(7, "thread %08lx now in ready_list",
-			  (long)thread);
+		log_debug(7, "thread %p:%s now in ready_list",
+			  thread, thread->name);
 	}
 
 	/* Disable alarm if nothing else pending */
@@ -274,13 +282,15 @@ actor_poll(void)
 		list_del_init(&thread->list);
 
 		if (thread->state != ACTOR_SCHEDULED)
-			log_error("ready_list: thread state corrupted! "
+			log_error("ready_list: thread %p:%s state corrupted! "
 				  "Thread with state %d in actor list.",
+				  thread, thread->name,
 				  thread->state);
 		thread->state = ACTOR_NOTSCHEDULED;
-		log_debug(7, "exec thread %08lx callback", (long)thread);
+		log_debug(7, "exec thread %p:%s",
+			  thread, thread->name);
 		thread->callback(thread->data);
-		log_debug(7, "thread %08lx done", (long)thread);
+		log_debug(7, "thread %p:%s done", thread, thread->name);
 	}
 	poll_in_progress = 0;
 }
diff -pruN 2.1.5-1/usr/actor.h 2.1.7-2/usr/actor.h
--- 2.1.5-1/usr/actor.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/actor.h	2022-05-06 17:37:21.000000000 +0000
@@ -19,9 +19,12 @@
 #ifndef ACTOR_H
 #define ACTOR_H
 
+#include <stdio.h>
 #include "types.h"
 #include "list.h"
 
+#define ACTOR_NAME_LEN 128
+
 typedef enum actor_state_e {
     ACTOR_INVALID,
     ACTOR_WAITING,
@@ -30,6 +33,7 @@ typedef enum actor_state_e {
 } actor_state_e;
 
 typedef struct actor {
+	char name[ACTOR_NAME_LEN];
 	struct list_head list;
 	actor_state_e state;
 	void *data;
@@ -37,14 +41,26 @@ typedef struct actor {
 	time_t ttschedule;
 } actor_t;
 
-extern void actor_init(actor_t *thread, void (*callback)(void *), void * data);
+extern void __actor_init(actor_t *thread, void (*callback)(void *), void * data);
 extern void actor_delete(actor_t *thread);
 extern void actor_schedule_head(actor_t *thread);
 extern void actor_schedule(actor_t *thread);
-extern void actor_timer(actor_t *thread, uint32_t delay_secs,
+extern void __actor_timer(actor_t *thread, uint32_t delay_secs,
 			void (*callback)(void *), void *data);
 extern void actor_timer_mod(actor_t *thread, uint32_t new_delay_secs,
 			    void *data);
 extern void actor_poll(void);
 
+#define actor_init(thread, callback, data) \
+do { \
+	snprintf((thread)->name, ACTOR_NAME_LEN, #callback); \
+	__actor_init(thread, callback, data); \
+} while (0)
+
+#define actor_timer(thread, timeout_secs, callback, data) \
+do { \
+	snprintf((thread)->name, ACTOR_NAME_LEN, #callback); \
+	__actor_timer(thread, timeout_secs, callback, data); \
+} while (0)
+
 #endif /* ACTOR_H */
diff -pruN 2.1.5-1/usr/auth.c 2.1.7-2/usr/auth.c
--- 2.1.5-1/usr/auth.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/auth.c	2022-05-06 17:37:21.000000000 +0000
@@ -109,7 +109,7 @@ acl_chap_auth_request(struct iscsi_acl *
 	unsigned char verify_data[client->chap_challenge_len];
 
 	/* the expected credentials are in the session */
-	if (session->username_in == NULL) {
+	if (session->username_in[0] == '\0') {
 		log_error("failing authentication, no incoming username "
 			  "configured to authenticate target %s",
 			  session->target_name);
@@ -122,7 +122,6 @@ acl_chap_auth_request(struct iscsi_acl *
 	}
 
 	if ((session->password_in_length < 1) ||
-	    (session->password_in == NULL) ||
 	    (session->password_in[0] == '\0')) {
 		log_error("failing authentication, no incoming password "
 		       "configured to authenticate target %s",
diff -pruN 2.1.5-1/usr/discovery.c 2.1.7-2/usr/discovery.c
--- 2.1.5-1/usr/discovery.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/discovery.c	2022-05-06 17:37:21.000000000 +0000
@@ -623,7 +623,7 @@ add_target_record(char *name, char *end,
 
 	/* if no address is provided, use the default */
 	if (text >= end) {
-		if (drec->address == NULL) {
+		if (drec->address[0] == '\0') {
 			log_error("no default address known for target %s",
 				  name);
 			return 0;
diff -pruN 2.1.5-1/usr/fwparam_ibft/fw_entry.c 2.1.7-2/usr/fwparam_ibft/fw_entry.c
--- 2.1.5-1/usr/fwparam_ibft/fw_entry.c	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/fw_entry.c	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) IBM Corporation. 2007
+ * Author: Doug Maxey <dwm@austin.ibm.com>
+ * based on code written by "Prasanna Mumbai" <mumbai.prasanna@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/route.h>
+
+#include "fw_context.h"
+#include "fwparam.h"
+#include "idbm_fields.h"
+#include "iscsi_net_util.h"
+#include "iscsi_err.h"
+#include "config.h"
+#include "iface.h"
+
+/**
+ * fw_setup_nics - setup nics (ethXs) based on ibft net info
+ *
+ * If this is a offload card, this function does nothing. The
+ * net info is used by the iscsi iface settings for the iscsi
+ * function.
+ */
+int fw_setup_nics(void)
+{
+	struct boot_context *context;
+	struct list_head targets;
+	char *iface_prev = NULL, transport[16];
+	int needs_bringup = 0, ret = 0, err;
+
+	INIT_LIST_HEAD(&targets);
+
+	ret = fw_get_targets(&targets);
+	if (ret || list_empty(&targets)) {
+		printf("Could not setup fw entries.\n");
+		return ISCSI_ERR_NO_OBJS_FOUND;
+	}
+
+	/*
+	 * For each target in iBFT bring up required NIC and use routing
+	 * to force iSCSI traffic through correct NIC
+	 */
+	list_for_each_entry(context, &targets, list) {
+		if (iface_prev == NULL || strcmp(context->iface, iface_prev)) {
+				/* Note: test above works because there is a
+				 * maximum of two targets in the iBFT
+				 */
+				iface_prev = context->iface;
+				needs_bringup = 1;
+		}
+		if (net_get_transport_name_from_netdev(context->iface, transport)) {
+			/* Setup software NIC, */
+			printf("Setting up software interface %s\n", context->iface);
+			err = net_setup_netdev(context->iface, context->ipaddr,
+								   context->mask, context->gateway,
+								   context->vlan,
+								   context->target_ipaddr, needs_bringup);
+			if (err) {
+				printf("Setting up software interface %s failed\n",
+						context->iface);
+				ret = err;
+			}
+		} else {
+			/* Setup offload NIC. */
+			struct iface_rec iface;
+
+			memset(&iface, 0, sizeof(iface));
+			iface_setup_defaults(&iface);
+			printf("Setting up offload interface %s\n", context->iface);
+			if (!iface_setup_from_boot_context(&iface, context)) {
+					printf("Setting up offload interface %s failed\n",
+						   context->iface);
+
+					ret = ISCSI_ERR;
+			}
+		}
+	}
+
+	fw_free_targets(&targets);
+	if (ret)
+		return ISCSI_ERR;
+	else
+		return 0;
+}
+
+/**
+ * fw_get_entry - return boot context of portal used for boot
+ * @context: firmware info of portal
+ *
+ * Returns non-zero if no portal was used for boot.
+ *
+ * This function is not thread safe.
+ */
+int fw_get_entry(struct boot_context *context)
+{
+	int ret;
+
+	ret = fwparam_ppc_boot_info(context);
+	if (ret)
+		ret = fwparam_sysfs_boot_info(context);
+	return ret;
+}
+
+/**
+ * fw_get_targets - get a boot_context struct for each target
+ * @list: list to add entires on.
+ *
+ * Returns zero if entries were found that can be traversed with the
+ * list.h helpers, or non-zero if no entries are found.
+ *
+ * fw_free_targets should be called to free the list.
+ *
+ * This function is not thread safe.
+ */
+int fw_get_targets(struct list_head *list)
+{
+	int ret;
+
+	ret = fwparam_ppc_get_targets(list);
+	if (ret)
+		ret = fwparam_sysfs_get_targets(list);
+	return ret;
+}
+
+void fw_free_targets(struct list_head *list)
+{
+	struct boot_context *curr, *tmp;
+
+	if (!list || list_empty(list))
+		return;
+
+	list_for_each_entry_safe(curr, tmp, list, list) {
+		list_del(&curr->list);
+		free(curr);
+	}
+}
+
+static void dump_initiator(struct boot_context *context)
+{
+	struct iface_rec iface;
+
+	memset(&iface, 0, sizeof(iface));
+	iface_setup_defaults(&iface);
+	iface_setup_from_boot_context(&iface, context);
+
+	if (strlen(context->initiatorname))
+		printf("%s = %s\n", IFACE_INAME, context->initiatorname);
+
+	if (strlen(context->isid))
+		printf("%s = %s\n", IFACE_ISID, context->isid);
+
+	printf("%s = %s\n", IFACE_TRANSPORTNAME, iface.transport_name);
+}
+
+static void dump_target(struct boot_context *context)
+{
+	if (strlen(context->targetname))
+		printf("%s = %s\n", NODE_NAME, context->targetname);
+
+	if (strlen(context->target_ipaddr))
+		printf(CONN_ADDR" = %s\n", 0, context->target_ipaddr);
+	printf(CONN_PORT" = %d\n", 0, context->target_port);
+
+	if (strlen(context->chap_name))
+		printf("%s = %s\n", SESSION_USERNAME, context->chap_name);
+	if (strlen(context->chap_password))
+		printf("%s = %s\n", SESSION_PASSWORD, context->chap_password);
+	if (strlen(context->chap_name_in))
+		printf("%s = %s\n", SESSION_USERNAME_IN, context->chap_name_in);
+	if (strlen(context->chap_password_in))
+		printf("%s = %s\n", SESSION_PASSWORD_IN,
+		       context->chap_password_in);
+
+	if (strlen(context->lun))
+		printf("%s = %s\n", NODE_BOOT_LUN, context->lun);
+}
+
+static void dump_network(struct boot_context *context)
+{
+	/* Dump the 8 byte mac address (not iser support) */
+	if (strlen(context->mac))
+		printf("%s = %s\n", IFACE_HWADDR, context->mac);
+	/*
+	 * If the 'origin' field is 3 (IBFT_IP_PREFIX_ORIGIN_DHCP),
+	 * then DHCP is used.
+	 * Otherwise evaluate the 'dhcp' field, if this has a valid
+	 * address then DHCP was used (broadcom sends 0.0.0.0).
+	 */
+	if ((context->origin == IBFT_IP_PREFIX_ORIGIN_DHCP) ||
+	    (strlen(context->dhcp) && strcmp(context->dhcp, "0.0.0.0")))
+		printf("%s = DHCP\n", IFACE_BOOT_PROTO);
+	else
+		printf("%s = STATIC\n", IFACE_BOOT_PROTO);
+	if (strlen(context->ipaddr))
+		printf("%s = %s\n", IFACE_IPADDR, context->ipaddr);
+	if (context->prefix)
+		printf("%s = %d\n", IFACE_PREFIX_LEN, context->prefix);
+	if (strlen(context->mask))
+		printf("%s = %s\n", IFACE_SUBNET_MASK, context->mask);
+	if (strlen(context->gateway))
+		printf("%s = %s\n", IFACE_GATEWAY, context->gateway);
+	if (strlen(context->primary_dns))
+		printf("%s = %s\n", IFACE_PRIMARY_DNS, context->primary_dns);
+	if (strlen(context->secondary_dns))
+		printf("%s = %s\n", IFACE_SEC_DNS, context->secondary_dns);
+	if (strlen(context->vlan))
+		printf("%s = %s\n", IFACE_VLAN_ID, context->vlan);
+	if (strlen(context->iface))
+		printf("%s = %s\n", IFACE_NETNAME, context->iface);
+}
+
+/**
+ * fw_print_entry - print boot context info of portal used for boot
+ * @context: firmware info of portal
+ *
+ * Does not print anything if no portal was used for boot.
+ *
+ * TODO: Merge this in with idbm.c helpers.
+ */
+void fw_print_entry(struct boot_context *context)
+{
+	printf("%s\n", ISCSI_BEGIN_REC);
+	dump_initiator(context);
+	dump_network(context);
+	dump_target(context);
+	printf("%s\n", ISCSI_END_REC);
+}
diff -pruN 2.1.5-1/usr/fwparam_ibft/fwparam.h 2.1.7-2/usr/fwparam_ibft/fwparam.h
--- 2.1.5-1/usr/fwparam_ibft/fwparam.h	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/fwparam.h	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,32 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ */
+#ifndef FWPARAM_H_
+#define FWPARAM_H_
+
+#include <stdint.h>
+#include "fw_context.h"
+
+#define FILENAMESZ (1024)
+
+struct boot_context;
+
+int fwparam_sysfs_boot_info(struct boot_context *context);
+int fwparam_sysfs_get_targets(struct list_head *list);
+int fwparam_ppc_boot_info(struct boot_context *context);
+int fwparam_ppc_get_targets(struct list_head *list);
+
+#endif /* FWPARAM_IBFT_H_ */
diff -pruN 2.1.5-1/usr/fwparam_ibft/fwparam_ppc.c 2.1.7-2/usr/fwparam_ibft/fwparam_ppc.c
--- 2.1.5-1/usr/fwparam_ibft/fwparam_ppc.c	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/fwparam_ppc.c	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,615 @@
+/*
+ * Copyright (C) IBM Corporation. 2007
+ * Author: Doug Maxey <dwm@austin.ibm.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define	 _XOPEN_SOURCE 500
+#include <ftw.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "fwparam.h"
+#include "fw_context.h"
+#include "iscsi_obp.h"
+#include "prom_parse.h"
+#include "sysdeps.h"
+#include "iscsi_err.h"
+
+void* yy_scan_string(const char *str);
+int yyparse(struct ofw_dev *ofwdev);
+
+#define BOOTPATH "/chosen/bootpath"
+#define DT_TOP "/proc/device-tree"
+#define LOCAL_MAC_FILE "/local-mac-address"
+
+static int devtree_offset;
+static char *bootpath_val;
+static int bytes_read;
+#define OFWDEV_MAX (10)
+static struct ofw_dev *ofwdevs[OFWDEV_MAX];
+static char *niclist[OFWDEV_MAX];
+static int nic_count;
+static int debug;
+static int dev_count;
+
+static void cp_param(char *dest,
+		     __attribute__((unused))const char *name,
+		     struct ofw_dev *dev,
+		     enum obp_param item, int len)
+{
+	if (dev->param[item])
+		strlcpy(dest, dev->param[item]->val, len);
+}
+
+static void cp_int_param(int *dest,
+			 __attribute__((unused))const char *name,
+			 struct ofw_dev *dev,
+			 enum obp_param item)
+{
+	if (dev->param[item])
+		*dest = strtol(dev->param[item]->val, NULL, 10);
+}
+
+static char *find_devtree(const char *filename)
+{
+	char *devtree = strdup(filename);
+	char *chop_at;
+	struct stat dt_stat;
+	int error;
+
+	/*
+	 * What is the path to the device-tree?	 The only valid
+	 * directories to locate the property are under /aliases or
+	 * /chosen.
+	 */
+
+	if (!devtree)
+		return NULL;
+
+	chop_at = strstr(devtree, "/chosen");
+	if (!chop_at)
+		chop_at = strstr(devtree, "/aliases");
+
+	if (!chop_at) {
+		char *vdev = malloc(strlen(filename) + strlen("/vdevice") + 1);
+
+		/*
+		 * test to see if there is /vdevice dir
+		 */
+		if (vdev) {
+			sprintf(vdev, "%s%s", filename, "/vdevice");
+			error = stat(vdev, &dt_stat);
+			free(vdev);
+			if (error) {
+				free(devtree);
+				return NULL;
+			}
+		}
+	} else
+		devtree[chop_at - devtree] = 0;
+
+	if (devtree)
+		devtree_offset = strlen(devtree);
+
+	return devtree;
+}
+
+/*
+ * Take the path to the property under chosen, and swizzle to make that
+ * the base for the device path discovered.
+ */
+static int locate_mac(const char *devtree, struct ofw_dev *ofwdev)
+{
+	int error = 0;
+	int mac_path_len = strlen(ofwdev->dev_path) + strlen(LOCAL_MAC_FILE) +
+		2;
+	char *mac_file;
+	int mac_fd;
+
+	mac_path_len += strlen(devtree);
+	mac_file = malloc(mac_path_len);
+	if (!mac_file) {
+		error = ENOMEM;
+		fprintf(stderr, "%s: malloc , %s\n", __func__,
+			strerror(errno));
+		goto lpm_bail;
+	}
+
+	snprintf(mac_file, mac_path_len, "%s%s%s", devtree, ofwdev->dev_path,
+		 LOCAL_MAC_FILE);
+	mac_fd = open(mac_file, O_RDONLY);
+	if (mac_fd < 0) {
+		error = errno;
+		fprintf(stderr, "%s: open %s, %s\n", __func__, mac_file,
+			strerror(errno));
+		free(mac_file);
+		goto lpm_bail;
+	}
+
+	bytes_read = read(mac_fd, ofwdev->mac, 6);
+	if (bytes_read != 6) {
+		error = EIO;
+		fprintf(stderr, "%s: read %s, %s\n", __func__, mac_file,
+			strerror(errno));
+	}
+	free(mac_file);
+	close(mac_fd);
+
+lpm_bail:
+	return error;
+}
+
+const char *obp_qual_set(struct ofw_dev *ofwdev, const char *qual)
+{
+	if (!strcmp("bootp", qual))
+		ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_BOOTP;
+	else if (!strcmp("dhcpv6", qual))
+		ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_DHCPV6;
+	else if (!strcmp("ipv6", qual))
+		ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_IPV6;
+	else if (!strcmp("iscsi", qual)) {
+		ofwdev->type = OFW_DT_ISCSI;
+		ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_ISCSI;
+	} else if (!strcmp("ping", qual))
+		ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_PING;
+	else
+		printf("%s: %s UNKNOWN\n", __func__, qual);
+	return qual;
+}
+
+void add_obp_parm(struct ofw_dev *ofwdev, enum obp_param parm, const char *str)
+{
+	int psz = sizeof(struct ofw_obp_param) + strlen(str);
+
+	ofwdev->param[parm] = malloc(psz);
+	if (ofwdev->param[parm] == NULL) {
+		printf("%s: ENOMEM!\n", __func__);
+		return;
+	}
+	memset(ofwdev->param[parm], 0, psz);
+	ofwdev->param[parm]->len = psz;
+	strcpy(ofwdev->param[parm]->val, str);
+}
+
+void obp_parm_addr(struct ofw_dev *ofwdev, const char *parm, const char *addr)
+{
+	if (!strcmp("ciaddr", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_CIADDR, addr);
+	else if (!strcmp("dhcp", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_DHCP, addr);
+	else if (!strcmp("giaddr", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_GIADDR, addr);
+	else if (!strcmp("isns", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_ISNS, addr);
+	else if (!strcmp("siaddr", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_SIADDR, addr);
+	else if (!strcmp("slp", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_SLP, addr);
+	else if (!strcmp("subnet-mask", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_SUBNET_MASK, addr);
+	else
+		printf("%s: %s UNKNOWN\n", __func__, parm);
+}
+
+void obp_parm_iqn(struct ofw_dev *ofwdev, const char *parm, const char *iqn)
+{
+	if (!strcmp("itname", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_ITNAME, iqn);
+	else if (!strcmp("iname", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_INAME, iqn);
+	else
+		printf("%s: %s UNKNOWN\n", __func__, parm);
+}
+
+void obp_parm_hexnum(struct ofw_dev *ofwdev, const char *parm,
+		     const char *numstr)
+{
+	if (!strcmp("bootp-retries", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_BOOTP_RETRIES, numstr);
+	else if (!strcmp("tftp-retries", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_TFTP_RETRIES, numstr);
+	else if (!strcmp("iport", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_IPORT, numstr);
+	else if (!strcmp("ilun", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_ILUN, numstr);
+	else if (!strcmp("isid", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_ISID, numstr);
+	else
+		printf("%s: %s UNKNOWN <%s>\n", __func__, parm, numstr);
+}
+
+void obp_parm_str(struct ofw_dev *ofwdev, const char *parm, const char *str)
+{
+	if (!strcmp("filename", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_FILENAME, str);
+	else if (!strcmp("ichapid", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_ICHAPID, str);
+	else if (!strcmp("ichappw", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_ICHAPPW, str);
+	else if (!strcmp("chapid", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_CHAPID, str);
+	else if (!strcmp("chappw", parm))
+		add_obp_parm(ofwdev, OBP_PARAM_CHAPPW, str);
+	else
+		printf("%s: %s UNKNOWN <%s>\n", __func__, parm, str);
+}
+
+void yyerror(struct ofw_dev *ofwdev,
+	     __attribute__((unused))const char *msg)
+{
+	fprintf(stderr, "%s: error in <%s> at l%d.c%d\n", "fwparam_ppc",
+		ofwdev->prop_path, yylloc.last_line, yylloc.last_column);
+}
+
+static int parse_params(const char *buf, struct ofw_dev *ofwdev)
+{
+	int error = 0;
+#if YYDEBUG
+	yydebug = 1;
+#endif
+
+
+	if (yy_scan_string(buf))
+		error = yyparse(ofwdev);
+
+	return error;
+}
+
+static int find_file(const char *filename)
+{
+	int error, fd;
+	struct stat bootpath_stat;
+
+	error = stat(filename, &bootpath_stat);
+	if (error < 0) {
+		fprintf(stderr, "%s: stat %s, %s\n", __func__, filename,
+			strerror(errno));
+		return error;
+	}
+
+	bootpath_val = malloc(bootpath_stat.st_size);
+	if (!bootpath_val) {
+		error = ENOMEM;
+		fprintf(stderr, "%s: Could not open %s: %s (%d)\n",
+			__func__, filename, strerror(error), error);
+		return -1;
+	}
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		fprintf(stderr, "%s: Could not open %s: %s (%d)\n",
+			__func__, filename, strerror(errno), errno);
+		free(bootpath_val);
+		bootpath_val = NULL;
+		return -1;
+	}
+
+	bytes_read = read(fd, bootpath_val, bootpath_stat.st_size);
+	close(fd);
+	if (bytes_read != bootpath_stat.st_size) {
+		fprintf(stderr, "%s: Failed to read %s: %s (%d)\n",
+			__func__, filename, strerror(EIO), EIO);
+		free(bootpath_val);
+		bootpath_val = NULL;
+		return -1;
+	}
+
+	return 1;
+}
+
+static int find_nics(const char *fpath,
+		     __attribute__((unused))const struct stat *sb,
+		     int tflag,
+		     struct FTW *ftw)
+{
+	if (tflag == FTW_D &&
+	    (strstr(fpath + ftw->base, "iscsi-toe") ||
+	     strstr(fpath + ftw->base, "ethernet"))) {
+
+		if (nic_count < OFWDEV_MAX)
+			niclist[nic_count++] = strdup(fpath + devtree_offset);
+
+	}
+	return 0;
+}
+
+static int nic_cmp(const void *a, const void *b)
+{
+	return strcmp(a, b);
+}
+
+static int find_initiator(const char *fpath,
+			  __attribute__((unused))const struct stat *sb,
+			  int tflag,
+			  struct FTW *ftw)
+{
+	struct ofw_dev *dev;
+
+	if (tflag == FTW_F && (strstr(fpath + ftw->base,
+				      "/aliases/iscsi-disk"))) {
+
+		if (dev_count < OFWDEV_MAX) {
+			dev = calloc(sizeof(struct ofw_dev), 1);
+			if (!dev)
+				return -ENOMEM;
+
+			dev->prop_path = strdup(fpath + devtree_offset);
+			if (!dev->prop_path) {
+				free(dev);
+				return errno;
+			}
+			ofwdevs[dev_count++] = dev;
+		}
+	}
+	return 0;
+}
+
+static int loop_devs(const char *devtree)
+{
+	int error;
+	int i;
+	char prefix[256];
+
+	nic_count = 0;
+	error = nftw(devtree, find_nics, 20, 0);
+	if (error)
+		return error;
+
+	/*
+	 * Sort the nics into "natural" order.	The proc fs
+	 * device-tree has them in somewhat random, or reversed order.
+	 */
+	qsort(niclist, nic_count, sizeof(char *), nic_cmp);
+
+	snprintf(prefix, sizeof(prefix), "%s/%s", devtree, "aliases");
+	dev_count = 0;
+	error = nftw(prefix, find_initiator, 20, 0);
+	if (error)
+		return error;
+
+	for (i = 0; i < dev_count; i++) {
+		snprintf(prefix, sizeof(prefix), "%s%s", devtree,
+			 ofwdevs[i]->prop_path);
+		if (find_file(prefix) > 0) {
+			error = parse_params(bootpath_val, ofwdevs[i]);
+			if (!error)
+				error = locate_mac(devtree, ofwdevs[i]);
+
+			free(bootpath_val);
+			bootpath_val = NULL;
+		}
+	}
+	return error;
+}
+
+#define set_context(fld,abrv,item)					\
+	cp_param(context->fld, (abrv), ofwdev, (item), sizeof(context->fld))
+#define set_int_context(fld,abrv,item)					    \
+	cp_int_param(&context->fld, (abrv), ofwdev, (item))
+
+static void fill_context(struct boot_context *context, struct ofw_dev *ofwdev)
+{
+	int ndx;
+
+	memset(context, 0, sizeof(*context));
+
+	set_context(initiatorname, "NAME", OBP_PARAM_ITNAME);
+
+	snprintf(context->mac, sizeof(context->mac),
+		 "%02x:%02x:%02x:%02x:%02x:%02x",
+		 ofwdev->mac[0], ofwdev->mac[1], ofwdev->mac[2],
+		 ofwdev->mac[3], ofwdev->mac[4], ofwdev->mac[5]);
+
+	/*
+	 * nic parameters
+	 */
+	for (ndx = 0; ndx < nic_count; ndx++) {
+		if (!strcmp(niclist[ndx], ofwdev->dev_path)) {
+			snprintf(context->iface, sizeof(context->iface),
+				 "eth%d", ndx);
+			break;
+		}
+	}
+
+	set_context(ipaddr, "IPADDR", OBP_PARAM_CIADDR);
+	set_context(mask, "MASK", OBP_PARAM_SUBNET_MASK);
+
+	/*
+	 * target parameters
+	 */
+	set_context(target_ipaddr, "IPADDR", OBP_PARAM_SIADDR);
+	set_int_context(target_port, "PORT", OBP_PARAM_IPORT);
+	set_context(lun, "LUN", OBP_PARAM_ILUN);
+	set_context(targetname, "NAME", OBP_PARAM_INAME);
+	set_context(isid, "ISID", OBP_PARAM_ISID);
+
+	/*
+	 * chap stuff is always associated with the target
+	 */
+	set_context(chap_name, "CHAP_NAME", OBP_PARAM_ICHAPID);
+	set_context(chap_password, "CHAP_PASSWORD", OBP_PARAM_ICHAPPW);
+	set_context(chap_name_in, "CHAP_NAME_IN", OBP_PARAM_CHAPID);
+	set_context(chap_password_in, "CHAP_PASSWORD_IN", OBP_PARAM_CHAPPW);
+
+}
+
+int fwparam_ppc_boot_info(struct boot_context *context)
+{
+	char filename[FILENAMESZ];
+	int error;
+	char *devtree;
+	int i;
+
+	/*
+	 * For powerpc, our operations are fundamentally to locate
+	 * either the one boot target (the singleton disk), or to find
+	 * the nics that support iscsi boot.  The only nics in IBM
+	 * systems that can support iscsi are the ones that provide
+	 * the appropriate FCODE with a load method.
+	 */
+	memset(filename, 0, FILENAMESZ);
+	snprintf(filename, FILENAMESZ, "%s%s", DT_TOP, BOOTPATH);
+
+	if (debug)
+		fprintf(stderr, "%s: file:%s; debug:%d\n", __func__, filename,
+			debug);
+
+	devtree = find_devtree(filename);
+	if (!devtree)
+		return ISCSI_ERR_INVAL;
+
+	/*
+	 * Always search the device-tree to find the capable nic devices.
+	 */
+	error = loop_devs(devtree);
+	if (error)
+		goto free_devtree;
+
+	if (find_file(filename) < 1) {
+		error = ISCSI_ERR_NO_OBJS_FOUND;
+		goto free_devtree;
+	} else {
+		if (debug)
+			printf("%s:\n%s\n\n", filename, bootpath_val);
+		/*
+		 * We find *almost* everything we need in the
+		 * bootpath, save the mac-address.
+		 */
+
+		if (!strstr(bootpath_val, "iscsi")) {
+			error = ISCSI_ERR_INVAL;
+			goto free_bootpath_val;
+		}
+		ofwdevs[0] = calloc(1, sizeof(struct ofw_dev));
+		if (!ofwdevs[0]) {
+			error = ISCSI_ERR_NOMEM;
+			goto free_bootpath_val;
+		}
+
+		error = parse_params(bootpath_val, ofwdevs[0]);
+		if (!error)
+			error = locate_mac(devtree, ofwdevs[0]);
+		if (!error) {
+			if (!context)
+				error = ISCSI_ERR_NOMEM;
+			else
+				fill_context(context, ofwdevs[0]);
+		}
+		free(ofwdevs[0]);
+	}
+
+free_bootpath_val:
+	free(bootpath_val);
+	bootpath_val = NULL;
+
+free_devtree:
+	free(devtree);
+	for (i = 0; i < dev_count; i++)
+		if (ofwdevs[i])
+			free(ofwdevs[i]);
+
+	return error;
+}
+
+/*
+ * Due to lack of time this is just fwparam_ppc_boot_info which
+ * adds the target used for boot to the list. It does not add
+ * all possible targets (IBM please add).
+ */
+int fwparam_ppc_get_targets(struct list_head *list)
+{
+	char filename[FILENAMESZ];
+	struct boot_context *context;
+	int error;
+	char *devtree;
+	int i;
+
+	/*
+	 * For powerpc, our operations are fundamentally to locate
+	 * either the one boot target (the singleton disk), or to find
+	 * the nics that support iscsi boot.  The only nics in IBM
+	 * systems that can support iscsi are the ones that provide
+	 * the appropriate FCODE with a load method.
+	 */
+	memset(filename, 0, FILENAMESZ);
+	snprintf(filename, FILENAMESZ, "%s%s", DT_TOP, BOOTPATH);
+
+	if (debug)
+		fprintf(stderr, "%s: file:%s; debug:%d\n", __func__, filename,
+			debug);
+
+	devtree = find_devtree(filename);
+	if (!devtree)
+		return ISCSI_ERR_INVAL;
+
+	/*
+	 * Always search the device-tree to find the capable nic devices.
+	 */
+	error = loop_devs(devtree);
+	if (error)
+		goto free_devtree;
+
+	if (find_file(filename) < 1) {
+		error = ISCSI_ERR_NO_OBJS_FOUND;
+		goto free_devtree;
+	} else {
+		if (debug)
+			printf("%s:\n%s\n\n", filename, bootpath_val);
+		/*
+		 * We find *almost* everything we need in the
+		 * bootpath, save the mac-address.
+		 */
+
+		if (!strstr(bootpath_val, "iscsi")) {
+			error = ISCSI_ERR_INVAL;
+			goto free_bootpath_val;
+		}
+		ofwdevs[0] = calloc(1, sizeof(struct ofw_dev));
+		if (!ofwdevs[0]) {
+			error = ISCSI_ERR_NOMEM;
+			goto free_bootpath_val;
+		}
+
+		error = parse_params(bootpath_val, ofwdevs[0]);
+		if (!error)
+			error = locate_mac(devtree, ofwdevs[0]);
+		if (!error) {
+			context = calloc(1, sizeof(*context));
+			if (!context)
+				error = ISCSI_ERR_NOMEM;
+			else {
+				fill_context(context, ofwdevs[0]);
+				list_add_tail(&context->list, list);
+			}
+		}
+		free(ofwdevs[0]);
+	}
+free_bootpath_val:
+	free(bootpath_val);
+	bootpath_val = NULL;
+
+free_devtree:
+	free(devtree);
+	for (i = 0; i < dev_count; i++)
+		if (ofwdevs[i])
+			free(ofwdevs[i]);
+
+	return error;
+}
diff -pruN 2.1.5-1/usr/fwparam_ibft/fwparam_sysfs.c 2.1.7-2/usr/fwparam_ibft/fwparam_sysfs.c
--- 2.1.5-1/usr/fwparam_ibft/fwparam_sysfs.c	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/fwparam_sysfs.c	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,533 @@
+/*
+ * Copyright (C) IBM Corporation. 2007
+ * Author: Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
+ * Copyright (C) Red Hat, Inc.  All rights reserved. 2008 - 2010
+ * Copyright (C) Mike Christie 2008 - 2010
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#define  _XOPEN_SOURCE 500
+#define _DEFAULT_SOURCE
+#include <ftw.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "sysfs.h"
+#include "fw_context.h"
+#include "fwparam.h"
+#include "sysdeps.h"
+#include "iscsi_net_util.h"
+#include "iscsi_err.h"
+
+#define ISCSI_BOOT_MAX		255
+#define IBFT_SYSFS_ROOT		"/sys/firmware/ibft/"
+#define IBFT_SUBSYS		"ibft"
+
+#define ISCSI_LLD_ROOT		"/sys/firmware/"
+#define ISCSI_LLD_SUBSYS_PREFIX	"iscsi_boot"
+
+static char *target_list[ISCSI_BOOT_MAX];
+static char *nic_list[ISCSI_BOOT_MAX];
+static int nic_cnt;
+static int tgt_cnt;
+
+static int file_exist(const char *file)
+{
+	struct stat bootpath_stat;
+
+	return !stat(file, &bootpath_stat);
+}
+
+/*
+ * Finds the etherrnetX and targetX under the sysfs directory.
+ */
+static int find_sysfs_dirs(const char *fpath,
+			   __attribute__((unused))const struct stat *sb,
+			   int tflag,
+			   struct FTW *ftw)
+{
+	if (tflag == FTW_D && (strstr(fpath + ftw->base, "target"))) {
+		if (tgt_cnt == ISCSI_BOOT_MAX) {
+			printf("Too many targets found in iSCSI boot data."
+			       "Max number of targets %d\n", ISCSI_BOOT_MAX);
+			return 0;
+		}
+		target_list[tgt_cnt++] = strdup(strstr(fpath, "target"));
+	}
+
+	if (tflag == FTW_D && (strstr(fpath + ftw->base, "ethernet"))) {
+		if (nic_cnt == ISCSI_BOOT_MAX) {
+			printf("Too many nics found in iSCSI boot data."
+			       "Max number of nics %d\n", ISCSI_BOOT_MAX);
+			return 0;
+		}
+		nic_list[nic_cnt++] = strdup(strstr(fpath, "ethernet"));
+	}
+
+	return 0;
+}
+ 
+static int get_iface_from_device(char *id, struct boot_context *context)
+{
+	char dev_dir[FILENAMESZ];
+	int rc = ENODEV;
+	DIR *dirfd;
+	struct dirent *dent;
+
+	memset(dev_dir, 0, FILENAMESZ);
+	snprintf(dev_dir, FILENAMESZ, IBFT_SYSFS_ROOT"/%s/device", id);
+
+	if (!file_exist(dev_dir))
+		return 0;
+
+	dirfd = opendir(dev_dir);
+	if (!dirfd)
+		return errno;
+
+	while ((dent = readdir(dirfd))) {
+		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..") ||
+		    strncmp(dent->d_name, "net:", 4))
+			continue;
+
+		if (!strncmp(dent->d_name, "net:", 4)) {
+			if ((strlen(dent->d_name) - 4) >
+			    (sizeof(context->iface) - 1)) {
+				rc = EINVAL;
+				printf("Net device %s too big for iface "
+				       "buffer.\n", dent->d_name);
+				break;
+			}
+
+			if (sscanf(dent->d_name, "net:%s", context->iface) != 1) {
+				rc = EINVAL;
+				break;
+			}
+
+			rc = 0;
+			break;
+		} else {
+			printf("Could not read ethernet to net link.\n");
+			rc = EOPNOTSUPP;
+			break;
+		}
+	}
+
+	closedir(dirfd);
+
+	if (rc != ENODEV)
+		return rc;
+
+	/* If not found try again with newer kernel networkdev sysfs layout */
+	strlcat(dev_dir, "/net", FILENAMESZ);
+
+	if (!file_exist(dev_dir))
+		return rc;
+
+	dirfd = opendir(dev_dir);
+	if (!dirfd)
+		return errno;
+
+	while ((dent = readdir(dirfd))) {
+		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
+			continue;
+
+		/* Take the first "regular" directory entry */
+		if (strlen(dent->d_name) > (sizeof(context->iface) - 1)) {
+			rc = EINVAL;
+			printf("Net device %s too big for iface buffer.\n",
+			       dent->d_name);
+			break;
+		}
+
+		strcpy(context->iface, dent->d_name);
+		rc = 0;
+		break;
+	}
+
+	closedir(dirfd);
+	return rc;
+}
+
+/*
+ * Routines to fill in the context values.
+ */
+static int fill_nic_context(char *subsys, char *id,
+			    struct boot_context *context)
+{
+	int rc;
+
+	rc = sysfs_get_int(id, subsys, "flags", &context->nic_flags);
+	/*
+	 * Per spec we would need to check against Bit 0
+	 * (Block Valid Flag), but some firmware only
+	 * sets Bit 1 (Firmware Booting Selected).
+	 * So any setting is deemed okay.
+	 */
+	if (!rc && (context->nic_flags == 0))
+		rc = ENODEV;
+	if (rc)
+		return rc;
+
+	rc = sysfs_get_str(id, subsys, "mac", context->mac,
+			   sizeof(context->mac));
+	if (rc)
+		return rc;
+
+	/*
+	 * Some offload cards like bnx2i use different MACs for the net and
+	 * iscsi functions, so we have to follow the sysfs links.
+	 *
+	 * Other ibft implementations may not be tied to a pci function,
+	 * so there will not be any device/net link, so we drop down to
+	 * the MAC matching.
+	 *
+	 * And finally, some cards like be2iscsi and qla4xxx do not have
+	 * any linux network subsys representation. These hosts will
+	 * not have the ibft subsys. Instead the subsys is the scsi host
+	 * number.
+	 */
+	if (!strcmp(IBFT_SUBSYS, subsys)) {
+		rc = get_iface_from_device(id, context);
+		if (rc) {
+			rc = net_get_netdev_from_hwaddress(context->mac,
+							   context->iface);
+			if (rc)
+				return rc;
+		}
+	} else
+		strlcpy(context->scsi_host_name, subsys,
+			sizeof(context->scsi_host_name));
+
+	memset(&context->boot_nic, 0, sizeof(context->boot_nic));
+	snprintf(context->boot_nic, sizeof(context->boot_nic), "%s", id);
+
+	sysfs_get_str(id, subsys, "ip-addr", context->ipaddr,
+		      sizeof(context->ipaddr));
+	sysfs_get_str(id, subsys, "vlan", context->vlan,
+		      sizeof(context->vlan));
+	sysfs_get_str(id, subsys, "subnet-mask", context->mask,
+		      sizeof(context->mask));
+	sysfs_get_int(id, subsys, "prefix-len", &context->prefix);
+	sysfs_get_str(id, subsys, "gateway", context->gateway,
+		      sizeof(context->gateway));
+	sysfs_get_str(id, subsys, "primary-dns", context->primary_dns,
+		      sizeof(context->primary_dns));
+	sysfs_get_str(id, subsys, "secondary-dns", context->secondary_dns,
+		      sizeof(context->secondary_dns));
+	sysfs_get_str(id, subsys, "dhcp", context->dhcp,
+		      sizeof(context->dhcp));
+	sysfs_get_int(id, subsys, "origin", (int *)&context->origin);
+	return 0;
+}
+
+static void fill_initiator_context(char *subsys, struct boot_context *context)
+{
+	sysfs_get_str("initiator", subsys, "initiator-name",
+		      context->initiatorname,
+		      sizeof(context->initiatorname));
+	sysfs_get_str("initiator", subsys, "isid", context->isid,
+		      sizeof(context->isid));
+
+	strlcpy(context->boot_root, subsys, sizeof(context->boot_root));
+}
+static int fill_tgt_context(char *subsys, char *id,
+			    struct boot_context *context)
+{
+	int rc;
+
+	rc = sysfs_get_int(id, subsys, "flags", &context->target_flags);
+	/*
+	 * Per spec we would need to check against Bit 0
+	 * (Block Valid Flag), but some firmware only
+	 * sets Bit 1 (Firmware Booting Selected).
+	 * So any setting is deemed okay.
+	 */
+	if (!rc && (context->target_flags == 0))
+		rc = ENODEV;
+	if (rc)
+		return rc;
+
+	rc = sysfs_get_str(id, subsys, "target-name", context->targetname,
+			   sizeof(context->targetname));
+	if (rc)
+		return rc;
+
+	rc = sysfs_get_str(id, subsys, "ip-addr", context->target_ipaddr,
+			   sizeof(context->target_ipaddr));
+	if (rc)
+		return rc;
+
+	memset(&context->boot_target, 0, sizeof(context->boot_target));
+	snprintf(context->boot_target, sizeof(context->boot_target), "%s", id);
+
+	/*
+	 * We can live without the rest of they do not exist. If we
+	 * failed to get them we will figure it out when we login.
+	 */
+	if (sysfs_get_int(id, subsys, "port", &context->target_port))
+		context->target_port = ISCSI_LISTEN_PORT;
+
+	sysfs_get_str(id, subsys, "lun", context->lun,
+		      sizeof(context->lun));
+	sysfs_get_str(id, subsys, "chap-name", context->chap_name,
+		      sizeof(context->chap_name));
+	sysfs_get_str(id, subsys, "chap-secret", context->chap_password,
+		      sizeof(context->chap_password));
+	sysfs_get_str(id, subsys, "rev-chap-name", context->chap_name_in,
+		      sizeof(context->chap_name_in));
+	sysfs_get_str(id, subsys, "rev-chap-name-secret",
+		      context->chap_password_in,
+		      sizeof(context->chap_password_in));
+	return 0;
+}
+
+#define IBFT_SYSFS_FLAG_FW_SEL_BOOT 2
+
+static int find_boot_flag(char *subsys, char *list[], ssize_t size,
+			  int *boot_idx)
+{
+	int rc = ENODEV;
+	int i, flag = 0;
+
+	for (i = 0; i < size; i++, flag = -1) {
+		rc = sysfs_get_int(list[i], subsys, "flags", &flag);
+		if (rc)
+			continue;
+
+		if (flag & IBFT_SYSFS_FLAG_FW_SEL_BOOT) {
+			*boot_idx = i;
+			rc = 0;
+			break;
+		}
+		rc = ENODEV;
+		flag = 0;
+
+	}
+
+	return rc;
+}
+
+static void deallocate_lists(void)
+{
+	int i;
+
+	for (i = 0; i < nic_cnt; i++)
+		free(nic_list[i]);
+
+	nic_cnt = 0;
+	for (i = 0; i < tgt_cnt; i++)
+		free(target_list[i]);
+
+	tgt_cnt = 0;
+
+}
+
+static int get_boot_info(struct boot_context *context, char *rootdir,
+			 char *subsys)
+{
+	char initiator_dir[FILENAMESZ];
+	int rc = ENODEV;
+	int nic_idx = -1, tgt_idx = -1;
+
+	memset(&initiator_dir, 0 , FILENAMESZ);
+	snprintf(initiator_dir, FILENAMESZ, "%sinitiator", rootdir);
+
+	nic_cnt = 0;
+	tgt_cnt = 0;
+	if (file_exist(initiator_dir)) {
+		/* Find the targets and the ethernets */
+		rc = nftw(rootdir, find_sysfs_dirs, 20, 1);
+
+		/* Find wihch target and which ethernet have
+		the boot flag set. */
+		rc = find_boot_flag(subsys, nic_list, nic_cnt, &nic_idx);
+		if (rc)
+			goto free;
+
+		rc = find_boot_flag(subsys, target_list, tgt_cnt, &tgt_idx);
+		if (rc)
+			goto free;
+
+		/* Fill in the context values */
+		rc = fill_nic_context(subsys, nic_list[nic_idx], context);
+		rc |= fill_tgt_context(subsys, target_list[tgt_idx], context);
+		fill_initiator_context(subsys, context);
+	}
+free:
+	deallocate_lists();
+	return rc;
+}
+
+int fwparam_sysfs_boot_info(struct boot_context *context)
+{
+	struct dirent *dent;
+	DIR *dirfd;
+	int rc = 0;
+
+	if (!get_boot_info(context, IBFT_SYSFS_ROOT, IBFT_SUBSYS))
+		return 0;
+	/*
+	 * We could have multiple iscsi llds and each lld could have
+	 * multiple targets/ethernet ports
+	 */
+	dirfd = opendir(ISCSI_LLD_ROOT);
+	if (!dirfd)
+		return ISCSI_ERR_SYSFS_LOOKUP;
+
+	while ((dent = readdir(dirfd))) {
+		char lld_root[FILENAMESZ];
+
+		memset(&lld_root, 0 , FILENAMESZ);
+
+		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
+			continue;
+
+		if (strncmp(dent->d_name, ISCSI_LLD_SUBSYS_PREFIX, 10))
+			continue;
+
+		snprintf(lld_root, FILENAMESZ, ISCSI_LLD_ROOT"%s/",
+			 dent->d_name);
+		if (!get_boot_info(context, lld_root, dent->d_name))
+			goto done;
+	}
+	rc = ISCSI_ERR_NO_OBJS_FOUND;
+done:
+	closedir(dirfd);
+	return rc;
+}
+
+static int get_targets(struct list_head *list, char *rootdir, char *subsys)
+{
+	struct boot_context *context;
+	int rc = 0, i, nic_idx, nic;
+	char initiator_dir[FILENAMESZ];
+
+	memset(&initiator_dir, 0 , FILENAMESZ);
+	snprintf(initiator_dir, FILENAMESZ, "%sinitiator", rootdir);
+
+	if (!file_exist(initiator_dir))
+		return ENODEV;
+
+	nic_cnt = 0;
+	tgt_cnt = 0;
+
+	/* Find the targets and the ethernets */
+	nftw(rootdir, find_sysfs_dirs, 20, 1);
+	for (i = 0; i < tgt_cnt; i++) {
+		context = calloc(1, sizeof(*context));
+		if (!context) {
+			rc = ENOMEM;
+			break;
+		}
+
+		rc = fill_tgt_context(subsys, target_list[i], context);
+		if (rc)
+			goto cleanup;
+
+		rc = sysfs_get_int(target_list[i], subsys, "nic-assoc",
+				   &nic_idx);
+		if (rc)
+			goto cleanup;
+
+		for (nic = 0; nic < nic_cnt; nic++) {
+			int id;
+
+			rc = sysfs_get_int(nic_list[nic], subsys, "index",
+					   &id);
+			if (!rc && (id == nic_idx))
+				break;
+		}
+
+		if (nic == nic_cnt) {
+			printf("Invalid nic-assoc of %d. Max id %d.\n",
+			       nic_idx, nic_cnt);
+			goto cleanup;
+		}
+
+		rc = fill_nic_context(subsys, nic_list[nic], context);
+		if (rc)
+			goto cleanup;
+
+		fill_initiator_context(subsys, context);
+		list_add_tail(&context->list, list);
+		continue;
+cleanup:
+		free(context);
+		context = NULL;
+	}
+
+	if (rc) {
+		if (context)
+			free(context);
+		/*
+		 * If there are some valid targets return them. Most likely,
+		 * the driver/ibft-implementation reported partial info
+		 * for targets/initiators that were not used for boot.
+		 */
+		if (!list_empty(list))
+			rc = 0;
+	}
+
+	deallocate_lists();
+	return rc;
+}
+
+int fwparam_sysfs_get_targets(struct list_head *list)
+{
+	struct dirent *dent;
+	DIR *dirfd;
+	int rc = 0;
+
+	/* ibft only has one instance */
+	get_targets(list, IBFT_SYSFS_ROOT, IBFT_SUBSYS);
+	/*
+	 * We could have multiple iscsi llds and each lld could have
+	 * multiple targets/ethernet ports
+	 */
+	dirfd = opendir(ISCSI_LLD_ROOT);
+	if (!dirfd) {
+		rc = ISCSI_ERR_SYSFS_LOOKUP;
+		goto done;
+	}
+
+	while ((dent = readdir(dirfd))) {
+		char lld_root[FILENAMESZ];
+
+		memset(&lld_root, 0 , FILENAMESZ);
+		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
+			continue;
+
+		if (strncmp(dent->d_name, ISCSI_LLD_SUBSYS_PREFIX, 10))
+			continue;
+
+		snprintf(lld_root, FILENAMESZ, ISCSI_LLD_ROOT"%s/",
+			 dent->d_name);
+		get_targets(list, lld_root, dent->d_name);
+	}
+	closedir(dirfd);
+done:
+	if (!rc && list_empty(list))
+		rc = ISCSI_ERR_NO_OBJS_FOUND;
+	if (rc)
+		fw_free_targets(list);
+	return rc;
+}
diff -pruN 2.1.5-1/usr/fwparam_ibft/iscsi_obp.h 2.1.7-2/usr/fwparam_ibft/iscsi_obp.h
--- 2.1.5-1/usr/fwparam_ibft/iscsi_obp.h	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/iscsi_obp.h	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) IBM Corporation. 2007
+ * Author: Doug Maxey <dwm@austin.ibm.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ISCSI_OBP_H_
+#define ISCSI_OBP_H_
+
+enum  ofw_dev_type {
+	OFW_DT_NONE,
+	OFW_DT_BLOCK,
+	OFW_DT_NETWORK,
+	OFW_DT_ISCSI,
+};
+
+enum obp_tftp_qual {
+	OBP_QUAL_NONE,
+	OBP_QUAL_BOOTP,
+	OBP_QUAL_DHCPV6,
+	OBP_QUAL_IPV6,
+	OBP_QUAL_ISCSI,
+	OBP_QUAL_PING,
+	OBP_QUAL_COUNT,		/* Numnber of defined OBP qualifiers */
+};
+
+enum obp_param {
+	/*
+	 * Defined iscsi boot parameters.
+	 */
+	OBP_PARAM_NONE,
+	OBP_PARAM_BLKSIZE,	/* default is 512 */
+	OBP_PARAM_BOOTP_RETRIES, /* default 5 */
+	OBP_PARAM_CHAPID,	/* target chap id */
+	OBP_PARAM_CHAPPW,	/* target chap password */
+	OBP_PARAM_CIADDR,	/* client (my) ip addr */
+	OBP_PARAM_DHCP,		/* dhcp server address */
+	OBP_PARAM_FILENAME,	/* boot filename */
+	OBP_PARAM_GIADDR,	/* gateway addr */
+	OBP_PARAM_ICHAPID,	/* initiator chapid */
+	OBP_PARAM_ICHAPPW,	/* initiator chap password */
+	OBP_PARAM_ILUN,		/* misnomer, really the target lun */
+	OBP_PARAM_INAME,	/* NB: target iqn */
+	OBP_PARAM_IPORT,	/* initiator port, defaults to 3260 */
+	OBP_PARAM_ISID,		/* session id */
+	OBP_PARAM_ISNS,		/* sns server address */
+	OBP_PARAM_ITNAME,	/* NB: Initiator iqn */
+	OBP_PARAM_SIADDR,	/* iscsi server ip address. */
+	OBP_PARAM_SLP,		/* slp server address */
+	OBP_PARAM_SUBNET_MASK,
+	OBP_PARAM_TFTP_RETRIES,	/* default 5 */
+	OBP_PARAM_TIMEOUT,	/* ping timeout period. */
+
+	OBP_PARAM_COUNT,	/* number of defined OBP_PARAMs */
+};
+
+struct ofw_obp_param {
+	unsigned char  len;	/* length of value string. */
+	char	       val[1];	/* string value from the property */
+};
+
+struct ofw_dev {
+	char *prop_path; /* where we found these properties. */
+	enum ofw_dev_type type;	/* known type of boot device. */
+	int qual_count;		/* count of qualifiers. */
+	enum obp_tftp_qual quals[OBP_QUAL_COUNT];
+	struct ofw_obp_param *param[OBP_PARAM_COUNT];
+	int cfg_part;		/* boot partition number. */
+	char *dev_path;		/* path to this ofw device. */
+	unsigned char mac[6];	/* The binary mac address. */
+};
+
+const char *obp_qual_set(struct ofw_dev *ofwdev, const char *qual);
+void add_obp_parm(struct ofw_dev *ofwdev, enum obp_param parm, const char *str);
+void obp_parm_addr(struct ofw_dev *ofwdev, const char *parm, const char *addr);
+void obp_parm_iqn(struct ofw_dev *ofwdev, const char *parm, const char *iqn);
+void obp_parm_hexnum(struct ofw_dev *ofwdev, const char *parm,
+		     const char *numstr);
+void obp_parm_str(struct ofw_dev *ofwdev, const char *parm, const char *str);
+
+#endif /* ISCSI_OBP_H_ */
diff -pruN 2.1.5-1/usr/fwparam_ibft/Makefile 2.1.7-2/usr/fwparam_ibft/Makefile
--- 2.1.5-1/usr/fwparam_ibft/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/Makefile	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,70 @@
+#
+#  Copyright (C) IBM Corporation. 2007
+#  Author: Doug Maxey <dwm@austin.ibm.com>
+#
+#  This program is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+#  Authors: Patrick Mansfield <patmans@us.ibm.com>
+#	    Mike Anderson <andmike@us.ibm.com>
+#	    Doug Maxey <dwm@austin.ibm.com>
+#	    "Prasanna Mumbai" <mumbai.prasanna@gmail.com>
+#
+ifeq ($(TOPDIR),)
+	TOPDIR = ../..
+endif
+
+BISON = bison
+
+SBINDIR ?= $(DESTDIR)/sbin
+
+SYSDEPS_OBJS = $(sort $(wildcard ../sysdeps/*.o))
+OBJS := fw_entry.o fwparam_sysfs.o \
+	prom_lex.o prom_parse.tab.o fwparam_ppc.o
+CLEANFILES = $(OBJS) *.output
+
+CFLAGS ?= -O2 -g
+WARNFLAGS ?= -Wall -Wstrict-prototypes -Wno-format-truncation
+CFLAGS += -fPIC $(WARNFLAGS) -I$(TOPDIR)/include -I$(TOPDIR)/usr -D_GNU_SOURCE \
+	  -I$(TOPDIR)/libopeniscsiusr
+CFLAGS += -DSBINDIR=\"$(SBINDIR)\"
+
+LDFLAGS += -L$(TOPDIR)/libopeniscsiusr -liscsiusr
+
+all: $(OBJS)
+
+clean:
+	$(RM) $(CLEANFILES) .depend
+
+$(OBJS): prom_parse.tab.h prom_parse.h
+
+#
+# This directory is set up so that lex and bison should not have
+# to be run to generate C files, since the C files have already
+# been checked in and are present. This eliminates the need to run
+# them on systems where those tools may not be present. If you wish
+# to run either of them to regenerate their output files, remove
+# the output files first. This prevents these tools from being run
+# again if the output files are already present.
+#
+
+prom_lex.c: prom_lex.l
+	@[ -f $@ ] || $(LEX) -t $? > $@
+
+prom_parse.tab.c prom_parse.tab.h: prom_parse.y
+	@[ -f prom_parse.tab.c ] && [ -f prom_parse.tab.h ] || $(BISON) -H $?
+
+depend:
+	$(CC) $(CFLAGS) -M `ls *.c` > .depend
+
+-include .depend
diff -pruN 2.1.5-1/usr/fwparam_ibft/prom_lex.c 2.1.7-2/usr/fwparam_ibft/prom_lex.c
--- 2.1.5-1/usr/fwparam_ibft/prom_lex.c	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/prom_lex.c	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,2298 @@
+
+#line 3 "<stdout>"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file  );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
+void yy_delete_buffer (YY_BUFFER_STATE b  );
+void yy_flush_buffer (YY_BUFFER_STATE b  );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );
+
+void *yyalloc (yy_size_t  );
+void *yyrealloc (void *,yy_size_t  );
+void yyfree (void *  );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
+extern char yytext[];
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	if ( yyleng >= YYLMAX ) \
+		YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \
+	yy_flex_strncpy( yytext, (yytext_ptr), yyleng + 1 ); \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 17
+#define YY_END_OF_BUFFER 18
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[444] =
+    {   0,
+        0,    0,   18,   16,   15,   15,   12,   12,   16,   12,
+       12,   12,   12,   12,   12,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   15,    0,   12,   12,   14,
+        0,    0,    0,   12,    0,    0,   12,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   10,    0,
+        0,    0,    0,    0,    0,    0,   12,   12,   14,    7,
+        0,    0,    0,    0,    0,    4,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   11,    0,
+
+        0,    0,    0,    0,   12,    0,    0,    0,    0,    0,
+       11,    0,    0,    0,    0,    0,    0,    0,    6,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       13,    0,    0,    6,    0,    0,    0,    0,    0,    0,
+        0,    3,    0,    9,    6,    0,    0,    5,    0,    0,
+        0,    0,    0,    0,   13,    0,    0,    0,    0,    0,
+        0,    0,    0,    9,    0,    0,    0,    0,    0,    8,
+        0,   13,    0,    0,    0,    0,    0,    9,    0,    0,
+        0,    0,    0,    0,    2,    8,   13,    1,    0,    9,
+        0,    0,    0,    0,    0,    0,    8,   13,    0,    9,
+
+        0,    0,   10,    0,    0,    0,   13,    0,    9,    0,
+        0,    0,    0,    0,   13,    0,    9,    0,    0,    0,
+       13,    0,    9,    0,    0,   13,    9,    0,    0,   13,
+        9,   13,    9,   13,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    4,    5,    1,    6,    6,    7,
+        6,    6,    6,    8,    6,    6,    6,    9,    1,    1,
+        1,    1,    1,    1,   10,   10,   10,   10,   10,   10,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+        1,   12,    1,    1,    1,    1,   13,   14,   15,   16,
+
+       17,   18,   19,   20,   21,   11,   22,   23,   24,   25,
+       26,   27,   28,   29,   30,   31,   32,   33,   34,   11,
+       11,   35,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[36] =
+    {   0,
+        1,    1,    1,    2,    3,    4,    4,    4,    5,    4,
+        2,    6,    4,    4,    4,    4,    4,    4,    2,    2,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2,    2,    2,    2
+    } ;
+
+static yyconst flex_int16_t yy_base[680] =
+    {   0,
+        0,    0, 1198, 1199,   34,   36,   35, 1192,    0,   39,
+       40,   41,   47,   42,   44,   29,   67, 1176, 1182, 1179,
+     1180,   86, 1174, 1161, 1174,   51,   69,   73, 1184,    0,
+     1175, 1165, 1160,   43, 1172, 1171,   51, 1168, 1152, 1161,
+     1157, 1166, 1163, 1162, 1156, 1158, 1142, 1160,   25, 1147,
+       85, 1146, 1153, 1139, 1147, 1133, 1135, 1135, 1199, 1151,
+     1136, 1148, 1130, 1146, 1142,   80, 1153, 1152,    0, 1199,
+     1126, 1124, 1128, 1126, 1136, 1199, 1124, 1128, 1132, 1131,
+     1131, 1116, 1132, 1119, 1119, 1113, 1133, 1135, 1109, 1122,
+     1107, 1123, 1122, 1130, 1112, 1119, 1110, 1114, 1199, 1104,
+
+     1101, 1094,   97,  106,    0, 1105,   42, 1101,   94, 1108,
+     1090, 1093, 1096, 1104, 1098, 1091, 1100, 1085, 1199,    0,
+     1094, 1090, 1099, 1086, 1095, 1093, 1105, 1087,  117, 1102,
+        0, 1071, 1076,  104, 1088, 1069, 1073, 1093, 1075, 1086,
+     1069, 1199,   99,    0, 1093, 1079, 1069, 1199, 1065, 1062,
+     1063, 1076,  121,  125,    0, 1073, 1070, 1059, 1056, 1069,
+     1061, 1068, 1049,    0,  120, 1056, 1077, 1063, 1062,  131,
+     1073,    0, 1047, 1059, 1055, 1043, 1056,    0, 1046, 1050,
+     1044, 1038, 1044, 1036, 1199,  134,    0, 1199, 1035,    0,
+     1039, 1034, 1046, 1046, 1048, 1031, 1199,    0, 1030,    0,
+
+     1027, 1035, 1199, 1039, 1025, 1033,    0, 1032,    0, 1039,
+      137, 1018, 1028, 1032,    0, 1031,    0, 1018, 1025, 1015,
+        0, 1014,    0,  145,  142,    0,    0,  120,  132,    0,
+        0,    0,    0, 1199,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0, 1199, 1199,  149,  152,  156,  159,  163,  144,  166,
+      143,  170,  142,  174,  131,  178,  115,  182,  112,  186,
+       92,  190,   89,  194,   87,  198,   85,  202,   67,  206,
+       56,  210,  214,  218,  222,  226,  230,  234,  238,  242,
+      246,  250,  254,  258,  262,  266,  270,  274,  278,  282,
+      286,  290,  294,  298,  302,  306,  310,  314,  318,  322,
+
+      326,  330,  334,  338,  342,  346,  350,  354,  358,  362,
+      366,  370,  374,  378,  382,  386,  390,  394,  398,  402,
+      406,  410,  414,  418,  422,  426,  430,  434,  438,  442,
+      446,  450,  454,  458,  462,  466,  470,  474,  478,  482,
+      486,  490,  494,  498,  502,  506,  510,  514,  518,  522,
+      526,  530,  534,  538,  542,  546,  550,  554,  558,  562,
+      566,  570,  574,  578,  582,  586,  590,  594,  598,  602,
+      606,  610,  614,  618,  622,  626,  630,  634,  638,  642,
+      646,  650,  654,  658,  662,  666,  670,  674,  678,  682,
+      686,  690,  694,  698,  702,  706,  710,  714,  718,  722,
+
+      726,  730,  734,  738,  742,  746,  750,  754,  758,  762,
+      766,  770,  774,  778,  782,  786,  790,  794,  798,  802,
+      806,  810,  814,  818,  822,  826,  830,  834,  838,  842,
+      846,  850,  854,  858,  862,  866,  870,  874,  878,  882,
+      886,  890,  894,  898,  902,  906,  910,  914,  918,  922,
+      926,  930,  934,  938,  942,  946,  950,  954,  958,  962,
+      966,  970,  974,  978,  982,  986,  990,  994,  998, 1002,
+     1006, 1010, 1014, 1018, 1022, 1026, 1030, 1034, 1038
+    } ;
+
+static yyconst flex_int16_t yy_def[680] =
+    {   0,
+      443,    1,  443,  443,  443,  443,  444,  444,  445,  444,
+      444,  444,  444,  444,  444,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  446,  446,  447,
+      443,  443,  443,  446,  443,  443,  446,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  448,  448,  447,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+
+      443,  443,  443,  443,  449,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  450,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      451,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  452,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  453,  443,  443,  443,  443,  443,
+      443,  443,  443,  454,  443,  443,  443,  443,  443,  443,
+      443,  455,  443,  443,  443,  443,  443,  456,  443,  443,
+      443,  443,  443,  443,  443,  443,  457,  443,  443,  458,
+      443,  443,  443,  443,  443,  443,  443,  459,  443,  460,
+
+      443,  443,  443,  443,  443,  443,  461,  443,  462,  443,
+      443,  443,  443,  443,  463,  443,  464,  443,  443,  443,
+      465,  443,  466,  443,  443,  467,  468,  443,  443,  469,
+      470,  471,  472,  443,  473,  474,  475,  476,  477,  478,
+      479,  480,  481,  482,  483,  484,  485,  486,  487,  488,
+      489,  490,  491,  492,  493,  494,  495,  496,  497,  498,
+      499,  500,  501,  502,  503,  504,  505,  506,  507,  508,
+      509,  510,  511,  512,  513,  514,  515,  516,  517,  518,
+      519,  520,  521,  522,  523,  524,  525,  526,  527,  528,
+      529,  530,  531,  532,  533,  534,  535,  536,  537,  538,
+
+      539,  540,  541,  542,  543,  544,  545,  546,  547,  548,
+      549,  550,  551,  552,  553,  554,  555,  556,  557,  558,
+      559,  560,  561,  562,  563,  564,  565,  566,  567,  568,
+      569,  570,  571,  572,  573,  574,  575,  576,  577,  578,
+      579,  580,  581,  582,  583,  584,  585,  586,  587,  588,
+      589,  590,  591,  592,  593,  594,  595,  596,  597,  598,
+      599,  600,  601,  602,  603,  604,  605,  606,  607,  608,
+      609,  610,  611,  612,  613,  614,  615,  616,  617,  618,
+      619,  620,  621,  622,  623,  624,  625,  626,  627,  628,
+      629,  630,  631,  632,  633,  634,  635,  636,  637,  638,
+
+      639,  640,  641,  642,  643,  644,  645,  646,  647,  648,
+      649,  650,  651,  652,  653,  654,  655,  656,  657,  658,
+      659,  660,  661,  662,  663,  664,  665,  666,  667,  668,
+      669,  670,  671,  672,  673,  674,  675,  676,  677,  678,
+      679,  443,    0,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443
+    } ;
+
+static yyconst flex_int16_t yy_nxt[1235] =
+    {   0,
+        4,    5,    6,    4,    4,    7,    7,    7,    4,    8,
+        4,    9,   10,   11,   12,   13,   14,   15,   16,    4,
+       17,    4,   18,    4,   19,    4,   20,    4,   21,   22,
+       23,   24,   25,    4,    4,   26,   26,   26,   26,   27,
+       28,   28,   28,  443,  443,  443,  443,  443,  443,   42,
+       86,  443,   26,   26,  133,  443,   34,   87,   43,  234,
+       35,   36,   32,   37,   41,   33,   38,   39,  134,   31,
+      232,   73,   40,   44,   66,   66,   66,   27,   67,   67,
+       67,   45,   46,   76,  103,  104,  104,  104,  230,   47,
+      226,   48,  221,   49,   50,  215,   51,   52,   57,   89,
+
+       58,   59,  129,  129,  129,   90,   60,  158,   61,   91,
+      103,  130,  130,  130,  135,  207,  159,   62,  198,  162,
+      136,  153,  154,  154,  154,  163,  170,  170,  170,  153,
+      171,  171,  171,  179,  187,  180,  186,  186,  186,  197,
+      197,  197,  203,  203,  203,  172,  155,  131,  188,  188,
+      181,   29,   29,   30,   30,   30,  229,   30,   68,   68,
+       69,   69,   69,  228,   69,  105,  105,  144,  144,  144,
+      144,  164,  164,  164,  164,  178,  178,  178,  178,  190,
+      190,  190,  190,  200,  200,  200,  200,  209,  209,  209,
+      209,  217,  217,  217,  217,  223,  223,  223,  223,  227,
+
+      227,  227,  227,  231,  231,  231,  231,  233,  233,  233,
+      233,  235,  235,  235,  235,  236,  236,  236,  236,  237,
+      237,  237,  237,  238,  238,  238,  238,  239,  239,  239,
+      239,  240,  240,  240,  240,  241,  241,  241,  241,  242,
+      242,  242,  242,  243,  243,  243,  243,  244,  244,  244,
+      244,  245,  245,  245,  245,  246,  246,  246,  246,  247,
+      247,  247,  247,  248,  248,  248,  248,  249,  249,  249,
+      249,  250,  250,  250,  250,  251,  251,  251,  251,  252,
+      252,  252,  252,  253,  253,  253,  253,  254,  254,  254,
+      254,  255,  255,  255,  255,  256,  256,  256,  256,  257,
+
+      257,  257,  257,  258,  258,  258,  258,  259,  259,  259,
+      259,  260,  260,  260,  260,  261,  261,  261,  261,  262,
+      262,  262,  262,  263,  263,  263,  263,  264,  264,  264,
+      264,  265,  265,  265,  265,  266,  266,  266,  266,  267,
+      267,  267,  267,  268,  268,  268,  268,  269,  269,  269,
+      269,  270,  270,  270,  270,  271,  271,  271,  271,  272,
+      272,  272,  272,  273,  273,  273,  273,  274,  274,  274,
+      274,  275,  275,  275,  275,  276,  276,  276,  276,  277,
+      277,  277,  277,  278,  278,  278,  278,  279,  279,  279,
+      279,  280,  280,  280,  280,  281,  281,  281,  281,  282,
+
+      282,  282,  282,  283,  283,  283,  283,  284,  284,  284,
+      284,  285,  285,  285,  285,  286,  286,  286,  286,  287,
+      287,  287,  287,  288,  288,  288,  288,  289,  289,  289,
+      289,  290,  290,  290,  290,  291,  291,  291,  291,  292,
+      292,  292,  292,  293,  293,  293,  293,  294,  294,  294,
+      294,  295,  295,  295,  295,  296,  296,  296,  296,  297,
+      297,  297,  297,  298,  298,  298,  298,  299,  299,  299,
+      299,  300,  300,  300,  300,  301,  301,  301,  301,  302,
+      302,  302,  302,  303,  303,  303,  303,  304,  304,  304,
+      304,  305,  305,  305,  305,  306,  306,  306,  306,  307,
+
+      307,  307,  307,  308,  308,  308,  308,  309,  309,  309,
+      309,  310,  310,  310,  310,  311,  311,  311,  311,  312,
+      312,  312,  312,  313,  313,  313,  313,  314,  314,  314,
+      314,  315,  315,  315,  315,  316,  316,  316,  316,  317,
+      317,  317,  317,  318,  318,  318,  318,  319,  319,  319,
+      319,  320,  320,  320,  320,  321,  321,  321,  321,  322,
+      322,  322,  322,  323,  323,  323,  323,  324,  324,  324,
+      324,  325,  325,  325,  325,  326,  326,  326,  326,  327,
+      327,  327,  327,  328,  328,  328,  328,  329,  329,  329,
+      329,  330,  330,  330,  330,  331,  331,  331,  331,  332,
+
+      332,  332,  332,  333,  333,  333,  333,  334,  334,  334,
+      334,  335,  335,  335,  335,  336,  336,  336,  336,  337,
+      337,  337,  337,  338,  338,  338,  338,  339,  339,  339,
+      339,  340,  340,  340,  340,  341,  341,  341,  341,  342,
+      342,  342,  342,  343,  343,  343,  343,  344,  344,  344,
+      344,  345,  345,  345,  345,  346,  346,  346,  346,  347,
+      347,  347,  347,  348,  348,  348,  348,  349,  349,  349,
+      349,  350,  350,  350,  350,  351,  351,  351,  351,  352,
+      352,  352,  352,  353,  353,  353,  353,  354,  354,  354,
+      354,  355,  355,  355,  355,  356,  356,  356,  356,  357,
+
+      357,  357,  357,  358,  358,  358,  358,  359,  359,  359,
+      359,  360,  360,  360,  360,  361,  361,  361,  361,  362,
+      362,  362,  362,  363,  363,  363,  363,  364,  364,  364,
+      364,  365,  365,  365,  365,  366,  366,  366,  366,  367,
+      367,  367,  367,  368,  368,  368,  368,  369,  369,  369,
+      369,  370,  370,  370,  370,  371,  371,  371,  371,  372,
+      372,  372,  372,  373,  373,  373,  373,  374,  374,  374,
+      374,  375,  375,  375,  375,  376,  376,  376,  376,  377,
+      377,  377,  377,  378,  378,  378,  378,  379,  379,  379,
+      379,  380,  380,  380,  380,  381,  381,  381,  381,  382,
+
+      382,  382,  382,  383,  383,  383,  383,  384,  384,  384,
+      384,  385,  385,  385,  385,  386,  386,  386,  386,  387,
+      387,  387,  387,  388,  388,  388,  388,  389,  389,  389,
+      389,  390,  390,  390,  390,  391,  391,  391,  391,  392,
+      392,  392,  392,  393,  393,  393,  393,  394,  394,  394,
+      394,  395,  395,  395,  395,  396,  396,  396,  396,  397,
+      397,  397,  397,  398,  398,  398,  398,  399,  399,  399,
+      399,  400,  400,  400,  400,  401,  401,  401,  401,  402,
+      402,  402,  402,  403,  403,  403,  403,  404,  404,  404,
+      404,  405,  405,  405,  405,  406,  406,  406,  406,  407,
+
+      407,  407,  407,  408,  408,  408,  408,  409,  409,  409,
+      409,  410,  410,  410,  410,  411,  411,  411,  411,  412,
+      412,  412,  412,  413,  413,  413,  413,  414,  414,  414,
+      414,  415,  415,  415,  415,  416,  416,  416,  416,  417,
+      417,  417,  417,  418,  418,  418,  418,  419,  419,  419,
+      419,  420,  420,  420,  420,  421,  421,  421,  421,  422,
+      422,  422,  422,  423,  423,  423,  423,  424,  424,  424,
+      424,  425,  425,  425,  425,  426,  426,  426,  426,  427,
+      427,  427,  427,  428,  428,  428,  428,  429,  429,  429,
+      429,  430,  430,  430,  430,  431,  431,  431,  431,  432,
+
+      432,  432,  432,  433,  433,  433,  433,  434,  434,  434,
+      434,  435,  435,  435,  435,  436,  436,  436,  436,  437,
+      437,  437,  437,  438,  438,  438,  438,  439,  439,  439,
+      439,  440,  440,  440,  440,  441,  441,  441,  441,  442,
+      442,  442,  442,   99,   99,  225,  224,  222,  220,   99,
+      219,  218,  216,  214,  213,  212,  211,  210,  208,  206,
+      205,  204,  203,  202,  201,  199,  196,  195,  194,  193,
+      192,  191,   99,   59,  188,  189,  188,  153,  185,  184,
+      183,  182,   99,   99,  177,  176,  175,  174,  173,   99,
+      169,  168,  167,   99,  166,   99,  165,   99,  161,  160,
+
+      119,   99,   99,   99,  157,  156,  103,  152,  151,  150,
+      149,  148,  147,  146,  145,   99,   99,  143,  142,  141,
+      140,  139,  138,  137,   59,  132,  128,  127,  126,  125,
+       70,   70,  124,  123,   70,  122,   99,   99,  121,  120,
+      119,  118,  117,   99,  116,  115,  114,  113,  112,   59,
+      111,  110,  109,  108,  107,  106,  443,   27,  102,   70,
+      101,  100,   99,   98,   97,   96,   95,   70,   94,   93,
+       92,   88,   85,   84,   70,   83,   70,   82,   81,   80,
+       79,   78,   77,   75,   74,   72,   71,   70,  443,   65,
+       64,   63,   56,   55,   54,   53,  443,  443,    3,  443,
+
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443
+    } ;
+
+static yyconst flex_int16_t yy_chk[1235] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    5,    5,    6,    6,    7,
+        7,    7,    7,   10,   11,   12,   14,   34,   15,   16,
+       49,   13,   26,   26,  107,   37,   12,   49,   16,  471,
+       12,   12,   11,   13,   15,   11,   13,   13,  107,   10,
+      469,   34,   14,   17,   27,   27,   27,   28,   28,   28,
+       28,   17,   17,   37,   66,   66,   66,   66,  467,   17,
+      465,   17,  463,   17,   17,  461,   17,   17,   22,   51,
+
+       22,   22,  103,  103,  103,   51,   22,  134,   22,   51,
+      104,  104,  104,  104,  109,  459,  134,   22,  457,  143,
+      109,  129,  129,  129,  129,  143,  153,  153,  153,  154,
+      154,  154,  154,  165,  455,  165,  170,  170,  170,  186,
+      186,  186,  211,  211,  211,  453,  451,  449,  229,  228,
+      165,  444,  444,  445,  445,  445,  225,  445,  446,  446,
+      447,  447,  447,  224,  447,  448,  448,  450,  450,  450,
+      450,  452,  452,  452,  452,  454,  454,  454,  454,  456,
+      456,  456,  456,  458,  458,  458,  458,  460,  460,  460,
+      460,  462,  462,  462,  462,  464,  464,  464,  464,  466,
+
+      466,  466,  466,  468,  468,  468,  468,  470,  470,  470,
+      470,  472,  472,  472,  472,  473,  473,  473,  473,  474,
+      474,  474,  474,  475,  475,  475,  475,  476,  476,  476,
+      476,  477,  477,  477,  477,  478,  478,  478,  478,  479,
+      479,  479,  479,  480,  480,  480,  480,  481,  481,  481,
+      481,  482,  482,  482,  482,  483,  483,  483,  483,  484,
+      484,  484,  484,  485,  485,  485,  485,  486,  486,  486,
+      486,  487,  487,  487,  487,  488,  488,  488,  488,  489,
+      489,  489,  489,  490,  490,  490,  490,  491,  491,  491,
+      491,  492,  492,  492,  492,  493,  493,  493,  493,  494,
+
+      494,  494,  494,  495,  495,  495,  495,  496,  496,  496,
+      496,  497,  497,  497,  497,  498,  498,  498,  498,  499,
+      499,  499,  499,  500,  500,  500,  500,  501,  501,  501,
+      501,  502,  502,  502,  502,  503,  503,  503,  503,  504,
+      504,  504,  504,  505,  505,  505,  505,  506,  506,  506,
+      506,  507,  507,  507,  507,  508,  508,  508,  508,  509,
+      509,  509,  509,  510,  510,  510,  510,  511,  511,  511,
+      511,  512,  512,  512,  512,  513,  513,  513,  513,  514,
+      514,  514,  514,  515,  515,  515,  515,  516,  516,  516,
+      516,  517,  517,  517,  517,  518,  518,  518,  518,  519,
+
+      519,  519,  519,  520,  520,  520,  520,  521,  521,  521,
+      521,  522,  522,  522,  522,  523,  523,  523,  523,  524,
+      524,  524,  524,  525,  525,  525,  525,  526,  526,  526,
+      526,  527,  527,  527,  527,  528,  528,  528,  528,  529,
+      529,  529,  529,  530,  530,  530,  530,  531,  531,  531,
+      531,  532,  532,  532,  532,  533,  533,  533,  533,  534,
+      534,  534,  534,  535,  535,  535,  535,  536,  536,  536,
+      536,  537,  537,  537,  537,  538,  538,  538,  538,  539,
+      539,  539,  539,  540,  540,  540,  540,  541,  541,  541,
+      541,  542,  542,  542,  542,  543,  543,  543,  543,  544,
+
+      544,  544,  544,  545,  545,  545,  545,  546,  546,  546,
+      546,  547,  547,  547,  547,  548,  548,  548,  548,  549,
+      549,  549,  549,  550,  550,  550,  550,  551,  551,  551,
+      551,  552,  552,  552,  552,  553,  553,  553,  553,  554,
+      554,  554,  554,  555,  555,  555,  555,  556,  556,  556,
+      556,  557,  557,  557,  557,  558,  558,  558,  558,  559,
+      559,  559,  559,  560,  560,  560,  560,  561,  561,  561,
+      561,  562,  562,  562,  562,  563,  563,  563,  563,  564,
+      564,  564,  564,  565,  565,  565,  565,  566,  566,  566,
+      566,  567,  567,  567,  567,  568,  568,  568,  568,  569,
+
+      569,  569,  569,  570,  570,  570,  570,  571,  571,  571,
+      571,  572,  572,  572,  572,  573,  573,  573,  573,  574,
+      574,  574,  574,  575,  575,  575,  575,  576,  576,  576,
+      576,  577,  577,  577,  577,  578,  578,  578,  578,  579,
+      579,  579,  579,  580,  580,  580,  580,  581,  581,  581,
+      581,  582,  582,  582,  582,  583,  583,  583,  583,  584,
+      584,  584,  584,  585,  585,  585,  585,  586,  586,  586,
+      586,  587,  587,  587,  587,  588,  588,  588,  588,  589,
+      589,  589,  589,  590,  590,  590,  590,  591,  591,  591,
+      591,  592,  592,  592,  592,  593,  593,  593,  593,  594,
+
+      594,  594,  594,  595,  595,  595,  595,  596,  596,  596,
+      596,  597,  597,  597,  597,  598,  598,  598,  598,  599,
+      599,  599,  599,  600,  600,  600,  600,  601,  601,  601,
+      601,  602,  602,  602,  602,  603,  603,  603,  603,  604,
+      604,  604,  604,  605,  605,  605,  605,  606,  606,  606,
+      606,  607,  607,  607,  607,  608,  608,  608,  608,  609,
+      609,  609,  609,  610,  610,  610,  610,  611,  611,  611,
+      611,  612,  612,  612,  612,  613,  613,  613,  613,  614,
+      614,  614,  614,  615,  615,  615,  615,  616,  616,  616,
+      616,  617,  617,  617,  617,  618,  618,  618,  618,  619,
+
+      619,  619,  619,  620,  620,  620,  620,  621,  621,  621,
+      621,  622,  622,  622,  622,  623,  623,  623,  623,  624,
+      624,  624,  624,  625,  625,  625,  625,  626,  626,  626,
+      626,  627,  627,  627,  627,  628,  628,  628,  628,  629,
+      629,  629,  629,  630,  630,  630,  630,  631,  631,  631,
+      631,  632,  632,  632,  632,  633,  633,  633,  633,  634,
+      634,  634,  634,  635,  635,  635,  635,  636,  636,  636,
+      636,  637,  637,  637,  637,  638,  638,  638,  638,  639,
+      639,  639,  639,  640,  640,  640,  640,  641,  641,  641,
+      641,  642,  642,  642,  642,  643,  643,  643,  643,  644,
+
+      644,  644,  644,  645,  645,  645,  645,  646,  646,  646,
+      646,  647,  647,  647,  647,  648,  648,  648,  648,  649,
+      649,  649,  649,  650,  650,  650,  650,  651,  651,  651,
+      651,  652,  652,  652,  652,  653,  653,  653,  653,  654,
+      654,  654,  654,  655,  655,  655,  655,  656,  656,  656,
+      656,  657,  657,  657,  657,  658,  658,  658,  658,  659,
+      659,  659,  659,  660,  660,  660,  660,  661,  661,  661,
+      661,  662,  662,  662,  662,  663,  663,  663,  663,  664,
+      664,  664,  664,  665,  665,  665,  665,  666,  666,  666,
+      666,  667,  667,  667,  667,  668,  668,  668,  668,  669,
+
+      669,  669,  669,  670,  670,  670,  670,  671,  671,  671,
+      671,  672,  672,  672,  672,  673,  673,  673,  673,  674,
+      674,  674,  674,  675,  675,  675,  675,  676,  676,  676,
+      676,  677,  677,  677,  677,  678,  678,  678,  678,  679,
+      679,  679,  679,  222,  220,  219,  218,  216,  214,  213,
+      212,  210,  208,  206,  205,  204,  202,  201,  199,  196,
+      195,  194,  193,  192,  191,  189,  184,  183,  182,  181,
+      180,  179,  177,  176,  175,  174,  173,  171,  169,  168,
+      167,  166,  163,  162,  161,  160,  159,  158,  157,  156,
+      152,  151,  150,  149,  147,  146,  145,  141,  140,  139,
+
+      138,  137,  136,  135,  133,  132,  130,  128,  127,  126,
+      125,  124,  123,  122,  121,  118,  117,  116,  115,  114,
+      113,  112,  111,  110,  108,  106,  102,  101,  100,   98,
+       97,   96,   95,   94,   93,   92,   91,   90,   89,   88,
+       87,   86,   85,   84,   83,   82,   81,   80,   79,   78,
+       77,   75,   74,   73,   72,   71,   68,   67,   65,   64,
+       63,   62,   61,   60,   58,   57,   56,   55,   54,   53,
+       52,   50,   48,   47,   46,   45,   44,   43,   42,   41,
+       40,   39,   38,   36,   35,   33,   32,   31,   29,   25,
+       24,   23,   21,   20,   19,   18,    8,    3,  443,  443,
+
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
+      443,  443,  443,  443
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#ifndef YYLMAX
+#define YYLMAX 8192
+#endif
+
+char yytext[YYLMAX];
+char *yytext_ptr;
+#line 1 "prom_lex.l"
+/*
+ * Copyright (C) IBM Corporation. 2007
+ * Author: Doug Maxey <dwm@austin.ibm.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+/* definitions */
+#line 23 "prom_lex.l"
+#include "prom_parse.h"
+
+#undef LEXDEBUG
+#ifdef LEXDEBUG
+#define dbg(a) dbgprint((a))
+#else
+#define dbg(a) do {} while (0)
+#endif  /* LEXDEBUG */
+
+#define upval(d)				\
+    dbg(#d);					\
+    yylval.str[0] = 0;                          \
+    strcat(yylval.str, yytext);			\
+    yylloc.first_column = yylloc.last_column;	\
+    yylloc.last_column += yyleng;		\
+    return d
+
+void dbgprint(const char *item) { fprintf(stderr, "%s: \"%s\" len=%d ", item, yytext, yyleng);}
+
+#define YY_NO_INPUT 1
+/* CHOSEN uses only boot related paths. */
+#line 975 "<stdout>"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (void );
+
+int yyget_debug (void );
+
+void yyset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE yyget_extra (void );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *yyget_in (void );
+
+void yyset_in  (FILE * in_str  );
+
+FILE *yyget_out (void );
+
+void yyset_out  (FILE * out_str  );
+
+int yyget_leng (void );
+
+char *yyget_text (void );
+
+int yyget_lineno (void );
+
+void yyset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 65 "prom_lex.l"
+
+
+#line 1163 "<stdout>"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer(yyin,YY_BUF_SIZE );
+		}
+
+		yy_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of yytext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 444 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_current_state != 443 );
+		yy_cp = (yy_last_accepting_cpos);
+		yy_current_state = (yy_last_accepting_state);
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 67 "prom_lex.l"
+{ upval(CHOSEN); }
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 68 "prom_lex.l"
+{ upval(VDEVICE); }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 69 "prom_lex.l"
+{ upval(VDEVINST); }
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 70 "prom_lex.l"
+{ upval(VDEVDEV); }
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 71 "prom_lex.l"
+{ upval(VDEVRAW); }
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 72 "prom_lex.l"
+{ upval(OBPQUAL); }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 73 "prom_lex.l"
+{ upval(BUSNAME); }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 74 "prom_lex.l"
+{ upval(IPV4); }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 75 "prom_lex.l"
+{ upval(IQN); }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 76 "prom_lex.l"
+{ upval(BOOTDEV); }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 77 "prom_lex.l"
+{ upval(OBPPARM); }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 78 "prom_lex.l"
+{ upval(HEX4); }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 79 "prom_lex.l"
+{ upval(HEX16); }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 80 "prom_lex.l"
+{ upval(FILENAME); }
+	YY_BREAK
+case 15:
+/* rule 15 can match eol */
+YY_RULE_SETUP
+#line 81 "prom_lex.l"
+{                  /* eat all whitespace. */
+	yylloc.first_column = yylloc.last_column;
+	yylloc.last_column += yyleng;
+}
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 85 "prom_lex.l"
+{			/* any other single char. */
+	dbg("??");
+	yylloc.first_column = yylloc.last_column;
+	yylloc.last_column += yyleng;
+	return *yytext;
+}
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+#line 92 "prom_lex.l"
+yyterminate();
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 93 "prom_lex.l"
+ECHO;
+	YY_BREAK
+#line 1340 "<stdout>"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_last_accepting_cpos);
+				yy_current_state = (yy_last_accepting_state);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( yywrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart(yyin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 444 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 444 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 443);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart(yyin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve yytext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE );
+	}
+
+	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+	yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * 
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree((void *) b->yy_ch_buf  );
+
+	yyfree((void *) b  );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	yy_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack();
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void yypop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+    
+	return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) yyalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = (yy_hold_char); \
+		(yy_c_buf_p) = yytext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+        
+    return yylineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *yyget_in  (void)
+{
+        return yyin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *yyget_out  (void)
+{
+        return yyout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int yyget_leng  (void)
+{
+        return yyleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *yyget_text  (void)
+{
+        return yytext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void yyset_lineno (int  line_number )
+{
+    
+    yylineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str )
+{
+        yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str )
+{
+        yyout = out_str ;
+}
+
+int yyget_debug  (void)
+{
+        return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug )
+{
+        yy_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	yyfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 93 "prom_lex.l"
+
+
+
diff -pruN 2.1.5-1/usr/fwparam_ibft/prom_lex.l 2.1.7-2/usr/fwparam_ibft/prom_lex.l
--- 2.1.5-1/usr/fwparam_ibft/prom_lex.l	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/prom_lex.l	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) IBM Corporation. 2007
+ * Author: Doug Maxey <dwm@austin.ibm.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* definitions */
+%option array
+
+%{
+#include "prom_parse.h"
+
+#undef LEXDEBUG
+#ifdef LEXDEBUG
+#define dbg(a) dbgprint((a))
+#else
+#define dbg(a) do {} while (0)
+#endif  /* LEXDEBUG */
+
+#define upval(d)				\
+    dbg(#d);					\
+    yylval.str[0] = 0;                          \
+    strcat(yylval.str, yytext);			\
+    yylloc.first_column = yylloc.last_column;	\
+    yylloc.last_column += yyleng;		\
+    return d
+
+void dbgprint(const char *item) { fprintf(stderr, "%s: \"%s\" len=%d ", item, yytext, yyleng);}
+
+%}
+
+%option noyywrap
+%option never-interactive
+%option nounput
+%option noinput
+
+VDEVICE     vdevice
+VDEVINST    gscsi
+VDEVDEV     dev
+VDEVRAW     rawio
+                                /* CHOSEN uses only boot related paths. */
+CHOSEN      bootpath|bootargs|iscsi-bootargs|nas-bootdevice
+BUSNAME     ata|i2c|ide|pci|sata|scsi|usb|lhea
+BOOTDEV     cdrom|disk|ethernet|iscsi-(disk[0-9]|toe)|sd
+HEX4        [[:xdigit:]]{1,4}
+HEX16       [[:xdigit:]]{5,16}
+IPV4        [0-9]{1,3}(\.[0-9]{1,3}){3}
+IQN         iqn\.[-[:alnum:]:.]{1,219}
+OBPQUAL     bootp|ipv6|iscsi|dhcpv6
+OBPPARM     blksize|bootp-retries|chapid|chappw|ciaddr|dhcp|filename|giaddr|ichapid|ichappw|ilun|iname|iport|isid|isns|itname|siaddr|slp|subnet-mask|tftp-retries
+FILENAME    \\[-[:alnum:]\\\.]{1,}
+
+%% /* rules */
+
+{CHOSEN}      { upval(CHOSEN); }
+{VDEVICE}     { upval(VDEVICE); }
+{VDEVINST}    { upval(VDEVINST); }
+{VDEVDEV}     { upval(VDEVDEV); }
+{VDEVRAW}     { upval(VDEVRAW); }
+{OBPQUAL}     { upval(OBPQUAL); }
+{BUSNAME}     { upval(BUSNAME); }
+{IPV4}        { upval(IPV4); }
+{IQN}         { upval(IQN); }
+{BOOTDEV}     { upval(BOOTDEV); }
+{OBPPARM}     { upval(OBPPARM); }
+{HEX4}        { upval(HEX4); }
+{HEX16}       { upval(HEX16); }
+{FILENAME}    { upval(FILENAME); }
+[ \t\n]+      {                  /* eat all whitespace. */
+	yylloc.first_column = yylloc.last_column;
+	yylloc.last_column += yyleng;
+}
+.             {			/* any other single char. */
+	dbg("??");
+	yylloc.first_column = yylloc.last_column;
+	yylloc.last_column += yyleng;
+	return *yytext;
+}
+
+<<EOF>> yyterminate();
+%% /* user code */
diff -pruN 2.1.5-1/usr/fwparam_ibft/prom_parse.h 2.1.7-2/usr/fwparam_ibft/prom_parse.h
--- 2.1.5-1/usr/fwparam_ibft/prom_parse.h	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/prom_parse.h	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) IBM Corporation. 2007
+ * Author: Doug Maxey <dwm@austin.ibm.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PROM_PARSE_H_
+#define PROM_PARSE_H_
+
+#include <stdlib.h>
+#include <string.h>
+#include "iscsi_obp.h"
+
+struct ofw_dev;
+void yyerror(struct ofw_dev *ofwdev, const char *msg);
+extern int yyleng;
+extern int yydebug;
+#include <stdio.h>
+extern FILE *yyin;
+extern char yytext[];
+int yylex(void);
+
+#define YY_NO_UNPUT 1 /* match this with %option never-interactive. */
+#include "prom_parse.tab.h"
+
+
+#endif /* PROM_PARSE_H_ */
diff -pruN 2.1.5-1/usr/fwparam_ibft/prom_parse.tab.c 2.1.7-2/usr/fwparam_ibft/prom_parse.tab.c
--- 2.1.5-1/usr/fwparam_ibft/prom_parse.tab.c	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/prom_parse.tab.c	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,2063 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 21 "prom_parse.y" /* yacc.c:339  */
+
+	/* literal block. include lines, decls, defns. */
+//#define YYDEBUG 1
+#if YYDEBUG
+#define DPRINT(fmt,...) printf(fmt,__VA_ARGS__)
+#else
+#define DPRINT(fmt,...) do {} while(0)
+#endif
+#include "prom_parse.h"
+#include "iscsi_obp.h"
+
+
+
+#line 80 "prom_parse.tab.c" /* yacc.c:339  */
+
+# ifndef YY_NULLPTR
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULLPTR nullptr
+#  else
+#   define YY_NULLPTR 0
+#  endif
+# endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* In a future release of Bison, this section will be replaced
+   by #include "prom_parse.tab.h".  */
+#ifndef YY_YY_PROM_PARSE_TAB_H_INCLUDED
+# define YY_YY_PROM_PARSE_TAB_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    BUSNAME = 258,
+    BOOTDEV = 259,
+    IPV4 = 260,
+    IQN = 261,
+    OBPPARM = 262,
+    OBPQUAL = 263,
+    HEX4 = 264,
+    HEX16 = 265,
+    VDEVICE = 266,
+    VDEVINST = 267,
+    VDEVDEV = 268,
+    VDEVRAW = 269,
+    CHOSEN = 270,
+    FILENAME = 271
+  };
+#endif
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 34 "prom_parse.y" /* yacc.c:355  */
+
+#define	STR_LEN		16384
+		char str[STR_LEN];
+
+#line 142 "prom_parse.tab.c" /* yacc.c:355  */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+/* Location type.  */
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE YYLTYPE;
+struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+};
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+extern YYSTYPE yylval;
+extern YYLTYPE yylloc;
+int yyparse (struct ofw_dev *ofwdev);
+
+#endif /* !YY_YY_PROM_PARSE_TAB_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+#line 173 "prom_parse.tab.c" /* yacc.c:358  */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+       && ! ((defined YYMALLOC || defined malloc) \
+             && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+         || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+             && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+  YYLTYPE yyls_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+      + 2 * YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  8
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   103
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  24
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  19
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  51
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  93
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   273
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,    19,     2,     2,    17,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    20,     2,
+       2,    21,     2,     2,    18,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    22,    23
+};
+
+#if YYDEBUG
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,    60,    60,    63,    66,    74,    82,    89,    96,    99,
+     104,   107,   110,   113,   116,   122,   125,   128,   133,   138,
+     141,   144,   149,   154,   157,   160,   165,   168,   173,   177,
+     181,   185,   191,   194,   199,   202,   207,   210,   215,   220,
+     223,   228,   231,   234,   237,   242,   245,   250,   253,   256,
+     261,   264
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 0
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "BUSNAME", "BOOTDEV", "IPV4", "IQN",
+  "OBPPARM", "OBPQUAL", "HEX4", "HEX16", "VDEVICE", "VDEVINST", "VDEVDEV",
+  "VDEVRAW", "CHOSEN", "FILENAME", "'/'", "'@'", "','", "':'", "'='",
+  "\"::\"", "\":\"", "$accept", "devpath", "busses", "bus", "bootdev",
+  "vdevice", "vdev_parms", "vdev_parm", "obp_params", "obp_param",
+  "obp_quals", "obp_qual", "ipaddr", "ipv4", "ipv6", "hexpart", "hexseq",
+  "disklabel", "diskpart", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,    47,    64,    44,
+      58,    61,   272,   273
+};
+# endif
+
+#define YYPACT_NINF -73
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-73)))
+
+#define YYTABLE_NINF -46
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int8 yypact[] =
+{
+     -15,    19,    13,    20,    18,    23,   -73,    25,   -73,    39,
+      51,    50,    49,    16,    46,    43,    42,   -73,    47,   -73,
+      -9,   -73,   -73,    44,    45,    58,    59,   -73,    52,   -73,
+     -73,   -73,    56,    24,    61,    62,    64,   -73,   -73,    60,
+      55,    57,    38,     8,   -73,    41,    52,   -73,   -73,    37,
+     -73,    68,    63,    65,   -73,   -73,   -73,     3,   -73,   -73,
+     -73,     8,    69,   -73,    44,   -73,    -2,    44,   -73,   -73,
+     -73,    67,   -73,   -73,   -73,    36,   -73,   -73,    71,   -73,
+     -73,   -73,    11,    66,   -73,   -73,    66,    76,    71,    73,
+     -73,    66,   -73
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       0,     2,     0,    10,     0,     0,     8,     0,     1,     0,
+       0,     0,     0,     3,     0,     0,    11,    13,     0,    18,
+       0,     9,    34,     0,     0,     0,     0,    35,     0,    32,
+       4,    47,     0,     0,     0,     0,     0,    15,    48,     0,
+       0,    50,     0,     5,    19,     0,     0,    12,    14,     0,
+      22,     0,     0,     0,    26,    23,    33,     0,     6,    21,
+      20,     0,     0,    16,     0,    51,     0,    26,    24,    25,
+       7,     0,    49,    38,    29,    30,    27,    31,     0,    28,
+      36,    37,    39,    41,    17,    45,    44,     0,    42,     0,
+      40,    43,    46
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -73,   -73,   -73,    72,    78,   -73,   -73,   -27,    48,    26,
+      70,    53,   -73,     1,   -73,   -73,   -72,   -42,   -23
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     2,     5,     6,    13,     7,    33,    27,    43,    55,
+      28,    29,    79,    80,    81,    82,    83,    30,    31
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_int8 yytable[] =
+{
+      38,    58,     1,    73,    74,    44,    86,    75,    76,    36,
+      53,    37,    67,     8,    77,    69,    91,    23,    60,    70,
+      78,    25,     3,    26,    22,    23,    25,    57,    26,    24,
+       4,    87,    22,    88,    25,    11,    26,    24,     9,    10,
+      12,    72,    14,    45,    38,    53,    22,    54,    16,    17,
+      20,    24,     3,    20,    24,    59,    62,    63,   -45,   -45,
+      18,    34,    19,    32,    26,    35,    39,    40,    41,    24,
+      47,    42,    48,    49,    51,    50,    52,    64,    71,    65,
+      85,    73,    92,    68,    21,    15,    66,    84,    90,    89,
+       0,     0,     0,     0,    61,    56,     0,     0,     0,     0,
+       0,     0,     0,    46
+};
+
+static const yytype_int8 yycheck[] =
+{
+      23,    43,    17,     5,     6,    32,    78,     9,    10,    18,
+       7,    20,     9,     0,    16,    57,    88,     9,    45,    61,
+      22,    18,     3,    20,     8,     9,    18,    19,    20,    13,
+      11,    20,     8,    22,    18,    17,    20,    13,    18,    19,
+      17,    64,    17,    19,    67,     7,     8,     9,     9,    10,
+       4,    13,     3,     4,    13,    14,    19,    20,    22,    23,
+       9,    19,    12,    20,    20,    18,    21,     9,     9,    13,
+       9,    19,    10,     9,    19,    15,    19,     9,     9,    16,
+       9,     5,     9,    57,    12,     7,    21,    20,    87,    23,
+      -1,    -1,    -1,    -1,    46,    42,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    33
+};
+
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,    17,    25,     3,    11,    26,    27,    29,     0,    18,
+      19,    17,    17,    28,    17,    28,     9,    10,     9,    12,
+       4,    27,     8,     9,    13,    18,    20,    31,    34,    35,
+      41,    42,    20,    30,    19,    18,    18,    20,    42,    21,
+       9,     9,    19,    32,    31,    19,    34,     9,    10,     9,
+      15,    19,    19,     7,     9,    33,    35,    19,    41,    14,
+      31,    32,    19,    20,     9,    16,    21,     9,    33,    41,
+      41,     9,    42,     5,     6,     9,    10,    16,    22,    36,
+      37,    38,    39,    40,    20,     9,    40,    20,    22,    23,
+      37,    40,     9
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    24,    25,    25,    25,    25,    25,    25,    26,    26,
+      27,    27,    27,    27,    27,    28,    28,    28,    29,    30,
+      30,    30,    31,    32,    32,    32,    33,    33,    33,    33,
+      33,    33,    34,    34,    35,    35,    36,    36,    37,    38,
+      38,    39,    39,    39,    39,    40,    40,    41,    41,    41,
+      42,    42
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     3,     4,     5,     6,     7,     1,     3,
+       1,     3,     5,     3,     5,     3,     5,     7,     3,     2,
+       3,     3,     3,     2,     3,     3,     1,     3,     3,     3,
+       3,     3,     1,     3,     1,     1,     1,     1,     1,     1,
+       3,     1,     2,     3,     2,     1,     3,     1,     2,     5,
+       2,     4
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
+      yyerror (ofwdev, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
+
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)                                \
+    do                                                                  \
+      if (N)                                                            \
+        {                                                               \
+          (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
+          (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
+          (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
+          (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
+        }                                                               \
+      else                                                              \
+        {                                                               \
+          (Current).first_line   = (Current).last_line   =              \
+            YYRHSLOC (Rhs, 0).last_line;                                \
+          (Current).first_column = (Current).last_column =              \
+            YYRHSLOC (Rhs, 0).last_column;                              \
+        }                                                               \
+    while (0)
+#endif
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+
+/* Print *YYLOCP on YYO.  Private, do not rely on its existence. */
+
+YY_ATTRIBUTE_UNUSED
+static unsigned
+yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
+{
+  unsigned res = 0;
+  int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
+  if (0 <= yylocp->first_line)
+    {
+      res += YYFPRINTF (yyo, "%d", yylocp->first_line);
+      if (0 <= yylocp->first_column)
+        res += YYFPRINTF (yyo, ".%d", yylocp->first_column);
+    }
+  if (0 <= yylocp->last_line)
+    {
+      if (yylocp->first_line < yylocp->last_line)
+        {
+          res += YYFPRINTF (yyo, "-%d", yylocp->last_line);
+          if (0 <= end_col)
+            res += YYFPRINTF (yyo, ".%d", end_col);
+        }
+      else if (0 <= end_col && yylocp->first_column < end_col)
+        res += YYFPRINTF (yyo, "-%d", end_col);
+    }
+  return res;
+ }
+
+#  define YY_LOCATION_PRINT(File, Loc)          \
+  yy_location_print_ (File, &(Loc))
+
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value, Location, ofwdev); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct ofw_dev *ofwdev)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  YYUSE (yylocationp);
+  YYUSE (ofwdev);
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+  YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct ofw_dev *ofwdev)
+{
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+  YY_LOCATION_PRINT (yyoutput, *yylocationp);
+  YYFPRINTF (yyoutput, ": ");
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, ofwdev);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, struct ofw_dev *ofwdev)
+{
+  unsigned long int yylno = yyrline[yyrule];
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+             yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                       , &(yylsp[(yyi + 1) - (yynrhs)])                       , ofwdev);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, yylsp, Rule, ofwdev); \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULLPTR;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
+    }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, struct ofw_dev *ofwdev)
+{
+  YYUSE (yyvaluep);
+  YYUSE (yylocationp);
+  YYUSE (ofwdev);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+/* Location data for the lookahead symbol.  */
+YYLTYPE yylloc
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+  = { 1, 1, 1, 1 }
+# endif
+;
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (struct ofw_dev *ofwdev)
+{
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+       'yyls': related to locations.
+
+       Refer to the stacks through separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    /* The location stack.  */
+    YYLTYPE yylsa[YYINITDEPTH];
+    YYLTYPE *yyls;
+    YYLTYPE *yylsp;
+
+    /* The locations where the error started and ended.  */
+    YYLTYPE yyerror_range[3];
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+  YYLTYPE yyloc;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yylsp = yyls = yylsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+  yylsp[0] = yylloc;
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+        YYLTYPE *yyls1 = yyls;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yyls1, yysize * sizeof (*yylsp),
+                    &yystacksize);
+
+        yyls = yyls1;
+        yyss = yyss1;
+        yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+        goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+        yystacksize = YYMAXDEPTH;
+
+      {
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+        YYSTACK_RELOCATE (yyls_alloc, yyls);
+#  undef YYSTACK_RELOCATE
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+      yylsp = yyls + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+        YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yypact_value_is_default (yyn))
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = yylex ();
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+  *++yylsp = yylloc;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     '$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+  /* Default location.  */
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+#line 60 "prom_parse.y" /* yacc.c:1646  */
+    {
+			DPRINT("****rootonly: \"%s\"\n", "/");
+		}
+#line 1410 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 3:
+#line 63 "prom_parse.y" /* yacc.c:1646  */
+    {
+			DPRINT("****devpath busses:\n/%s/%s\n", (yyvsp[-1].str), (yyvsp[0].str));
+		}
+#line 1418 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 4:
+#line 66 "prom_parse.y" /* yacc.c:1646  */
+    {
+			ofwdev->dev_path = malloc(strlen((yyvsp[-2].str)) +
+                                      strlen((yyvsp[-1].str)) + 3);
+			sprintf(ofwdev->dev_path, "/%s%s", (yyvsp[-2].str), (yyvsp[-1].str));
+			DPRINT("****devpath busses bootdev "
+                   "disklabel:\n/%s/%s%s\n",
+				   (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str));
+		}
+#line 1431 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 5:
+#line 74 "prom_parse.y" /* yacc.c:1646  */
+    {
+			ofwdev->dev_path = malloc(strlen((yyvsp[-3].str)) +
+                                      strlen((yyvsp[-2].str)) + 3);
+			sprintf(ofwdev->dev_path, "/%s%s", (yyvsp[-3].str), (yyvsp[-2].str));
+			DPRINT("****busses bootdev obp_quals obp_parms:\n"
+                   "/%s/%s:%s%s\n",
+				   (yyvsp[-3].str), (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str));
+		}
+#line 1444 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 6:
+#line 82 "prom_parse.y" /* yacc.c:1646  */
+    {
+			ofwdev->dev_path = malloc(strlen((yyvsp[-4].str)) +
+                                      strlen((yyvsp[-3].str)) + 3);
+			sprintf(ofwdev->dev_path, "/%s%s", (yyvsp[-4].str), (yyvsp[-3].str));
+			DPRINT("****busses bootdev obp_quals obp_parms "
+                   "disklabel:\n/%s:%s%s%s\n", (yyvsp[-4].str), (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str));
+		}
+#line 1456 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 7:
+#line 89 "prom_parse.y" /* yacc.c:1646  */
+    {
+			DPRINT("****vdevice bootdev obp_parms "
+                   "disklabel:\n/%s:%s%s%s%s\n",
+				   (yyvsp[-5].str), (yyvsp[-3].str), (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str));
+		}
+#line 1466 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 8:
+#line 96 "prom_parse.y" /* yacc.c:1646  */
+    {
+			strcpy((yyval.str), (yyvsp[0].str));
+		}
+#line 1474 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 9:
+#line 99 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s/%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1482 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 10:
+#line 104 "prom_parse.y" /* yacc.c:1646  */
+    {
+			strcpy((yyval.str), (yyvsp[0].str));
+		}
+#line 1490 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 11:
+#line 107 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s@%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1498 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 12:
+#line 110 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s@%s,%s", (yyvsp[-4].str), (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1506 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 13:
+#line 113 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s@%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1514 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 14:
+#line 116 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s,%s@%s", (yyvsp[-4].str), (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1522 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 15:
+#line 122 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "/%s", (yyvsp[-1].str));
+		}
+#line 1530 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 16:
+#line 125 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "/%s@%s", (yyvsp[-3].str), (yyvsp[-1].str));
+		}
+#line 1538 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 17:
+#line 128 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "/%s@%s,%s", (yyvsp[-5].str), (yyvsp[-3].str), (yyvsp[-1].str));
+		}
+#line 1546 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 18:
+#line 133 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s/%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1554 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 19:
+#line 138 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, ":%s", (yyvsp[0].str));
+		}
+#line 1562 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 20:
+#line 141 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s,%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1570 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 21:
+#line 144 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s,%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1578 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 22:
+#line 149 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s=%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1586 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 23:
+#line 154 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, ",%s", (yyvsp[0].str));
+		}
+#line 1594 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 24:
+#line 157 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s,%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1602 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 25:
+#line 160 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s,%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1610 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 26:
+#line 165 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
+		}
+#line 1618 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 27:
+#line 168 "prom_parse.y" /* yacc.c:1646  */
+    {
+			/* luns > 0 are the SAM-3+ hex representation. */
+			obp_parm_hexnum(ofwdev, (yyvsp[-2].str), (yyvsp[0].str));
+			snprintf((yyval.str), STR_LEN, "%s=%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1628 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 28:
+#line 173 "prom_parse.y" /* yacc.c:1646  */
+    {
+			obp_parm_addr(ofwdev, (yyvsp[-2].str), (yyvsp[0].str));
+			snprintf((yyval.str), STR_LEN, "%s=%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1637 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 29:
+#line 177 "prom_parse.y" /* yacc.c:1646  */
+    {
+			obp_parm_iqn(ofwdev, (yyvsp[-2].str), (yyvsp[0].str));
+			snprintf((yyval.str), STR_LEN, "%s=%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1646 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 30:
+#line 181 "prom_parse.y" /* yacc.c:1646  */
+    {
+			obp_parm_hexnum(ofwdev, (yyvsp[-2].str), (yyvsp[0].str));
+			snprintf((yyval.str), STR_LEN, "%s=%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1655 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 31:
+#line 185 "prom_parse.y" /* yacc.c:1646  */
+    {
+			obp_parm_str(ofwdev, (yyvsp[-2].str), (yyvsp[0].str));
+			snprintf((yyval.str), STR_LEN, "%s=%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1664 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 32:
+#line 191 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
+		}
+#line 1672 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 33:
+#line 194 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s,%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1680 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 34:
+#line 199 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s", obp_qual_set(ofwdev, (yyvsp[0].str)));
+		}
+#line 1688 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 35:
+#line 202 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
+		}
+#line 1696 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 36:
+#line 207 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
+		}
+#line 1704 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 37:
+#line 210 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
+		}
+#line 1712 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 38:
+#line 215 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
+		}
+#line 1720 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 39:
+#line 220 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
+		}
+#line 1728 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 40:
+#line 223 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s:%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1736 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 41:
+#line 228 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
+		}
+#line 1744 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 42:
+#line 231 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s::", (yyvsp[-1].str));
+		}
+#line 1752 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 43:
+#line 234 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "%s::%s", (yyvsp[-2].str), (yyvsp[0].str));
+		}
+#line 1760 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 44:
+#line 237 "prom_parse.y" /* yacc.c:1646  */
+    {
+			snprintf((yyval.str), STR_LEN, "::%s", (yyvsp[0].str));
+		}
+#line 1768 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 45:
+#line 242 "prom_parse.y" /* yacc.c:1646  */
+    {
+            snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
+        }
+#line 1776 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 46:
+#line 245 "prom_parse.y" /* yacc.c:1646  */
+    {
+            snprintf((yyval.str), STR_LEN, "%s:%s", (yyvsp[-2].str), (yyvsp[0].str));
+        }
+#line 1784 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 47:
+#line 250 "prom_parse.y" /* yacc.c:1646  */
+    {
+            snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
+        }
+#line 1792 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 48:
+#line 253 "prom_parse.y" /* yacc.c:1646  */
+    {
+            snprintf((yyval.str), STR_LEN, "%s%s", (yyvsp[-1].str), (yyvsp[0].str));
+        }
+#line 1800 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 49:
+#line 256 "prom_parse.y" /* yacc.c:1646  */
+    {
+            snprintf((yyval.str), STR_LEN, "@%s,%s%s", (yyvsp[-3].str), (yyvsp[-1].str), (yyvsp[0].str));
+        }
+#line 1808 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 50:
+#line 261 "prom_parse.y" /* yacc.c:1646  */
+    {
+            snprintf((yyval.str), STR_LEN, ":%s", (yyvsp[0].str));
+        }
+#line 1816 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+  case 51:
+#line 264 "prom_parse.y" /* yacc.c:1646  */
+    {
+            snprintf((yyval.str), STR_LEN, ":%s,%s", (yyvsp[-2].str), (yyvsp[0].str));
+        }
+#line 1824 "prom_parse.tab.c" /* yacc.c:1646  */
+    break;
+
+
+#line 1828 "prom_parse.tab.c" /* yacc.c:1646  */
+      default: break;
+    }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+  *++yylsp = yyloc;
+
+  /* Now 'shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
+yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (ofwdev, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
+      {
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (ofwdev, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
+      }
+# undef YYSYNTAX_ERROR
+#endif
+    }
+
+  yyerror_range[1] = yylloc;
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+         error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
+      else
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, &yylloc, ofwdev);
+          yychar = YYEMPTY;
+        }
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  yyerror_range[1] = yylsp[1-yylen];
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+        YYABORT;
+
+      yyerror_range[1] = *yylsp;
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp, yylsp, ofwdev);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+  yyerror_range[2] = yylloc;
+  /* Using YYLLOC is tempting, but would change the location of
+     the lookahead.  YYLOC is available though.  */
+  YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
+  *++yylsp = yyloc;
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (ofwdev, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval, &yylloc, ofwdev);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                  yystos[*yyssp], yyvsp, yylsp, ofwdev);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  return yyresult;
+}
+#line 269 "prom_parse.y" /* yacc.c:1906  */
+
diff -pruN 2.1.5-1/usr/fwparam_ibft/prom_parse.tab.h 2.1.7-2/usr/fwparam_ibft/prom_parse.tab.h
--- 2.1.5-1/usr/fwparam_ibft/prom_parse.tab.h	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/prom_parse.tab.h	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,102 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+#ifndef YY_YY_PROM_PARSE_TAB_H_INCLUDED
+# define YY_YY_PROM_PARSE_TAB_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    BUSNAME = 258,
+    BOOTDEV = 259,
+    IPV4 = 260,
+    IQN = 261,
+    OBPPARM = 262,
+    OBPQUAL = 263,
+    HEX4 = 264,
+    HEX16 = 265,
+    VDEVICE = 266,
+    VDEVINST = 267,
+    VDEVDEV = 268,
+    VDEVRAW = 269,
+    CHOSEN = 270,
+    FILENAME = 271
+  };
+#endif
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 34 "prom_parse.y" /* yacc.c:1909  */
+
+#define	STR_LEN		16384
+		char str[STR_LEN];
+
+#line 76 "prom_parse.tab.h" /* yacc.c:1909  */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+/* Location type.  */
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE YYLTYPE;
+struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+};
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+extern YYSTYPE yylval;
+extern YYLTYPE yylloc;
+int yyparse (struct ofw_dev *ofwdev);
+
+#endif /* !YY_YY_PROM_PARSE_TAB_H_INCLUDED  */
diff -pruN 2.1.5-1/usr/fwparam_ibft/prom_parse.y 2.1.7-2/usr/fwparam_ibft/prom_parse.y
--- 2.1.5-1/usr/fwparam_ibft/prom_parse.y	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/prom_parse.y	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) IBM Corporation. 2007
+ * Author: Doug Maxey <dwm@austin.ibm.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* - DEFINITION section. */
+
+%{
+	/* literal block. include lines, decls, defns. */
+//#define YYDEBUG 1
+#if YYDEBUG
+#define DPRINT(fmt,...) printf(fmt,__VA_ARGS__)
+#else
+#define DPRINT(fmt,...) do {} while(0)
+#endif
+#include "prom_parse.h"
+#include "iscsi_obp.h"
+
+
+%}
+%union {
+#define	STR_LEN		16384
+		char str[STR_LEN];
+}
+
+/* definitions. */
+%token <str> BUSNAME BOOTDEV
+%token <str> IPV4 IQN
+%token <str> OBPPARM OBPQUAL
+%token <str> HEX4 HEX16
+%token <str> VDEVICE VDEVINST VDEVDEV VDEVRAW
+%token <str> CHOSEN
+%token <str> FILENAME
+
+%type <str> devpath busses bus bootdev
+%type <str> disklabel diskpart
+%type <str> vdevice vdev_parms vdev_parm
+%type <str> obp_quals obp_qual obp_params obp_param
+%type <str> ipaddr ipv4 ipv6
+%type <str> hexpart hexseq
+
+%locations
+%parse-param {struct ofw_dev *ofwdev}
+
+%%
+
+devpath: '/'   {
+			DPRINT("****rootonly: \"%s\"\n", "/");
+		}
+	| '/' busses  bootdev  {
+			DPRINT("****devpath busses:\n/%s/%s\n", $2, $3);
+		}
+	| '/' busses  bootdev disklabel {
+			ofwdev->dev_path = malloc(strlen($<str>2) +
+                                      strlen($<str>3) + 3);
+			sprintf(ofwdev->dev_path, "/%s%s", $<str>2, $<str>3);
+			DPRINT("****devpath busses bootdev "
+                   "disklabel:\n/%s/%s%s\n",
+				   $2, $3, $4);
+		}
+	| '/' busses  bootdev obp_quals obp_params {
+			ofwdev->dev_path = malloc(strlen($<str>2) +
+                                      strlen($<str>3) + 3);
+			sprintf(ofwdev->dev_path, "/%s%s", $<str>2, $<str>3);
+			DPRINT("****busses bootdev obp_quals obp_parms:\n"
+                   "/%s/%s:%s%s\n",
+				   $2, $3, $4, $5);
+		}
+	| '/' busses  bootdev obp_quals obp_params disklabel {
+			ofwdev->dev_path = malloc(strlen($<str>2) +
+                                      strlen($<str>3) + 3);
+			sprintf(ofwdev->dev_path, "/%s%s", $<str>2, $<str>3);
+			DPRINT("****busses bootdev obp_quals obp_parms "
+                   "disklabel:\n/%s:%s%s%s\n", $2, $4, $5, $6);
+		}
+	| '/' vdevice bootdev vdev_parms obp_quals obp_params disklabel {
+			DPRINT("****vdevice bootdev obp_parms "
+                   "disklabel:\n/%s:%s%s%s%s\n",
+				   $2, $4, $5, $6, $7);
+		}
+	;
+
+busses:	   bus	{
+			strcpy($$, $1);
+		}
+	| busses '/' bus {
+			snprintf($$, STR_LEN, "%s/%s", $<str>1, $<str>3);
+		}
+	;
+
+bus:	BUSNAME {
+			strcpy($$, $1);
+		}
+	| BUSNAME '@' HEX4 {
+			snprintf($$, STR_LEN, "%s@%s", $<str>1, $<str>3);
+		}
+	| BUSNAME '@' HEX4 ',' HEX4 {
+			snprintf($$, STR_LEN, "%s@%s,%s", $<str>1, $<str>3, $<str>5);
+		}
+	| BUSNAME '@' HEX16 {
+			snprintf($$, STR_LEN, "%s@%s", $<str>1, $<str>3);
+		}
+	| BUSNAME ',' HEX4 '@' HEX16  {
+			snprintf($$, STR_LEN, "%s,%s@%s", $<str>1, $<str>3, $<str>5);
+		}
+	;
+
+
+bootdev:  '/' BOOTDEV ':' {
+			snprintf($$, STR_LEN, "/%s", $<str>2);
+		}
+	| '/' BOOTDEV '@' HEX4 ':' {
+			snprintf($$, STR_LEN, "/%s@%s", $<str>2, $<str>4);
+		}
+	| '/' BOOTDEV '@' HEX4 ',' HEX4 ':' {
+			snprintf($$, STR_LEN, "/%s@%s,%s", $<str>2, $<str>4, $<str>6);
+		}
+	;
+
+vdevice: VDEVICE '/' VDEVINST {
+			snprintf($$, STR_LEN, "%s/%s", $<str>1, $<str>3);
+		}
+	;
+
+vdev_parms: ':' vdev_parm {
+			snprintf($$, STR_LEN, ":%s", $<str>2);
+		}
+	| vdev_parms ',' vdev_parm {
+			snprintf($$, STR_LEN, "%s,%s", $<str>1, $<str>3);
+		}
+	| vdev_parms ',' VDEVRAW {
+			snprintf($$, STR_LEN, "%s,%s", $<str>1, $<str>3);
+		}
+	;
+
+vdev_parm: VDEVDEV '=' CHOSEN {
+			snprintf($$, STR_LEN, "%s=%s", $<str>1, $<str>3);
+		}
+	;
+
+obp_params: ',' obp_param	{
+			snprintf($$, STR_LEN, ",%s", $2);
+		}
+	| obp_params ',' obp_param {
+			snprintf($$, STR_LEN, "%s,%s", $<str>1, $<str>3);
+		}
+	| obp_params ',' disklabel {
+			snprintf($$, STR_LEN, "%s,%s", $<str>1, $<str>3);
+		}
+	;
+
+obp_param: HEX4 {
+			snprintf($$, STR_LEN, "%s", $1);
+		}
+	| OBPPARM '=' HEX16 {
+			/* luns > 0 are the SAM-3+ hex representation. */
+			obp_parm_hexnum(ofwdev, $<str>1, $<str>3);
+			snprintf($$, STR_LEN, "%s=%s", $<str>1, $<str>3);
+		}
+	| OBPPARM '=' ipaddr {
+			obp_parm_addr(ofwdev, $<str>1, $<str>3);
+			snprintf($$, STR_LEN, "%s=%s", $<str>1, $<str>3);
+		}
+	| OBPPARM '=' IQN {
+			obp_parm_iqn(ofwdev, $<str>1, $<str>3);
+			snprintf($$, STR_LEN, "%s=%s", $<str>1, $<str>3);
+		}
+	| OBPPARM '=' HEX4 {
+			obp_parm_hexnum(ofwdev, $<str>1, $<str>3);
+			snprintf($$, STR_LEN, "%s=%s", $<str>1, $<str>3);
+		}
+	| OBPPARM '=' FILENAME {
+			obp_parm_str(ofwdev, $<str>1, $<str>3);
+			snprintf($$, STR_LEN, "%s=%s", $<str>1, $<str>3);
+		}
+	;
+
+obp_quals: obp_qual {
+			snprintf($$, STR_LEN, "%s", $1);
+		}
+	|  obp_quals ',' obp_qual {
+			snprintf($$, STR_LEN, "%s,%s", $<str>1, $<str>3);
+		}
+	;
+
+obp_qual: OBPQUAL {
+			snprintf($$, STR_LEN, "%s", obp_qual_set(ofwdev, $<str>1));
+		}
+	| vdev_parm {
+			snprintf($$, STR_LEN, "%s", $<str>1);
+		}
+	;
+
+ipaddr: ipv4 {
+			snprintf($$, STR_LEN, "%s", $<str>1);
+		}
+	| ipv6 {
+			snprintf($$, STR_LEN, "%s", $<str>1);
+		}
+	;
+
+ipv4: IPV4 {
+			snprintf($$, STR_LEN, "%s", $1);
+		}
+	;
+
+ipv6: hexpart {
+			snprintf($$, STR_LEN, "%s", $1);
+		}
+	| hexpart ':' ipv4 {
+			snprintf($$, STR_LEN, "%s:%s", $1, $3);
+		}
+	;
+
+hexpart: hexseq {
+			snprintf($$, STR_LEN, "%s", $1);
+		}
+	| hexpart "::"	{
+			snprintf($$, STR_LEN, "%s::", $<str>1);
+		}
+	| hexpart "::" hexseq {
+			snprintf($$, STR_LEN, "%s::%s", $<str>1, $<str>3);
+		}
+	| "::" hexseq {
+			snprintf($$, STR_LEN, "::%s", $<str>2);
+		}
+	;
+
+hexseq:	HEX4 {
+            snprintf($$, STR_LEN, "%s", $1);
+        }
+    | hexseq ":" HEX4 {
+            snprintf($$, STR_LEN, "%s:%s", $<str>1, $<str>3);
+        }
+    ;
+
+disklabel:   diskpart {
+            snprintf($$, STR_LEN, "%s", $<str>1);
+        }
+    | HEX4 diskpart {
+            snprintf($$, STR_LEN, "%s%s", $<str>1, $<str>2);
+        }
+    | '@' HEX4 ',' HEX4 diskpart {
+            snprintf($$, STR_LEN, "@%s,%s%s", $<str>2, $<str>4, $<str>5);
+        }
+    ;
+
+diskpart: ':' HEX4 {
+            snprintf($$, STR_LEN, ":%s", $<str>2);
+        }
+    | ':' HEX4 ',' FILENAME {
+            snprintf($$, STR_LEN, ":%s,%s", $<str>2, $<str>4);
+        }
+    ;
+
+%%
diff -pruN 2.1.5-1/usr/fwparam_ibft/README 2.1.7-2/usr/fwparam_ibft/README
--- 2.1.5-1/usr/fwparam_ibft/README	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/usr/fwparam_ibft/README	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,27 @@
+The files in this directory are used by
+iscsi programs in "usr" to access and parse
+the iBFT data.
+
+This code uses bison/lex to parse the data,
+but at some point it was decided to check in
+the output files from bison and flex, so that
+the average source-code user would not have
+to run those tools to compile the code.
+
+Now it is likely that most folks can get those
+tools, but the system of having static
+parsing and lexical analysis has worked for
+so long (and isn't broken), it would be a
+shame to change and break it. So the static
+files remain, for now. If you actually wish
+to rerun either of these tools, the Makefile
+is set up so that you have to first remove the
+generated files (prom_lex.c for lex, prom_parse.tab.c,
+and prom_parse.tab.h for bison).
+
+Note: if you wish to use these object files,
+they have two external requirements: they
+need the compatability routines in sysdeps.o,
+and they need the file iscsi_net_util.o.
+
+Lee Duncan	Mar, 2022
diff -pruN 2.1.5-1/usr/.gitignore 2.1.7-2/usr/.gitignore
--- 2.1.5-1/usr/.gitignore	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/.gitignore	2022-05-06 17:37:21.000000000 +0000
@@ -1,3 +1,4 @@
 iscsiadm
 iscsid
 iscsistart
+.depend
diff -pruN 2.1.5-1/usr/idbm.c 2.1.7-2/usr/idbm.c
--- 2.1.5-1/usr/idbm.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/idbm.c	2022-05-06 17:37:21.000000000 +0000
@@ -1241,7 +1241,7 @@ void idbm_recinfo_config(recinfo_t *info
 			*(name+i) = *nl; i++; nl++;
 		}
 		if (!*nl) {
-			log_warning("config file line %d do not has value",
+			log_warning("Config file line %d does not have value",
 			       line_number);
 			continue;
 		}
@@ -1249,7 +1249,7 @@ void idbm_recinfo_config(recinfo_t *info
 		/* skip after-name traling spaces */
 		while (*nl && isspace(c = *nl)) nl++;
 		if (*nl && *nl != '=') {
-			log_warning("config file line %d has not '=' sepa",
+			log_warning("Config file line %d does not have '=' separator",
 			       line_number);
 			continue;
 		}
@@ -1258,7 +1258,7 @@ void idbm_recinfo_config(recinfo_t *info
 		/* skip after-sepa traling spaces */
 		while (*nl && isspace(c = *nl)) nl++;
 		if (!*nl) {
-			log_warning("config file line %d do not has value",
+			log_warning("Config file line %d does not have value",
 			       line_number);
 			continue;
 		}
@@ -1835,7 +1835,7 @@ int idbm_print_all_discovery(int info_le
  * @port: rec's port
  *
  * This will run fn over all recs with the {targetname,tpgt,ip,port}
- * id. It does not iterate over the ifaces setup in /etc/iscsi/ifaces.
+ * id. It does not iterate over the ifaces setup in the iface DB directory.
  *
  * fn should return -1 if it skipped the rec, an ISCSI_ERR error code if
  * the operation failed or 0 if fn was run successfully.
@@ -3031,9 +3031,9 @@ free_info:
 int idbm_init(idbm_get_config_file_fn *fn)
 {
 	/* make sure root db dir is there */
-	if (access(ISCSI_CONFIG_ROOT, F_OK) != 0) {
-		if (mkdir(ISCSI_CONFIG_ROOT, 0770) != 0) {
-			log_error("Could not make %s %d", ISCSI_CONFIG_ROOT,
+	if (access(ISCSI_DB_ROOT, F_OK) != 0) {
+		if (mkdir(ISCSI_DB_ROOT, 0770) != 0) {
+			log_error("Could not make %s %d", ISCSI_DB_ROOT,
 				   errno);
 			return errno;
 		}
diff -pruN 2.1.5-1/usr/idbm.h 2.1.7-2/usr/idbm.h
--- 2.1.5-1/usr/idbm.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/idbm.h	2022-05-06 17:37:21.000000000 +0000
@@ -30,12 +30,13 @@
 #include "list.h"
 #include "flashnode.h"
 
-#define NODE_CONFIG_DIR		ISCSI_CONFIG_ROOT"nodes"
-#define SLP_CONFIG_DIR		ISCSI_CONFIG_ROOT"slp"
-#define ISNS_CONFIG_DIR		ISCSI_CONFIG_ROOT"isns"
-#define STATIC_CONFIG_DIR	ISCSI_CONFIG_ROOT"static"
-#define FW_CONFIG_DIR		ISCSI_CONFIG_ROOT"fw"
-#define ST_CONFIG_DIR		ISCSI_CONFIG_ROOT"send_targets"
+#define NODE_CONFIG_DIR		ISCSI_DB_ROOT"/nodes"
+#define SLP_CONFIG_DIR		ISCSI_DB_ROOT"/slp"
+#define ISNS_CONFIG_DIR		ISCSI_DB_ROOT"/isns"
+#define STATIC_CONFIG_DIR	ISCSI_DB_ROOT"/static"
+#define FW_CONFIG_DIR		ISCSI_DB_ROOT"/fw"
+#define ST_CONFIG_DIR		ISCSI_DB_ROOT"/send_targets"
+
 #define ST_CONFIG_NAME		"st_config"
 #define ISNS_CONFIG_NAME	"isns_config"
 
diff -pruN 2.1.5-1/usr/iface.c 2.1.7-2/usr/iface.c
--- 2.1.5-1/usr/iface.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/iface.c	2022-05-06 17:37:21.000000000 +0000
@@ -93,8 +93,8 @@ static void iface_init(struct iface_rec
 }
 
 /*
- * default is to use tcp through whatever the network layer
- * selects for us with the /etc/iscsi/initiatorname.iscsi iname.
+ * Default is to use tcp through whatever the network layer
+ * selects for us with the initiatorname.iscsi iname.
  */
 void iface_setup_defaults(struct iface_rec *iface)
 {
diff -pruN 2.1.5-1/usr/iface.h 2.1.7-2/usr/iface.h
--- 2.1.5-1/usr/iface.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/iface.h	2022-05-06 17:37:21.000000000 +0000
@@ -22,7 +22,7 @@
 
 #include <libopeniscsiusr/libopeniscsiusr.h>
 
-#define IFACE_CONFIG_DIR	ISCSI_CONFIG_ROOT"ifaces"
+#define IFACE_CONFIG_DIR	ISCSI_DB_ROOT"/ifaces"
 
 struct iface_rec;
 struct list_head;
diff -pruN 2.1.5-1/usr/initiator.c 2.1.7-2/usr/initiator.c
--- 2.1.5-1/usr/initiator.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/initiator.c	2022-05-06 17:37:21.000000000 +0000
@@ -99,7 +99,7 @@ static void iscsi_ev_context_free(iscsi_
 
 		if (conn->context_pool[i]->allocated)
 			/* missing flush on shutdown */
-			log_error("BUG: context_pool leak %p",
+			conn_error(conn, "BUG: context_pool leak %p",
 				  conn->context_pool[i]);
 		free(conn->context_pool[i]);
 	}
@@ -127,7 +127,7 @@ iscsi_ev_context_get(iscsi_conn_t *conn,
 			/* some callers abuse this pointer */
 			ev_context->data = (void *)ev_context +
 					sizeof(struct iscsi_ev_context);
-			log_debug(7, "get ev context %p",
+			conn_debug(7, conn, "get ev context %p",
 				  &ev_context->actor);
 			return ev_context;
 		}
@@ -137,7 +137,8 @@ iscsi_ev_context_get(iscsi_conn_t *conn,
 
 static void iscsi_ev_context_put(struct iscsi_ev_context *ev_context)
 {
-	log_debug(7, "put ev context %p", &ev_context->actor);
+	log_debug(7, "put ev context %p:%s", &ev_context->actor,
+		  (&ev_context->actor)->name);
 	ev_context->allocated = 0;
 }
 
@@ -161,8 +162,7 @@ __login_response_status(iscsi_conn_t *co
 	case LOGIN_REDIRECTION_FAILED:
 		return CONN_LOGIN_RETRY;
 	default:
-		log_error("Login error (Login status %d) on conn %d", conn->id,
-			  login_status);
+		conn_error(conn, "Login error (Login status %d)", login_status);
 		break;
 	}
 
@@ -192,9 +192,8 @@ __check_iscsi_status_class(iscsi_session
 			conn->failback_saddr = conn->saddr;
                         return CONN_LOGIN_IMM_REDIRECT_RETRY;
 		default:
-			log_error("conn %d login rejected: redirection "
-			        "type 0x%x not supported",
-				conn->id, status_detail);
+			conn_error(conn, "login rejected: redirection "
+			        "type 0x%x not supported", status_detail);
 			return CONN_LOGIN_RETRY;
 		}
 	case ISCSI_STATUS_CLS_INITIATOR_ERR:
@@ -205,13 +204,13 @@ __check_iscsi_status_class(iscsi_session
 				session->id);
 			return CONN_LOGIN_AUTH_FAILED;
 		case ISCSI_LOGIN_STATUS_TGT_FORBIDDEN:
-			log_error("conn %d login rejected: initiator "
-			       "failed authorization with target", conn->id);
+			conn_error(conn, "login rejected: initiator "
+			       "failed authorization with target");
 			return CONN_LOGIN_AUTH_FAILED;
 		case ISCSI_LOGIN_STATUS_TGT_NOT_FOUND:
-			log_error("conn %d login rejected: initiator "
+			conn_error(conn, "login rejected: initiator "
 			       "error - target not found (%02x/%02x)",
-			       conn->id, status_class, status_detail);
+			       status_class, status_detail);
 			return CONN_LOGIN_FAILED;
 		case ISCSI_LOGIN_STATUS_NO_VERSION:
 			/*
@@ -219,29 +218,26 @@ __check_iscsi_status_class(iscsi_session
 			 * before we log an error, try the other supported
 			 * versions.
 			 */
-			log_error("conn %d login rejected: incompatible "
+			conn_error(conn, "login rejected: incompatible "
 			       "version (%02x/%02x), non-retryable, "
-			       "giving up", conn->id, status_class,
-			       status_detail);
+			       "giving up", status_class, status_detail);
 			return CONN_LOGIN_FAILED;
 		default:
-			log_error("conn %d login rejected: initiator "
-			       "error (%02x/%02x)", conn->id, status_class,
-			       status_detail);
+			conn_error(conn, "login rejected: initiator "
+			       "error (%02x/%02x)", status_class, status_detail);
 			return CONN_LOGIN_FAILED;
 		}
 	case ISCSI_STATUS_CLS_TARGET_ERR:
-		log_error("conn %d login rejected: target error "
-		       "(%02x/%02x)", conn->id, status_class, status_detail);
+		conn_error(conn, "login rejected: target error "
+		       "(%02x/%02x)", status_class, status_detail);
 		/*
 		 * We have no idea what the problem is. But spec says initiator
 		 * may retry later.
 		 */
 		 return CONN_LOGIN_RETRY;
 	default:
-		log_error("conn %d login response with unknown status "
-		       "class 0x%x, detail 0x%x", conn->id, status_class,
-		       status_detail);
+		conn_error(conn, "login response with unknown status "
+		       "class 0x%x, detail 0x%x", status_class, status_detail);
 		break;
 	}
 
@@ -256,8 +252,9 @@ __session_conn_create(iscsi_session_t *s
 	node_rec_t *rec = &session->nrec;
 	int err;
 
+	conn->id = cid;
 	if (iscsi_ev_context_alloc(conn)) {
-		log_error("cannot allocate context_pool for conn cid %d", cid);
+		conn_error(conn, "cannot allocate context_pool");
 		return ISCSI_ERR_NOMEM;
 	}
 
@@ -276,10 +273,9 @@ __session_conn_create(iscsi_session_t *s
 	conn->socket_fd = -1;
 	conn->transport_ep_handle = -1;
 	/* connection's timeouts */
-	conn->id = cid;
 	conn->logout_timeout = conn_rec->timeo.logout_timeout;
 	if (!conn->logout_timeout) {
-		log_error("Invalid timeo.logout_timeout. Must be greater "
+		conn_error(conn, "Invalid timeo.logout_timeout. Must be greater "
 			  "than zero. Using default %d.",
 			  DEF_LOGOUT_TIMEO);
 		conn->logout_timeout = DEF_LOGOUT_TIMEO;
@@ -287,7 +283,7 @@ __session_conn_create(iscsi_session_t *s
 
 	conn->login_timeout = conn_rec->timeo.login_timeout;
 	if (!conn->login_timeout) {
-		log_error("Invalid timeo.login_timeout. Must be greater "
+		conn_error(conn, "Invalid timeo.login_timeout. Must be greater "
 			  "than zero. Using default %d.",
 			  DEF_LOGIN_TIMEO);
 		conn->login_timeout = DEF_LOGIN_TIMEO;
@@ -299,14 +295,14 @@ __session_conn_create(iscsi_session_t *s
 	conn->noop_out_interval = conn_rec->timeo.noop_out_interval;
 	conn->noop_out_timeout = conn_rec->timeo.noop_out_timeout;
 	if (conn->noop_out_interval && !conn->noop_out_timeout) {
-		log_error("Invalid timeo.noop_out_timeout. Must be greater "
+		conn_error(conn, "Invalid timeo.noop_out_timeout. Must be greater "
 			  "than zero. Using default %d.",
 			  DEF_NOOP_OUT_TIMEO);
 		conn->noop_out_timeout = DEF_NOOP_OUT_TIMEO;
 	}
 
 	if (conn->noop_out_timeout && !conn->noop_out_interval) {
-		log_error("Invalid timeo.noop_out_interval. Must be greater "
+		conn_error(conn, "Invalid timeo.noop_out_interval. Must be greater "
 			  "than zero. Using default %d.",
 			  DEF_NOOP_OUT_INTERVAL);
 		conn->noop_out_interval = DEF_NOOP_OUT_INTERVAL;
@@ -329,7 +325,7 @@ __session_conn_create(iscsi_session_t *s
 static void
 session_release(iscsi_session_t *session)
 {
-	log_debug(2, "Releasing session %p", session);
+	log_debug(2, "Releasing session:%d %p", session->id, session);
 
 	if (session->target_alias)
 		free(session->target_alias);
@@ -452,7 +448,7 @@ static void iscsi_flush_context_pool(str
 static void
 __session_destroy(iscsi_session_t *session)
 {
-	log_debug(1, "destroying session");
+	log_debug(1, "destroying session:%d", session->id);
 	list_del(&session->list);
 	iscsi_flush_context_pool(session);
 	session_release(session);
@@ -471,7 +467,7 @@ session_conn_shutdown(iscsi_conn_t *conn
 {
 	iscsi_session_t *session = conn->session;
 
-	log_debug(2, "disconnect conn");
+	conn_debug(2, conn, "disconnect conn");
 	/* this will check for a valid interconnect connection */
 	if (session->t->template->ep_disconnect)
 		session->t->template->ep_disconnect(conn);
@@ -485,19 +481,18 @@ session_conn_shutdown(iscsi_conn_t *conn
 	if (conn->state == ISCSI_CONN_STATE_IN_LOGIN ||
 	    conn->state == ISCSI_CONN_STATE_IN_LOGOUT ||
 	    conn->state == ISCSI_CONN_STATE_LOGGED_IN) {
-		log_debug(2, "stop conn (conn state %d)", conn->state);
+		conn_debug(2, conn, "stop conn (conn state %d)", conn->state);
 		if (ipc->stop_conn(session->t->handle, session->id,
 				   conn->id, STOP_CONN_TERM)) {
-			log_error("can't stop connection %d:%d (%d)",
-				  session->id, conn->id, errno);
+			conn_error(conn, "can't stop connection (%d)", errno);
 			return ISCSI_ERR_INTERNAL;
 		}
 	}
 
-	log_debug(2, "kdestroy conn");
+	conn_debug(2, conn, "kdestroy conn");
 	if (ipc->destroy_conn(session->t->handle, session->id,
 		conn->id)) {
-		log_error("can not safely destroy connection %d", conn->id);
+		conn_error(conn, "can not safely destroy connection");
 		return ISCSI_ERR_INTERNAL;
 	}
 
@@ -530,7 +525,7 @@ queue_delayed_reopen(queue_task_t *qtask
 {
 	iscsi_conn_t *conn = qtask->conn;
 
-	log_debug(4, "Requeue reopen attempt in %d secs", delay);
+	conn_debug(4, conn, "Requeue reopen attempt in %d secs", delay);
 
 	/*
  	 * iscsi_login_eh can handle the login resched as
@@ -547,7 +542,7 @@ static int iscsi_conn_connect(struct isc
 	ev_context = iscsi_ev_context_get(conn, 0);
 	if (!ev_context) {
 		/* while reopening the recv pool should be full */
-		log_error("BUG: __session_conn_reopen could not get conn "
+		conn_error(conn, "BUG: __session_conn_reopen could not get conn "
 			  "context for recv.");
 		return ENOMEM;
 	}
@@ -562,14 +557,14 @@ static int iscsi_conn_connect(struct isc
 			    conn->host, sizeof(conn->host), serv, sizeof(serv),
 			    NI_NUMERICHOST|NI_NUMERICSERV);
 
-		log_error("cannot make a connection to %s:%s (%d,%d)",
+		conn_error(conn, "cannot make a connection to %s:%s (%d,%d)",
 			  conn->host, serv, rc, errno);
 		iscsi_ev_context_put(ev_context);
 		return ENOTCONN;
 	}
 
 	iscsi_sched_ev_context(ev_context, conn, 0, EV_CONN_POLL);
-	log_debug(3, "Setting login timer %p timeout %d", &conn->login_timer,
+	conn_debug(3, conn, "Setting login timer %p timeout %d", &conn->login_timer,
 		  conn->login_timeout);
 	actor_timer_mod(&conn->login_timer, conn->login_timeout, qtask);
 	return 0;
@@ -628,7 +623,7 @@ __session_conn_reopen(iscsi_conn_t *conn
 	return;
 
 queue_reopen:
-	log_debug(4, "Waiting %u seconds before trying to reconnect.", delay);
+	conn_debug(4, conn, "Waiting %u seconds before trying to reconnect.", delay);
 	queue_delayed_reopen(qtask, delay);
 }
 
@@ -660,7 +655,7 @@ static int iscsi_retry_initial_login(str
 
 	timeout.tv_sec = initial_login_retry_max * conn->login_timeout;
 	if (gettimeofday(&now, NULL)) {
-		log_error("Could not get time of day. Dropping down to "
+		conn_error(conn, "Could not get time of day. Dropping down to "
 			  "max retry check.");
 		return initial_login_retry_max > conn->session->reopen_cnt;
 	}
@@ -671,7 +666,7 @@ static int iscsi_retry_initial_login(str
 	 * then it is time to give up
 	 */
 	if (timercmp(&now, &fail_time, >)) {
-		log_debug(1, "Giving up on initial login attempt after "
+		conn_debug(1, conn, "Giving up on initial login attempt after "
 			  "%u seconds.",
 			  initial_login_retry_max * conn->login_timeout);
 		return 0;
@@ -694,7 +689,7 @@ static void iscsi_login_eh(struct iscsi_
 	struct iscsi_session *session = conn->session;
 	int stop_flag = 0;
 
-	log_debug(3, "iscsi_login_eh");
+	conn_debug(3, conn, "iscsi_login_eh");
 	/*
 	 * Flush polls and other events
 	 */
@@ -704,7 +699,7 @@ static void iscsi_login_eh(struct iscsi_
 	case ISCSI_CONN_STATE_XPT_WAIT:
 		switch (session->r_stage) {
 		case R_STAGE_NO_CHANGE:
-			log_debug(6, "login failed ISCSI_CONN_STATE_XPT_WAIT/"
+			conn_debug(6, conn, "login failed ISCSI_CONN_STATE_XPT_WAIT/"
 				  "R_STAGE_NO_CHANGE");
 			/* timeout during initial connect.
 			 * clean connection. write ipc rsp or retry */
@@ -713,14 +708,13 @@ static void iscsi_login_eh(struct iscsi_
 				session_conn_shutdown(conn, qtask, err);
 			else {
 				stop_flag = (session->id < INVALID_SESSION_ID) ? STOP_CONN_TERM : 0;
-				log_debug(6, "connection %p socket_fd: %d, "
-					  "session id: %d stop_flag: %d\n",
-					  conn, conn->socket_fd, session->id, stop_flag);
+				conn_debug(6, conn, "connection %p socket_fd: %d stop_flag: %d\n",
+					  conn, conn->socket_fd, stop_flag);
 				session_conn_reopen(conn, qtask, stop_flag);
 			}
 			break;
 		case R_STAGE_SESSION_REDIRECT:
-			log_debug(6, "login failed ISCSI_CONN_STATE_XPT_WAIT/"
+			conn_debug(6, conn, "login failed ISCSI_CONN_STATE_XPT_WAIT/"
 				  "R_STAGE_SESSION_REDIRECT");
 			/* timeout during initial redirect connect
 			 * clean connection. write ipc rsp or retry */
@@ -731,7 +725,7 @@ static void iscsi_login_eh(struct iscsi_
 				session_conn_reopen(conn, qtask, 0);
 			break;
 		case R_STAGE_SESSION_REOPEN:
-			log_debug(6, "login failed ISCSI_CONN_STATE_XPT_WAIT/"
+			conn_debug(6, conn, "login failed ISCSI_CONN_STATE_XPT_WAIT/"
 				  "R_STAGE_SESSION_REOPEN (reopen_cnt=%d, reopen_max=%d)",
 				  session->reopen_cnt, session->reopen_max);
 			if (session->reopen_max &&
@@ -756,7 +750,7 @@ static void iscsi_login_eh(struct iscsi_
 		switch (session->r_stage) {
 		case R_STAGE_NO_CHANGE:
 		case R_STAGE_SESSION_REDIRECT:
-			log_debug(6, "login failed ISCSI_CONN_STATE_IN_LOGIN/"
+			conn_debug(6, conn, "login failed ISCSI_CONN_STATE_IN_LOGIN/"
 				  "R_STAGE_NO_CHANGE %d",
 				  session->reopen_cnt);
 			/*
@@ -772,7 +766,7 @@ static void iscsi_login_eh(struct iscsi_
 						    STOP_CONN_RECOVER);
 			break;
 		case R_STAGE_SESSION_REOPEN:
-			log_debug(6, "login failed ISCSI_CONN_STATE_IN_LOGIN/"
+			conn_debug(6, conn, "login failed ISCSI_CONN_STATE_IN_LOGIN/"
 				  "R_STAGE_SESSION_REOPEN %d",
 				  session->reopen_cnt);
 			session_conn_reopen(conn, qtask, STOP_CONN_RECOVER);
@@ -787,7 +781,7 @@ static void iscsi_login_eh(struct iscsi_
 
 		break;
 	default:
-		log_error("Ignoring login error %d in conn state %d.",
+		conn_error(conn, "Ignoring login error %d in conn state %d.",
 			  err, conn->state);
 		break;
 	}
@@ -849,19 +843,19 @@ __conn_error_handle(iscsi_session_t *ses
 			iscsi_login_eh(conn, qtask, ISCSI_ERR_TRANS);
 			return;
 		}
-		log_debug(1, "ignoring conn error in login. "
+		conn_debug(1, conn, "ignoring conn error in login. "
 			  "let it timeout");
 		return;
 	case ISCSI_CONN_STATE_XPT_WAIT:
-		log_debug(1, "ignoring conn error in XPT_WAIT. "
+		conn_debug(1, conn, "ignoring conn error in XPT_WAIT. "
 			  "let connection fail on its own");
 		return;
 	case ISCSI_CONN_STATE_CLEANUP_WAIT:
-		log_debug(1, "ignoring conn error in CLEANUP_WAIT. "
+		conn_debug(1, conn, "ignoring conn error in CLEANUP_WAIT. "
 			  "let connection stop");
 		return;
 	default:
-		log_debug(8, "invalid state %d", conn->state);
+		conn_debug(8, conn, "invalid state %d", conn->state);
 		return;
 	}
 
@@ -878,6 +872,7 @@ static void session_conn_error(void *dat
 	enum iscsi_err error = *(enum iscsi_err *)ev_context->data;
 	iscsi_conn_t *conn = ev_context->conn;
 	iscsi_session_t *session = conn->session;
+	int sid = session->id;
 
 	log_warning("Kernel reported iSCSI connection %d:%d error (%d - %s) "
 		    "state (%d)", session->id, conn->id, error,
@@ -888,7 +883,7 @@ static void session_conn_error(void *dat
 	switch (error) {
 	case ISCSI_ERR_INVALID_HOST:
 		if (session_conn_shutdown(conn, NULL, ISCSI_SUCCESS))
-			log_error("BUG: Could not shutdown session.");
+			log_error("BUG: Could not shutdown session:%d.", sid);
 		break;
 	default:
 		__conn_error_handle(session, conn);
@@ -918,7 +913,7 @@ static void iscsi_login_redirect(iscsi_c
 	iscsi_session_t *session = conn->session;
 	iscsi_login_context_t *c = &conn->login_context;
 
-	log_debug(3, "login redirect ...");
+	conn_debug(3, conn, "login redirect ...");
 
 	if (session->r_stage == R_STAGE_NO_CHANGE)
 		session->r_stage = R_STAGE_SESSION_REDIRECT;
@@ -987,7 +982,7 @@ static void conn_send_nop_out(void *data
 
 	actor_timer(&conn->nop_out_timer, conn->noop_out_timeout,
 		    conn_nop_out_timeout, conn);
-	log_debug(3, "noop out timeout timer %p start, timeout %d",
+	conn_debug(3, conn, "noop out timeout timer %p start, timeout %d",
 		 &conn->nop_out_timer, conn->noop_out_timeout);
 }
 
@@ -1090,7 +1085,7 @@ setup_full_feature_phase(iscsi_conn_t *c
 	if (conn->userspace_nop && conn->noop_out_interval) {
 		actor_timer(&conn->nop_out_timer, conn->noop_out_interval,
 			   conn_send_nop_out, conn);
-		log_debug(3, "noop out timer %p start",
+		conn_debug(3, conn, "noop out timer %p start",
 			  &conn->nop_out_timer);
 	}
 }
@@ -1105,7 +1100,7 @@ static void iscsi_logout_timedout(void *
 	 * assume we were in ISCSI_CONN_STATE_IN_LOGOUT or there
 	 * was some nasty error
 	 */
-	log_debug(3, "logout timeout, dropping conn...");
+	conn_debug(3, conn, "logout timeout, dropping conn...");
 	__conn_error_handle(conn->session, conn);
 }
 
@@ -1129,14 +1124,16 @@ static int iscsi_send_logout(iscsi_conn_
 	conn->state = ISCSI_CONN_STATE_IN_LOGOUT;
 
 	ev_context = iscsi_ev_context_get(conn, 0);
-	if (!ev_context)
+	if (!ev_context) {
 		/* unbounded logout */
-		log_warning("Could not allocate conn context for logout.");
-	else {
+		log_warning("connection%d:%d Could not allocate conn context for logout.",
+			conn->session->id, conn->id);
+		return ENOMEM;
+	} else {
 		iscsi_sched_ev_context(ev_context, conn,
 					 conn->logout_timeout,
 					 EV_CONN_LOGOUT_TIMER);
-		log_debug(3, "logout timeout timer %u",
+		conn_debug(3, conn, "logout timeout timer %u",
 			  conn->logout_timeout * 1000);
 	}
 
@@ -1148,23 +1145,27 @@ static void iscsi_stop(void *data)
 	struct iscsi_ev_context *ev_context = data;
 	struct iscsi_conn *conn = ev_context->conn;
 	int rc = 0;
+	int sid = conn->session->id;
 
 	iscsi_ev_context_put(ev_context);
 
 	if (!(conn->session->t->caps & CAP_LOGIN_OFFLOAD)) {
-		if (!iscsi_send_logout(conn))
+		rc = iscsi_send_logout(conn);
+		if (!rc)
 			return;
+		conn_error(conn, "Could not send logout pdu(%s) from iscsi_stop."
+			"Dropping session", strerror(rc));
 	}
 
 	rc = session_conn_shutdown(conn, conn->logout_qtask, ISCSI_SUCCESS);
 	if (rc)
-		log_error("BUG: Could not shutdown session.");
+		log_error("BUG: Could not shutdown session:%d.", sid);
 }
 
 static void iscsi_recv_nop_in(iscsi_conn_t *conn, struct iscsi_hdr *hdr)
 {
 	if (!conn->userspace_nop) {
-		log_error("Got nop in, but kernel supports nop handling.");
+		conn_error(conn, "Got nop in, but kernel supports nop handling.");
 		return;
 	}
 
@@ -1177,7 +1178,7 @@ static void iscsi_recv_nop_in(iscsi_conn
 	} else /*  noop in req */
 		if (!__send_nopin_rsp(conn, (struct iscsi_nopin*)hdr,
 				      conn->data)) {
-			log_error("can not send nopin response");
+			conn_error(conn, "can not send nopin response");
 		}
 }
 
@@ -1185,10 +1186,10 @@ static void iscsi_recv_logout_rsp(iscsi_
 {
 	struct iscsi_logout_rsp *logout_rsp = (struct iscsi_logout_rsp *)hdr;
 
-	log_debug(3, "Recv: logout response %d", logout_rsp->response);
+	conn_debug(3, conn, "Recv: logout response %d", logout_rsp->response);
 	if (logout_rsp->response == 2 || logout_rsp->response == 3) {
 		conn->session->def_time2wait = ntohs(logout_rsp->t2wait);
-		log_debug(4, "logout rsp returned time2wait %u",
+		conn_debug(4, conn, "logout rsp returned time2wait %u",
 			  conn->session->def_time2wait);
 	}
 	/* TODO process the hdr */
@@ -1202,8 +1203,9 @@ static void iscsi_recv_async_msg(iscsi_c
 	char *buf = conn->data;
 	unsigned int senselen;
 	struct scsi_sense_hdr sshdr;
+	int rc = 0;
 
-	log_debug(3, "Read AEN %d", async_hdr->async_event);
+	conn_debug(3, conn, "Read AEN %d", async_hdr->async_event);
 
 	switch (async_hdr->async_event) {
 	case ISCSI_ASYNC_MSG_SCSI_EVENT:
@@ -1211,7 +1213,7 @@ static void iscsi_recv_async_msg(iscsi_c
 		buf += 2;
 
 		if (!scsi_normalize_sense((uint8_t *)buf, senselen, &sshdr)) {
-			log_error("Could not handle AEN %d. Invalid sense.",
+			conn_error(conn, "Could not handle AEN %d. Invalid sense.",
 				  async_hdr->async_event);
 			break;
 		}
@@ -1221,15 +1223,27 @@ static void iscsi_recv_async_msg(iscsi_c
 			session_scan_host(session, session->hostno, NULL);
 		break;
 	case ISCSI_ASYNC_MSG_REQUEST_LOGOUT:
-		log_warning("Target requests logout within %u seconds for "
-			   "connection", ntohs(async_hdr->param3));
-		if (iscsi_send_logout(conn))
-			log_error("Could not send logout in response to"
-				 "logout request aen");
+		conn_warn(conn, "Target requests logout within %u seconds" , ntohs(async_hdr->param3));
+		/*
+		 * for ASYNC LOUOUT request, initiator would try to send a
+		 * logout request and desire target's logout response, in
+		 * logout response handler, initiator would call __conn_error_handle()
+		 * to try to relogin.
+		 *
+		 * While if iscsi_send_logout() failed, we don't know what target
+		 * would do, maybe target would close connection? Which would trigger
+		 * initiator relogin too.
+		 *
+		 * Now we just print an error log to tell the iscsi_send_logout()
+		 * failed and the failed reason, do nothing special.
+		 */
+		rc = iscsi_send_logout(conn);
+		if (rc)
+			conn_error(conn, "Could not send logout in response to"
+				 "logout request aen:%s", strerror(rc));
 		break;
 	case ISCSI_ASYNC_MSG_DROPPING_CONNECTION:
-		log_warning("Target dropping connection %u, reconnect min %u "
-			    "max %u", ntohs(async_hdr->param1),
+		conn_warn(conn, "Target dropping %u, reconnect min %u max %u", ntohs(async_hdr->param1),
 			    ntohs(async_hdr->param2), ntohs(async_hdr->param3));
 		session->def_time2wait =
 			(uint32_t)ntohs(async_hdr->param2) & 0x0000FFFFFL;
@@ -1243,7 +1257,7 @@ static void iscsi_recv_async_msg(iscsi_c
 		break;
 	case ISCSI_ASYNC_MSG_PARAM_NEGOTIATION:
 		log_warning("Received async event param negotiation, "
-			    "dropping session");
+			    "dropping session:%d", session->id);
 		__conn_error_handle(session, conn);
 		break;
 	case ISCSI_ASYNC_MSG_VENDOR_SPECIFIC:
@@ -1259,7 +1273,7 @@ static void iscsi_recv_login_rsp(struct
 	int err = ISCSI_ERR_FATAL_LOGIN;
 
 	if (iscsi_login_rsp(session, c)) {
-		log_debug(1, "login_rsp ret (%d)", c->ret);
+		conn_debug(1, conn, "login_rsp ret (%d)", c->ret);
 
 		switch (__login_response_status(conn, c->ret)) {
 		case CONN_LOGIN_FAILED:
@@ -1347,23 +1361,23 @@ static void session_conn_recv_pdu(void *
 			iscsi_recv_async_msg(conn, &hdr);
 			break;
 		default:
-			log_error("unsupported opcode 0x%x", hdr.opcode);
+			conn_error(conn, "unsupported opcode 0x%x", hdr.opcode);
 			break;
 		}
 		break;
 	case ISCSI_CONN_STATE_XPT_WAIT:
 		iscsi_ev_context_put(ev_context);
-		log_debug(1, "ignoring incoming PDU in XPT_WAIT. "
+		conn_debug(1, conn, "ignoring incoming PDU in XPT_WAIT. "
 			  "let connection re-establish or fail");
 		break;
 	case ISCSI_CONN_STATE_CLEANUP_WAIT:
 		iscsi_ev_context_put(ev_context);
-		log_debug(1, "ignoring incoming PDU in XPT_WAIT. "
+		conn_debug(1, conn, "ignoring incoming PDU in XPT_WAIT. "
 			  "let connection cleanup");
 		break;
 	default:
 		iscsi_ev_context_put(ev_context);
-		log_error("Invalid state. Dropping PDU.");
+		conn_error(conn, "Invalid state %d. Dropping PDU.", conn->state);
 	}
 }
 
@@ -1510,7 +1524,7 @@ static void setup_offload_login_phase(is
 	if (ipc->start_conn(session->t->handle, session->id, conn->id,
 			    &rc) || rc) {
 		if (rc == -EEXIST) {
-			log_error("Session already exists.");
+			conn_error(conn, "Session already exists.");
 			session_conn_shutdown(conn, c->qtask,
 					      ISCSI_ERR_SESS_EXISTS);
 		} else {
@@ -1542,11 +1556,11 @@ static void session_conn_poll(void *data
 
 	rc = session->t->template->ep_poll(conn, 1);
 	if (rc == 0) {
-		log_debug(4, "poll not connected %d", rc);
+		conn_debug(4, conn, "poll not connected %d", rc);
 		ev_context = iscsi_ev_context_get(conn, 0);
 		if (!ev_context) {
 			/* while polling the recv pool should be full */
-			log_error("BUG: session_conn_poll could not get conn "
+			conn_error(conn, "BUG: session_conn_poll could not get conn "
 				  "context.");
 			iscsi_login_eh(conn, qtask, ISCSI_ERR_INTERNAL);
 			return;
@@ -1571,7 +1585,8 @@ static void session_conn_poll(void *data
 			err = ipc->create_conn(session->t->handle,
 					session->id, conn->id, &conn->id);
 			if (err) {
-				log_error("Can't create connection.");
+				log_error("Can't create connection for session%d.",
+					session->id);
 				err = ISCSI_ERR_INTERNAL;
 				goto cleanup;
 			}
@@ -1635,7 +1650,7 @@ static void session_conn_poll(void *data
 			return;
 		}
 	} else {
-		log_debug(4, "poll error %d", rc);
+		conn_debug(4, conn, "poll error %d", rc);
 		queue_delayed_reopen(qtask, ISCSI_CONN_ERR_REOPEN_DELAY);
 	}
 
@@ -1707,7 +1722,8 @@ failed_login:
 	session->notify_qtask = NULL;
 	mgmt_ipc_write_rsp(qtask, ISCSI_ERR_LOGIN);
 	if (ipc->destroy_conn(session->t->handle, session->id, conn->id))
-		log_error("can not safely destroy connection %d", conn->id);
+		log_error("can not safely destroy connection%d:%d",
+			session->id, conn->id);
 	if (ipc->destroy_session(session->t->handle, session->id))
 		log_error("can not safely destroy session %d", session->id);
 	__session_destroy(session);
@@ -1720,7 +1736,7 @@ static int iscsi_sched_ev_context(struct
 {
 	enum iscsi_err error;
 
-	log_debug(7, "sched conn context %p event %d, tmo %lu",
+	conn_debug(7, conn, "sched conn context %p event %d, tmo %lu",
 		  &ev_context->actor, event, tmo);
 
 	ev_context->conn = conn;
@@ -1764,7 +1780,7 @@ static int iscsi_sched_ev_context(struct
 		actor_schedule(&ev_context->actor);
 		break;
 	default:
-		log_error("Invalid event type %d.", event);
+		conn_error(conn, "Invalid event type %d.", event);
 	}
 	return 0;
 }
@@ -2012,6 +2028,10 @@ iscsi_sync_session(node_rec_t *rec, queu
 	struct iscsi_transport *t;
 	int err;
 
+	session = session_find_by_sid(sid);
+	if (session != NULL)
+		return ISCSI_ERR_SESS_EXISTS;
+
 	t = iscsi_sysfs_get_transport_by_name(rec->iface.transport_name);
 	if (!t)
 		return ISCSI_ERR_TRANS_NOT_FOUND;
@@ -2055,7 +2075,7 @@ static int session_unbind(struct iscsi_s
 	err = ipc->unbind_session(session->t->handle, session->id);
 	if (err)
 		/* older kernels did not support unbind */
-		log_debug(2, "Could not unbind session %d.", err);
+		log_debug(2, "Could not unbind session%d %d.", session->id, err);
 	return err;
 }
 
@@ -2080,7 +2100,9 @@ int session_logout_task(int sid, queue_t
 	if (session->notify_qtask &&
 	    (conn->state == ISCSI_CONN_STATE_XPT_WAIT) &&
 	    (session->r_stage == R_STAGE_SESSION_REOPEN)) {
-		log_warning("session cannot be terminted because it's trying to reconnect: try again later");
+		log_warning("session %d cannot be terminted because "
+			    "it's trying to reconnect: try again later",
+			session->id);
 		return ISCSI_ERR_SESSION_NOT_CONNECTED;
 	}
 
@@ -2095,14 +2117,14 @@ int session_logout_task(int sid, queue_t
 	    (session->r_stage == R_STAGE_NO_CHANGE ||
 	     session->r_stage == R_STAGE_SESSION_REDIRECT))) {
 invalid_state:
-		log_error("session in invalid state for logout. "
-			   "Try again later");
+		log_error("session %d in invalid state for logout. "
+			   "Try again later", session->id);
 		return ISCSI_ERR_INTERNAL;
 	}
 
 	if (dconfig->safe_logout && session_in_use(sid)) {
-		log_error("Session is actively in use for mounted storage, "
-			  "and iscsid.safe_logout is configured.");
+		log_error("Session %d is actively in use for mounted storage, "
+			  "and iscsid.safe_logout is configured.", session->id);
 		return ISCSI_ERR_BUSY;
 	}
 
@@ -2123,11 +2145,13 @@ invalid_state:
 		/* LLDs that offload login also offload logout */
 		if (!(session->t->caps & CAP_LOGIN_OFFLOAD)) {
 			/* unbind is not supported so just do old logout */
-			if (!iscsi_send_logout(conn))
+			rc = iscsi_send_logout(conn);
+			if (rc)
 				return ISCSI_SUCCESS;
 		}
 
-		log_error("Could not send logout pdu. Dropping session");
+		conn_error(conn, "Could not send logout pdu(%s) from session_logout_task."
+			"Dropping session", strerror(rc));
 		/* fallthrough */
 	default:
 		rc = session_conn_shutdown(conn, qtask, ISCSI_SUCCESS);
diff -pruN 2.1.5-1/usr/initiator_common.c 2.1.7-2/usr/initiator_common.c
--- 2.1.5-1/usr/initiator_common.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/initiator_common.c	2022-05-06 17:37:21.000000000 +0000
@@ -273,12 +273,10 @@ static int host_set_param(struct iscsi_t
 
 static void print_param_value(enum iscsi_param param, void *value, int type)
 {
-	log_debug(3, "set operational parameter %d to:", param);
-
 	if (type == ISCSI_STRING)
-		log_debug(3, "%s", value ? (char *)value : "NULL");
+		log_debug(3, "set operational parameter %d to %s", param, value ? (char *)value : "NULL");
 	else
-		log_debug(3, "%u", *(uint32_t *)value);
+		log_debug(3, "set operational parameter %d to %u", param, *(uint32_t *)value);
 }
 
 #define MAX_HOST_PARAMS 2
diff -pruN 2.1.5-1/usr/initiator.h 2.1.7-2/usr/initiator.h
--- 2.1.5-1/usr/initiator.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/initiator.h	2022-05-06 17:37:21.000000000 +0000
@@ -32,19 +32,64 @@
 #include "config.h"
 #include "actor.h"
 #include "list.h"
+#include "log.h"
 
+#ifndef ISCSI_CONFIG_ROOT
 #define ISCSI_CONFIG_ROOT	"/etc/iscsi/"
+#endif
 
-#define CONFIG_FILE		ISCSI_CONFIG_ROOT"iscsid.conf"
-#define INITIATOR_NAME_FILE	ISCSI_CONFIG_ROOT"initiatorname.iscsi"
+#define CONFIG_FILE		ISCSI_CONFIG_ROOT"/iscsid.conf"
+#define INITIATOR_NAME_FILE	ISCSI_CONFIG_ROOT"/initiatorname.iscsi"
 
 #define PID_FILE		"/run/iscsid.pid"
+
 #ifndef LOCK_DIR
 #define LOCK_DIR		"/run/lock/iscsi"
 #endif
+
 #define LOCK_FILE		LOCK_DIR"/lock"
 #define LOCK_WRITE_FILE		LOCK_DIR"/lock.write"
 
+#define conn_info(conn, fmt, ...)				\
+do {								\
+	if (conn->session == NULL) { 				\
+		log_info(fmt, ##__VA_ARGS__);			\
+		break;						\
+	}							\
+	log_info("connection%d:%d " fmt,			\
+		   conn->session->id, conn->id, ##__VA_ARGS__);	\
+} while(0)
+
+#define conn_warn(conn, fmt, ...)				\
+do {								\
+	if (conn->session == NULL) { 				\
+		log_warning(fmt, ##__VA_ARGS__);		\
+		break;						\
+	}							\
+	log_warning("connection%d:%d " fmt,			\
+		   conn->session->id, conn->id, ##__VA_ARGS__);	\
+} while(0)
+
+#define conn_error(conn, fmt, ...)				\
+do {								\
+	if (conn->session == NULL) { 				\
+		log_error(fmt, ##__VA_ARGS__);			\
+		break;						\
+	}							\
+	log_error("connection%d:%d " fmt,			\
+		   conn->session->id, conn->id, ##__VA_ARGS__);	\
+} while(0)
+
+#define conn_debug(level, conn, fmt, ...)			\
+do {								\
+	if (conn->session == NULL) { 				\
+		log_debug(level, fmt, ##__VA_ARGS__);		\
+		break;						\
+	}							\
+	log_debug(level, "connection%d:%d " fmt,		\
+		   conn->session->id, conn->id, ##__VA_ARGS__);	\
+} while(0)
+
 typedef enum iscsi_session_r_stage_e {
 	R_STAGE_NO_CHANGE,
 	R_STAGE_SESSION_CLEANUP,
diff -pruN 2.1.5-1/usr/iscsiadm.c 2.1.7-2/usr/iscsiadm.c
--- 2.1.5-1/usr/iscsiadm.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/iscsiadm.c	2022-05-06 17:37:21.000000000 +0000
@@ -114,7 +114,7 @@ static const struct verify_mode_t mode_p
 	[MODE_SESSION] = {"session", "PiRdrmusonuSv", 1},
 	[MODE_HOST] = {"host", "CHdmPotnvxA", 0},
 	[MODE_IFACE] = {"iface", "HIdnvmPoCabci", 0},
-	[MODE_FW] = {"fw", "dmlW", 0},
+	[MODE_FW] = {"fw", "dmlWnv", 0},
 };
 
 static struct option const long_options[] =
@@ -165,10 +165,10 @@ iscsiadm -m discoverydb [-hV] [-d debug_
 [-o operation] [-n name] [-v value] [-lD]] \n\
 iscsiadm -m discovery [-hV] [-d debug_level] [-P printlevel] [-t type -p ip:port -I ifaceN ... [-l]] | [[-p ip:port] [-l | -D]] [-W]\n\
 iscsiadm -m node [-hV] [-d debug_level] [-P printlevel] [-L all,manual,automatic,onboot] [-W] [-U all,manual,automatic,onboot] [-S] [[-T targetname -p ip:port -I ifaceN] [-l | -u | -R | -s]] \
-[[-o  operation ] [-n name] [-v value]]\n\
-iscsiadm -m session [-hV] [-d debug_level] [-P  printlevel] [-r sessionid | sysfsdir [-R | -u | -s] [-o operation] [-n name] [-v value]]\n\
-iscsiadm -m iface [-hV] [-d debug_level] [-P printlevel] [-I ifacename | -H hostno|MAC] [[-o  operation ] [-n name] [-v value]] [-C ping [-a ip] [-b packetsize] [-c count] [-i interval]]\n\
-iscsiadm -m fw [-d debug_level] [-l] [-W]\n\
+[[-o operation ] [-n name] [-v value]]\n\
+iscsiadm -m session [-hV] [-d debug_level] [-P printlevel] [-r sessionid | sysfsdir [-R | -u | -s] [-o operation] [-n name] [-v value]]\n\
+iscsiadm -m iface [-hV] [-d debug_level] [-P printlevel] [-I ifacename | -H hostno|MAC] [[-o operation ] [-n name] [-v value]] [-C ping [-a ip] [-b packetsize] [-c count] [-i interval]]\n\
+iscsiadm -m fw [-d debug_level] [-l] [-W] [[-n name] [-v value]]\n\
 iscsiadm -m host [-P printlevel] [-H hostno|MAC] [[-C chap [-x chap_tbl_idx]] | [-C flashnode [-A portal_type] [-x flashnode_idx]] | [-C stats]] [[-o operation] [-n name] [-v value]] \n\
 iscsiadm -k priority\n");
 	}
@@ -3013,8 +3013,61 @@ done:
 	return rc;
 }
 
+static int fill_in_default_fw_values(node_rec_t *rec, struct list_head *params)
+{
+	struct user_param *param;
+	int rc;
+
+	/* must init this so we can check if user overrode them */
+	rec->session.initial_login_retry_max = -1;
+	rec->conn[0].timeo.noop_out_interval = -1;
+	rec->conn[0].timeo.noop_out_timeout = -1;
+	rec->session.scan = -1;
+
+	list_for_each_entry(param, params, list) {
+		/*
+		 * do not allow user to override iface parameters, since
+		 * firmware/ibft values should be used and not overridden
+		 */
+		if (!strcmp(param->name, IFACE_NETNAME) ||
+		    !strcmp(param->name, IFACE_HWADDR) ||
+		    !strcmp(param->name, IFACE_TRANSPORTNAME)) {
+			log_error("Cannot override interface parameters for firmware logins");
+			return ISCSI_ERR_INVAL;
+		}
+	}
+
+	if (!list_empty(params)) {
+		rc = idbm_node_set_rec_from_param(params, rec, 0);
+		if (rc)
+			return rc;
+	}
+
+	/*
+	 * For root boot we could not change this in older versions so
+	 * if user did not override then use the defaults.
+	 *
+	 * Increase to account for boot using static setup.
+	 */
+	if (rec->session.initial_login_retry_max == -1)
+		rec->session.initial_login_retry_max = 30;
+
+	/* firmware logins are usually used for booting, so no NOPs */
+	if (rec->conn[0].timeo.noop_out_interval == -1)
+		rec->conn[0].timeo.noop_out_interval = 0;
+	if (rec->conn[0].timeo.noop_out_timeout == -1)
+		rec->conn[0].timeo.noop_out_timeout = 0;
+
+	/* default scan mode is "auto" */
+	if (rec->session.scan == -1)
+		rec->session.scan = DEF_INITIAL_SCAN;
+
+	return 0;
+}
+
 static int exec_fw_op(discovery_rec_t *drec, struct list_head *ifaces,
-		      int info_level, int do_login, int op, bool wait)
+		      int info_level, int do_login, int op, bool wait,
+		      struct list_head *params)
 {
 	struct boot_context *context;
 	LIST_HEAD(targets);
@@ -3042,6 +3095,12 @@ static int exec_fw_op(discovery_rec_t *d
 				rc = ISCSI_ERR_NOMEM;
 				break;
 			}
+			/* update rec based on params and default values */
+			rc = fill_in_default_fw_values(rec, params);
+			if (rc) {
+				log_error("Could not merge user params");
+				break;
+			}
 
 			if (wait)
 				iscsi_login_portal(NULL, NULL, rec);
@@ -3205,7 +3264,7 @@ static int exec_disc2_op(int disc_type,
 		}
 
 		drec.type = DISCOVERY_TYPE_FW;
-		rc = exec_fw_op(&drec, ifaces, info_level, do_login, op, true);
+		rc = exec_fw_op(&drec, ifaces, info_level, do_login, op, true, NULL);
 		goto done;
 	default:
 		rc = ISCSI_ERR_INVAL;
@@ -3323,7 +3382,7 @@ static int exec_disc_op(int disc_type,
 		break;
 	case DISCOVERY_TYPE_FW:
 		drec.type = DISCOVERY_TYPE_FW;
-		rc = exec_fw_op(&drec, ifaces, info_level, do_login, op, wait);
+		rc = exec_fw_op(&drec, ifaces, info_level, do_login, op, wait, NULL);
 		break;
 	default:
 		if (ip) {
@@ -3599,6 +3658,9 @@ main(int argc, char **argv)
 	struct iscsi_session *se = NULL;
 	bool wait = true;
 
+	/* enable stdout logging */
+	log_init(program_name, 1024, log_do_log_std, NULL);
+
 	ctx = iscsi_context_new();
 	if (ctx == NULL) {
 		log_error("No memory");
@@ -3616,8 +3678,6 @@ main(int argc, char **argv)
 
 	umask(0077);
 
-	/* enable stdout logging */
-	log_init(program_name, 1024, log_do_log_std, NULL);
 	sysfs_init();
 
 	optopt = 0;
@@ -3805,7 +3865,7 @@ main(int argc, char **argv)
 		usage(ISCSI_ERR_INVAL);
 
 	if (mode == MODE_FW) {
-		rc = exec_fw_op(NULL, NULL, info_level, do_login, op, wait);
+		rc = exec_fw_op(NULL, NULL, info_level, do_login, op, wait, &params);
 		goto out;
 	}
 
diff -pruN 2.1.5-1/usr/iscsid.c 2.1.7-2/usr/iscsid.c
--- 2.1.5-1/usr/iscsid.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/iscsid.c	2022-05-06 17:37:21.000000000 +0000
@@ -95,16 +95,16 @@ static void usage(int status)
 		printf("Usage: %s [OPTION]\n", program_name);
 		printf("\
 Open-iSCSI initiator daemon.\n\
-  -c, --config=[path]     Execute in the config file (" CONFIG_FILE ").\n\
+  -c, --config=[path]     Execute using the config file (" CONFIG_FILE ").\n\
   -i, --initiatorname=[path]     read initiatorname from file (" INITIATOR_NAME_FILE ").\n\
-  -f, --foreground        make the program run in the foreground\n\
-  -d, --debug debuglevel  print debugging information\n\
-  -u, --uid=uid           run as uid, default is current user\n\
-  -g, --gid=gid           run as gid, default is current user group\n\
-  -n, --no-pid-file       do not use a pid file\n\
-  -p, --pid=pidfile       use pid file (default " PID_FILE ").\n\
-  -h, --help              display this help and exit\n\
-  -v, --version           display version and exit\n\
+  -f, --foreground        Make the program run in the foreground\n\
+  -d, --debug debuglevel  Print debugging information\n\
+  -u, --uid=uid           Run as uid, default is current user\n\
+  -g, --gid=gid           Run as gid, default is current user group\n\
+  -n, --no-pid-file       Do not use a pid file\n\
+  -p, --pid=pidfile       Use pid file (default " PID_FILE ").\n\
+  -h, --help              Display this help and exit\n\
+  -v, --version           Display version and exit\n\
 ");
 	}
 	exit(status);
@@ -289,7 +289,10 @@ retry:
 		retries++;
 		sleep(1);
 		goto retry;
+	} else if (rc == ISCSI_ERR_SESS_EXISTS) {
+		log_debug(1, "sync session %d returned ISCSI_ERR_SESS_EXISTS", info->sid);
 	}
+
 	return 0;
 }
 
diff -pruN 2.1.5-1/usr/iscsid_req.c 2.1.7-2/usr/iscsid_req.c
--- 2.1.5-1/usr/iscsid_req.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/iscsid_req.c	2022-05-06 17:37:21.000000000 +0000
@@ -46,7 +46,7 @@ static void iscsid_startup(void)
 	if (!startup_cmd) {
 		log_error("iscsid is not running. Could not start it up "
 			  "automatically using the startup command in the "
-			  "/etc/iscsi/iscsid.conf iscsid.startup setting. "
+			  "iscsid.conf iscsid.startup setting. "
 			  "Please check that the file exists or that your "
 			  "init scripts have started iscsid.");
 		return;
@@ -141,12 +141,7 @@ int iscsid_response(int fd, iscsiadm_cmd
 	size_t len = sizeof(*rsp);
 	int iscsi_err = ISCSI_ERR_ISCSID_COMM_ERR;
 	int err;
-	int poll_wait = 0;
 
-	if (timeout == -1) {
-		timeout = ISCSID_REQ_TIMEOUT;
-		poll_wait = 1;
-	}
 	while (len) {
 		struct pollfd pfd;
 
@@ -154,9 +149,7 @@ int iscsid_response(int fd, iscsiadm_cmd
 		pfd.events = POLLIN;
 		err = poll(&pfd, 1, timeout);
 		if (!err) {
-			if (poll_wait)
-				continue;
-			return ISCSI_ERR_SESSION_NOT_CONNECTED;
+			return ISCSI_ERR_REQ_TIMEDOUT;
 		} else if (err < 0) {
 			if (errno == EINTR)
 				continue;
diff -pruN 2.1.5-1/usr/iscsi_err.c 2.1.7-2/usr/iscsi_err.c
--- 2.1.5-1/usr/iscsi_err.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/iscsi_err.c	2022-05-06 17:37:21.000000000 +0000
@@ -57,6 +57,7 @@ static char *iscsi_err_msgs[] = {
 	/* 30 */ "unknown discovery type",
 	/* 31 */ "child process terminated",
 	/* 32 */ "target likely not connected",
+	/* 33 */ "iscsid request timed out",
 };
 
 char *iscsi_err_to_str(int err)
diff -pruN 2.1.5-1/usr/iscsistart.c 2.1.7-2/usr/iscsistart.c
--- 2.1.5-1/usr/iscsistart.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/iscsistart.c	2022-05-06 17:37:21.000000000 +0000
@@ -241,26 +241,18 @@ static int login_session(struct node_rec
 	/*
 	 * Need to handle race where iscsid proc is starting up while we are
 	 * trying to connect. Retry with exponential backoff, start from 50 ms.
-	 *
-	 * NOTE: another race condition can occur if the system is just coming
-	 * up, where our login request will be sent, but the login response
-	 * takes a while. In such a case, if we timeout and give up, the
-	 * login response may still show up once we give up, in which case
-	 * it seems to get iscsistart into a state where it cannot try to
-	 * login again because it thinks there's already a session. So make
-	 * sure our timeout is long enough, on each try, to give the response
-	 * a chance to show up. The old value of 1 second was not enough,
-	 * so we multiply that by 10, which seems reasonable for initial
-	 * login.
 	 */
 	for (msec = 50; msec <= 15000; msec <<= 1) {
-		int tmo = ISCSID_REQ_TIMEOUT * 10;
-
-		rc = iscsid_exec_req(&req, &rsp, 0, tmo);
+		/*
+		 * Once our event loop is up then we want to wait for the login
+		 * response. Either it logs in, we hit the login retries count,
+		 * or this program crashes, so there no need for the response
+		 * timeout.
+		 */
+		rc = iscsid_exec_req(&req, &rsp, 0, -1);
 		if (rc == 0) {
 			return rc;
-		} else if (rc == ISCSI_ERR_SESSION_NOT_CONNECTED ||
-			   rc == ISCSI_ERR_ISCSID_NOTCONN) {
+		} else if (rc == ISCSI_ERR_ISCSID_NOTCONN) {
 			ts.tv_sec = msec / 1000;
 			ts.tv_nsec = (msec % 1000) * 1000000L;
 
diff -pruN 2.1.5-1/usr/iscsi_sysfs.c 2.1.7-2/usr/iscsi_sysfs.c
--- 2.1.5-1/usr/iscsi_sysfs.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/iscsi_sysfs.c	2022-05-06 17:37:21.000000000 +0000
@@ -1416,8 +1416,8 @@ int iscsi_sysfs_get_sessioninfo_by_id(st
 	log_debug(7, "found targetname %s address %s pers address %s port %d "
 		 "pers port %d driver %s iface name %s ipaddress %s "
 		 "netdev %s hwaddress %s iname %s",
-		  info->targetname, info->address ? info->address : "NA",
-		  info->persistent_address ? info->persistent_address : "NA",
+		  info->targetname, info->address[0] ? info->address : "NA",
+		  info->persistent_address[0] ? info->persistent_address : "NA",
 		  info->port, info->persistent_port, info->iface.transport_name,
 		  info->iface.name, info->iface.ipaddress,
 		  info->iface.netdev, info->iface.hwaddress,
@@ -1929,18 +1929,41 @@ void iscsi_sysfs_set_queue_depth(void *d
 void iscsi_sysfs_set_device_online(__attribute__((unused))void *data,
 				   int hostno, int target, int lun)
 {
-	char *write_buf = "running\n";
+	char *write_buf = "running\n", *state;
 	char id[NAME_SIZE];
 	int err;
 
 	snprintf(id, sizeof(id), "%d:0:%d:%d", hostno, target, lun);
 	log_debug(4, "online device %s", id);
 
+	state = sysfs_get_value(id, SCSI_SUBSYS, "state");
+	if (!state) {
+		log_error("Could not read state for LUN %s\n", id);
+		goto set_state;
+	}
+
+	if (!strcmp(state, "running"))
+		goto done;
+	/*
+	 * The kernel can start to perform session level recovery cleanup
+	 * any time after the conn start call, so we only want to change the
+	 * state if we are in one of the offline states.
+	 */
+	if (strcmp(state, "offline") && strcmp(state, "transport-offline")) {
+		log_debug(4, "Dev not offline. Skip onlining %s", id);
+		goto done;
+	}
+
+set_state:
 	err = sysfs_set_param(id, SCSI_SUBSYS, "state", write_buf,
 			      strlen(write_buf));
 	if (err && err != EINVAL)
 		/* we should read the state */
 		log_error("Could not online LUN %d err %d.", lun, err);
+
+done:
+	if (state)
+		free(state);
 }
 
 void iscsi_sysfs_rescan_device(__attribute__((unused))void *data,
diff -pruN 2.1.5-1/usr/login.c 2.1.7-2/usr/login.c
--- 2.1.5-1/usr/login.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/login.c	2022-05-06 17:37:21.000000000 +0000
@@ -657,7 +657,7 @@ iscsi_process_login_response(iscsi_sessi
 	struct iscsi_acl *auth_client;
 	iscsi_conn_t *conn = &session->conn[cid];
 
-	auth_client = (session->auth_buffers && session->num_auth_buffers) ?
+	auth_client = (session->num_auth_buffers > 0) ?
 		(struct iscsi_acl *)session->auth_buffers[0].address : NULL;
 
 	end = text + ntoh24(login_rsp->dlength) + 1;
@@ -1135,7 +1135,7 @@ iscsi_make_login_pdu(iscsi_session_t *se
 	struct iscsi_acl *auth_client;
 	iscsi_conn_t *conn = &session->conn[cid];
 
-	auth_client = (session->auth_buffers && session->num_auth_buffers) ?
+	auth_client = (session->num_auth_buffers > 0) ?
 		(struct iscsi_acl *)session->auth_buffers[0].address : NULL;
 
 	/* initialize the PDU header */
@@ -1170,7 +1170,7 @@ iscsi_make_login_pdu(iscsi_session_t *se
 				return 0;
 		}
 
-		if ((session->target_name && session->target_name[0]) &&
+		if ((session->target_name[0] != '\0') &&
 		    (session->type == ISCSI_SESSION_TYPE_NORMAL)) {
 			if (!iscsi_add_text(hdr, data, max_data_length,
 			    "TargetName", session->target_name))
@@ -1248,16 +1248,16 @@ check_for_authentication(iscsi_session_t
 		return LOGIN_FAILED;
 	}
 
-	if (session->username &&
+	if ((session->username[0] != '\0') &&
 	    (acl_set_user_name(auth_client, session->username) !=
-	    AUTH_STATUS_NO_ERROR)) {
+	     AUTH_STATUS_NO_ERROR)) {
 		log_error("Couldn't set username");
 		goto end;
 	}
 
-	if (session->password && (acl_set_passwd(auth_client,
-	    session->password, session->password_length) !=
-		 AUTH_STATUS_NO_ERROR)) {
+	if ((session->password[0] != '\0') &&
+       	    (acl_set_passwd(auth_client, session->password, session->password_length) !=
+	     AUTH_STATUS_NO_ERROR)) {
 		log_error("Couldn't set password");
 		goto end;
 	}
@@ -1366,7 +1366,7 @@ iscsi_login_begin(iscsi_session_t *sessi
 	conn->current_stage = ISCSI_INITIAL_LOGIN_STAGE;
 	conn->partial_response = 0;
 
-	if (session->auth_buffers && session->num_auth_buffers) {
+	if (session->num_auth_buffers > 0) {
 		c->ret = check_for_authentication(session, c->auth_client);
 		if (c->ret != LOGIN_OK)
 			return 1;
diff -pruN 2.1.5-1/usr/Makefile 2.1.7-2/usr/Makefile
--- 2.1.5-1/usr/Makefile	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/Makefile	2022-05-06 17:37:21.000000000 +0000
@@ -4,6 +4,12 @@ ifeq ($(TOPDIR),)
 	TOPDIR = ..
 endif
 
+INSTALL = install
+
+DESTDR ?=
+SBINDIR ?= /sbin
+etcdir = /etc
+
 OSNAME=$(shell uname -s)
 
 # allow users to override these
@@ -32,13 +38,17 @@ IPC_OBJ=ioctl.o
 endif
 endif
 
-PKG_CONFIG = /usr/bin/pkg-config
+DBROOT ?= $(etcdir)/iscsi
+HOMEDIR ?= $(etcdir)/iscsi
+
+PKG_CONFIG ?= /usr/bin/pkg-config
 
 CFLAGS ?= -O2 -g
 WARNFLAGS ?= -Wall -Wextra -Werror -Wstrict-prototypes -fno-common
 CFLAGS += $(WARNFLAGS) -I../include -I. -D_GNU_SOURCE \
 	  -I$(TOPDIR)/libopeniscsiusr
 CFLAGS += $(shell $(PKG_CONFIG) --cflags libkmod)
+CFLAGS += $(shell $(PKG_CONFIG) --cflags libsystemd)
 ISCSI_LIB = -L$(TOPDIR)/libopeniscsiusr -lopeniscsiusr
 LDFLAGS += $(shell $(PKG_CONFIG) --libs libkmod)
 ifeq ($(NO_SYSTEMD),)
@@ -46,41 +56,72 @@ LDFLAGS += $(shell $(PKG_CONFIG) --libs
 else
 CFLAGS += -DNO_SYSTEMD
 endif
-PROGRAMS = iscsid iscsiadm iscsistart
+CFLAGS += -DISCSI_DB_ROOT=\"$(DBROOT)\"
+CFLAGS += -DISCSI_CONFIG_ROOT=\"$(HOMEDIR)\"
+
+PROGRAMS	= iscsid iscsiadm iscsistart
+PROGRAMS_DEST	= $(addprefix $(DESTDIR)$(SBINDIR)/,$(PROGRAMS))
+
+ISCSID_OBJS	= iscsid.o session_mgmt.o discoveryd.o mntcheck.o
+ISCSIADM_OBJS	= iscsiadm.o session_mgmt.o mntcheck.o
+ISCSISTART_OBJS	= iscsistart.o statics.o
 
 # libc compat files
-SYSDEPS_SRCS = $(sort $(wildcard ../utils/sysdeps/*.o))
+SYSDEPS_DIR = $(TOPDIR)/utils/sysdeps
+SYSDEPS_OBJS = $(SYSDEPS_DIR)/sysdeps.o
 # sources shared between iscsid, iscsiadm and iscsistart
-ISCSI_LIB_SRCS = iscsi_util.o io.o auth.o iscsi_timer.o login.o log.o \
+ISCSI_LIB_OBJS = iscsi_util.o io.o auth.o iscsi_timer.o login.o log.o \
 	iface.o idbm.o sysfs.o host.o session_info.o iscsi_sysfs.o \
 	iscsi_net_util.o iscsid_req.o transport.o iser.o cxgbi.o be2iscsi.o \
 	initiator_common.o iscsi_err.o flashnode.o uip_mgmt_ipc.o \
-	netlink.o $(SYSDEPS_SRCS)
+	netlink.o
 # core initiator files
-INITIATOR_SRCS = initiator.o scsi.o actor.o event_poll.o mgmt_ipc.o kern_err_table.o
+INITIATOR_OBJS = initiator.o scsi.o actor.o event_poll.o mgmt_ipc.o kern_err_table.o
 
 # fw boot files
-FW_BOOT_SRCS = $(sort $(wildcard ../utils/fwparam_ibft/*.o))
+FW_BOOT_DIR = fwparam_ibft
+FW_BOOT_OBJ_FILES = fw_entry.o fwparam_sysfs.o prom_lex.o prom_parse.tab.o fwparam_ppc.o
+FW_BOOT_OBJS = $(addprefix $(FW_BOOT_DIR)/,$(FW_BOOT_OBJ_FILES))
 
 # core discovery files
-DISCOVERY_SRCS = $(FW_BOOT_SRCS) local_strings.o discovery.o
+DISCOVERY_OBJS = local_strings.o discovery.o
 
 all: $(PROGRAMS)
 
-iscsid: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(DISCOVERY_SRCS) \
-	iscsid.o session_mgmt.o discoveryd.o mntcheck.o
+iscsid: $(ISCSI_LIB_OBJS) $(SYSDEPS_OBJS) $(INITIATOR_OBJS) $(DISCOVERY_OBJS) $(FW_BOOT_OBJS) \
+	$(ISCSID_OBJS)
 	$(CC) $(CFLAGS) $^ -o $@  -lisns -lcrypto -lrt -lmount $(LDFLAGS) $(ISCSI_LIB)
 
-iscsiadm: $(ISCSI_LIB_SRCS) $(DISCOVERY_SRCS) iscsiadm.o session_mgmt.o mntcheck.o
+iscsiadm: $(ISCSI_LIB_OBJS) $(SYSDEPS_OBJS) $(DISCOVERY_OBJS) $(FW_BOOT_OBJS) \
+	$(ISCSIADM_OBJS)
 	$(CC) $(CFLAGS) $^ -o $@ -lisns -lcrypto -lmount $(LDFLAGS) $(ISCSI_LIB)
 
-iscsistart: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(FW_BOOT_SRCS) \
-		iscsistart.o statics.o
+iscsistart: $(ISCSI_LIB_OBJS) $(SYSDEPS_OBJS) $(INITIATOR_OBJS) $(FW_BOOT_OBJS) \
+	$(ISCSISTART_OBJS)
 	$(CC) $(CFLAGS) $^ -o $@ -lcrypto -lrt $(LDFLAGS) $(ISCSI_LIB)
+
+install: $(DESTDIR)$(SBINDIR) $(PROGRAMS_DEST)
+
+$(DESTDIR)$(SBINDIR):
+	[ -d $@ ] || $(INSTALL) -d $@
+
+$(PROGRAMS_DEST): $(DESTDIR)$(SBINDIR)/%: %
+	$(INSTALL) -m 755 $? $@
+
+$(SYSDEPS_OBJS):
+	$(MAKE) $(MFLAGS) -C $(SYSDEPS_DIR)
+
+$(FW_BOOT_OBJS):
+	$(MAKE) $(MFLAGS) -C $(FW_BOOT_DIR)
+
 clean:
-	rm -f *.o $(PROGRAMS) .depend $(LIBSYS)
+	$(RM) $(ISCSI_LIB_OBJS) $(INITIATOR_OBJS) $(DISCOVERY_OBJS) \
+		$(ISCSISTART_OBJS) $(ISCSID_OBJS) $(ISCSIADM_OBJS) \
+		$(PROGRAMS) .depend
+	$(MAKE) $(MFLAGS) -C $(FW_BOOT_DIR) clean
 
 depend:
-	gcc $(CFLAGS) -M `ls *.c` > .depend
+	$(CC) $(CFLAGS) -M `ls *.c` > .depend
+	$(MAKE) $(MFLAGS) -C $(FW_BOOT_DIR) depend
 
 -include .depend
diff -pruN 2.1.5-1/usr/mgmt_ipc.c 2.1.7-2/usr/mgmt_ipc.c
--- 2.1.5-1/usr/mgmt_ipc.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/mgmt_ipc.c	2022-05-06 17:37:21.000000000 +0000
@@ -411,8 +411,12 @@ mgmt_ipc_write_rsp(queue_task_t *qtask,
 	}
 
 	qtask->rsp.err = err;
-	if (write(qtask->mgmt_ipc_fd, &qtask->rsp, sizeof(qtask->rsp)) < 0)
-		log_error("IPC qtask write failed: %s", strerror(errno));
+	if (write(qtask->mgmt_ipc_fd, &qtask->rsp, sizeof(qtask->rsp)) < 0) {
+		if (qtask->conn && qtask->conn->session)
+			conn_error(qtask->conn, "IPC qtask write failed: %s", strerror(errno));
+		else
+			log_error("IPC qtask write failed: %s", strerror(errno));
+	}
 	mgmt_ipc_destroy_queue_task(qtask);
 }
 
diff -pruN 2.1.5-1/usr/version.h 2.1.7-2/usr/version.h
--- 2.1.5-1/usr/version.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/usr/version.h	2022-05-06 17:37:21.000000000 +0000
@@ -6,7 +6,7 @@
  * This may not be the same value as the kernel versions because
  * some other maintainer could merge a patch without going through us
  */
-#define ISCSI_VERSION_STR	"2.1.5"
+#define ISCSI_VERSION_STR	"2.1.7"
 #define ISCSI_VERSION_FILE	"/sys/module/scsi_transport_iscsi/version"
 
 #endif
diff -pruN 2.1.5-1/utils/50-iscsi-firmware-login.rules 2.1.7-2/utils/50-iscsi-firmware-login.rules
--- 2.1.5-1/utils/50-iscsi-firmware-login.rules	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/50-iscsi-firmware-login.rules	1970-01-01 00:00:00.000000000 +0000
@@ -1,15 +0,0 @@
-# This file contains the rules to handle iscsi firmware changes
-
-# DO NOT WRAP THIS LINE
-#
-# old udev does not understand some of it,
-# and would end up skipping only some lines, not the full rule.
-# which can cause all sort of trouble with strange-named device nodes
-# for completely unrelated devices,
-# resulting in unusable network lookback, etc.
-#
-# in case this is "accidentally" installed on a system with old udev,
-# having it as one single line avoids those problems.
-#
-# DO NOT WRAP THIS LINE
-SUBSYSTEM=="iscsi_boot*", ACTION=="add", DEVPATH=="*/target*", RUN+="/sbin/iscsi_fw_login"
diff -pruN 2.1.5-1/utils/50-iscsi-firmware-login.rules.template 2.1.7-2/utils/50-iscsi-firmware-login.rules.template
--- 2.1.5-1/utils/50-iscsi-firmware-login.rules.template	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/utils/50-iscsi-firmware-login.rules.template	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,15 @@
+# This file contains the rules to handle iscsi firmware changes
+
+# DO NOT WRAP THIS LINE
+#
+# old udev does not understand some of it,
+# and would end up skipping only some lines, not the full rule.
+# which can cause all sort of trouble with strange-named device nodes
+# for completely unrelated devices,
+# resulting in unusable network lookback, etc.
+#
+# in case this is "accidentally" installed on a system with old udev,
+# having it as one single line avoids those problems.
+#
+# DO NOT WRAP THIS LINE
+SUBSYSTEM=="iscsi_boot*", ACTION=="add", DEVPATH=="*/target*", RUN+="@SBINDIR@/iscsi_fw_login"
diff -pruN 2.1.5-1/utils/fwparam_ibft/fw_entry.c 2.1.7-2/utils/fwparam_ibft/fw_entry.c
--- 2.1.5-1/utils/fwparam_ibft/fw_entry.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/fw_entry.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) IBM Corporation. 2007
- * Author: Doug Maxey <dwm@austin.ibm.com>
- * based on code written by "Prasanna Mumbai" <mumbai.prasanna@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stddef.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <net/route.h>
-
-#include "fw_context.h"
-#include "fwparam.h"
-#include "idbm_fields.h"
-#include "iscsi_net_util.h"
-#include "iscsi_err.h"
-#include "config.h"
-#include "iface.h"
-
-/**
- * fw_setup_nics - setup nics (ethXs) based on ibft net info
- *
- * If this is a offload card, this function does nothing. The
- * net info is used by the iscsi iface settings for the iscsi
- * function.
- */
-int fw_setup_nics(void)
-{
-	struct boot_context *context;
-	struct list_head targets;
-	char *iface_prev = NULL, transport[16];
-	int needs_bringup = 0, ret = 0, err;
-
-	INIT_LIST_HEAD(&targets);
-
-	ret = fw_get_targets(&targets);
-	if (ret || list_empty(&targets)) {
-		printf("Could not setup fw entries.\n");
-		return ISCSI_ERR_NO_OBJS_FOUND;
-	}
-
-	/*
-	 * For each target in iBFT bring up required NIC and use routing
-	 * to force iSCSI traffic through correct NIC
-	 */
-	list_for_each_entry(context, &targets, list) {
-		if (iface_prev == NULL || strcmp(context->iface, iface_prev)) {
-				/* Note: test above works because there is a
-				 * maximum of two targets in the iBFT
-				 */
-				iface_prev = context->iface;
-				needs_bringup = 1;
-		}
-		if (net_get_transport_name_from_netdev(context->iface, transport)) {
-			/* Setup software NIC, */
-			printf("Setting up software interface %s\n", context->iface);
-			err = net_setup_netdev(context->iface, context->ipaddr,
-								   context->mask, context->gateway,
-								   context->vlan,
-								   context->target_ipaddr, needs_bringup);
-			if (err) {
-				printf("Setting up software interface %s failed\n",
-						context->iface);
-				ret = err;
-			}
-		} else {
-			/* Setup offload NIC. */
-			struct iface_rec iface;
-
-			memset(&iface, 0, sizeof(iface));
-			iface_setup_defaults(&iface);
-			printf("Setting up offload interface %s\n", context->iface);
-			if (!iface_setup_from_boot_context(&iface, context)) {
-					printf("Setting up offload interface %s failed\n",
-						   context->iface);
-
-					ret = ISCSI_ERR;
-			}
-		}
-	}
-
-	fw_free_targets(&targets);
-	if (ret)
-		return ISCSI_ERR;
-	else
-		return 0;
-}
-
-/**
- * fw_get_entry - return boot context of portal used for boot
- * @context: firmware info of portal
- *
- * Returns non-zero if no portal was used for boot.
- *
- * This function is not thread safe.
- */
-int fw_get_entry(struct boot_context *context)
-{
-	int ret;
-
-	ret = fwparam_ppc_boot_info(context);
-	if (ret)
-		ret = fwparam_sysfs_boot_info(context);
-	return ret;
-}
-
-/**
- * fw_get_targets - get a boot_context struct for each target
- * @list: list to add entires on.
- *
- * Returns zero if entries were found that can be traversed with the
- * list.h helpers, or non-zero if no entries are found.
- *
- * fw_free_targets should be called to free the list.
- *
- * This function is not thread safe.
- */
-int fw_get_targets(struct list_head *list)
-{
-	int ret;
-
-	ret = fwparam_ppc_get_targets(list);
-	if (ret)
-		ret = fwparam_sysfs_get_targets(list);
-	return ret;
-}
-
-void fw_free_targets(struct list_head *list)
-{
-	struct boot_context *curr, *tmp;
-
-	if (!list || list_empty(list))
-		return;
-
-	list_for_each_entry_safe(curr, tmp, list, list) {
-		list_del(&curr->list);
-		free(curr);
-	}
-}
-
-static void dump_initiator(struct boot_context *context)
-{
-	struct iface_rec iface;
-
-	memset(&iface, 0, sizeof(iface));
-	iface_setup_defaults(&iface);
-	iface_setup_from_boot_context(&iface, context);
-
-	if (strlen(context->initiatorname))
-		printf("%s = %s\n", IFACE_INAME, context->initiatorname);
-
-	if (strlen(context->isid))
-		printf("%s = %s\n", IFACE_ISID, context->isid);
-
-	printf("%s = %s\n", IFACE_TRANSPORTNAME, iface.transport_name);
-}
-
-static void dump_target(struct boot_context *context)
-{
-	if (strlen(context->targetname))
-		printf("%s = %s\n", NODE_NAME, context->targetname);
-
-	if (strlen(context->target_ipaddr))
-		printf(CONN_ADDR" = %s\n", 0, context->target_ipaddr);
-	printf(CONN_PORT" = %d\n", 0, context->target_port);
-
-	if (strlen(context->chap_name))
-		printf("%s = %s\n", SESSION_USERNAME, context->chap_name);
-	if (strlen(context->chap_password))
-		printf("%s = %s\n", SESSION_PASSWORD, context->chap_password);
-	if (strlen(context->chap_name_in))
-		printf("%s = %s\n", SESSION_USERNAME_IN, context->chap_name_in);
-	if (strlen(context->chap_password_in))
-		printf("%s = %s\n", SESSION_PASSWORD_IN,
-		       context->chap_password_in);
-
-	if (strlen(context->lun))
-		printf("%s = %s\n", NODE_BOOT_LUN, context->lun);
-}
-
-static void dump_network(struct boot_context *context)
-{
-	/* Dump the 8 byte mac address (not iser support) */
-	if (strlen(context->mac))
-		printf("%s = %s\n", IFACE_HWADDR, context->mac);
-	/*
-	 * If the 'origin' field is 3 (IBFT_IP_PREFIX_ORIGIN_DHCP),
-	 * then DHCP is used.
-	 * Otherwise evaluate the 'dhcp' field, if this has a valid
-	 * address then DHCP was used (broadcom sends 0.0.0.0).
-	 */
-	if ((context->origin == IBFT_IP_PREFIX_ORIGIN_DHCP) ||
-	    (strlen(context->dhcp) && strcmp(context->dhcp, "0.0.0.0")))
-		printf("%s = DHCP\n", IFACE_BOOT_PROTO);
-	else
-		printf("%s = STATIC\n", IFACE_BOOT_PROTO);
-	if (strlen(context->ipaddr))
-		printf("%s = %s\n", IFACE_IPADDR, context->ipaddr);
-	if (context->prefix)
-		printf("%s = %d\n", IFACE_PREFIX_LEN, context->prefix);
-	if (strlen(context->mask))
-		printf("%s = %s\n", IFACE_SUBNET_MASK, context->mask);
-	if (strlen(context->gateway))
-		printf("%s = %s\n", IFACE_GATEWAY, context->gateway);
-	if (strlen(context->primary_dns))
-		printf("%s = %s\n", IFACE_PRIMARY_DNS, context->primary_dns);
-	if (strlen(context->secondary_dns))
-		printf("%s = %s\n", IFACE_SEC_DNS, context->secondary_dns);
-	if (strlen(context->vlan))
-		printf("%s = %s\n", IFACE_VLAN_ID, context->vlan);
-	if (strlen(context->iface))
-		printf("%s = %s\n", IFACE_NETNAME, context->iface);
-}
-
-/**
- * fw_print_entry - print boot context info of portal used for boot
- * @context: firmware info of portal
- *
- * Does not print anything if no portal was used for boot.
- *
- * TODO: Merge this in with idbm.c helpers.
- */
-void fw_print_entry(struct boot_context *context)
-{
-	printf("%s\n", ISCSI_BEGIN_REC);
-	dump_initiator(context);
-	dump_network(context);
-	dump_target(context);
-	printf("%s\n", ISCSI_END_REC);
-}
diff -pruN 2.1.5-1/utils/fwparam_ibft/fwparam.h 2.1.7-2/utils/fwparam_ibft/fwparam.h
--- 2.1.5-1/utils/fwparam_ibft/fwparam.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/fwparam.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,32 +0,0 @@
-/*
- * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
- */
-#ifndef FWPARAM_H_
-#define FWPARAM_H_
-
-#include <stdint.h>
-#include "fw_context.h"
-
-#define FILENAMESZ (1024)
-
-struct boot_context;
-
-int fwparam_sysfs_boot_info(struct boot_context *context);
-int fwparam_sysfs_get_targets(struct list_head *list);
-int fwparam_ppc_boot_info(struct boot_context *context);
-int fwparam_ppc_get_targets(struct list_head *list);
-
-#endif /* FWPARAM_IBFT_H_ */
diff -pruN 2.1.5-1/utils/fwparam_ibft/fwparam_ibft.c 2.1.7-2/utils/fwparam_ibft/fwparam_ibft.c
--- 2.1.5-1/utils/fwparam_ibft/fwparam_ibft.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/fwparam_ibft.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,499 +0,0 @@
-/*
- * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
- *
- * Copyright (C) IBM Corporation, 2006
- *
- * Authors:	Patrick Mansfield <patmans@us.ibm.com>
- * 		Mike Anderson	<andmike@us.ibm.com>
- *
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "fwparam_ibft.h"
-#include "fw_context.h"
-
-char *progname = "fwparam_ibft";
-int debug;
-int dev_count;
-char filename[FILENAMESZ];
-
-const char nulls[16]; /* defaults to zero */
-
-int
-verify_hdr(char *name, struct ibft_hdr *hdr, int id, int version, int length)
-{
-#define VERIFY_HDR_FIELD(val) \
-	if (hdr->val != val) { \
-		fprintf(stderr, \
-			"%s: error, %s structure expected %s %d but" \
-			" got %d\n", \
-			progname, name, #val, hdr->val, val); \
-		return -1; \
-	}
-
-	if (debug > 1)
-		fprintf(stderr, "%s: verifying %s header\n", __FUNCTION__,
-			name);
-
-	VERIFY_HDR_FIELD(id);
-	VERIFY_HDR_FIELD(version);
-	VERIFY_HDR_FIELD(length);
-
-#undef VERIFY_HDR_FIELD
-	return 0;
-}
-
-#define CHECK_HDR(ident, name) \
-	verify_hdr(#name, &ident->hdr, id_##name, version_##name, \
-		   sizeof(*ident))
-
-/*
- * Format 8 byte scsi LUN. Just format 8 bytes of hex, we could also
- * format in the format as specified in rfc4173 (1-2-3-4, or 1-2), that is
- * a nice format for humans :)
- */
-void
-format_lun(char *buf, size_t size, uint8_t *lun)
-{
-	int i;
-
-	for (i = 0; i < 8; i++)
-		snprintf(buf++, size--, "%x", lun[i]);
-}
-
-void
-dump_lun(char *prefix, char *id, uint8_t *lun)
-{
-	char buf[32];
-
-	format_lun(buf, sizeof(buf), lun);
-
-	if (prefix)
-		printf("%s%s=%s\n", prefix, id, buf);
-	else
-		printf("%s=%s\n", id, buf);
-
-}
-
-void
-dump_word(char *prefix, char *id, unsigned short value)
-{
-	if (prefix)
-		printf("%s%s=%d\n", prefix, id, value);
-	else
-		printf("%s=%d\n", id, value);
-}
-
-void
-dump_string(char *prefix, char *id, char *value, int len)
-{
-	if (len == 0)
-		return;
-	/*
-	 * Not checking if the offset is non-zero, it is not even passed
-	 * in, else we need to pass a start and offset rather than value.
-	 */
-
-	/*
-	 * prints the string in "value" that has "len" characters (the
-	 * printf "*" * means use the next argument as the length).
-	 */
-	if (prefix)
-		printf("%s%s=%.*s\n", prefix, id, len, value);
-	else
-		printf("%s=%.*s\n", id, len, value);
-}
-
-void
-format_ipaddr(char *buf, size_t size, uint8_t *ip)
-{
-	if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 &&
-	    ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && ip[7] == 0 &&
-	    ip[8] == 0 && ip[9] == 0 && ip[10] == 0xff && ip[11] == 0xff) {
-		/*
-		 * IPV4
-		 */
-		snprintf(buf, size, "%d.%d.%d.%d", ip[12], ip[13], ip[14], ip[15]);
-	} else {
-		/* XXX ... */
-		fprintf(stderr, "%s: warning no IPV6 support.\n", progname);
-		buf[0] = '\0';
-		return;
-	}
-
-}
-
-/*
- * Dump the 16 byte ipaddr, as IPV6 or IPV4.
- */
-void
-dump_ipaddr(char *prefix, char *id, uint8_t *ip)
-{
-	char buf[32];
-
-	/*
-	 * Assumes all zero means no IP address.
-	 */
-	if (!memcmp(ip, nulls, sizeof(nulls)))
-		return;
-
-	format_ipaddr(buf, sizeof(buf), ip);
-
-	if (prefix)
-		printf("%s%s=%s\n", prefix, id, buf);
-	else
-		printf("%s=%s\n", id, buf);
-
-}
-
-/*
- * Dump the 8 byte mac address
- */
-void
-dump_mac(char *prefix, char *id, uint8_t *mac)
-{
-	int i;
-
-	if (prefix)
-		printf("%s%s=", prefix, id);
-	else
-		printf("%s=", id);
-
-	for (i = 0; i < 5; i++)
-		printf("%02x:", mac[i]);
-	printf("%02x\n", mac[i]);
-}
-
-
-void
-dump_initiator_prefix(void *ibft_loc, struct ibft_initiator *initiator, char *prefix)
-{
-	if (!initiator)
-		return;
-	/*
-	 * Not all fields are (or were) supported by open-iscsi. Plus,
-	 * some of these are for discovery.
-	 */
-	dump_ipaddr(prefix, "ISNS", initiator->isns_server);
-	dump_ipaddr(prefix, "SLP", initiator->slp_server);
-	dump_ipaddr(prefix, "PRIMARY_RADIUS_SERVER", initiator->pri_radius_server);
-	dump_ipaddr(prefix, "SECONDARY_RADIUS_SERVER", initiator->sec_radius_server);
-	dump_string(prefix, "NAME", ibft_loc +
-		    initiator->initiator_name_off, initiator->initiator_name_len);
-}
-
-void
-dump_nic_prefix(void *ibft_loc, struct ibft_nic *nic, char *prefix)
-{
-
-	if (!nic)
-		return;
-
-	dump_mac(prefix, "HWADDR", nic->mac);
-	/*
-	 * Assume dhcp if any non-zero portions of its address are set
-	 * (again, undocumented).
-	 */
-	if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp))) {
-		dump_ipaddr(prefix, "DHCP", nic->dhcp);
-	} else {
-		dump_ipaddr(prefix, "IPADDR", nic->ip_addr);
-		/*
-		 * XXX: Not sure how a mask "prefix" will be used in network
-		 * bringup, this sounds less flexible than the normal
-		 * masks used.
-		 */
-		printf("%s%s=%d\n", prefix, "MASK", nic->subnet_mask_prefix);
-		dump_ipaddr(prefix, "GATEWAY", nic->gateway);
-		dump_ipaddr(prefix, "DNSADDR1", nic->primary_dns);
-		dump_ipaddr(prefix, "DNSADDR2", nic->secondary_dns);
-	}
-
-	dump_string(prefix, "HOSTNAME", ibft_loc + nic->hostname_off,
-		    nic->hostname_len);
-	/*
-	 * XXX unknown vlan:
-	 */
-	dump_word(prefix, "VLAN", nic->vlan);
-	/*
-	 * XXX sort of unknown pci_bdf: 8 bits bus, 5 bits device, 3 bits
-	 * function.
-	 */
-	if (prefix )
-		printf("%s%s=%d:%d:%d\n", prefix, "PCI_BDF",
-		       /* bus */ (nic->pci_bdf & 0xff00) >> 8,
-		       /* device */ (nic->pci_bdf & 0xf8) >> 3,
-		       /* function */ (nic->pci_bdf & 0x07));
-	else
-		printf("%s=%d:%d:%d\n", "PCI_BDF",
-		       /* bus */ (nic->pci_bdf & 0xff00) >> 8,
-		       /* device */ (nic->pci_bdf & 0xf8) >> 3,
-		       /* function */ (nic->pci_bdf & 0x07));
-}
-
-void
-dump_tgt_prefix(void *ibft_loc, struct ibft_tgt *tgt, char *prefix)
-{
-
-	if (!tgt)
-		return;
-
-	dump_ipaddr(prefix, "IPADDR", tgt->ip_addr);
-	dump_word(prefix, "PORT", tgt->port);
-	/*
-	 * XXX there should at least be a "no LUN specified field", or
-	 * have different location objects, so the setup can search for
-	 * the appropriate LU (like mount by label, or use of the
-	 * /dev/disk/by-id names, or ....
-	 *
-	 * Like:
-	 * 	uint8_t lu_type; 0: nothing specified, 1: LUN, 2: misc
-	 * 	name - OS can use any way it wants, would have embedded a
-	 * 	"NAME=string", like "LABEL=myrootvolume", or
-	 * 	"DEV_NAME=/dev/disk/by-id/scsi-198279562093043094003030903".
-	 * 	union lu_value {
-	 * 		uint8_t lun[8];
-	 * 		uint8_t misc_name[64];
-	 * 	};
-	 *
-	 * Maybe just add an extension header, and let the admin/user put
-	 * strings like: "area:VALUE=string" into it?
-	 */
-	dump_lun(prefix, "LUN", tgt->lun);
-	dump_string(prefix, "NAME", ibft_loc + tgt->tgt_name_off,
-		    tgt->tgt_name_len);
-	/*
-	 * Note: don't dump the nic association, just let the IP address take
-	 * care of the routing.
-	 */
-	/*
-	 * Note: don't dump the chap "type", just the chap names and secrets
-	 * if any are specified - they imply CHAP and reversed CHAP.
-	 */
-	dump_string(prefix, "CHAP_NAME", ibft_loc + tgt->chap_name_off,
-		    tgt->chap_name_len);
-	dump_string(prefix, "CHAP_PASSWORD", ibft_loc + tgt->chap_secret_off,
-		    tgt->chap_secret_len);
-	dump_string(prefix, "CHAP_NAME_IN", ibft_loc + tgt->rev_chap_name_off,
-		    tgt->rev_chap_name_len);
-	dump_string(prefix, "CHAP_PASSWORD_IN",
-		    ibft_loc + tgt->rev_chap_secret_off,
-		    tgt->rev_chap_secret_len);
-}
-
-/*
- * Read in and dump ASCII output for ibft starting at ibft_loc.
- */
-int
-dump_ibft(void *ibft_loc, struct boot_context *context)
-{
-	struct ibft_table_hdr *ibft_hdr = ibft_loc;
-	struct ibft_control *control;
-	struct ibft_initiator *initiator = NULL;
-	struct ibft_nic *nic0 = NULL, *nic1 = NULL;
-	struct ibft_tgt *tgt0 = NULL, *tgt1 = NULL;
-	char ipbuf[32];
-
-	control = ibft_loc + sizeof(*ibft_hdr);
-	CHECK_HDR(control, control);
-
-	/*
-	 * The ibft is setup to return multiple pieces for each
-	 * object (like multiple nic's or multiple targets), but it only
-	 * maps 1 initiator, two targets, and two nics, follow that layout
-	 * here (i.e. don't search for others).
-	 *
-	 * Also, unknown what to do for extensions piece, it is not
-	 * documented.
-	 */
-
-	if (control->initiator_off) {
-		initiator = ibft_loc + control->initiator_off;
-		CHECK_HDR(initiator, initiator);
-	}
-
-	if (control->nic0_off) {
-		nic0 = ibft_loc + control->nic0_off;
-		CHECK_HDR(nic0, nic);
-	}
-
-	if (control->nic1_off) {
-		nic1 = ibft_loc + control->nic1_off;
-		CHECK_HDR(nic1, nic);
-	}
-
-	if (control->tgt0_off) {
-		tgt0 = ibft_loc + control->tgt0_off;
-		CHECK_HDR(tgt0, target);
-	}
-
-	if (control->tgt1_off) {
-		tgt1 = ibft_loc + control->tgt1_off;
-		CHECK_HDR(tgt1, target);
-	}
-
-	strlcpy(context->initiatorname,
-		(char *)ibft_loc+initiator->initiator_name_off,
-		initiator->initiator_name_len + 1);
-
-	if (tgt0 && (tgt0->hdr.flags & INIT_FLAG_FW_SEL_BOOT)) {
-		strlcpy((char *)context->targetname,
-			(char *)(ibft_loc+tgt0->tgt_name_off),
-			tgt0->tgt_name_len);
-		format_ipaddr(ipbuf, sizeof(ipbuf),
-			      tgt0->ip_addr);
-		strlcpy((char *)context->target_ipaddr, ipbuf,
-			sizeof(ipbuf));
-		context->target_port = tgt0->port;
-		strlcpy(context->chap_name,
-			(char *)(ibft_loc + tgt0->chap_name_off),
-			tgt0->chap_name_len);
-		strlcpy(context->chap_password,
-			(char*)(ibft_loc + tgt0->chap_secret_off),
-			tgt0->chap_secret_len);
-		strlcpy(context->chap_name_in,
-			(char *)(ibft_loc + tgt0->rev_chap_name_off),
-			tgt0->rev_chap_name_len);
-		strlcpy(context->chap_password_in,
-			(char *)(ibft_loc + tgt0->rev_chap_secret_off),
-			tgt0->rev_chap_secret_len);
-	} else if (tgt1 &&
-		   (tgt1->hdr.flags & INIT_FLAG_FW_SEL_BOOT)) {
-		strlcpy((char *)context->targetname,
-			(char *)(ibft_loc+tgt1->tgt_name_off),
-			tgt1->tgt_name_len);
-		format_ipaddr(ipbuf, sizeof(ipbuf),
-			      tgt1->ip_addr);
-		strlcpy((char *)context->target_ipaddr,ipbuf,
-			sizeof(ipbuf));
-		context->target_port = tgt1->port;
-		strlcpy(context->chap_name,
-			(char *)(ibft_loc + tgt1->chap_name_off),
-			tgt1->chap_name_len);
-		strlcpy(context->chap_password,
-			(char*)(ibft_loc + tgt1->chap_secret_off),
-			tgt1->chap_secret_len);
-		strlcpy(context->chap_name_in,
-			(char *)(ibft_loc + tgt1->rev_chap_name_off),
-			tgt1->rev_chap_name_len);
-		strlcpy(context->chap_password_in,
-			(char *)(ibft_loc + tgt1->rev_chap_secret_off),
-			tgt1->rev_chap_secret_len);
-	}
-
-	return 0;
-}
-
-char *search_ibft(unsigned char *start, int length)
-{
-	unsigned char *cur_ptr;
-	struct ibft_table_hdr *ibft_hdr;
-	unsigned char check_sum;
-	uint32_t i;
-
-	cur_ptr = (unsigned char *)start;
-	for (cur_ptr = (unsigned char *)start;
-	     cur_ptr < (start + length);
-	     cur_ptr++) {
-		if (memcmp(cur_ptr, iBFTSTR,strlen(iBFTSTR)))
-			continue;
-
-		ibft_hdr = (struct ibft_table_hdr *)cur_ptr;
-		/* Make sure it's correct version. */
-		if (ibft_hdr->revision != iBFT_REV)
-			continue;
-
-		/* Make sure that length is valid. */
-		if ((cur_ptr + ibft_hdr->length) <= (start + length)) {
-			/* Let verify the checksum */
-			for (i = 0, check_sum = 0; i < ibft_hdr->length; i++)
-				check_sum += cur_ptr[i];
-
-			if (check_sum == 0)
-				return (char *)cur_ptr;
-		}
-	}
-	return NULL;
-}
-
-int
-fwparam_ibft(struct boot_context *context, const char *filepath)
-{
-	int fd, ret;
-	char *filebuf, *ibft_loc;
-	int start = 512 * 1024; /* 512k */
-	int end_search = (1024 * 1024) - start; /* 512k */
-	struct stat buf;
-
-	if (filepath)
-		strlcpy(filename, filepath, FILENAMESZ);
-	else
-		strlcpy(filename, X86_DEFAULT_FILENAME, FILENAMESZ);
-
-	fd = open(filename, O_RDONLY);
-	if (fd < 0) {
-		fprintf(stderr, "Could not open %s: %s (%d)\n",
-			filename, strerror(errno), errno);
-		return -1;
-	}
-
-	/* Find the size. */
-	if (stat(filename, &buf)!=0) {
-		fprintf(stderr, "Could not stat file %s: %s (%d)\n",
-			filename, strerror(errno), errno);
-		close(fd);
-		return -1;
-	}
-	/* And if not zero use that size */
-	if (buf.st_size > 0) {
-		start = 0;
-		end_search=buf.st_size;
-	}
-	/*
-	 * XXX Possibly warn and exit if start > filesize(fd), or if start +
-	 * end_search > filesize(fd). Else, we will get a bus error for
-	 * small files (with memmap, and for testing at least, it would
-	 * be hard to find a system with less than 1024k).
-	 */
-	filebuf = mmap(NULL, end_search, PROT_READ, MAP_PRIVATE, fd, start);
-	if (filebuf == MAP_FAILED) {
-		fprintf(stderr, "Could not mmap %s: %s (%d)\n",
-			filename, strerror(errno), errno);
-		ret = -1;
-		goto done;
-	}
-
-	ibft_loc = search_ibft((unsigned char *)filebuf, end_search);
-	if (ibft_loc)
-		ret = dump_ibft(ibft_loc, context);
-	else {
-		printf("Could not find iBFT.\n");
-		ret = -1;
-	}
-	munmap(filebuf, end_search);
-done:
-	close(fd);
-	return ret;
-}
diff -pruN 2.1.5-1/utils/fwparam_ibft/fwparam_ibft.h 2.1.7-2/utils/fwparam_ibft/fwparam_ibft.h
--- 2.1.5-1/utils/fwparam_ibft/fwparam_ibft.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/fwparam_ibft.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,149 +0,0 @@
-/*
- * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
- *
- * Copyright (C) IBM Corporation, 2006,2007
- *
- * Authors: 	Doug Maxey <dwm@austin.ibm.com>
- * 		Patrick Mansfield <patmans@us.ibm.com>
- *
- */
-
-#ifndef FWPARAM_IBFT_H_
-#define FWPARAM_IBFT_H_
-
-/* #include <sys/types.h> */
-#include <stdint.h>
-#include "fw_context.h"
-
-/*
- * Structures here are is based on Doug's original code, and Patrick's
- * interpretation of the IBM internal design document title the "iSCSI
- * Boot Firmware Table (iBFT)".
- */
-#define iBFTSTR "iBFT"
-#define iBFT_SIG { 'i','B','F','T' }
-
-#define iBFT_REV 1
-
-/*
- * These macros are lower case to make the verify_hdr macro easier.
- */
-#define version_control	1
-#define version_initiator	1
-#define version_nic	1
-#define version_target	1
-#define version_extensions	1
-
-enum ibft_id {
-	id_control = 1,
-	id_initiator,
-	id_nic,
-	id_target,
-	id_extensions,
-};
-
-struct ibft_hdr {
-	uint8_t id;
-	uint8_t version;
-	uint16_t length;
-	uint8_t ind;
-	uint8_t flags;
-};
-
-struct ibft_table_hdr {
-	uint8_t signature[4];
-	uint32_t length;
-	uint8_t revision;
-	uint8_t checksum;
-	uint8_t oemid[6];
-	uint8_t oem_table_id[8];
-	uint8_t rsvd1[24];
-} __attribute__((__packed__));
-
-struct ibft_control {
-	struct ibft_hdr hdr;
-	uint16_t extensions;
-	uint16_t initiator_off;
-	uint16_t nic0_off;
-	uint16_t tgt0_off;
-	uint16_t nic1_off;
-	uint16_t tgt1_off;
-} __attribute__((__packed__));
-
-struct ibft_initiator {
-#define INIT_FLAG_VALID 1
-#define INIT_FLAG_FW_SEL_BOOT 2
-	struct ibft_hdr hdr;
-	uint8_t isns_server[16];
-	uint8_t slp_server[16];
-	uint8_t pri_radius_server[16];
-	uint8_t sec_radius_server[16];
-	uint16_t initiator_name_len;
-	uint16_t initiator_name_off;
-} __attribute__((__packed__));
-
-struct ibft_nic {
-#define NIC_FLAG_VALID 1
-#define NIC_FLAG_FW_SEL_BOOT 2
-	struct ibft_hdr hdr;
-	uint8_t ip_addr[16];
-	uint8_t subnet_mask_prefix;
-	uint8_t origin;
-	uint8_t gateway[16];
-	uint8_t primary_dns[16];
-	uint8_t secondary_dns[16];
-	uint8_t dhcp[16];
-	uint16_t vlan;
-	uint8_t mac[6];
-	uint16_t pci_bdf;
-	uint16_t hostname_len;
-	uint16_t hostname_off;
-} __attribute__((__packed__));
-
-struct ibft_tgt {
-#define TGT_FLAG_VALID 1
-#define TGT_FLAG_FW_SEL_BOOT 2
-#define TGT_FLAG_USE_RADIUS_CHAT 4
-#define TGT_FLAG_USE_RADIUS_RCHAT 8
-	struct ibft_hdr hdr;
-	uint8_t ip_addr[16];
-	uint16_t port;
-	uint8_t lun[8];
-#define TGT_CHAP 1
-#define TGT_MUTUAL_CHAP 2
-	uint8_t chap_type;
-	uint8_t nic_assoc;
-	uint16_t tgt_name_len;
-	uint16_t tgt_name_off;
-	uint16_t chap_name_len;
-	uint16_t chap_name_off;
-	uint16_t chap_secret_len;
-	uint16_t chap_secret_off;
-	uint16_t rev_chap_name_len;
-	uint16_t rev_chap_name_off;
-	uint16_t rev_chap_secret_len;
-	uint16_t rev_chap_secret_off;
-} __attribute__((__packed__));
-
-/* Common variables */
-#define FILENAMESZ (1024)
-extern char filename[FILENAMESZ];
-#define X86_DEFAULT_FILENAME "/dev/mem"
-extern int debug;
-extern int dev_count;
-
-extern int fwparam_ibft(struct boot_context *context, const char *filepath);
-#endif /* FWPARAM_IBFT_H_ */
diff -pruN 2.1.5-1/utils/fwparam_ibft/fwparam_ppc.c 2.1.7-2/utils/fwparam_ibft/fwparam_ppc.c
--- 2.1.5-1/utils/fwparam_ibft/fwparam_ppc.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/fwparam_ppc.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,606 +0,0 @@
-/*
- * Copyright (C) IBM Corporation. 2007
- * Author: Doug Maxey <dwm@austin.ibm.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define	 _XOPEN_SOURCE 500
-#include <ftw.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "fwparam.h"
-#include "fw_context.h"
-#include "iscsi_obp.h"
-#include "prom_parse.h"
-#include "sysdeps.h"
-#include "iscsi_err.h"
-
-void* yy_scan_string(const char *str);
-int yyparse(struct ofw_dev *ofwdev);
-
-#define BOOTPATH "/chosen/bootpath"
-#define DT_TOP "/proc/device-tree"
-#define LOCAL_MAC_FILE "/local-mac-address"
-
-static int devtree_offset;
-static char *bootpath_val;
-static int bytes_read;
-#define OFWDEV_MAX (10)
-static struct ofw_dev *ofwdevs[OFWDEV_MAX];
-static char *niclist[OFWDEV_MAX];
-static int nic_count;
-static int debug;
-static int dev_count;
-
-static void cp_param(char *dest, const char *name, struct ofw_dev *dev,
-		     enum obp_param item, int len)
-{
-	if (dev->param[item])
-		strlcpy(dest, dev->param[item]->val, len);
-}
-
-static void cp_int_param(int *dest, const char *name, struct ofw_dev *dev,
-			 enum obp_param item)
-{
-	if (dev->param[item])
-		*dest = strtol(dev->param[item]->val, NULL, 10);
-}
-
-static char *find_devtree(const char *filename)
-{
-	char *devtree = strdup(filename);
-	char *chop_at;
-	struct stat dt_stat;
-	int error;
-
-	/*
-	 * What is the path to the device-tree?	 The only valid
-	 * directories to locate the property are under /aliases or
-	 * /chosen.
-	 */
-
-	if (!devtree)
-		return NULL;
-
-	chop_at = strstr(devtree, "/chosen");
-	if (!chop_at)
-		chop_at = strstr(devtree, "/aliases");
-
-	if (!chop_at) {
-		char *vdev = malloc(strlen(filename) + strlen("/vdevice") + 1);
-
-		/*
-		 * test to see if there is /vdevice dir
-		 */
-		if (vdev) {
-			sprintf(vdev, "%s%s", filename, "/vdevice");
-			error = stat(vdev, &dt_stat);
-			free(vdev);
-			if (error) {
-				free(devtree);
-				return NULL;
-			}
-		}
-	} else
-		devtree[chop_at - devtree] = 0;
-
-	if (devtree)
-		devtree_offset = strlen(devtree);
-
-	return devtree;
-}
-
-/*
- * Take the path to the property under chosen, and swizzle to make that
- * the base for the device path discovered.
- */
-static int locate_mac(const char *devtree, struct ofw_dev *ofwdev)
-{
-	int error = 0;
-	int mac_path_len = strlen(ofwdev->dev_path) + strlen(LOCAL_MAC_FILE) +
-		2;
-	char *mac_file;
-	int mac_fd;
-
-	mac_path_len += strlen(devtree);
-	mac_file = malloc(mac_path_len);
-	if (!mac_file) {
-		error = ENOMEM;
-		fprintf(stderr, "%s: malloc , %s\n", __func__,
-			strerror(errno));
-		goto lpm_bail;
-	}
-
-	snprintf(mac_file, mac_path_len, "%s%s%s", devtree, ofwdev->dev_path,
-		 LOCAL_MAC_FILE);
-	mac_fd = open(mac_file, O_RDONLY);
-	if (mac_fd < 0) {
-		error = errno;
-		fprintf(stderr, "%s: open %s, %s\n", __func__, mac_file,
-			strerror(errno));
-		free(mac_file);
-		goto lpm_bail;
-	}
-
-	bytes_read = read(mac_fd, ofwdev->mac, 6);
-	if (bytes_read != 6) {
-		error = EIO;
-		fprintf(stderr, "%s: read %s, %s\n", __func__, mac_file,
-			strerror(errno));
-	}
-	free(mac_file);
-	close(mac_fd);
-
-lpm_bail:
-	return error;
-}
-
-const char *obp_qual_set(struct ofw_dev *ofwdev, const char *qual)
-{
-	if (!strcmp("bootp", qual))
-		ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_BOOTP;
-	else if (!strcmp("dhcpv6", qual))
-		ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_DHCPV6;
-	else if (!strcmp("ipv6", qual))
-		ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_IPV6;
-	else if (!strcmp("iscsi", qual)) {
-		ofwdev->type = OFW_DT_ISCSI;
-		ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_ISCSI;
-	} else if (!strcmp("ping", qual))
-		ofwdev->quals[ofwdev->qual_count++] = OBP_QUAL_PING;
-	else
-		printf("%s: %s UNKNOWN\n", __func__, qual);
-	return qual;
-}
-
-void add_obp_parm(struct ofw_dev *ofwdev, enum obp_param parm, const char *str)
-{
-	int psz = sizeof(struct ofw_obp_param) + strlen(str);
-
-	ofwdev->param[parm] = malloc(psz);
-	if (ofwdev->param[parm] == NULL) {
-		printf("%s: ENOMEM!\n", __func__);
-		return;
-	}
-	memset(ofwdev->param[parm], 0, psz);
-	ofwdev->param[parm]->len = psz;
-	strcpy(ofwdev->param[parm]->val, str);
-}
-
-void obp_parm_addr(struct ofw_dev *ofwdev, const char *parm, const char *addr)
-{
-	if (!strcmp("ciaddr", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_CIADDR, addr);
-	else if (!strcmp("dhcp", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_DHCP, addr);
-	else if (!strcmp("giaddr", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_GIADDR, addr);
-	else if (!strcmp("isns", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_ISNS, addr);
-	else if (!strcmp("siaddr", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_SIADDR, addr);
-	else if (!strcmp("slp", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_SLP, addr);
-	else if (!strcmp("subnet-mask", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_SUBNET_MASK, addr);
-	else
-		printf("%s: %s UNKNOWN\n", __func__, parm);
-}
-
-void obp_parm_iqn(struct ofw_dev *ofwdev, const char *parm, const char *iqn)
-{
-	if (!strcmp("itname", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_ITNAME, iqn);
-	else if (!strcmp("iname", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_INAME, iqn);
-	else
-		printf("%s: %s UNKNOWN\n", __func__, parm);
-}
-
-void obp_parm_hexnum(struct ofw_dev *ofwdev, const char *parm,
-		     const char *numstr)
-{
-	if (!strcmp("bootp-retries", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_BOOTP_RETRIES, numstr);
-	else if (!strcmp("tftp-retries", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_TFTP_RETRIES, numstr);
-	else if (!strcmp("iport", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_IPORT, numstr);
-	else if (!strcmp("ilun", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_ILUN, numstr);
-	else if (!strcmp("isid", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_ISID, numstr);
-	else
-		printf("%s: %s UNKNOWN <%s>\n", __func__, parm, numstr);
-}
-
-void obp_parm_str(struct ofw_dev *ofwdev, const char *parm, const char *str)
-{
-	if (!strcmp("filename", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_FILENAME, str);
-	else if (!strcmp("ichapid", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_ICHAPID, str);
-	else if (!strcmp("ichappw", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_ICHAPPW, str);
-	else if (!strcmp("chapid", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_CHAPID, str);
-	else if (!strcmp("chappw", parm))
-		add_obp_parm(ofwdev, OBP_PARAM_CHAPPW, str);
-	else
-		printf("%s: %s UNKNOWN <%s>\n", __func__, parm, str);
-}
-
-void yyerror(struct ofw_dev *ofwdev, const char *msg)
-{
-	fprintf(stderr, "%s: error in <%s> at l%d.c%d\n", "fwparam_ppc",
-		ofwdev->prop_path, yylloc.last_line, yylloc.last_column);
-}
-
-static int parse_params(const char *buf, struct ofw_dev *ofwdev)
-{
-	int error = 0;
-#if YYDEBUG
-	yydebug = 1;
-#endif
-
-
-	if (yy_scan_string(buf))
-		error = yyparse(ofwdev);
-
-	return error;
-}
-
-static int find_file(const char *filename)
-{
-	int error, fd;
-	struct stat bootpath_stat;
-
-	error = stat(filename, &bootpath_stat);
-	if (error < 0) {
-		fprintf(stderr, "%s: stat %s, %s\n", __func__, filename,
-			strerror(errno));
-		return error;
-	}
-
-	bootpath_val = malloc(bootpath_stat.st_size);
-	if (!bootpath_val) {
-		error = ENOMEM;
-		fprintf(stderr, "%s: Could not open %s: %s (%d)\n",
-			__func__, filename, strerror(error), error);
-		return -1;
-	}
-
-	fd = open(filename, O_RDONLY);
-	if (fd < 0) {
-		fprintf(stderr, "%s: Could not open %s: %s (%d)\n",
-			__func__, filename, strerror(errno), errno);
-		free(bootpath_val);
-		bootpath_val = NULL;
-		return -1;
-	}
-
-	bytes_read = read(fd, bootpath_val, bootpath_stat.st_size);
-	close(fd);
-	if (bytes_read != bootpath_stat.st_size) {
-		fprintf(stderr, "%s: Failed to read %s: %s (%d)\n",
-			__func__, filename, strerror(EIO), EIO);
-		free(bootpath_val);
-		bootpath_val = NULL;
-		return -1;
-	}
-
-	return 1;
-}
-
-static int find_nics(const char *fpath, const struct stat *sb, int tflag,
-		     struct FTW *ftw)
-{
-	if (tflag == FTW_D &&
-	    (strstr(fpath + ftw->base, "iscsi-toe") ||
-	     strstr(fpath + ftw->base, "ethernet"))) {
-
-		if (nic_count < OFWDEV_MAX)
-			niclist[nic_count++] = strdup(fpath + devtree_offset);
-
-	}
-	return 0;
-}
-
-static int nic_cmp(const void *a, const void *b)
-{
-	return strcmp(a, b);
-}
-
-static int find_initiator(const char *fpath, const struct stat *sb, int tflag,
-			  struct FTW *ftw)
-{
-	struct ofw_dev *dev;
-
-	if (tflag == FTW_F && (strstr(fpath + ftw->base,
-				      "/aliases/iscsi-disk"))) {
-
-		if (dev_count < OFWDEV_MAX) {
-			dev = calloc(sizeof(struct ofw_dev), 1);
-			if (!dev)
-				return -ENOMEM;
-
-			dev->prop_path = strdup(fpath + devtree_offset);
-			if (!dev->prop_path) {
-				free(dev);
-				return errno;
-			}
-			ofwdevs[dev_count++] = dev;
-		}
-	}
-	return 0;
-}
-
-static int loop_devs(const char *devtree)
-{
-	int error;
-	int i;
-	char prefix[256];
-
-	nic_count = 0;
-	error = nftw(devtree, find_nics, 20, 0);
-	if (error)
-		return error;
-
-	/*
-	 * Sort the nics into "natural" order.	The proc fs
-	 * device-tree has them in somewhat random, or reversed order.
-	 */
-	qsort(niclist, nic_count, sizeof(char *), nic_cmp);
-
-	snprintf(prefix, sizeof(prefix), "%s/%s", devtree, "aliases");
-	dev_count = 0;
-	error = nftw(prefix, find_initiator, 20, 0);
-	if (error)
-		return error;
-
-	for (i = 0; i < dev_count; i++) {
-		snprintf(prefix, sizeof(prefix), "%s%s", devtree,
-			 ofwdevs[i]->prop_path);
-		if (find_file(prefix) > 0) {
-			error = parse_params(bootpath_val, ofwdevs[i]);
-			if (!error)
-				error = locate_mac(devtree, ofwdevs[i]);
-
-			free(bootpath_val);
-			bootpath_val = NULL;
-		}
-	}
-	return error;
-}
-
-#define set_context(fld,abrv,item)					\
-	cp_param(context->fld, (abrv), ofwdev, (item), sizeof(context->fld))
-#define set_int_context(fld,abrv,item)					    \
-	cp_int_param(&context->fld, (abrv), ofwdev, (item))
-
-static void fill_context(struct boot_context *context, struct ofw_dev *ofwdev)
-{
-	int ndx;
-
-	memset(context, 0, sizeof(*context));
-
-	set_context(initiatorname, "NAME", OBP_PARAM_ITNAME);
-
-	snprintf(context->mac, sizeof(context->mac),
-		 "%02x:%02x:%02x:%02x:%02x:%02x",
-		 ofwdev->mac[0], ofwdev->mac[1], ofwdev->mac[2],
-		 ofwdev->mac[3], ofwdev->mac[4], ofwdev->mac[5]);
-
-	/*
-	 * nic parameters
-	 */
-	for (ndx = 0; ndx < nic_count; ndx++) {
-		if (!strcmp(niclist[ndx], ofwdev->dev_path)) {
-			snprintf(context->iface, sizeof(context->iface),
-				 "eth%d", ndx);
-			break;
-		}
-	}
-
-	set_context(ipaddr, "IPADDR", OBP_PARAM_CIADDR);
-	set_context(mask, "MASK", OBP_PARAM_SUBNET_MASK);
-
-	/*
-	 * target parameters
-	 */
-	set_context(target_ipaddr, "IPADDR", OBP_PARAM_SIADDR);
-	set_int_context(target_port, "PORT", OBP_PARAM_IPORT);
-	set_context(lun, "LUN", OBP_PARAM_ILUN);
-	set_context(targetname, "NAME", OBP_PARAM_INAME);
-	set_context(isid, "ISID", OBP_PARAM_ISID);
-
-	/*
-	 * chap stuff is always associated with the target
-	 */
-	set_context(chap_name, "CHAP_NAME", OBP_PARAM_ICHAPID);
-	set_context(chap_password, "CHAP_PASSWORD", OBP_PARAM_ICHAPPW);
-	set_context(chap_name_in, "CHAP_NAME_IN", OBP_PARAM_CHAPID);
-	set_context(chap_password_in, "CHAP_PASSWORD_IN", OBP_PARAM_CHAPPW);
-
-}
-
-int fwparam_ppc_boot_info(struct boot_context *context)
-{
-	char filename[FILENAMESZ];
-	int error;
-	char *devtree;
-	int i;
-
-	/*
-	 * For powerpc, our operations are fundamentally to locate
-	 * either the one boot target (the singleton disk), or to find
-	 * the nics that support iscsi boot.  The only nics in IBM
-	 * systems that can support iscsi are the ones that provide
-	 * the appropriate FCODE with a load method.
-	 */
-	memset(filename, 0, FILENAMESZ);
-	snprintf(filename, FILENAMESZ, "%s%s", DT_TOP, BOOTPATH);
-
-	if (debug)
-		fprintf(stderr, "%s: file:%s; debug:%d\n", __func__, filename,
-			debug);
-
-	devtree = find_devtree(filename);
-	if (!devtree)
-		return ISCSI_ERR_INVAL;
-
-	/*
-	 * Always search the device-tree to find the capable nic devices.
-	 */
-	error = loop_devs(devtree);
-	if (error)
-		goto free_devtree;
-
-	if (find_file(filename) < 1) {
-		error = ISCSI_ERR_NO_OBJS_FOUND;
-		goto free_devtree;
-	} else {
-		if (debug)
-			printf("%s:\n%s\n\n", filename, bootpath_val);
-		/*
-		 * We find *almost* everything we need in the
-		 * bootpath, save the mac-address.
-		 */
-
-		if (!strstr(bootpath_val, "iscsi")) {
-			error = ISCSI_ERR_INVAL;
-			goto free_bootpath_val;
-		}
-		ofwdevs[0] = calloc(1, sizeof(struct ofw_dev));
-		if (!ofwdevs[0]) {
-			error = ISCSI_ERR_NOMEM;
-			goto free_bootpath_val;
-		}
-
-		error = parse_params(bootpath_val, ofwdevs[0]);
-		if (!error)
-			error = locate_mac(devtree, ofwdevs[0]);
-		if (!error) {
-			if (!context)
-				error = ISCSI_ERR_NOMEM;
-			else
-				fill_context(context, ofwdevs[0]);
-		}
-		free(ofwdevs[0]);
-	}
-
-free_bootpath_val:
-	free(bootpath_val);
-	bootpath_val = NULL;
-
-free_devtree:
-	free(devtree);
-	for (i = 0; i < dev_count; i++)
-		if (ofwdevs[i])
-			free(ofwdevs[i]);
-
-	return error;
-}
-
-/*
- * Due to lack of time this is just fwparam_ppc_boot_info which
- * adds the target used for boot to the list. It does not add
- * all possible targets (IBM please add).
- */
-int fwparam_ppc_get_targets(struct list_head *list)
-{
-	char filename[FILENAMESZ];
-	struct boot_context *context;
-	int error;
-	char *devtree;
-	int i;
-
-	/*
-	 * For powerpc, our operations are fundamentally to locate
-	 * either the one boot target (the singleton disk), or to find
-	 * the nics that support iscsi boot.  The only nics in IBM
-	 * systems that can support iscsi are the ones that provide
-	 * the appropriate FCODE with a load method.
-	 */
-	memset(filename, 0, FILENAMESZ);
-	snprintf(filename, FILENAMESZ, "%s%s", DT_TOP, BOOTPATH);
-
-	if (debug)
-		fprintf(stderr, "%s: file:%s; debug:%d\n", __func__, filename,
-			debug);
-
-	devtree = find_devtree(filename);
-	if (!devtree)
-		return ISCSI_ERR_INVAL;
-
-	/*
-	 * Always search the device-tree to find the capable nic devices.
-	 */
-	error = loop_devs(devtree);
-	if (error)
-		goto free_devtree;
-
-	if (find_file(filename) < 1) {
-		error = ISCSI_ERR_NO_OBJS_FOUND;
-		goto free_devtree;
-	} else {
-		if (debug)
-			printf("%s:\n%s\n\n", filename, bootpath_val);
-		/*
-		 * We find *almost* everything we need in the
-		 * bootpath, save the mac-address.
-		 */
-
-		if (!strstr(bootpath_val, "iscsi")) {
-			error = ISCSI_ERR_INVAL;
-			goto free_bootpath_val;
-		}
-		ofwdevs[0] = calloc(1, sizeof(struct ofw_dev));
-		if (!ofwdevs[0]) {
-			error = ISCSI_ERR_NOMEM;
-			goto free_bootpath_val;
-		}
-
-		error = parse_params(bootpath_val, ofwdevs[0]);
-		if (!error)
-			error = locate_mac(devtree, ofwdevs[0]);
-		if (!error) {
-			context = calloc(1, sizeof(*context));
-			if (!context)
-				error = ISCSI_ERR_NOMEM;
-			else {
-				fill_context(context, ofwdevs[0]);
-				list_add_tail(&context->list, list);
-			}
-		}
-		free(ofwdevs[0]);
-	}
-free_bootpath_val:
-	free(bootpath_val);
-	bootpath_val = NULL;
-
-free_devtree:
-	free(devtree);
-	for (i = 0; i < dev_count; i++)
-		if (ofwdevs[i])
-			free(ofwdevs[i]);
-
-	return error;
-}
diff -pruN 2.1.5-1/utils/fwparam_ibft/fwparam_sysfs.c 2.1.7-2/utils/fwparam_ibft/fwparam_sysfs.c
--- 2.1.5-1/utils/fwparam_ibft/fwparam_sysfs.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/fwparam_sysfs.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,531 +0,0 @@
-/*
- * Copyright (C) IBM Corporation. 2007
- * Author: Konrad Rzeszutek <konradr@linux.vnet.ibm.com>
- * Copyright (C) Red Hat, Inc.  All rights reserved. 2008 - 2010
- * Copyright (C) Mike Christie 2008 - 2010
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#define  _XOPEN_SOURCE 500
-#define _DEFAULT_SOURCE
-#include <ftw.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <dirent.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "sysfs.h"
-#include "fw_context.h"
-#include "fwparam.h"
-#include "sysdeps.h"
-#include "iscsi_net_util.h"
-#include "iscsi_err.h"
-
-#define ISCSI_BOOT_MAX		255
-#define IBFT_SYSFS_ROOT		"/sys/firmware/ibft/"
-#define IBFT_SUBSYS		"ibft"
-
-#define ISCSI_LLD_ROOT		"/sys/firmware/"
-#define ISCSI_LLD_SUBSYS_PREFIX	"iscsi_boot"
-
-static char *target_list[ISCSI_BOOT_MAX];
-static char *nic_list[ISCSI_BOOT_MAX];
-static int nic_cnt;
-static int tgt_cnt;
-
-static int file_exist(const char *file)
-{
-	struct stat bootpath_stat;
-
-	return !stat(file, &bootpath_stat);
-}
-
-/*
- * Finds the etherrnetX and targetX under the sysfs directory.
- */
-static int find_sysfs_dirs(const char *fpath, const struct stat *sb,
-			   int tflag, struct FTW *ftw)
-{
-	if (tflag == FTW_D && (strstr(fpath + ftw->base, "target"))) {
-		if (tgt_cnt == ISCSI_BOOT_MAX) {
-			printf("Too many targets found in iSCSI boot data."
-			       "Max number of targets %d\n", ISCSI_BOOT_MAX);
-			return 0;
-		}
-		target_list[tgt_cnt++] = strdup(strstr(fpath, "target"));
-	}
-
-	if (tflag == FTW_D && (strstr(fpath + ftw->base, "ethernet"))) {
-		if (nic_cnt == ISCSI_BOOT_MAX) {
-			printf("Too many nics found in iSCSI boot data."
-			       "Max number of nics %d\n", ISCSI_BOOT_MAX);
-			return 0;
-		}
-		nic_list[nic_cnt++] = strdup(strstr(fpath, "ethernet"));
-	}
-
-	return 0;
-}
- 
-static int get_iface_from_device(char *id, struct boot_context *context)
-{
-	char dev_dir[FILENAMESZ];
-	int rc = ENODEV;
-	DIR *dirfd;
-	struct dirent *dent;
-
-	memset(dev_dir, 0, FILENAMESZ);
-	snprintf(dev_dir, FILENAMESZ, IBFT_SYSFS_ROOT"/%s/device", id);
-
-	if (!file_exist(dev_dir))
-		return 0;
-
-	dirfd = opendir(dev_dir);
-	if (!dirfd)
-		return errno;
-
-	while ((dent = readdir(dirfd))) {
-		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..") ||
-		    strncmp(dent->d_name, "net:", 4))
-			continue;
-
-		if (!strncmp(dent->d_name, "net:", 4)) {
-			if ((strlen(dent->d_name) - 4) >
-			    (sizeof(context->iface) - 1)) {
-				rc = EINVAL;
-				printf("Net device %s too big for iface "
-				       "buffer.\n", dent->d_name);
-				break;
-			}
-
-			if (sscanf(dent->d_name, "net:%s", context->iface) != 1) {
-				rc = EINVAL;
-				break;
-			}
-
-			rc = 0;
-			break;
-		} else {
-			printf("Could not read ethernet to net link.\n");
-			rc = EOPNOTSUPP;
-			break;
-		}
-	}
-
-	closedir(dirfd);
-
-	if (rc != ENODEV)
-		return rc;
-
-	/* If not found try again with newer kernel networkdev sysfs layout */
-	strlcat(dev_dir, "/net", FILENAMESZ);
-
-	if (!file_exist(dev_dir))
-		return rc;
-
-	dirfd = opendir(dev_dir);
-	if (!dirfd)
-		return errno;
-
-	while ((dent = readdir(dirfd))) {
-		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
-			continue;
-
-		/* Take the first "regular" directory entry */
-		if (strlen(dent->d_name) > (sizeof(context->iface) - 1)) {
-			rc = EINVAL;
-			printf("Net device %s too big for iface buffer.\n",
-			       dent->d_name);
-			break;
-		}
-
-		strcpy(context->iface, dent->d_name);
-		rc = 0;
-		break;
-	}
-
-	closedir(dirfd);
-	return rc;
-}
-
-/*
- * Routines to fill in the context values.
- */
-static int fill_nic_context(char *subsys, char *id,
-			    struct boot_context *context)
-{
-	int rc;
-
-	rc = sysfs_get_int(id, subsys, "flags", &context->nic_flags);
-	/*
-	 * Per spec we would need to check against Bit 0
-	 * (Block Valid Flag), but some firmware only
-	 * sets Bit 1 (Firmware Booting Selected).
-	 * So any setting is deemed okay.
-	 */
-	if (!rc && (context->nic_flags == 0))
-		rc = ENODEV;
-	if (rc)
-		return rc;
-
-	rc = sysfs_get_str(id, subsys, "mac", context->mac,
-			   sizeof(context->mac));
-	if (rc)
-		return rc;
-
-	/*
-	 * Some offload cards like bnx2i use different MACs for the net and
-	 * iscsi functions, so we have to follow the sysfs links.
-	 *
-	 * Other ibft implementations may not be tied to a pci function,
-	 * so there will not be any device/net link, so we drop down to
-	 * the MAC matching.
-	 *
-	 * And finally, some cards like be2iscsi and qla4xxx do not have
-	 * any linux network subsys representation. These hosts will
-	 * not have the ibft subsys. Instead the subsys is the scsi host
-	 * number.
-	 */
-	if (!strcmp(IBFT_SUBSYS, subsys)) {
-		rc = get_iface_from_device(id, context);
-		if (rc) {
-			rc = net_get_netdev_from_hwaddress(context->mac,
-							   context->iface);
-			if (rc)
-				return rc;
-		}
-	} else
-		strlcpy(context->scsi_host_name, subsys,
-			sizeof(context->scsi_host_name));
-
-	memset(&context->boot_nic, 0, sizeof(context->boot_nic));
-	snprintf(context->boot_nic, sizeof(context->boot_nic), "%s", id);
-
-	sysfs_get_str(id, subsys, "ip-addr", context->ipaddr,
-		      sizeof(context->ipaddr));
-	sysfs_get_str(id, subsys, "vlan", context->vlan,
-		      sizeof(context->vlan));
-	sysfs_get_str(id, subsys, "subnet-mask", context->mask,
-		      sizeof(context->mask));
-	sysfs_get_int(id, subsys, "prefix-len", &context->prefix);
-	sysfs_get_str(id, subsys, "gateway", context->gateway,
-		      sizeof(context->gateway));
-	sysfs_get_str(id, subsys, "primary-dns", context->primary_dns,
-		      sizeof(context->primary_dns));
-	sysfs_get_str(id, subsys, "secondary-dns", context->secondary_dns,
-		      sizeof(context->secondary_dns));
-	sysfs_get_str(id, subsys, "dhcp", context->dhcp,
-		      sizeof(context->dhcp));
-	sysfs_get_int(id, subsys, "origin", (int *)&context->origin);
-	return 0;
-}
-
-static void fill_initiator_context(char *subsys, struct boot_context *context)
-{
-	sysfs_get_str("initiator", subsys, "initiator-name",
-		      context->initiatorname,
-		      sizeof(context->initiatorname));
-	sysfs_get_str("initiator", subsys, "isid", context->isid,
-		      sizeof(context->isid));
-
-	strlcpy(context->boot_root, subsys, sizeof(context->boot_root));
-}
-static int fill_tgt_context(char *subsys, char *id,
-			    struct boot_context *context)
-{
-	int rc;
-
-	rc = sysfs_get_int(id, subsys, "flags", &context->target_flags);
-	/*
-	 * Per spec we would need to check against Bit 0
-	 * (Block Valid Flag), but some firmware only
-	 * sets Bit 1 (Firmware Booting Selected).
-	 * So any setting is deemed okay.
-	 */
-	if (!rc && (context->target_flags == 0))
-		rc = ENODEV;
-	if (rc)
-		return rc;
-
-	rc = sysfs_get_str(id, subsys, "target-name", context->targetname,
-			   sizeof(context->targetname));
-	if (rc)
-		return rc;
-
-	rc = sysfs_get_str(id, subsys, "ip-addr", context->target_ipaddr,
-			   sizeof(context->target_ipaddr));
-	if (rc)
-		return rc;
-
-	memset(&context->boot_target, 0, sizeof(context->boot_target));
-	snprintf(context->boot_target, sizeof(context->boot_target), "%s", id);
-
-	/*
-	 * We can live without the rest of they do not exist. If we
-	 * failed to get them we will figure it out when we login.
-	 */
-	if (sysfs_get_int(id, subsys, "port", &context->target_port))
-		context->target_port = ISCSI_LISTEN_PORT;
-
-	sysfs_get_str(id, subsys, "lun", context->lun,
-		      sizeof(context->lun));
-	sysfs_get_str(id, subsys, "chap-name", context->chap_name,
-		      sizeof(context->chap_name));
-	sysfs_get_str(id, subsys, "chap-secret", context->chap_password,
-		      sizeof(context->chap_password));
-	sysfs_get_str(id, subsys, "rev-chap-name", context->chap_name_in,
-		      sizeof(context->chap_name_in));
-	sysfs_get_str(id, subsys, "rev-chap-name-secret",
-		      context->chap_password_in,
-		      sizeof(context->chap_password_in));
-	return 0;
-}
-
-#define IBFT_SYSFS_FLAG_FW_SEL_BOOT 2
-
-static int find_boot_flag(char *subsys, char *list[], ssize_t size,
-			  int *boot_idx)
-{
-	int rc = ENODEV;
-	int i, flag = 0;
-
-	for (i = 0; i < size; i++, flag = -1) {
-		rc = sysfs_get_int(list[i], subsys, "flags", &flag);
-		if (rc)
-			continue;
-
-		if (flag & IBFT_SYSFS_FLAG_FW_SEL_BOOT) {
-			*boot_idx = i;
-			rc = 0;
-			break;
-		}
-		rc = ENODEV;
-		flag = 0;
-
-	}
-
-	return rc;
-}
-
-static void deallocate_lists(void)
-{
-	int i;
-
-	for (i = 0; i < nic_cnt; i++)
-		free(nic_list[i]);
-
-	nic_cnt = 0;
-	for (i = 0; i < tgt_cnt; i++)
-		free(target_list[i]);
-
-	tgt_cnt = 0;
-
-}
-
-static int get_boot_info(struct boot_context *context, char *rootdir,
-			 char *subsys)
-{
-	char initiator_dir[FILENAMESZ];
-	int rc = ENODEV;
-	int nic_idx = -1, tgt_idx = -1;
-
-	memset(&initiator_dir, 0 , FILENAMESZ);
-	snprintf(initiator_dir, FILENAMESZ, "%sinitiator", rootdir);
-
-	nic_cnt = 0;
-	tgt_cnt = 0;
-	if (file_exist(initiator_dir)) {
-		/* Find the targets and the ethernets */
-		rc = nftw(rootdir, find_sysfs_dirs, 20, 1);
-
-		/* Find wihch target and which ethernet have
-		the boot flag set. */
-		rc = find_boot_flag(subsys, nic_list, nic_cnt, &nic_idx);
-		if (rc)
-			goto free;
-
-		rc = find_boot_flag(subsys, target_list, tgt_cnt, &tgt_idx);
-		if (rc)
-			goto free;
-
-		/* Fill in the context values */
-		rc = fill_nic_context(subsys, nic_list[nic_idx], context);
-		rc |= fill_tgt_context(subsys, target_list[tgt_idx], context);
-		fill_initiator_context(subsys, context);
-	}
-free:
-	deallocate_lists();
-	return rc;
-}
-
-int fwparam_sysfs_boot_info(struct boot_context *context)
-{
-	struct dirent *dent;
-	DIR *dirfd;
-	int rc = 0;
-
-	if (!get_boot_info(context, IBFT_SYSFS_ROOT, IBFT_SUBSYS))
-		return 0;
-	/*
-	 * We could have multiple iscsi llds and each lld could have
-	 * multiple targets/ethernet ports
-	 */
-	dirfd = opendir(ISCSI_LLD_ROOT);
-	if (!dirfd)
-		return ISCSI_ERR_SYSFS_LOOKUP;
-
-	while ((dent = readdir(dirfd))) {
-		char lld_root[FILENAMESZ];
-
-		memset(&lld_root, 0 , FILENAMESZ);
-
-		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
-			continue;
-
-		if (strncmp(dent->d_name, ISCSI_LLD_SUBSYS_PREFIX, 10))
-			continue;
-
-		snprintf(lld_root, FILENAMESZ, ISCSI_LLD_ROOT"%s/",
-			 dent->d_name);
-		if (!get_boot_info(context, lld_root, dent->d_name))
-			goto done;
-	}
-	rc = ISCSI_ERR_NO_OBJS_FOUND;
-done:
-	closedir(dirfd);
-	return rc;
-}
-
-static int get_targets(struct list_head *list, char *rootdir, char *subsys)
-{
-	struct boot_context *context;
-	int rc = 0, i, nic_idx, nic;
-	char initiator_dir[FILENAMESZ];
-
-	memset(&initiator_dir, 0 , FILENAMESZ);
-	snprintf(initiator_dir, FILENAMESZ, "%sinitiator", rootdir);
-
-	if (!file_exist(initiator_dir))
-		return ENODEV;
-
-	nic_cnt = 0;
-	tgt_cnt = 0;
-
-	/* Find the targets and the ethernets */
-	nftw(rootdir, find_sysfs_dirs, 20, 1);
-	for (i = 0; i < tgt_cnt; i++) {
-		context = calloc(1, sizeof(*context));
-		if (!context) {
-			rc = ENOMEM;
-			break;
-		}
-
-		rc = fill_tgt_context(subsys, target_list[i], context);
-		if (rc)
-			goto cleanup;
-
-		rc = sysfs_get_int(target_list[i], subsys, "nic-assoc",
-				   &nic_idx);
-		if (rc)
-			goto cleanup;
-
-		for (nic = 0; nic < nic_cnt; nic++) {
-			int id;
-
-			rc = sysfs_get_int(nic_list[nic], subsys, "index",
-					   &id);
-			if (!rc && (id == nic_idx))
-				break;
-		}
-
-		if (nic == nic_cnt) {
-			printf("Invalid nic-assoc of %d. Max id %d.\n",
-			       nic_idx, nic_cnt);
-			goto cleanup;
-		}
-
-		rc = fill_nic_context(subsys, nic_list[nic], context);
-		if (rc)
-			goto cleanup;
-
-		fill_initiator_context(subsys, context);
-		list_add_tail(&context->list, list);
-		continue;
-cleanup:
-		free(context);
-		context = NULL;
-	}
-
-	if (rc) {
-		if (context)
-			free(context);
-		/*
-		 * If there are some valid targets return them. Most likely,
-		 * the driver/ibft-implementation reported partial info
-		 * for targets/initiators that were not used for boot.
-		 */
-		if (!list_empty(list))
-			rc = 0;
-	}
-
-	deallocate_lists();
-	return rc;
-}
-
-int fwparam_sysfs_get_targets(struct list_head *list)
-{
-	struct dirent *dent;
-	DIR *dirfd;
-	int rc = 0;
-
-	/* ibft only has one instance */
-	get_targets(list, IBFT_SYSFS_ROOT, IBFT_SUBSYS);
-	/*
-	 * We could have multiple iscsi llds and each lld could have
-	 * multiple targets/ethernet ports
-	 */
-	dirfd = opendir(ISCSI_LLD_ROOT);
-	if (!dirfd) {
-		rc = ISCSI_ERR_SYSFS_LOOKUP;
-		goto done;
-	}
-
-	while ((dent = readdir(dirfd))) {
-		char lld_root[FILENAMESZ];
-
-		memset(&lld_root, 0 , FILENAMESZ);
-		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
-			continue;
-
-		if (strncmp(dent->d_name, ISCSI_LLD_SUBSYS_PREFIX, 10))
-			continue;
-
-		snprintf(lld_root, FILENAMESZ, ISCSI_LLD_ROOT"%s/",
-			 dent->d_name);
-		get_targets(list, lld_root, dent->d_name);
-	}
-	closedir(dirfd);
-done:
-	if (!rc && list_empty(list))
-		rc = ISCSI_ERR_NO_OBJS_FOUND;
-	if (rc)
-		fw_free_targets(list);
-	return rc;
-}
diff -pruN 2.1.5-1/utils/fwparam_ibft/iscsi_obp.h 2.1.7-2/utils/fwparam_ibft/iscsi_obp.h
--- 2.1.5-1/utils/fwparam_ibft/iscsi_obp.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/iscsi_obp.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) IBM Corporation. 2007
- * Author: Doug Maxey <dwm@austin.ibm.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef ISCSI_OBP_H_
-#define ISCSI_OBP_H_
-
-enum  ofw_dev_type {
-	OFW_DT_NONE,
-	OFW_DT_BLOCK,
-	OFW_DT_NETWORK,
-	OFW_DT_ISCSI,
-};
-
-enum obp_tftp_qual {
-	OBP_QUAL_NONE,
-	OBP_QUAL_BOOTP,
-	OBP_QUAL_DHCPV6,
-	OBP_QUAL_IPV6,
-	OBP_QUAL_ISCSI,
-	OBP_QUAL_PING,
-	OBP_QUAL_COUNT,		/* Numnber of defined OBP qualifiers */
-};
-
-enum obp_param {
-	/*
-	 * Defined iscsi boot parameters.
-	 */
-	OBP_PARAM_NONE,
-	OBP_PARAM_BLKSIZE,	/* default is 512 */
-	OBP_PARAM_BOOTP_RETRIES, /* default 5 */
-	OBP_PARAM_CHAPID,	/* target chap id */
-	OBP_PARAM_CHAPPW,	/* target chap password */
-	OBP_PARAM_CIADDR,	/* client (my) ip addr */
-	OBP_PARAM_DHCP,		/* dhcp server address */
-	OBP_PARAM_FILENAME,	/* boot filename */
-	OBP_PARAM_GIADDR,	/* gateway addr */
-	OBP_PARAM_ICHAPID,	/* initiator chapid */
-	OBP_PARAM_ICHAPPW,	/* initiator chap password */
-	OBP_PARAM_ILUN,		/* misnomer, really the target lun */
-	OBP_PARAM_INAME,	/* NB: target iqn */
-	OBP_PARAM_IPORT,	/* initiator port, defaults to 3260 */
-	OBP_PARAM_ISID,		/* session id */
-	OBP_PARAM_ISNS,		/* sns server address */
-	OBP_PARAM_ITNAME,	/* NB: Initiator iqn */
-	OBP_PARAM_SIADDR,	/* iscsi server ip address. */
-	OBP_PARAM_SLP,		/* slp server address */
-	OBP_PARAM_SUBNET_MASK,
-	OBP_PARAM_TFTP_RETRIES,	/* default 5 */
-	OBP_PARAM_TIMEOUT,	/* ping timeout period. */
-
-	OBP_PARAM_COUNT,	/* number of defined OBP_PARAMs */
-};
-
-struct ofw_obp_param {
-	unsigned char  len;	/* length of value string. */
-	char	       val[1];	/* string value from the property */
-};
-
-struct ofw_dev {
-	char *prop_path; /* where we found these properties. */
-	enum ofw_dev_type type;	/* known type of boot device. */
-	int qual_count;		/* count of qualifiers. */
-	enum obp_tftp_qual quals[OBP_QUAL_COUNT];
-	struct ofw_obp_param *param[OBP_PARAM_COUNT];
-	int cfg_part;		/* boot partition number. */
-	char *dev_path;		/* path to this ofw device. */
-	unsigned char mac[6];	/* The binary mac address. */
-};
-
-const char *obp_qual_set(struct ofw_dev *ofwdev, const char *qual);
-void add_obp_parm(struct ofw_dev *ofwdev, enum obp_param parm, const char *str);
-void obp_parm_addr(struct ofw_dev *ofwdev, const char *parm, const char *addr);
-void obp_parm_iqn(struct ofw_dev *ofwdev, const char *parm, const char *iqn);
-void obp_parm_hexnum(struct ofw_dev *ofwdev, const char *parm,
-		     const char *numstr);
-void obp_parm_str(struct ofw_dev *ofwdev, const char *parm, const char *str);
-
-#endif /* ISCSI_OBP_H_ */
diff -pruN 2.1.5-1/utils/fwparam_ibft/Makefile 2.1.7-2/utils/fwparam_ibft/Makefile
--- 2.1.5-1/utils/fwparam_ibft/Makefile	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/Makefile	1970-01-01 00:00:00.000000000 +0000
@@ -1,51 +0,0 @@
-#
-#  Copyright (C) IBM Corporation. 2007
-#  Author: Doug Maxey <dwm@austin.ibm.com>
-#
-#  This program is free software: you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation, either version 2 of the License, or
-#  (at your option) any later version.
-#
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-#
-#  You should have received a copy of the GNU General Public License
-#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-#  Authors: Patrick Mansfield <patmans@us.ibm.com>
-#	    Mike Anderson <andmike@us.ibm.com>
-#	    Doug Maxey <dwm@austin.ibm.com>
-#	    "Prasanna Mumbai" <mumbai.prasanna@gmail.com>
-#
-ifeq ($(TOPDIR),)
-	TOPDIR = ../..
-endif
-
-
-SYSDEPS_OBJS = $(sort $(wildcard ../sysdeps/*.o))
-OBJS := fw_entry.o fwparam_sysfs.o $(SYSDEPS_OBJS) \
-	$(TOPDIR)/usr/iscsi_net_util.o
-OBJS += prom_lex.o prom_parse.tab.o fwparam_ppc.o
-CLEANFILES = $(OBJS) *.output *~
-
-CFLAGS ?= -O2 -g
-WARNFLAGS ?= -Wall -Wstrict-prototypes -Wno-format-truncation
-CFLAGS += -fPIC $(WARNFLAGS) -I$(TOPDIR)/include -I$(TOPDIR)/usr -D_GNU_SOURCE \
-	  -I$(TOPDIR)/libopeniscsiusr
-
-LDFLAGS += -L$(TOPDIR)/libopeniscsiusr -liscsiusr
-
-all: $(OBJS)
-
-clean:
-	rm -f *.o $(CLEANFILES) .depend
-
-$(OBJS): prom_parse.tab.h prom_parse.h fwparam_ibft.h
-
-depend:
-	gcc $(CFLAGS) -M `ls *.c` > .depend
-
--include .depend
diff -pruN 2.1.5-1/utils/fwparam_ibft/prom_lex.c 2.1.7-2/utils/fwparam_ibft/prom_lex.c
--- 2.1.5-1/utils/fwparam_ibft/prom_lex.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/prom_lex.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,2298 +0,0 @@
-
-#line 3 "<stdout>"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN (yy_start) = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START (((yy_start) - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE yyrestart(yyin  )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-extern int yyleng;
-
-extern FILE *yyin, *yyout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-    #define YY_LESS_LINENO(n)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = (yy_hold_char); \
-		YY_RESTORE_YY_MORE_OFFSET \
-		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, (yytext_ptr)  )
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via yyrestart()), so that the user can continue scanning by
-	 * just pointing yyin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-
-/* yy_hold_char holds the character lost when yytext is formed. */
-static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int yyleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 0;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow yywrap()'s to do buffer switches
- * instead of setting up a fresh yyin.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void yyrestart (FILE *input_file  );
-void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
-YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
-void yy_delete_buffer (YY_BUFFER_STATE b  );
-void yy_flush_buffer (YY_BUFFER_STATE b  );
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
-void yypop_buffer_state (void );
-
-static void yyensure_buffer_stack (void );
-static void yy_load_buffer_state (void );
-static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );
-
-void *yyalloc (yy_size_t  );
-void *yyrealloc (void *,yy_size_t  );
-void yyfree (void *  );
-
-#define yy_new_buffer yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        yyensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            yy_create_buffer(yyin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        yyensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            yy_create_buffer(yyin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define yywrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
-
-FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int yylineno;
-
-int yylineno = 1;
-
-extern char yytext[];
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[]  );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-	(yytext_ptr) = yy_bp; \
-	yyleng = (size_t) (yy_cp - yy_bp); \
-	(yy_hold_char) = *yy_cp; \
-	*yy_cp = '\0'; \
-	if ( yyleng >= YYLMAX ) \
-		YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \
-	yy_flex_strncpy( yytext, (yytext_ptr), yyleng + 1 ); \
-	(yy_c_buf_p) = yy_cp;
-
-#define YY_NUM_RULES 17
-#define YY_END_OF_BUFFER 18
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[444] =
-    {   0,
-        0,    0,   18,   16,   15,   15,   12,   12,   16,   12,
-       12,   12,   12,   12,   12,   16,   16,   16,   16,   16,
-       16,   16,   16,   16,   16,   15,    0,   12,   12,   14,
-        0,    0,    0,   12,    0,    0,   12,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,   10,    0,
-        0,    0,    0,    0,    0,    0,   12,   12,   14,    7,
-        0,    0,    0,    0,    0,    4,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,   11,    0,
-
-        0,    0,    0,    0,   12,    0,    0,    0,    0,    0,
-       11,    0,    0,    0,    0,    0,    0,    0,    6,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       13,    0,    0,    6,    0,    0,    0,    0,    0,    0,
-        0,    3,    0,    9,    6,    0,    0,    5,    0,    0,
-        0,    0,    0,    0,   13,    0,    0,    0,    0,    0,
-        0,    0,    0,    9,    0,    0,    0,    0,    0,    8,
-        0,   13,    0,    0,    0,    0,    0,    9,    0,    0,
-        0,    0,    0,    0,    2,    8,   13,    1,    0,    9,
-        0,    0,    0,    0,    0,    0,    8,   13,    0,    9,
-
-        0,    0,   10,    0,    0,    0,   13,    0,    9,    0,
-        0,    0,    0,    0,   13,    0,    9,    0,    0,    0,
-       13,    0,    9,    0,    0,   13,    9,    0,    0,   13,
-        9,   13,    9,   13,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
-        9,    9,    0
-    } ;
-
-static yyconst flex_int32_t yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    4,    5,    1,    6,    6,    7,
-        6,    6,    6,    8,    6,    6,    6,    9,    1,    1,
-        1,    1,    1,    1,   10,   10,   10,   10,   10,   10,
-       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
-       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
-        1,   12,    1,    1,    1,    1,   13,   14,   15,   16,
-
-       17,   18,   19,   20,   21,   11,   22,   23,   24,   25,
-       26,   27,   28,   29,   30,   31,   32,   33,   34,   11,
-       11,   35,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-static yyconst flex_int32_t yy_meta[36] =
-    {   0,
-        1,    1,    1,    2,    3,    4,    4,    4,    5,    4,
-        2,    6,    4,    4,    4,    4,    4,    4,    2,    2,
-        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-        2,    2,    2,    2,    2
-    } ;
-
-static yyconst flex_int16_t yy_base[680] =
-    {   0,
-        0,    0, 1198, 1199,   34,   36,   35, 1192,    0,   39,
-       40,   41,   47,   42,   44,   29,   67, 1176, 1182, 1179,
-     1180,   86, 1174, 1161, 1174,   51,   69,   73, 1184,    0,
-     1175, 1165, 1160,   43, 1172, 1171,   51, 1168, 1152, 1161,
-     1157, 1166, 1163, 1162, 1156, 1158, 1142, 1160,   25, 1147,
-       85, 1146, 1153, 1139, 1147, 1133, 1135, 1135, 1199, 1151,
-     1136, 1148, 1130, 1146, 1142,   80, 1153, 1152,    0, 1199,
-     1126, 1124, 1128, 1126, 1136, 1199, 1124, 1128, 1132, 1131,
-     1131, 1116, 1132, 1119, 1119, 1113, 1133, 1135, 1109, 1122,
-     1107, 1123, 1122, 1130, 1112, 1119, 1110, 1114, 1199, 1104,
-
-     1101, 1094,   97,  106,    0, 1105,   42, 1101,   94, 1108,
-     1090, 1093, 1096, 1104, 1098, 1091, 1100, 1085, 1199,    0,
-     1094, 1090, 1099, 1086, 1095, 1093, 1105, 1087,  117, 1102,
-        0, 1071, 1076,  104, 1088, 1069, 1073, 1093, 1075, 1086,
-     1069, 1199,   99,    0, 1093, 1079, 1069, 1199, 1065, 1062,
-     1063, 1076,  121,  125,    0, 1073, 1070, 1059, 1056, 1069,
-     1061, 1068, 1049,    0,  120, 1056, 1077, 1063, 1062,  131,
-     1073,    0, 1047, 1059, 1055, 1043, 1056,    0, 1046, 1050,
-     1044, 1038, 1044, 1036, 1199,  134,    0, 1199, 1035,    0,
-     1039, 1034, 1046, 1046, 1048, 1031, 1199,    0, 1030,    0,
-
-     1027, 1035, 1199, 1039, 1025, 1033,    0, 1032,    0, 1039,
-      137, 1018, 1028, 1032,    0, 1031,    0, 1018, 1025, 1015,
-        0, 1014,    0,  145,  142,    0,    0,  120,  132,    0,
-        0,    0,    0, 1199,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0, 1199, 1199,  149,  152,  156,  159,  163,  144,  166,
-      143,  170,  142,  174,  131,  178,  115,  182,  112,  186,
-       92,  190,   89,  194,   87,  198,   85,  202,   67,  206,
-       56,  210,  214,  218,  222,  226,  230,  234,  238,  242,
-      246,  250,  254,  258,  262,  266,  270,  274,  278,  282,
-      286,  290,  294,  298,  302,  306,  310,  314,  318,  322,
-
-      326,  330,  334,  338,  342,  346,  350,  354,  358,  362,
-      366,  370,  374,  378,  382,  386,  390,  394,  398,  402,
-      406,  410,  414,  418,  422,  426,  430,  434,  438,  442,
-      446,  450,  454,  458,  462,  466,  470,  474,  478,  482,
-      486,  490,  494,  498,  502,  506,  510,  514,  518,  522,
-      526,  530,  534,  538,  542,  546,  550,  554,  558,  562,
-      566,  570,  574,  578,  582,  586,  590,  594,  598,  602,
-      606,  610,  614,  618,  622,  626,  630,  634,  638,  642,
-      646,  650,  654,  658,  662,  666,  670,  674,  678,  682,
-      686,  690,  694,  698,  702,  706,  710,  714,  718,  722,
-
-      726,  730,  734,  738,  742,  746,  750,  754,  758,  762,
-      766,  770,  774,  778,  782,  786,  790,  794,  798,  802,
-      806,  810,  814,  818,  822,  826,  830,  834,  838,  842,
-      846,  850,  854,  858,  862,  866,  870,  874,  878,  882,
-      886,  890,  894,  898,  902,  906,  910,  914,  918,  922,
-      926,  930,  934,  938,  942,  946,  950,  954,  958,  962,
-      966,  970,  974,  978,  982,  986,  990,  994,  998, 1002,
-     1006, 1010, 1014, 1018, 1022, 1026, 1030, 1034, 1038
-    } ;
-
-static yyconst flex_int16_t yy_def[680] =
-    {   0,
-      443,    1,  443,  443,  443,  443,  444,  444,  445,  444,
-      444,  444,  444,  444,  444,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  446,  446,  447,
-      443,  443,  443,  446,  443,  443,  446,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  448,  448,  447,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-
-      443,  443,  443,  443,  449,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  450,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      451,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  452,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  453,  443,  443,  443,  443,  443,
-      443,  443,  443,  454,  443,  443,  443,  443,  443,  443,
-      443,  455,  443,  443,  443,  443,  443,  456,  443,  443,
-      443,  443,  443,  443,  443,  443,  457,  443,  443,  458,
-      443,  443,  443,  443,  443,  443,  443,  459,  443,  460,
-
-      443,  443,  443,  443,  443,  443,  461,  443,  462,  443,
-      443,  443,  443,  443,  463,  443,  464,  443,  443,  443,
-      465,  443,  466,  443,  443,  467,  468,  443,  443,  469,
-      470,  471,  472,  443,  473,  474,  475,  476,  477,  478,
-      479,  480,  481,  482,  483,  484,  485,  486,  487,  488,
-      489,  490,  491,  492,  493,  494,  495,  496,  497,  498,
-      499,  500,  501,  502,  503,  504,  505,  506,  507,  508,
-      509,  510,  511,  512,  513,  514,  515,  516,  517,  518,
-      519,  520,  521,  522,  523,  524,  525,  526,  527,  528,
-      529,  530,  531,  532,  533,  534,  535,  536,  537,  538,
-
-      539,  540,  541,  542,  543,  544,  545,  546,  547,  548,
-      549,  550,  551,  552,  553,  554,  555,  556,  557,  558,
-      559,  560,  561,  562,  563,  564,  565,  566,  567,  568,
-      569,  570,  571,  572,  573,  574,  575,  576,  577,  578,
-      579,  580,  581,  582,  583,  584,  585,  586,  587,  588,
-      589,  590,  591,  592,  593,  594,  595,  596,  597,  598,
-      599,  600,  601,  602,  603,  604,  605,  606,  607,  608,
-      609,  610,  611,  612,  613,  614,  615,  616,  617,  618,
-      619,  620,  621,  622,  623,  624,  625,  626,  627,  628,
-      629,  630,  631,  632,  633,  634,  635,  636,  637,  638,
-
-      639,  640,  641,  642,  643,  644,  645,  646,  647,  648,
-      649,  650,  651,  652,  653,  654,  655,  656,  657,  658,
-      659,  660,  661,  662,  663,  664,  665,  666,  667,  668,
-      669,  670,  671,  672,  673,  674,  675,  676,  677,  678,
-      679,  443,    0,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443
-    } ;
-
-static yyconst flex_int16_t yy_nxt[1235] =
-    {   0,
-        4,    5,    6,    4,    4,    7,    7,    7,    4,    8,
-        4,    9,   10,   11,   12,   13,   14,   15,   16,    4,
-       17,    4,   18,    4,   19,    4,   20,    4,   21,   22,
-       23,   24,   25,    4,    4,   26,   26,   26,   26,   27,
-       28,   28,   28,  443,  443,  443,  443,  443,  443,   42,
-       86,  443,   26,   26,  133,  443,   34,   87,   43,  234,
-       35,   36,   32,   37,   41,   33,   38,   39,  134,   31,
-      232,   73,   40,   44,   66,   66,   66,   27,   67,   67,
-       67,   45,   46,   76,  103,  104,  104,  104,  230,   47,
-      226,   48,  221,   49,   50,  215,   51,   52,   57,   89,
-
-       58,   59,  129,  129,  129,   90,   60,  158,   61,   91,
-      103,  130,  130,  130,  135,  207,  159,   62,  198,  162,
-      136,  153,  154,  154,  154,  163,  170,  170,  170,  153,
-      171,  171,  171,  179,  187,  180,  186,  186,  186,  197,
-      197,  197,  203,  203,  203,  172,  155,  131,  188,  188,
-      181,   29,   29,   30,   30,   30,  229,   30,   68,   68,
-       69,   69,   69,  228,   69,  105,  105,  144,  144,  144,
-      144,  164,  164,  164,  164,  178,  178,  178,  178,  190,
-      190,  190,  190,  200,  200,  200,  200,  209,  209,  209,
-      209,  217,  217,  217,  217,  223,  223,  223,  223,  227,
-
-      227,  227,  227,  231,  231,  231,  231,  233,  233,  233,
-      233,  235,  235,  235,  235,  236,  236,  236,  236,  237,
-      237,  237,  237,  238,  238,  238,  238,  239,  239,  239,
-      239,  240,  240,  240,  240,  241,  241,  241,  241,  242,
-      242,  242,  242,  243,  243,  243,  243,  244,  244,  244,
-      244,  245,  245,  245,  245,  246,  246,  246,  246,  247,
-      247,  247,  247,  248,  248,  248,  248,  249,  249,  249,
-      249,  250,  250,  250,  250,  251,  251,  251,  251,  252,
-      252,  252,  252,  253,  253,  253,  253,  254,  254,  254,
-      254,  255,  255,  255,  255,  256,  256,  256,  256,  257,
-
-      257,  257,  257,  258,  258,  258,  258,  259,  259,  259,
-      259,  260,  260,  260,  260,  261,  261,  261,  261,  262,
-      262,  262,  262,  263,  263,  263,  263,  264,  264,  264,
-      264,  265,  265,  265,  265,  266,  266,  266,  266,  267,
-      267,  267,  267,  268,  268,  268,  268,  269,  269,  269,
-      269,  270,  270,  270,  270,  271,  271,  271,  271,  272,
-      272,  272,  272,  273,  273,  273,  273,  274,  274,  274,
-      274,  275,  275,  275,  275,  276,  276,  276,  276,  277,
-      277,  277,  277,  278,  278,  278,  278,  279,  279,  279,
-      279,  280,  280,  280,  280,  281,  281,  281,  281,  282,
-
-      282,  282,  282,  283,  283,  283,  283,  284,  284,  284,
-      284,  285,  285,  285,  285,  286,  286,  286,  286,  287,
-      287,  287,  287,  288,  288,  288,  288,  289,  289,  289,
-      289,  290,  290,  290,  290,  291,  291,  291,  291,  292,
-      292,  292,  292,  293,  293,  293,  293,  294,  294,  294,
-      294,  295,  295,  295,  295,  296,  296,  296,  296,  297,
-      297,  297,  297,  298,  298,  298,  298,  299,  299,  299,
-      299,  300,  300,  300,  300,  301,  301,  301,  301,  302,
-      302,  302,  302,  303,  303,  303,  303,  304,  304,  304,
-      304,  305,  305,  305,  305,  306,  306,  306,  306,  307,
-
-      307,  307,  307,  308,  308,  308,  308,  309,  309,  309,
-      309,  310,  310,  310,  310,  311,  311,  311,  311,  312,
-      312,  312,  312,  313,  313,  313,  313,  314,  314,  314,
-      314,  315,  315,  315,  315,  316,  316,  316,  316,  317,
-      317,  317,  317,  318,  318,  318,  318,  319,  319,  319,
-      319,  320,  320,  320,  320,  321,  321,  321,  321,  322,
-      322,  322,  322,  323,  323,  323,  323,  324,  324,  324,
-      324,  325,  325,  325,  325,  326,  326,  326,  326,  327,
-      327,  327,  327,  328,  328,  328,  328,  329,  329,  329,
-      329,  330,  330,  330,  330,  331,  331,  331,  331,  332,
-
-      332,  332,  332,  333,  333,  333,  333,  334,  334,  334,
-      334,  335,  335,  335,  335,  336,  336,  336,  336,  337,
-      337,  337,  337,  338,  338,  338,  338,  339,  339,  339,
-      339,  340,  340,  340,  340,  341,  341,  341,  341,  342,
-      342,  342,  342,  343,  343,  343,  343,  344,  344,  344,
-      344,  345,  345,  345,  345,  346,  346,  346,  346,  347,
-      347,  347,  347,  348,  348,  348,  348,  349,  349,  349,
-      349,  350,  350,  350,  350,  351,  351,  351,  351,  352,
-      352,  352,  352,  353,  353,  353,  353,  354,  354,  354,
-      354,  355,  355,  355,  355,  356,  356,  356,  356,  357,
-
-      357,  357,  357,  358,  358,  358,  358,  359,  359,  359,
-      359,  360,  360,  360,  360,  361,  361,  361,  361,  362,
-      362,  362,  362,  363,  363,  363,  363,  364,  364,  364,
-      364,  365,  365,  365,  365,  366,  366,  366,  366,  367,
-      367,  367,  367,  368,  368,  368,  368,  369,  369,  369,
-      369,  370,  370,  370,  370,  371,  371,  371,  371,  372,
-      372,  372,  372,  373,  373,  373,  373,  374,  374,  374,
-      374,  375,  375,  375,  375,  376,  376,  376,  376,  377,
-      377,  377,  377,  378,  378,  378,  378,  379,  379,  379,
-      379,  380,  380,  380,  380,  381,  381,  381,  381,  382,
-
-      382,  382,  382,  383,  383,  383,  383,  384,  384,  384,
-      384,  385,  385,  385,  385,  386,  386,  386,  386,  387,
-      387,  387,  387,  388,  388,  388,  388,  389,  389,  389,
-      389,  390,  390,  390,  390,  391,  391,  391,  391,  392,
-      392,  392,  392,  393,  393,  393,  393,  394,  394,  394,
-      394,  395,  395,  395,  395,  396,  396,  396,  396,  397,
-      397,  397,  397,  398,  398,  398,  398,  399,  399,  399,
-      399,  400,  400,  400,  400,  401,  401,  401,  401,  402,
-      402,  402,  402,  403,  403,  403,  403,  404,  404,  404,
-      404,  405,  405,  405,  405,  406,  406,  406,  406,  407,
-
-      407,  407,  407,  408,  408,  408,  408,  409,  409,  409,
-      409,  410,  410,  410,  410,  411,  411,  411,  411,  412,
-      412,  412,  412,  413,  413,  413,  413,  414,  414,  414,
-      414,  415,  415,  415,  415,  416,  416,  416,  416,  417,
-      417,  417,  417,  418,  418,  418,  418,  419,  419,  419,
-      419,  420,  420,  420,  420,  421,  421,  421,  421,  422,
-      422,  422,  422,  423,  423,  423,  423,  424,  424,  424,
-      424,  425,  425,  425,  425,  426,  426,  426,  426,  427,
-      427,  427,  427,  428,  428,  428,  428,  429,  429,  429,
-      429,  430,  430,  430,  430,  431,  431,  431,  431,  432,
-
-      432,  432,  432,  433,  433,  433,  433,  434,  434,  434,
-      434,  435,  435,  435,  435,  436,  436,  436,  436,  437,
-      437,  437,  437,  438,  438,  438,  438,  439,  439,  439,
-      439,  440,  440,  440,  440,  441,  441,  441,  441,  442,
-      442,  442,  442,   99,   99,  225,  224,  222,  220,   99,
-      219,  218,  216,  214,  213,  212,  211,  210,  208,  206,
-      205,  204,  203,  202,  201,  199,  196,  195,  194,  193,
-      192,  191,   99,   59,  188,  189,  188,  153,  185,  184,
-      183,  182,   99,   99,  177,  176,  175,  174,  173,   99,
-      169,  168,  167,   99,  166,   99,  165,   99,  161,  160,
-
-      119,   99,   99,   99,  157,  156,  103,  152,  151,  150,
-      149,  148,  147,  146,  145,   99,   99,  143,  142,  141,
-      140,  139,  138,  137,   59,  132,  128,  127,  126,  125,
-       70,   70,  124,  123,   70,  122,   99,   99,  121,  120,
-      119,  118,  117,   99,  116,  115,  114,  113,  112,   59,
-      111,  110,  109,  108,  107,  106,  443,   27,  102,   70,
-      101,  100,   99,   98,   97,   96,   95,   70,   94,   93,
-       92,   88,   85,   84,   70,   83,   70,   82,   81,   80,
-       79,   78,   77,   75,   74,   72,   71,   70,  443,   65,
-       64,   63,   56,   55,   54,   53,  443,  443,    3,  443,
-
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443
-    } ;
-
-static yyconst flex_int16_t yy_chk[1235] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    5,    5,    6,    6,    7,
-        7,    7,    7,   10,   11,   12,   14,   34,   15,   16,
-       49,   13,   26,   26,  107,   37,   12,   49,   16,  471,
-       12,   12,   11,   13,   15,   11,   13,   13,  107,   10,
-      469,   34,   14,   17,   27,   27,   27,   28,   28,   28,
-       28,   17,   17,   37,   66,   66,   66,   66,  467,   17,
-      465,   17,  463,   17,   17,  461,   17,   17,   22,   51,
-
-       22,   22,  103,  103,  103,   51,   22,  134,   22,   51,
-      104,  104,  104,  104,  109,  459,  134,   22,  457,  143,
-      109,  129,  129,  129,  129,  143,  153,  153,  153,  154,
-      154,  154,  154,  165,  455,  165,  170,  170,  170,  186,
-      186,  186,  211,  211,  211,  453,  451,  449,  229,  228,
-      165,  444,  444,  445,  445,  445,  225,  445,  446,  446,
-      447,  447,  447,  224,  447,  448,  448,  450,  450,  450,
-      450,  452,  452,  452,  452,  454,  454,  454,  454,  456,
-      456,  456,  456,  458,  458,  458,  458,  460,  460,  460,
-      460,  462,  462,  462,  462,  464,  464,  464,  464,  466,
-
-      466,  466,  466,  468,  468,  468,  468,  470,  470,  470,
-      470,  472,  472,  472,  472,  473,  473,  473,  473,  474,
-      474,  474,  474,  475,  475,  475,  475,  476,  476,  476,
-      476,  477,  477,  477,  477,  478,  478,  478,  478,  479,
-      479,  479,  479,  480,  480,  480,  480,  481,  481,  481,
-      481,  482,  482,  482,  482,  483,  483,  483,  483,  484,
-      484,  484,  484,  485,  485,  485,  485,  486,  486,  486,
-      486,  487,  487,  487,  487,  488,  488,  488,  488,  489,
-      489,  489,  489,  490,  490,  490,  490,  491,  491,  491,
-      491,  492,  492,  492,  492,  493,  493,  493,  493,  494,
-
-      494,  494,  494,  495,  495,  495,  495,  496,  496,  496,
-      496,  497,  497,  497,  497,  498,  498,  498,  498,  499,
-      499,  499,  499,  500,  500,  500,  500,  501,  501,  501,
-      501,  502,  502,  502,  502,  503,  503,  503,  503,  504,
-      504,  504,  504,  505,  505,  505,  505,  506,  506,  506,
-      506,  507,  507,  507,  507,  508,  508,  508,  508,  509,
-      509,  509,  509,  510,  510,  510,  510,  511,  511,  511,
-      511,  512,  512,  512,  512,  513,  513,  513,  513,  514,
-      514,  514,  514,  515,  515,  515,  515,  516,  516,  516,
-      516,  517,  517,  517,  517,  518,  518,  518,  518,  519,
-
-      519,  519,  519,  520,  520,  520,  520,  521,  521,  521,
-      521,  522,  522,  522,  522,  523,  523,  523,  523,  524,
-      524,  524,  524,  525,  525,  525,  525,  526,  526,  526,
-      526,  527,  527,  527,  527,  528,  528,  528,  528,  529,
-      529,  529,  529,  530,  530,  530,  530,  531,  531,  531,
-      531,  532,  532,  532,  532,  533,  533,  533,  533,  534,
-      534,  534,  534,  535,  535,  535,  535,  536,  536,  536,
-      536,  537,  537,  537,  537,  538,  538,  538,  538,  539,
-      539,  539,  539,  540,  540,  540,  540,  541,  541,  541,
-      541,  542,  542,  542,  542,  543,  543,  543,  543,  544,
-
-      544,  544,  544,  545,  545,  545,  545,  546,  546,  546,
-      546,  547,  547,  547,  547,  548,  548,  548,  548,  549,
-      549,  549,  549,  550,  550,  550,  550,  551,  551,  551,
-      551,  552,  552,  552,  552,  553,  553,  553,  553,  554,
-      554,  554,  554,  555,  555,  555,  555,  556,  556,  556,
-      556,  557,  557,  557,  557,  558,  558,  558,  558,  559,
-      559,  559,  559,  560,  560,  560,  560,  561,  561,  561,
-      561,  562,  562,  562,  562,  563,  563,  563,  563,  564,
-      564,  564,  564,  565,  565,  565,  565,  566,  566,  566,
-      566,  567,  567,  567,  567,  568,  568,  568,  568,  569,
-
-      569,  569,  569,  570,  570,  570,  570,  571,  571,  571,
-      571,  572,  572,  572,  572,  573,  573,  573,  573,  574,
-      574,  574,  574,  575,  575,  575,  575,  576,  576,  576,
-      576,  577,  577,  577,  577,  578,  578,  578,  578,  579,
-      579,  579,  579,  580,  580,  580,  580,  581,  581,  581,
-      581,  582,  582,  582,  582,  583,  583,  583,  583,  584,
-      584,  584,  584,  585,  585,  585,  585,  586,  586,  586,
-      586,  587,  587,  587,  587,  588,  588,  588,  588,  589,
-      589,  589,  589,  590,  590,  590,  590,  591,  591,  591,
-      591,  592,  592,  592,  592,  593,  593,  593,  593,  594,
-
-      594,  594,  594,  595,  595,  595,  595,  596,  596,  596,
-      596,  597,  597,  597,  597,  598,  598,  598,  598,  599,
-      599,  599,  599,  600,  600,  600,  600,  601,  601,  601,
-      601,  602,  602,  602,  602,  603,  603,  603,  603,  604,
-      604,  604,  604,  605,  605,  605,  605,  606,  606,  606,
-      606,  607,  607,  607,  607,  608,  608,  608,  608,  609,
-      609,  609,  609,  610,  610,  610,  610,  611,  611,  611,
-      611,  612,  612,  612,  612,  613,  613,  613,  613,  614,
-      614,  614,  614,  615,  615,  615,  615,  616,  616,  616,
-      616,  617,  617,  617,  617,  618,  618,  618,  618,  619,
-
-      619,  619,  619,  620,  620,  620,  620,  621,  621,  621,
-      621,  622,  622,  622,  622,  623,  623,  623,  623,  624,
-      624,  624,  624,  625,  625,  625,  625,  626,  626,  626,
-      626,  627,  627,  627,  627,  628,  628,  628,  628,  629,
-      629,  629,  629,  630,  630,  630,  630,  631,  631,  631,
-      631,  632,  632,  632,  632,  633,  633,  633,  633,  634,
-      634,  634,  634,  635,  635,  635,  635,  636,  636,  636,
-      636,  637,  637,  637,  637,  638,  638,  638,  638,  639,
-      639,  639,  639,  640,  640,  640,  640,  641,  641,  641,
-      641,  642,  642,  642,  642,  643,  643,  643,  643,  644,
-
-      644,  644,  644,  645,  645,  645,  645,  646,  646,  646,
-      646,  647,  647,  647,  647,  648,  648,  648,  648,  649,
-      649,  649,  649,  650,  650,  650,  650,  651,  651,  651,
-      651,  652,  652,  652,  652,  653,  653,  653,  653,  654,
-      654,  654,  654,  655,  655,  655,  655,  656,  656,  656,
-      656,  657,  657,  657,  657,  658,  658,  658,  658,  659,
-      659,  659,  659,  660,  660,  660,  660,  661,  661,  661,
-      661,  662,  662,  662,  662,  663,  663,  663,  663,  664,
-      664,  664,  664,  665,  665,  665,  665,  666,  666,  666,
-      666,  667,  667,  667,  667,  668,  668,  668,  668,  669,
-
-      669,  669,  669,  670,  670,  670,  670,  671,  671,  671,
-      671,  672,  672,  672,  672,  673,  673,  673,  673,  674,
-      674,  674,  674,  675,  675,  675,  675,  676,  676,  676,
-      676,  677,  677,  677,  677,  678,  678,  678,  678,  679,
-      679,  679,  679,  222,  220,  219,  218,  216,  214,  213,
-      212,  210,  208,  206,  205,  204,  202,  201,  199,  196,
-      195,  194,  193,  192,  191,  189,  184,  183,  182,  181,
-      180,  179,  177,  176,  175,  174,  173,  171,  169,  168,
-      167,  166,  163,  162,  161,  160,  159,  158,  157,  156,
-      152,  151,  150,  149,  147,  146,  145,  141,  140,  139,
-
-      138,  137,  136,  135,  133,  132,  130,  128,  127,  126,
-      125,  124,  123,  122,  121,  118,  117,  116,  115,  114,
-      113,  112,  111,  110,  108,  106,  102,  101,  100,   98,
-       97,   96,   95,   94,   93,   92,   91,   90,   89,   88,
-       87,   86,   85,   84,   83,   82,   81,   80,   79,   78,
-       77,   75,   74,   73,   72,   71,   68,   67,   65,   64,
-       63,   62,   61,   60,   58,   57,   56,   55,   54,   53,
-       52,   50,   48,   47,   46,   45,   44,   43,   42,   41,
-       40,   39,   38,   36,   35,   33,   32,   31,   29,   25,
-       24,   23,   21,   20,   19,   18,    8,    3,  443,  443,
-
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443,  443,  443,  443,  443,  443,  443,
-      443,  443,  443,  443
-    } ;
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-extern int yy_flex_debug;
-int yy_flex_debug = 0;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-#ifndef YYLMAX
-#define YYLMAX 8192
-#endif
-
-char yytext[YYLMAX];
-char *yytext_ptr;
-#line 1 "prom_lex.l"
-/*
- * Copyright (C) IBM Corporation. 2007
- * Author: Doug Maxey <dwm@austin.ibm.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-/* definitions */
-#line 23 "prom_lex.l"
-#include "prom_parse.h"
-
-#undef LEXDEBUG
-#ifdef LEXDEBUG
-#define dbg(a) dbgprint((a))
-#else
-#define dbg(a) do {} while (0)
-#endif  /* LEXDEBUG */
-
-#define upval(d)				\
-    dbg(#d);					\
-    yylval.str[0] = 0;                          \
-    strcat(yylval.str, yytext);			\
-    yylloc.first_column = yylloc.last_column;	\
-    yylloc.last_column += yyleng;		\
-    return d
-
-void dbgprint(const char *item) { fprintf(stderr, "%s: \"%s\" len=%d ", item, yytext, yyleng);}
-
-#define YY_NO_INPUT 1
-/* CHOSEN uses only boot related paths. */
-#line 975 "<stdout>"
-
-#define INITIAL 0
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-static int yy_init_globals (void );
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int yylex_destroy (void );
-
-int yyget_debug (void );
-
-void yyset_debug (int debug_flag  );
-
-YY_EXTRA_TYPE yyget_extra (void );
-
-void yyset_extra (YY_EXTRA_TYPE user_defined  );
-
-FILE *yyget_in (void );
-
-void yyset_in  (FILE * in_str  );
-
-FILE *yyget_out (void );
-
-void yyset_out  (FILE * out_str  );
-
-int yyget_leng (void );
-
-char *yyget_text (void );
-
-int yyget_lineno (void );
-
-void yyset_lineno (int line_number  );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap (void );
-#else
-extern int yywrap (void );
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (void );
-#else
-static int input (void );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
-		{ \
-		int c = '*'; \
-		size_t n; \
-		for ( n = 0; n < max_size && \
-			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
-			buf[n] = (char) c; \
-		if ( c == '\n' ) \
-			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( yyin ) ) \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-		result = n; \
-		} \
-	else \
-		{ \
-		errno=0; \
-		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
-			{ \
-			if( errno != EINTR) \
-				{ \
-				YY_FATAL_ERROR( "input in flex scanner failed" ); \
-				break; \
-				} \
-			errno=0; \
-			clearerr(yyin); \
-			} \
-		}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int yylex (void);
-
-#define YY_DECL int yylex (void)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    
-#line 65 "prom_lex.l"
-
-
-#line 1163 "<stdout>"
-
-	if ( !(yy_init) )
-		{
-		(yy_init) = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! (yy_start) )
-			(yy_start) = 1;	/* first start state */
-
-		if ( ! yyin )
-			yyin = stdin;
-
-		if ( ! yyout )
-			yyout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			yyensure_buffer_stack ();
-			YY_CURRENT_BUFFER_LVALUE =
-				yy_create_buffer(yyin,YY_BUF_SIZE );
-		}
-
-		yy_load_buffer_state( );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = (yy_c_buf_p);
-
-		/* Support of yytext. */
-		*yy_cp = (yy_hold_char);
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = (yy_start);
-yy_match:
-		do
-			{
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
-			if ( yy_accept[yy_current_state] )
-				{
-				(yy_last_accepting_state) = yy_current_state;
-				(yy_last_accepting_cpos) = yy_cp;
-				}
-			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-				{
-				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 444 )
-					yy_c = yy_meta[(unsigned int) yy_c];
-				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-			++yy_cp;
-			}
-		while ( yy_current_state != 443 );
-		yy_cp = (yy_last_accepting_cpos);
-		yy_current_state = (yy_last_accepting_state);
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-
-		YY_DO_BEFORE_ACTION;
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = (yy_hold_char);
-			yy_cp = (yy_last_accepting_cpos);
-			yy_current_state = (yy_last_accepting_state);
-			goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 67 "prom_lex.l"
-{ upval(CHOSEN); }
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 68 "prom_lex.l"
-{ upval(VDEVICE); }
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 69 "prom_lex.l"
-{ upval(VDEVINST); }
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 70 "prom_lex.l"
-{ upval(VDEVDEV); }
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 71 "prom_lex.l"
-{ upval(VDEVRAW); }
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 72 "prom_lex.l"
-{ upval(OBPQUAL); }
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 73 "prom_lex.l"
-{ upval(BUSNAME); }
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 74 "prom_lex.l"
-{ upval(IPV4); }
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 75 "prom_lex.l"
-{ upval(IQN); }
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 76 "prom_lex.l"
-{ upval(BOOTDEV); }
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 77 "prom_lex.l"
-{ upval(OBPPARM); }
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 78 "prom_lex.l"
-{ upval(HEX4); }
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 79 "prom_lex.l"
-{ upval(HEX16); }
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 80 "prom_lex.l"
-{ upval(FILENAME); }
-	YY_BREAK
-case 15:
-/* rule 15 can match eol */
-YY_RULE_SETUP
-#line 81 "prom_lex.l"
-{                  /* eat all whitespace. */
-	yylloc.first_column = yylloc.last_column;
-	yylloc.last_column += yyleng;
-}
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 85 "prom_lex.l"
-{			/* any other single char. */
-	dbg("??");
-	yylloc.first_column = yylloc.last_column;
-	yylloc.last_column += yyleng;
-	return *yytext;
-}
-	YY_BREAK
-case YY_STATE_EOF(INITIAL):
-#line 92 "prom_lex.l"
-yyterminate();
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 93 "prom_lex.l"
-ECHO;
-	YY_BREAK
-#line 1340 "<stdout>"
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = (yy_hold_char);
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed yyin at a new source and called
-			 * yylex().  If so, then we have to assure
-			 * consistency between YY_CURRENT_BUFFER and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state(  );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++(yy_c_buf_p);
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = (yy_last_accepting_cpos);
-				yy_current_state = (yy_last_accepting_state);
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer(  ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				(yy_did_buffer_switch_on_eof) = 0;
-
-				if ( yywrap( ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * yytext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				(yy_c_buf_p) =
-					(yytext_ptr) + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				(yy_c_buf_p) =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of yylex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (void)
-{
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = (yytext_ptr);
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-			int yy_c_buf_p_offset =
-				(int) ((yy_c_buf_p) - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), (size_t) num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	if ( (yy_n_chars) == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			yyrestart(yyin  );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	(yy_n_chars) += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
-
-	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (void)
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    
-	yy_current_state = (yy_start);
-
-	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
-		{
-		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-			{
-			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 444 )
-				yy_c = yy_meta[(unsigned int) yy_c];
-			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
-{
-	register int yy_is_jam;
-    	register char *yy_cp = (yy_c_buf_p);
-
-	register YY_CHAR yy_c = 1;
-	if ( yy_accept[yy_current_state] )
-		{
-		(yy_last_accepting_state) = yy_current_state;
-		(yy_last_accepting_cpos) = yy_cp;
-		}
-	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-		{
-		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 444 )
-			yy_c = yy_meta[(unsigned int) yy_c];
-		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 443);
-
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (void)
-#else
-    static int input  (void)
-#endif
-
-{
-	int c;
-    
-	*(yy_c_buf_p) = (yy_hold_char);
-
-	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			/* This was really a NUL. */
-			*(yy_c_buf_p) = '\0';
-
-		else
-			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
-			++(yy_c_buf_p);
-
-			switch ( yy_get_next_buffer(  ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					yyrestart(yyin );
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( yywrap( ) )
-						return EOF;
-
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					(yy_c_buf_p) = (yytext_ptr) + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
-	*(yy_c_buf_p) = '\0';	/* preserve yytext */
-	(yy_hold_char) = *++(yy_c_buf_p);
-
-	return c;
-}
-#endif	/* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * 
- * @note This function does not reset the start condition to @c INITIAL .
- */
-    void yyrestart  (FILE * input_file )
-{
-    
-	if ( ! YY_CURRENT_BUFFER ){
-        yyensure_buffer_stack ();
-		YY_CURRENT_BUFFER_LVALUE =
-            yy_create_buffer(yyin,YY_BUF_SIZE );
-	}
-
-	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
-	yy_load_buffer_state( );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * 
- */
-    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
-{
-    
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		yypop_buffer_state();
-	 *		yypush_buffer_state(new_buffer);
-     */
-	yyensure_buffer_stack ();
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	yy_load_buffer_state( );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (yywrap()) processing, but the only time this flag
-	 * is looked at is after yywrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-static void yy_load_buffer_state  (void)
-{
-    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	(yy_hold_char) = *(yy_c_buf_p);
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * 
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	yy_init_buffer(b,file );
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with yy_create_buffer()
- * 
- */
-    void yy_delete_buffer (YY_BUFFER_STATE  b )
-{
-    
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		yyfree((void *) b->yy_ch_buf  );
-
-	yyfree((void *) b  );
-}
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a yyrestart() or at EOF.
- */
-    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
-
-{
-	int oerrno = errno;
-    
-	yy_flush_buffer(b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then yy_init_buffer was _probably_
-     * called from yyrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * 
- */
-    void yy_flush_buffer (YY_BUFFER_STATE  b )
-{
-    	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		yy_load_buffer_state( );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  
- */
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
-{
-    	if (new_buffer == NULL)
-		return;
-
-	yyensure_buffer_stack();
-
-	/* This block is copied from yy_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		(yy_buffer_stack_top)++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from yy_switch_to_buffer. */
-	yy_load_buffer_state( );
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  
- */
-void yypop_buffer_state (void)
-{
-    	if (!YY_CURRENT_BUFFER)
-		return;
-
-	yy_delete_buffer(YY_CURRENT_BUFFER );
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if ((yy_buffer_stack_top) > 0)
-		--(yy_buffer_stack_top);
-
-	if (YY_CURRENT_BUFFER) {
-		yy_load_buffer_state( );
-		(yy_did_buffer_switch_on_eof) = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void yyensure_buffer_stack (void)
-{
-	int num_to_alloc;
-    
-	if (!(yy_buffer_stack)) {
-
-		/* First allocation is just for 2 elements, since we don't know if this
-		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
-		 * immediate realloc on the next call.
-         */
-		num_to_alloc = 1;
-		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-
-		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		(yy_buffer_stack_max) = num_to_alloc;
-		(yy_buffer_stack_top) = 0;
-		return;
-	}
-
-	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = (yy_buffer_stack_max) + grow_size;
-		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
-								((yy_buffer_stack),
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
-		(yy_buffer_stack_max) = num_to_alloc;
-	}
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * 
- * @return the newly allocated buffer state object. 
- */
-YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	yy_switch_to_buffer(b  );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to yylex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * 
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       yy_scan_bytes() instead.
- */
-YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
-{
-    
-	return yy_scan_bytes(yystr,strlen(yystr) );
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * 
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) yyalloc(n  );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = yy_scan_buffer(buf,n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg )
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		yytext[yyleng] = (yy_hold_char); \
-		(yy_c_buf_p) = yytext + yyless_macro_arg; \
-		(yy_hold_char) = *(yy_c_buf_p); \
-		*(yy_c_buf_p) = '\0'; \
-		yyleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the current line number.
- * 
- */
-int yyget_lineno  (void)
-{
-        
-    return yylineno;
-}
-
-/** Get the input stream.
- * 
- */
-FILE *yyget_in  (void)
-{
-        return yyin;
-}
-
-/** Get the output stream.
- * 
- */
-FILE *yyget_out  (void)
-{
-        return yyout;
-}
-
-/** Get the length of the current token.
- * 
- */
-int yyget_leng  (void)
-{
-        return yyleng;
-}
-
-/** Get the current token.
- * 
- */
-
-char *yyget_text  (void)
-{
-        return yytext;
-}
-
-/** Set the current line number.
- * @param line_number
- * 
- */
-void yyset_lineno (int  line_number )
-{
-    
-    yylineno = line_number;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * 
- * @see yy_switch_to_buffer
- */
-void yyset_in (FILE *  in_str )
-{
-        yyin = in_str ;
-}
-
-void yyset_out (FILE *  out_str )
-{
-        yyout = out_str ;
-}
-
-int yyget_debug  (void)
-{
-        return yy_flex_debug;
-}
-
-void yyset_debug (int  bdebug )
-{
-        yy_flex_debug = bdebug ;
-}
-
-static int yy_init_globals (void)
-{
-        /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from yylex_destroy(), so don't allocate here.
-     */
-
-    (yy_buffer_stack) = 0;
-    (yy_buffer_stack_top) = 0;
-    (yy_buffer_stack_max) = 0;
-    (yy_c_buf_p) = (char *) 0;
-    (yy_init) = 0;
-    (yy_start) = 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    yyin = stdin;
-    yyout = stdout;
-#else
-    yyin = (FILE *) 0;
-    yyout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * yylex_init()
-     */
-    return 0;
-}
-
-/* yylex_destroy is for both reentrant and non-reentrant scanners. */
-int yylex_destroy  (void)
-{
-    
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		yy_delete_buffer(YY_CURRENT_BUFFER  );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		yypop_buffer_state();
-	}
-
-	/* Destroy the stack itself. */
-	yyfree((yy_buffer_stack) );
-	(yy_buffer_stack) = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * yylex() is called, initialization will occur. */
-    yy_init_globals( );
-
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
-{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
-{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *yyalloc (yy_size_t  size )
-{
-	return (void *) malloc( size );
-}
-
-void *yyrealloc  (void * ptr, yy_size_t  size )
-{
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return (void *) realloc( (char *) ptr, size );
-}
-
-void yyfree (void * ptr )
-{
-	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 93 "prom_lex.l"
-
-
-
diff -pruN 2.1.5-1/utils/fwparam_ibft/prom_lex.l 2.1.7-2/utils/fwparam_ibft/prom_lex.l
--- 2.1.5-1/utils/fwparam_ibft/prom_lex.l	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/prom_lex.l	1970-01-01 00:00:00.000000000 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) IBM Corporation. 2007
- * Author: Doug Maxey <dwm@austin.ibm.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* definitions */
-%option array
-
-%{
-#include "prom_parse.h"
-
-#undef LEXDEBUG
-#ifdef LEXDEBUG
-#define dbg(a) dbgprint((a))
-#else
-#define dbg(a) do {} while (0)
-#endif  /* LEXDEBUG */
-
-#define upval(d)				\
-    dbg(#d);					\
-    yylval.str[0] = 0;                          \
-    strcat(yylval.str, yytext);			\
-    yylloc.first_column = yylloc.last_column;	\
-    yylloc.last_column += yyleng;		\
-    return d
-
-void dbgprint(const char *item) { fprintf(stderr, "%s: \"%s\" len=%d ", item, yytext, yyleng);}
-
-%}
-
-%option noyywrap
-%option never-interactive
-%option nounput
-%option noinput
-
-VDEVICE     vdevice
-VDEVINST    gscsi
-VDEVDEV     dev
-VDEVRAW     rawio
-                                /* CHOSEN uses only boot related paths. */
-CHOSEN      bootpath|bootargs|iscsi-bootargs|nas-bootdevice
-BUSNAME     ata|i2c|ide|pci|sata|scsi|usb|lhea
-BOOTDEV     cdrom|disk|ethernet|iscsi-(disk[0-9]|toe)|sd
-HEX4        [[:xdigit:]]{1,4}
-HEX16       [[:xdigit:]]{5,16}
-IPV4        [0-9]{1,3}(\.[0-9]{1,3}){3}
-IQN         iqn\.[-[:alnum:]:.]{1,219}
-OBPQUAL     bootp|ipv6|iscsi|dhcpv6
-OBPPARM     blksize|bootp-retries|chapid|chappw|ciaddr|dhcp|filename|giaddr|ichapid|ichappw|ilun|iname|iport|isid|isns|itname|siaddr|slp|subnet-mask|tftp-retries
-FILENAME    \\[-[:alnum:]\\\.]{1,}
-
-%% /* rules */
-
-{CHOSEN}      { upval(CHOSEN); }
-{VDEVICE}     { upval(VDEVICE); }
-{VDEVINST}    { upval(VDEVINST); }
-{VDEVDEV}     { upval(VDEVDEV); }
-{VDEVRAW}     { upval(VDEVRAW); }
-{OBPQUAL}     { upval(OBPQUAL); }
-{BUSNAME}     { upval(BUSNAME); }
-{IPV4}        { upval(IPV4); }
-{IQN}         { upval(IQN); }
-{BOOTDEV}     { upval(BOOTDEV); }
-{OBPPARM}     { upval(OBPPARM); }
-{HEX4}        { upval(HEX4); }
-{HEX16}       { upval(HEX16); }
-{FILENAME}    { upval(FILENAME); }
-[ \t\n]+      {                  /* eat all whitespace. */
-	yylloc.first_column = yylloc.last_column;
-	yylloc.last_column += yyleng;
-}
-.             {			/* any other single char. */
-	dbg("??");
-	yylloc.first_column = yylloc.last_column;
-	yylloc.last_column += yyleng;
-	return *yytext;
-}
-
-<<EOF>> yyterminate();
-%% /* user code */
diff -pruN 2.1.5-1/utils/fwparam_ibft/prom_parse.h 2.1.7-2/utils/fwparam_ibft/prom_parse.h
--- 2.1.5-1/utils/fwparam_ibft/prom_parse.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/prom_parse.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) IBM Corporation. 2007
- * Author: Doug Maxey <dwm@austin.ibm.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef PROM_PARSE_H_
-#define PROM_PARSE_H_
-
-#include <stdlib.h>
-#include <string.h>
-#include "iscsi_obp.h"
-
-struct ofw_dev;
-void yyerror(struct ofw_dev *ofwdev, const char *msg);
-extern int yyleng;
-extern int yydebug;
-#include <stdio.h>
-extern FILE *yyin;
-extern char yytext[];
-int yylex(void);
-
-#define YY_NO_UNPUT 1 /* match this with %option never-interactive. */
-#include "prom_parse.tab.h"
-
-
-#endif /* PROM_PARSE_H_ */
diff -pruN 2.1.5-1/utils/fwparam_ibft/prom_parse.tab.c 2.1.7-2/utils/fwparam_ibft/prom_parse.tab.c
--- 2.1.5-1/utils/fwparam_ibft/prom_parse.tab.c	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/prom_parse.tab.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,2063 +0,0 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
-
-/* Bison implementation for Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
-
-   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 3 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, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "3.0.4"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 0
-
-/* Push parsers.  */
-#define YYPUSH 0
-
-/* Pull parsers.  */
-#define YYPULL 1
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 21 "prom_parse.y" /* yacc.c:339  */
-
-	/* literal block. include lines, decls, defns. */
-//#define YYDEBUG 1
-#if YYDEBUG
-#define DPRINT(fmt,...) printf(fmt,__VA_ARGS__)
-#else
-#define DPRINT(fmt,...) do {} while(0)
-#endif
-#include "prom_parse.h"
-#include "iscsi_obp.h"
-
-
-
-#line 80 "prom_parse.tab.c" /* yacc.c:339  */
-
-# ifndef YY_NULLPTR
-#  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULLPTR nullptr
-#  else
-#   define YY_NULLPTR 0
-#  endif
-# endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* In a future release of Bison, this section will be replaced
-   by #include "prom_parse.tab.h".  */
-#ifndef YY_YY_PROM_PARSE_TAB_H_INCLUDED
-# define YY_YY_PROM_PARSE_TAB_H_INCLUDED
-/* Debug traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
-
-/* Token type.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-  enum yytokentype
-  {
-    BUSNAME = 258,
-    BOOTDEV = 259,
-    IPV4 = 260,
-    IQN = 261,
-    OBPPARM = 262,
-    OBPQUAL = 263,
-    HEX4 = 264,
-    HEX16 = 265,
-    VDEVICE = 266,
-    VDEVINST = 267,
-    VDEVDEV = 268,
-    VDEVRAW = 269,
-    CHOSEN = 270,
-    FILENAME = 271
-  };
-#endif
-
-/* Value type.  */
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-
-union YYSTYPE
-{
-#line 34 "prom_parse.y" /* yacc.c:355  */
-
-#define	STR_LEN		16384
-		char str[STR_LEN];
-
-#line 142 "prom_parse.tab.c" /* yacc.c:355  */
-};
-
-typedef union YYSTYPE YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-/* Location type.  */
-#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE YYLTYPE;
-struct YYLTYPE
-{
-  int first_line;
-  int first_column;
-  int last_line;
-  int last_column;
-};
-# define YYLTYPE_IS_DECLARED 1
-# define YYLTYPE_IS_TRIVIAL 1
-#endif
-
-
-extern YYSTYPE yylval;
-extern YYLTYPE yylloc;
-int yyparse (struct ofw_dev *ofwdev);
-
-#endif /* !YY_YY_PROM_PARSE_TAB_H_INCLUDED  */
-
-/* Copy the second part of user declarations.  */
-
-#line 173 "prom_parse.tab.c" /* yacc.c:358  */
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#else
-typedef signed char yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(Msgid) Msgid
-# endif
-#endif
-
-#ifndef YY_ATTRIBUTE
-# if (defined __GNUC__                                               \
-      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
-     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
-#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
-# else
-#  define YY_ATTRIBUTE(Spec) /* empty */
-# endif
-#endif
-
-#ifndef YY_ATTRIBUTE_PURE
-# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
-#endif
-
-#ifndef YY_ATTRIBUTE_UNUSED
-# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
-#endif
-
-#if !defined _Noreturn \
-     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
-# if defined _MSC_VER && 1200 <= _MSC_VER
-#  define _Noreturn __declspec (noreturn)
-# else
-#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
-#else
-# define YYUSE(E) /* empty */
-#endif
-
-#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
-/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
-    _Pragma ("GCC diagnostic push") \
-    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
-    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
-    _Pragma ("GCC diagnostic pop")
-#else
-# define YY_INITIAL_VALUE(Value) Value
-#endif
-#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END
-#endif
-#ifndef YY_INITIAL_VALUE
-# define YY_INITIAL_VALUE(Value) /* Nothing. */
-#endif
-
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
-#     ifndef EXIT_SUCCESS
-#      define EXIT_SUCCESS 0
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's 'empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
-       && ! ((defined YYMALLOC || defined malloc) \
-             && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef EXIT_SUCCESS
-#    define EXIT_SUCCESS 0
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-         || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
-             && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss_alloc;
-  YYSTYPE yyvs_alloc;
-  YYLTYPE yyls_alloc;
-};
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
-      + 2 * YYSTACK_GAP_MAXIMUM)
-
-# define YYCOPY_NEEDED 1
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
-    do                                                                  \
-      {                                                                 \
-        YYSIZE_T yynewbytes;                                            \
-        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
-        Stack = &yyptr->Stack_alloc;                                    \
-        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-        yyptr += yynewbytes / sizeof (*yyptr);                          \
-      }                                                                 \
-    while (0)
-
-#endif
-
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from SRC to DST.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(Dst, Src, Count) \
-      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
-#  else
-#   define YYCOPY(Dst, Src, Count)              \
-      do                                        \
-        {                                       \
-          YYSIZE_T yyi;                         \
-          for (yyi = 0; yyi < (Count); yyi++)   \
-            (Dst)[yyi] = (Src)[yyi];            \
-        }                                       \
-      while (0)
-#  endif
-# endif
-#endif /* !YYCOPY_NEEDED */
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  8
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   103
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  24
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  19
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  51
-/* YYNSTATES -- Number of states.  */
-#define YYNSTATES  93
-
-/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
-   by yylex, with out-of-bounds checking.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   273
-
-#define YYTRANSLATE(YYX)                                                \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
-   as returned by yylex, without out-of-bounds checking.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,    19,     2,     2,    17,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    20,     2,
-       2,    21,     2,     2,    18,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    22,    23
-};
-
-#if YYDEBUG
-  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] =
-{
-       0,    60,    60,    63,    66,    74,    82,    89,    96,    99,
-     104,   107,   110,   113,   116,   122,   125,   128,   133,   138,
-     141,   144,   149,   154,   157,   160,   165,   168,   173,   177,
-     181,   185,   191,   194,   199,   202,   207,   210,   215,   220,
-     223,   228,   231,   234,   237,   242,   245,   250,   253,   256,
-     261,   264
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || 0
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "BUSNAME", "BOOTDEV", "IPV4", "IQN",
-  "OBPPARM", "OBPQUAL", "HEX4", "HEX16", "VDEVICE", "VDEVINST", "VDEVDEV",
-  "VDEVRAW", "CHOSEN", "FILENAME", "'/'", "'@'", "','", "':'", "'='",
-  "\"::\"", "\":\"", "$accept", "devpath", "busses", "bus", "bootdev",
-  "vdevice", "vdev_parms", "vdev_parm", "obp_params", "obp_param",
-  "obp_quals", "obp_qual", "ipaddr", "ipv4", "ipv6", "hexpart", "hexseq",
-  "disklabel", "diskpart", YY_NULLPTR
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[NUM] -- (External) token number corresponding to the
-   (internal) symbol number NUM (which must be that of a token).  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,    47,    64,    44,
-      58,    61,   272,   273
-};
-# endif
-
-#define YYPACT_NINF -73
-
-#define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-73)))
-
-#define YYTABLE_NINF -46
-
-#define yytable_value_is_error(Yytable_value) \
-  0
-
-  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-     STATE-NUM.  */
-static const yytype_int8 yypact[] =
-{
-     -15,    19,    13,    20,    18,    23,   -73,    25,   -73,    39,
-      51,    50,    49,    16,    46,    43,    42,   -73,    47,   -73,
-      -9,   -73,   -73,    44,    45,    58,    59,   -73,    52,   -73,
-     -73,   -73,    56,    24,    61,    62,    64,   -73,   -73,    60,
-      55,    57,    38,     8,   -73,    41,    52,   -73,   -73,    37,
-     -73,    68,    63,    65,   -73,   -73,   -73,     3,   -73,   -73,
-     -73,     8,    69,   -73,    44,   -73,    -2,    44,   -73,   -73,
-     -73,    67,   -73,   -73,   -73,    36,   -73,   -73,    71,   -73,
-     -73,   -73,    11,    66,   -73,   -73,    66,    76,    71,    73,
-     -73,    66,   -73
-};
-
-  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
-     Performed when YYTABLE does not specify something else to do.  Zero
-     means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       0,     2,     0,    10,     0,     0,     8,     0,     1,     0,
-       0,     0,     0,     3,     0,     0,    11,    13,     0,    18,
-       0,     9,    34,     0,     0,     0,     0,    35,     0,    32,
-       4,    47,     0,     0,     0,     0,     0,    15,    48,     0,
-       0,    50,     0,     5,    19,     0,     0,    12,    14,     0,
-      22,     0,     0,     0,    26,    23,    33,     0,     6,    21,
-      20,     0,     0,    16,     0,    51,     0,    26,    24,    25,
-       7,     0,    49,    38,    29,    30,    27,    31,     0,    28,
-      36,    37,    39,    41,    17,    45,    44,     0,    42,     0,
-      40,    43,    46
-};
-
-  /* YYPGOTO[NTERM-NUM].  */
-static const yytype_int8 yypgoto[] =
-{
-     -73,   -73,   -73,    72,    78,   -73,   -73,   -27,    48,    26,
-      70,    53,   -73,     1,   -73,   -73,   -72,   -42,   -23
-};
-
-  /* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int8 yydefgoto[] =
-{
-      -1,     2,     5,     6,    13,     7,    33,    27,    43,    55,
-      28,    29,    79,    80,    81,    82,    83,    30,    31
-};
-
-  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
-     positive, shift that token.  If negative, reduce the rule whose
-     number is the opposite.  If YYTABLE_NINF, syntax error.  */
-static const yytype_int8 yytable[] =
-{
-      38,    58,     1,    73,    74,    44,    86,    75,    76,    36,
-      53,    37,    67,     8,    77,    69,    91,    23,    60,    70,
-      78,    25,     3,    26,    22,    23,    25,    57,    26,    24,
-       4,    87,    22,    88,    25,    11,    26,    24,     9,    10,
-      12,    72,    14,    45,    38,    53,    22,    54,    16,    17,
-      20,    24,     3,    20,    24,    59,    62,    63,   -45,   -45,
-      18,    34,    19,    32,    26,    35,    39,    40,    41,    24,
-      47,    42,    48,    49,    51,    50,    52,    64,    71,    65,
-      85,    73,    92,    68,    21,    15,    66,    84,    90,    89,
-       0,     0,     0,     0,    61,    56,     0,     0,     0,     0,
-       0,     0,     0,    46
-};
-
-static const yytype_int8 yycheck[] =
-{
-      23,    43,    17,     5,     6,    32,    78,     9,    10,    18,
-       7,    20,     9,     0,    16,    57,    88,     9,    45,    61,
-      22,    18,     3,    20,     8,     9,    18,    19,    20,    13,
-      11,    20,     8,    22,    18,    17,    20,    13,    18,    19,
-      17,    64,    17,    19,    67,     7,     8,     9,     9,    10,
-       4,    13,     3,     4,    13,    14,    19,    20,    22,    23,
-       9,    19,    12,    20,    20,    18,    21,     9,     9,    13,
-       9,    19,    10,     9,    19,    15,    19,     9,     9,    16,
-       9,     5,     9,    57,    12,     7,    21,    20,    87,    23,
-      -1,    -1,    -1,    -1,    46,    42,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    33
-};
-
-  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-     symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,    17,    25,     3,    11,    26,    27,    29,     0,    18,
-      19,    17,    17,    28,    17,    28,     9,    10,     9,    12,
-       4,    27,     8,     9,    13,    18,    20,    31,    34,    35,
-      41,    42,    20,    30,    19,    18,    18,    20,    42,    21,
-       9,     9,    19,    32,    31,    19,    34,     9,    10,     9,
-      15,    19,    19,     7,     9,    33,    35,    19,    41,    14,
-      31,    32,    19,    20,     9,    16,    21,     9,    33,    41,
-      41,     9,    42,     5,     6,     9,    10,    16,    22,    36,
-      37,    38,    39,    40,    20,     9,    40,    20,    22,    23,
-      37,    40,     9
-};
-
-  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    24,    25,    25,    25,    25,    25,    25,    26,    26,
-      27,    27,    27,    27,    27,    28,    28,    28,    29,    30,
-      30,    30,    31,    32,    32,    32,    33,    33,    33,    33,
-      33,    33,    34,    34,    35,    35,    36,    36,    37,    38,
-      38,    39,    39,    39,    39,    40,    40,    41,    41,    41,
-      42,    42
-};
-
-  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     1,     3,     4,     5,     6,     7,     1,     3,
-       1,     3,     5,     3,     5,     3,     5,     7,     3,     2,
-       3,     3,     3,     2,     3,     3,     1,     3,     3,     3,
-       3,     3,     1,     3,     1,     1,     1,     1,     1,     1,
-       3,     1,     2,     3,     2,     1,     3,     1,     2,     5,
-       2,     4
-};
-
-
-#define yyerrok         (yyerrstatus = 0)
-#define yyclearin       (yychar = YYEMPTY)
-#define YYEMPTY         (-2)
-#define YYEOF           0
-
-#define YYACCEPT        goto yyacceptlab
-#define YYABORT         goto yyabortlab
-#define YYERROR         goto yyerrorlab
-
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)                                  \
-do                                                              \
-  if (yychar == YYEMPTY)                                        \
-    {                                                           \
-      yychar = (Token);                                         \
-      yylval = (Value);                                         \
-      YYPOPSTACK (yylen);                                       \
-      yystate = *yyssp;                                         \
-      goto yybackup;                                            \
-    }                                                           \
-  else                                                          \
-    {                                                           \
-      yyerror (ofwdev, YY_("syntax error: cannot back up")); \
-      YYERROR;                                                  \
-    }                                                           \
-while (0)
-
-/* Error token number */
-#define YYTERROR        1
-#define YYERRCODE       256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)                                \
-    do                                                                  \
-      if (N)                                                            \
-        {                                                               \
-          (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
-          (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
-          (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
-          (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
-        }                                                               \
-      else                                                              \
-        {                                                               \
-          (Current).first_line   = (Current).last_line   =              \
-            YYRHSLOC (Rhs, 0).last_line;                                \
-          (Current).first_column = (Current).last_column =              \
-            YYRHSLOC (Rhs, 0).last_column;                              \
-        }                                                               \
-    while (0)
-#endif
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)                        \
-do {                                            \
-  if (yydebug)                                  \
-    YYFPRINTF Args;                             \
-} while (0)
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-
-/* Print *YYLOCP on YYO.  Private, do not rely on its existence. */
-
-YY_ATTRIBUTE_UNUSED
-static unsigned
-yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
-{
-  unsigned res = 0;
-  int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
-  if (0 <= yylocp->first_line)
-    {
-      res += YYFPRINTF (yyo, "%d", yylocp->first_line);
-      if (0 <= yylocp->first_column)
-        res += YYFPRINTF (yyo, ".%d", yylocp->first_column);
-    }
-  if (0 <= yylocp->last_line)
-    {
-      if (yylocp->first_line < yylocp->last_line)
-        {
-          res += YYFPRINTF (yyo, "-%d", yylocp->last_line);
-          if (0 <= end_col)
-            res += YYFPRINTF (yyo, ".%d", end_col);
-        }
-      else if (0 <= end_col && yylocp->first_column < end_col)
-        res += YYFPRINTF (yyo, "-%d", end_col);
-    }
-  return res;
- }
-
-#  define YY_LOCATION_PRINT(File, Loc)          \
-  yy_location_print_ (File, &(Loc))
-
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
-do {                                                                      \
-  if (yydebug)                                                            \
-    {                                                                     \
-      YYFPRINTF (stderr, "%s ", Title);                                   \
-      yy_symbol_print (stderr,                                            \
-                  Type, Value, Location, ofwdev); \
-      YYFPRINTF (stderr, "\n");                                           \
-    }                                                                     \
-} while (0)
-
-
-/*----------------------------------------.
-| Print this symbol's value on YYOUTPUT.  |
-`----------------------------------------*/
-
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct ofw_dev *ofwdev)
-{
-  FILE *yyo = yyoutput;
-  YYUSE (yyo);
-  YYUSE (yylocationp);
-  YYUSE (ofwdev);
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
-  YYUSE (yytype);
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, struct ofw_dev *ofwdev)
-{
-  YYFPRINTF (yyoutput, "%s %s (",
-             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
-
-  YY_LOCATION_PRINT (yyoutput, *yylocationp);
-  YYFPRINTF (yyoutput, ": ");
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, ofwdev);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; yybottom <= yytop; yybottom++)
-    {
-      int yybot = *yybottom;
-      YYFPRINTF (stderr, " %d", yybot);
-    }
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)                            \
-do {                                                            \
-  if (yydebug)                                                  \
-    yy_stack_print ((Bottom), (Top));                           \
-} while (0)
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-static void
-yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, struct ofw_dev *ofwdev)
-{
-  unsigned long int yylno = yyrline[yyrule];
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-             yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr,
-                       yystos[yyssp[yyi + 1 - yynrhs]],
-                       &(yyvsp[(yyi + 1) - (yynrhs)])
-                       , &(yylsp[(yyi + 1) - (yynrhs)])                       , ofwdev);
-      YYFPRINTF (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)          \
-do {                                    \
-  if (yydebug)                          \
-    yy_reduce_print (yyssp, yyvsp, yylsp, Rule, ofwdev); \
-} while (0)
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-static YYSIZE_T
-yystrlen (const char *yystr)
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-        switch (*++yyp)
-          {
-          case '\'':
-          case ',':
-            goto do_not_strip_quotes;
-
-          case '\\':
-            if (*++yyp != '\\')
-              goto do_not_strip_quotes;
-            /* Fall through.  */
-          default:
-            if (yyres)
-              yyres[yyn] = *yyp;
-            yyn++;
-            break;
-
-          case '"':
-            if (yyres)
-              yyres[yyn] = '\0';
-            return yyn;
-          }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
-   about the unexpected token YYTOKEN for the state stack whose top is
-   YYSSP.
-
-   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
-   not large enough to hold the message.  In that case, also set
-   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
-   required number of bytes is too large to store.  */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
-                yytype_int16 *yyssp, int yytoken)
-{
-  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
-  YYSIZE_T yysize = yysize0;
-  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-  /* Internationalized format string. */
-  const char *yyformat = YY_NULLPTR;
-  /* Arguments of yyformat. */
-  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-  /* Number of reported tokens (one for the "unexpected", one per
-     "expected"). */
-  int yycount = 0;
-
-  /* There are many possibilities here to consider:
-     - If this state is a consistent state with a default action, then
-       the only way this function was invoked is if the default action
-       is an error action.  In that case, don't check for expected
-       tokens because there are none.
-     - The only way there can be no lookahead present (in yychar) is if
-       this state is a consistent state with a default action.  Thus,
-       detecting the absence of a lookahead is sufficient to determine
-       that there is no unexpected or expected token to report.  In that
-       case, just report a simple "syntax error".
-     - Don't assume there isn't a lookahead just because this state is a
-       consistent state with a default action.  There might have been a
-       previous inconsistent state, consistent state with a non-default
-       action, or user semantic action that manipulated yychar.
-     - Of course, the expected token list depends on states to have
-       correct lookahead information, and it depends on the parser not
-       to perform extra reductions after fetching a lookahead from the
-       scanner and before detecting a syntax error.  Thus, state merging
-       (from LALR or IELR) and default reductions corrupt the expected
-       token list.  However, the list is correct for canonical LR with
-       one exception: it will still contain any token that will not be
-       accepted due to an error action in a later state.
-  */
-  if (yytoken != YYEMPTY)
-    {
-      int yyn = yypact[*yyssp];
-      yyarg[yycount++] = yytname[yytoken];
-      if (!yypact_value_is_default (yyn))
-        {
-          /* Start YYX at -YYN if negative to avoid negative indexes in
-             YYCHECK.  In other words, skip the first -YYN actions for
-             this state because they are default actions.  */
-          int yyxbegin = yyn < 0 ? -yyn : 0;
-          /* Stay within bounds of both yycheck and yytname.  */
-          int yychecklim = YYLAST - yyn + 1;
-          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-          int yyx;
-
-          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
-                && !yytable_value_is_error (yytable[yyx + yyn]))
-              {
-                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-                  {
-                    yycount = 1;
-                    yysize = yysize0;
-                    break;
-                  }
-                yyarg[yycount++] = yytname[yyx];
-                {
-                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
-                  if (! (yysize <= yysize1
-                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                    return 2;
-                  yysize = yysize1;
-                }
-              }
-        }
-    }
-
-  switch (yycount)
-    {
-# define YYCASE_(N, S)                      \
-      case N:                               \
-        yyformat = S;                       \
-      break
-      YYCASE_(0, YY_("syntax error"));
-      YYCASE_(1, YY_("syntax error, unexpected %s"));
-      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
-      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
-      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
-      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
-    }
-
-  {
-    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
-    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-      return 2;
-    yysize = yysize1;
-  }
-
-  if (*yymsg_alloc < yysize)
-    {
-      *yymsg_alloc = 2 * yysize;
-      if (! (yysize <= *yymsg_alloc
-             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
-        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
-      return 1;
-    }
-
-  /* Avoid sprintf, as that infringes on the user's name space.
-     Don't have undefined behavior even if the translation
-     produced a string with the wrong number of "%s"s.  */
-  {
-    char *yyp = *yymsg;
-    int yyi = 0;
-    while ((*yyp = *yyformat) != '\0')
-      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
-        {
-          yyp += yytnamerr (yyp, yyarg[yyi++]);
-          yyformat += 2;
-        }
-      else
-        {
-          yyp++;
-          yyformat++;
-        }
-  }
-  return 0;
-}
-#endif /* YYERROR_VERBOSE */
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, struct ofw_dev *ofwdev)
-{
-  YYUSE (yyvaluep);
-  YYUSE (yylocationp);
-  YYUSE (ofwdev);
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  YYUSE (yytype);
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-}
-
-
-
-
-/* The lookahead symbol.  */
-int yychar;
-
-/* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval;
-/* Location data for the lookahead symbol.  */
-YYLTYPE yylloc
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-  = { 1, 1, 1, 1 }
-# endif
-;
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-int
-yyparse (struct ofw_dev *ofwdev)
-{
-    int yystate;
-    /* Number of tokens to shift before error messages enabled.  */
-    int yyerrstatus;
-
-    /* The stacks and their tools:
-       'yyss': related to states.
-       'yyvs': related to semantic values.
-       'yyls': related to locations.
-
-       Refer to the stacks through separate pointers, to allow yyoverflow
-       to reallocate them elsewhere.  */
-
-    /* The state stack.  */
-    yytype_int16 yyssa[YYINITDEPTH];
-    yytype_int16 *yyss;
-    yytype_int16 *yyssp;
-
-    /* The semantic value stack.  */
-    YYSTYPE yyvsa[YYINITDEPTH];
-    YYSTYPE *yyvs;
-    YYSTYPE *yyvsp;
-
-    /* The location stack.  */
-    YYLTYPE yylsa[YYINITDEPTH];
-    YYLTYPE *yyls;
-    YYLTYPE *yylsp;
-
-    /* The locations where the error started and ended.  */
-    YYLTYPE yyerror_range[3];
-
-    YYSIZE_T yystacksize;
-
-  int yyn;
-  int yyresult;
-  /* Lookahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-  YYLTYPE yyloc;
-
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  yyssp = yyss = yyssa;
-  yyvsp = yyvs = yyvsa;
-  yylsp = yyls = yylsa;
-  yystacksize = YYINITDEPTH;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY; /* Cause a token to be read.  */
-  yylsp[0] = yylloc;
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-        /* Give user a chance to reallocate the stack.  Use copies of
-           these so that the &'s don't force the real ones into
-           memory.  */
-        YYSTYPE *yyvs1 = yyvs;
-        yytype_int16 *yyss1 = yyss;
-        YYLTYPE *yyls1 = yyls;
-
-        /* Each stack pointer address is followed by the size of the
-           data in use in that stack, in bytes.  This used to be a
-           conditional around just the two extra args, but that might
-           be undefined if yyoverflow is a macro.  */
-        yyoverflow (YY_("memory exhausted"),
-                    &yyss1, yysize * sizeof (*yyssp),
-                    &yyvs1, yysize * sizeof (*yyvsp),
-                    &yyls1, yysize * sizeof (*yylsp),
-                    &yystacksize);
-
-        yyls = yyls1;
-        yyss = yyss1;
-        yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-        goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-        yystacksize = YYMAXDEPTH;
-
-      {
-        yytype_int16 *yyss1 = yyss;
-        union yyalloc *yyptr =
-          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-        if (! yyptr)
-          goto yyexhaustedlab;
-        YYSTACK_RELOCATE (yyss_alloc, yyss);
-        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-        YYSTACK_RELOCATE (yyls_alloc, yyls);
-#  undef YYSTACK_RELOCATE
-        if (yyss1 != yyssa)
-          YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-      yylsp = yyls + yysize - 1;
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                  (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-        YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  if (yystate == YYFINAL)
-    YYACCEPT;
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     lookahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to lookahead token.  */
-  yyn = yypact[yystate];
-  if (yypact_value_is_default (yyn))
-    goto yydefault;
-
-  /* Not known => get a lookahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = yylex ();
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yytable_value_is_error (yyn))
-        goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the lookahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token.  */
-  yychar = YYEMPTY;
-
-  yystate = yyn;
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  *++yyvsp = yylval;
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-  *++yylsp = yylloc;
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     '$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-  /* Default location.  */
-  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 2:
-#line 60 "prom_parse.y" /* yacc.c:1646  */
-    {
-			DPRINT("****rootonly: \"%s\"\n", "/");
-		}
-#line 1410 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 3:
-#line 63 "prom_parse.y" /* yacc.c:1646  */
-    {
-			DPRINT("****devpath busses:\n/%s/%s\n", (yyvsp[-1].str), (yyvsp[0].str));
-		}
-#line 1418 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 4:
-#line 66 "prom_parse.y" /* yacc.c:1646  */
-    {
-			ofwdev->dev_path = malloc(strlen((yyvsp[-2].str)) +
-                                      strlen((yyvsp[-1].str)) + 3);
-			sprintf(ofwdev->dev_path, "/%s%s", (yyvsp[-2].str), (yyvsp[-1].str));
-			DPRINT("****devpath busses bootdev "
-                   "disklabel:\n/%s/%s%s\n",
-				   (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str));
-		}
-#line 1431 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 5:
-#line 74 "prom_parse.y" /* yacc.c:1646  */
-    {
-			ofwdev->dev_path = malloc(strlen((yyvsp[-3].str)) +
-                                      strlen((yyvsp[-2].str)) + 3);
-			sprintf(ofwdev->dev_path, "/%s%s", (yyvsp[-3].str), (yyvsp[-2].str));
-			DPRINT("****busses bootdev obp_quals obp_parms:\n"
-                   "/%s/%s:%s%s\n",
-				   (yyvsp[-3].str), (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str));
-		}
-#line 1444 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 6:
-#line 82 "prom_parse.y" /* yacc.c:1646  */
-    {
-			ofwdev->dev_path = malloc(strlen((yyvsp[-4].str)) +
-                                      strlen((yyvsp[-3].str)) + 3);
-			sprintf(ofwdev->dev_path, "/%s%s", (yyvsp[-4].str), (yyvsp[-3].str));
-			DPRINT("****busses bootdev obp_quals obp_parms "
-                   "disklabel:\n/%s:%s%s%s\n", (yyvsp[-4].str), (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str));
-		}
-#line 1456 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 7:
-#line 89 "prom_parse.y" /* yacc.c:1646  */
-    {
-			DPRINT("****vdevice bootdev obp_parms "
-                   "disklabel:\n/%s:%s%s%s%s\n",
-				   (yyvsp[-5].str), (yyvsp[-3].str), (yyvsp[-2].str), (yyvsp[-1].str), (yyvsp[0].str));
-		}
-#line 1466 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 8:
-#line 96 "prom_parse.y" /* yacc.c:1646  */
-    {
-			strcpy((yyval.str), (yyvsp[0].str));
-		}
-#line 1474 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 9:
-#line 99 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s/%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1482 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 10:
-#line 104 "prom_parse.y" /* yacc.c:1646  */
-    {
-			strcpy((yyval.str), (yyvsp[0].str));
-		}
-#line 1490 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 11:
-#line 107 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s@%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1498 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 12:
-#line 110 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s@%s,%s", (yyvsp[-4].str), (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1506 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 13:
-#line 113 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s@%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1514 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 14:
-#line 116 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s,%s@%s", (yyvsp[-4].str), (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1522 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 15:
-#line 122 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "/%s", (yyvsp[-1].str));
-		}
-#line 1530 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 16:
-#line 125 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "/%s@%s", (yyvsp[-3].str), (yyvsp[-1].str));
-		}
-#line 1538 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 17:
-#line 128 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "/%s@%s,%s", (yyvsp[-5].str), (yyvsp[-3].str), (yyvsp[-1].str));
-		}
-#line 1546 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 18:
-#line 133 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s/%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1554 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 19:
-#line 138 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, ":%s", (yyvsp[0].str));
-		}
-#line 1562 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 20:
-#line 141 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s,%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1570 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 21:
-#line 144 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s,%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1578 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 22:
-#line 149 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s=%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1586 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 23:
-#line 154 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, ",%s", (yyvsp[0].str));
-		}
-#line 1594 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 24:
-#line 157 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s,%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1602 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 25:
-#line 160 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s,%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1610 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 26:
-#line 165 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
-		}
-#line 1618 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 27:
-#line 168 "prom_parse.y" /* yacc.c:1646  */
-    {
-			/* luns > 0 are the SAM-3+ hex representation. */
-			obp_parm_hexnum(ofwdev, (yyvsp[-2].str), (yyvsp[0].str));
-			snprintf((yyval.str), STR_LEN, "%s=%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1628 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 28:
-#line 173 "prom_parse.y" /* yacc.c:1646  */
-    {
-			obp_parm_addr(ofwdev, (yyvsp[-2].str), (yyvsp[0].str));
-			snprintf((yyval.str), STR_LEN, "%s=%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1637 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 29:
-#line 177 "prom_parse.y" /* yacc.c:1646  */
-    {
-			obp_parm_iqn(ofwdev, (yyvsp[-2].str), (yyvsp[0].str));
-			snprintf((yyval.str), STR_LEN, "%s=%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1646 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 30:
-#line 181 "prom_parse.y" /* yacc.c:1646  */
-    {
-			obp_parm_hexnum(ofwdev, (yyvsp[-2].str), (yyvsp[0].str));
-			snprintf((yyval.str), STR_LEN, "%s=%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1655 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 31:
-#line 185 "prom_parse.y" /* yacc.c:1646  */
-    {
-			obp_parm_str(ofwdev, (yyvsp[-2].str), (yyvsp[0].str));
-			snprintf((yyval.str), STR_LEN, "%s=%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1664 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 32:
-#line 191 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
-		}
-#line 1672 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 33:
-#line 194 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s,%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1680 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 34:
-#line 199 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s", obp_qual_set(ofwdev, (yyvsp[0].str)));
-		}
-#line 1688 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 35:
-#line 202 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
-		}
-#line 1696 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 36:
-#line 207 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
-		}
-#line 1704 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 37:
-#line 210 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
-		}
-#line 1712 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 38:
-#line 215 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
-		}
-#line 1720 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 39:
-#line 220 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
-		}
-#line 1728 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 40:
-#line 223 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s:%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1736 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 41:
-#line 228 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
-		}
-#line 1744 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 42:
-#line 231 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s::", (yyvsp[-1].str));
-		}
-#line 1752 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 43:
-#line 234 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "%s::%s", (yyvsp[-2].str), (yyvsp[0].str));
-		}
-#line 1760 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 44:
-#line 237 "prom_parse.y" /* yacc.c:1646  */
-    {
-			snprintf((yyval.str), STR_LEN, "::%s", (yyvsp[0].str));
-		}
-#line 1768 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 45:
-#line 242 "prom_parse.y" /* yacc.c:1646  */
-    {
-            snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
-        }
-#line 1776 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 46:
-#line 245 "prom_parse.y" /* yacc.c:1646  */
-    {
-            snprintf((yyval.str), STR_LEN, "%s:%s", (yyvsp[-2].str), (yyvsp[0].str));
-        }
-#line 1784 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 47:
-#line 250 "prom_parse.y" /* yacc.c:1646  */
-    {
-            snprintf((yyval.str), STR_LEN, "%s", (yyvsp[0].str));
-        }
-#line 1792 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 48:
-#line 253 "prom_parse.y" /* yacc.c:1646  */
-    {
-            snprintf((yyval.str), STR_LEN, "%s%s", (yyvsp[-1].str), (yyvsp[0].str));
-        }
-#line 1800 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 49:
-#line 256 "prom_parse.y" /* yacc.c:1646  */
-    {
-            snprintf((yyval.str), STR_LEN, "@%s,%s%s", (yyvsp[-3].str), (yyvsp[-1].str), (yyvsp[0].str));
-        }
-#line 1808 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 50:
-#line 261 "prom_parse.y" /* yacc.c:1646  */
-    {
-            snprintf((yyval.str), STR_LEN, ":%s", (yyvsp[0].str));
-        }
-#line 1816 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-  case 51:
-#line 264 "prom_parse.y" /* yacc.c:1646  */
-    {
-            snprintf((yyval.str), STR_LEN, ":%s,%s", (yyvsp[-2].str), (yyvsp[0].str));
-        }
-#line 1824 "prom_parse.tab.c" /* yacc.c:1646  */
-    break;
-
-
-#line 1828 "prom_parse.tab.c" /* yacc.c:1646  */
-      default: break;
-    }
-  /* User semantic actions sometimes alter yychar, and that requires
-     that yytoken be updated with the new translation.  We take the
-     approach of translating immediately before every use of yytoken.
-     One alternative is translating here after every semantic action,
-     but that translation would be missed if the semantic action invokes
-     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
-     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
-     incorrect destructor might then be invoked immediately.  In the
-     case of YYERROR or YYBACKUP, subsequent parser actions might lead
-     to an incorrect destructor call or verbose syntax error message
-     before the lookahead is translated.  */
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-  *++yylsp = yyloc;
-
-  /* Now 'shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*--------------------------------------.
-| yyerrlab -- here on detecting error.  |
-`--------------------------------------*/
-yyerrlab:
-  /* Make sure we have latest lookahead translation.  See comments at
-     user semantic actions for why this is necessary.  */
-  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (ofwdev, YY_("syntax error"));
-#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
-                                        yyssp, yytoken)
-      {
-        char const *yymsgp = YY_("syntax error");
-        int yysyntax_error_status;
-        yysyntax_error_status = YYSYNTAX_ERROR;
-        if (yysyntax_error_status == 0)
-          yymsgp = yymsg;
-        else if (yysyntax_error_status == 1)
-          {
-            if (yymsg != yymsgbuf)
-              YYSTACK_FREE (yymsg);
-            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
-            if (!yymsg)
-              {
-                yymsg = yymsgbuf;
-                yymsg_alloc = sizeof yymsgbuf;
-                yysyntax_error_status = 2;
-              }
-            else
-              {
-                yysyntax_error_status = YYSYNTAX_ERROR;
-                yymsgp = yymsg;
-              }
-          }
-        yyerror (ofwdev, yymsgp);
-        if (yysyntax_error_status == 2)
-          goto yyexhaustedlab;
-      }
-# undef YYSYNTAX_ERROR
-#endif
-    }
-
-  yyerror_range[1] = yylloc;
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse lookahead token after an
-         error, discard it.  */
-
-      if (yychar <= YYEOF)
-        {
-          /* Return failure if at end of input.  */
-          if (yychar == YYEOF)
-            YYABORT;
-        }
-      else
-        {
-          yydestruct ("Error: discarding",
-                      yytoken, &yylval, &yylloc, ofwdev);
-          yychar = YYEMPTY;
-        }
-    }
-
-  /* Else will try to reuse lookahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  yyerror_range[1] = yylsp[1-yylen];
-  /* Do not reclaim the symbols of the rule whose action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (!yypact_value_is_default (yyn))
-        {
-          yyn += YYTERROR;
-          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-            {
-              yyn = yytable[yyn];
-              if (0 < yyn)
-                break;
-            }
-        }
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-        YYABORT;
-
-      yyerror_range[1] = *yylsp;
-      yydestruct ("Error: popping",
-                  yystos[yystate], yyvsp, yylsp, ofwdev);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  *++yyvsp = yylval;
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-
-  yyerror_range[2] = yylloc;
-  /* Using YYLLOC is tempting, but would change the location of
-     the lookahead.  YYLOC is available though.  */
-  YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
-  *++yylsp = yyloc;
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#if !defined yyoverflow || YYERROR_VERBOSE
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (ofwdev, YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEMPTY)
-    {
-      /* Make sure we have latest lookahead translation.  See comments at
-         user semantic actions for why this is necessary.  */
-      yytoken = YYTRANSLATE (yychar);
-      yydestruct ("Cleanup: discarding lookahead",
-                  yytoken, &yylval, &yylloc, ofwdev);
-    }
-  /* Do not reclaim the symbols of the rule whose action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-                  yystos[*yyssp], yyvsp, yylsp, ofwdev);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  return yyresult;
-}
-#line 269 "prom_parse.y" /* yacc.c:1906  */
-
diff -pruN 2.1.5-1/utils/fwparam_ibft/prom_parse.tab.h 2.1.7-2/utils/fwparam_ibft/prom_parse.tab.h
--- 2.1.5-1/utils/fwparam_ibft/prom_parse.tab.h	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/prom_parse.tab.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,102 +0,0 @@
-/* A Bison parser, made by GNU Bison 3.0.4.  */
-
-/* Bison interface for Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
-
-   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 3 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, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-#ifndef YY_YY_PROM_PARSE_TAB_H_INCLUDED
-# define YY_YY_PROM_PARSE_TAB_H_INCLUDED
-/* Debug traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
-
-/* Token type.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-  enum yytokentype
-  {
-    BUSNAME = 258,
-    BOOTDEV = 259,
-    IPV4 = 260,
-    IQN = 261,
-    OBPPARM = 262,
-    OBPQUAL = 263,
-    HEX4 = 264,
-    HEX16 = 265,
-    VDEVICE = 266,
-    VDEVINST = 267,
-    VDEVDEV = 268,
-    VDEVRAW = 269,
-    CHOSEN = 270,
-    FILENAME = 271
-  };
-#endif
-
-/* Value type.  */
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-
-union YYSTYPE
-{
-#line 34 "prom_parse.y" /* yacc.c:1909  */
-
-#define	STR_LEN		16384
-		char str[STR_LEN];
-
-#line 76 "prom_parse.tab.h" /* yacc.c:1909  */
-};
-
-typedef union YYSTYPE YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-/* Location type.  */
-#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE YYLTYPE;
-struct YYLTYPE
-{
-  int first_line;
-  int first_column;
-  int last_line;
-  int last_column;
-};
-# define YYLTYPE_IS_DECLARED 1
-# define YYLTYPE_IS_TRIVIAL 1
-#endif
-
-
-extern YYSTYPE yylval;
-extern YYLTYPE yylloc;
-int yyparse (struct ofw_dev *ofwdev);
-
-#endif /* !YY_YY_PROM_PARSE_TAB_H_INCLUDED  */
diff -pruN 2.1.5-1/utils/fwparam_ibft/prom_parse.y 2.1.7-2/utils/fwparam_ibft/prom_parse.y
--- 2.1.5-1/utils/fwparam_ibft/prom_parse.y	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/fwparam_ibft/prom_parse.y	1970-01-01 00:00:00.000000000 +0000
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) IBM Corporation. 2007
- * Author: Doug Maxey <dwm@austin.ibm.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* - DEFINITION section. */
-
-%{
-	/* literal block. include lines, decls, defns. */
-//#define YYDEBUG 1
-#if YYDEBUG
-#define DPRINT(fmt,...) printf(fmt,__VA_ARGS__)
-#else
-#define DPRINT(fmt,...) do {} while(0)
-#endif
-#include "prom_parse.h"
-#include "iscsi_obp.h"
-
-
-%}
-%union {
-#define	STR_LEN		16384
-		char str[STR_LEN];
-}
-
-/* definitions. */
-%token <str> BUSNAME BOOTDEV
-%token <str> IPV4 IQN
-%token <str> OBPPARM OBPQUAL
-%token <str> HEX4 HEX16
-%token <str> VDEVICE VDEVINST VDEVDEV VDEVRAW
-%token <str> CHOSEN
-%token <str> FILENAME
-
-%type <str> devpath busses bus bootdev
-%type <str> disklabel diskpart
-%type <str> vdevice vdev_parms vdev_parm
-%type <str> obp_quals obp_qual obp_params obp_param
-%type <str> ipaddr ipv4 ipv6
-%type <str> hexpart hexseq
-
-%locations
-%parse-param {struct ofw_dev *ofwdev}
-
-%%
-
-devpath: '/'   {
-			DPRINT("****rootonly: \"%s\"\n", "/");
-		}
-	| '/' busses  bootdev  {
-			DPRINT("****devpath busses:\n/%s/%s\n", $2, $3);
-		}
-	| '/' busses  bootdev disklabel {
-			ofwdev->dev_path = malloc(strlen($<str>2) +
-                                      strlen($<str>3) + 3);
-			sprintf(ofwdev->dev_path, "/%s%s", $<str>2, $<str>3);
-			DPRINT("****devpath busses bootdev "
-                   "disklabel:\n/%s/%s%s\n",
-				   $2, $3, $4);
-		}
-	| '/' busses  bootdev obp_quals obp_params {
-			ofwdev->dev_path = malloc(strlen($<str>2) +
-                                      strlen($<str>3) + 3);
-			sprintf(ofwdev->dev_path, "/%s%s", $<str>2, $<str>3);
-			DPRINT("****busses bootdev obp_quals obp_parms:\n"
-                   "/%s/%s:%s%s\n",
-				   $2, $3, $4, $5);
-		}
-	| '/' busses  bootdev obp_quals obp_params disklabel {
-			ofwdev->dev_path = malloc(strlen($<str>2) +
-                                      strlen($<str>3) + 3);
-			sprintf(ofwdev->dev_path, "/%s%s", $<str>2, $<str>3);
-			DPRINT("****busses bootdev obp_quals obp_parms "
-                   "disklabel:\n/%s:%s%s%s\n", $2, $4, $5, $6);
-		}
-	| '/' vdevice bootdev vdev_parms obp_quals obp_params disklabel {
-			DPRINT("****vdevice bootdev obp_parms "
-                   "disklabel:\n/%s:%s%s%s%s\n",
-				   $2, $4, $5, $6, $7);
-		}
-	;
-
-busses:	   bus	{
-			strcpy($$, $1);
-		}
-	| busses '/' bus {
-			snprintf($$, STR_LEN, "%s/%s", $<str>1, $<str>3);
-		}
-	;
-
-bus:	BUSNAME {
-			strcpy($$, $1);
-		}
-	| BUSNAME '@' HEX4 {
-			snprintf($$, STR_LEN, "%s@%s", $<str>1, $<str>3);
-		}
-	| BUSNAME '@' HEX4 ',' HEX4 {
-			snprintf($$, STR_LEN, "%s@%s,%s", $<str>1, $<str>3, $<str>5);
-		}
-	| BUSNAME '@' HEX16 {
-			snprintf($$, STR_LEN, "%s@%s", $<str>1, $<str>3);
-		}
-	| BUSNAME ',' HEX4 '@' HEX16  {
-			snprintf($$, STR_LEN, "%s,%s@%s", $<str>1, $<str>3, $<str>5);
-		}
-	;
-
-
-bootdev:  '/' BOOTDEV ':' {
-			snprintf($$, STR_LEN, "/%s", $<str>2);
-		}
-	| '/' BOOTDEV '@' HEX4 ':' {
-			snprintf($$, STR_LEN, "/%s@%s", $<str>2, $<str>4);
-		}
-	| '/' BOOTDEV '@' HEX4 ',' HEX4 ':' {
-			snprintf($$, STR_LEN, "/%s@%s,%s", $<str>2, $<str>4, $<str>6);
-		}
-	;
-
-vdevice: VDEVICE '/' VDEVINST {
-			snprintf($$, STR_LEN, "%s/%s", $<str>1, $<str>3);
-		}
-	;
-
-vdev_parms: ':' vdev_parm {
-			snprintf($$, STR_LEN, ":%s", $<str>2);
-		}
-	| vdev_parms ',' vdev_parm {
-			snprintf($$, STR_LEN, "%s,%s", $<str>1, $<str>3);
-		}
-	| vdev_parms ',' VDEVRAW {
-			snprintf($$, STR_LEN, "%s,%s", $<str>1, $<str>3);
-		}
-	;
-
-vdev_parm: VDEVDEV '=' CHOSEN {
-			snprintf($$, STR_LEN, "%s=%s", $<str>1, $<str>3);
-		}
-	;
-
-obp_params: ',' obp_param	{
-			snprintf($$, STR_LEN, ",%s", $2);
-		}
-	| obp_params ',' obp_param {
-			snprintf($$, STR_LEN, "%s,%s", $<str>1, $<str>3);
-		}
-	| obp_params ',' disklabel {
-			snprintf($$, STR_LEN, "%s,%s", $<str>1, $<str>3);
-		}
-	;
-
-obp_param: HEX4 {
-			snprintf($$, STR_LEN, "%s", $1);
-		}
-	| OBPPARM '=' HEX16 {
-			/* luns > 0 are the SAM-3+ hex representation. */
-			obp_parm_hexnum(ofwdev, $<str>1, $<str>3);
-			snprintf($$, STR_LEN, "%s=%s", $<str>1, $<str>3);
-		}
-	| OBPPARM '=' ipaddr {
-			obp_parm_addr(ofwdev, $<str>1, $<str>3);
-			snprintf($$, STR_LEN, "%s=%s", $<str>1, $<str>3);
-		}
-	| OBPPARM '=' IQN {
-			obp_parm_iqn(ofwdev, $<str>1, $<str>3);
-			snprintf($$, STR_LEN, "%s=%s", $<str>1, $<str>3);
-		}
-	| OBPPARM '=' HEX4 {
-			obp_parm_hexnum(ofwdev, $<str>1, $<str>3);
-			snprintf($$, STR_LEN, "%s=%s", $<str>1, $<str>3);
-		}
-	| OBPPARM '=' FILENAME {
-			obp_parm_str(ofwdev, $<str>1, $<str>3);
-			snprintf($$, STR_LEN, "%s=%s", $<str>1, $<str>3);
-		}
-	;
-
-obp_quals: obp_qual {
-			snprintf($$, STR_LEN, "%s", $1);
-		}
-	|  obp_quals ',' obp_qual {
-			snprintf($$, STR_LEN, "%s,%s", $<str>1, $<str>3);
-		}
-	;
-
-obp_qual: OBPQUAL {
-			snprintf($$, STR_LEN, "%s", obp_qual_set(ofwdev, $<str>1));
-		}
-	| vdev_parm {
-			snprintf($$, STR_LEN, "%s", $<str>1);
-		}
-	;
-
-ipaddr: ipv4 {
-			snprintf($$, STR_LEN, "%s", $<str>1);
-		}
-	| ipv6 {
-			snprintf($$, STR_LEN, "%s", $<str>1);
-		}
-	;
-
-ipv4: IPV4 {
-			snprintf($$, STR_LEN, "%s", $1);
-		}
-	;
-
-ipv6: hexpart {
-			snprintf($$, STR_LEN, "%s", $1);
-		}
-	| hexpart ':' ipv4 {
-			snprintf($$, STR_LEN, "%s:%s", $1, $3);
-		}
-	;
-
-hexpart: hexseq {
-			snprintf($$, STR_LEN, "%s", $1);
-		}
-	| hexpart "::"	{
-			snprintf($$, STR_LEN, "%s::", $<str>1);
-		}
-	| hexpart "::" hexseq {
-			snprintf($$, STR_LEN, "%s::%s", $<str>1, $<str>3);
-		}
-	| "::" hexseq {
-			snprintf($$, STR_LEN, "::%s", $<str>2);
-		}
-	;
-
-hexseq:	HEX4 {
-            snprintf($$, STR_LEN, "%s", $1);
-        }
-    | hexseq ":" HEX4 {
-            snprintf($$, STR_LEN, "%s:%s", $<str>1, $<str>3);
-        }
-    ;
-
-disklabel:   diskpart {
-            snprintf($$, STR_LEN, "%s", $<str>1);
-        }
-    | HEX4 diskpart {
-            snprintf($$, STR_LEN, "%s%s", $<str>1, $<str>2);
-        }
-    | '@' HEX4 ',' HEX4 diskpart {
-            snprintf($$, STR_LEN, "@%s,%s%s", $<str>2, $<str>4, $<str>5);
-        }
-    ;
-
-diskpart: ':' HEX4 {
-            snprintf($$, STR_LEN, ":%s", $<str>2);
-        }
-    | ':' HEX4 ',' FILENAME {
-            snprintf($$, STR_LEN, ":%s,%s", $<str>2, $<str>4);
-        }
-    ;
-
-%%
diff -pruN 2.1.5-1/utils/.gitignore 2.1.7-2/utils/.gitignore
--- 2.1.5-1/utils/.gitignore	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/.gitignore	2022-05-06 17:37:21.000000000 +0000
@@ -1 +1,4 @@
 iscsi-iname
+50-iscsi-firmware-login.rules
+iscsi-gen-initiatorname.sh
+iscsi_fw_login.sh
diff -pruN 2.1.5-1/utils/iscsi_discovery 2.1.7-2/utils/iscsi_discovery
--- 2.1.5-1/utils/iscsi_discovery	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/iscsi_discovery	1970-01-01 00:00:00.000000000 +0000
@@ -1,195 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) Voltaire Ltd. 2006.  ALL RIGHTS RESERVED.
-#
-# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-#
-# Author: Dan Bar Dov <danb@voltaire.com>
-
-# iscsi_discovery:
-#    * does a send-targets discovery to the given IP
-#    * set the transport type to the preferred transport (or tcp is -t flag is not used)
-#    * tries to login
-#    * if succeeds,
-#          o logout,
-#          o mark record autmatic (unless -m flag is used)
-#    * else
-#          o reset transport type to TCP
-#          o try to login
-#          o if succeeded
-#                + logout
-#                + mark record automatic (unless -m flag is used)
-#
-
-usage()
-{
-	echo "Usage: $0 <IP> [-p <port>] [-d] [-t <tcp|iser> [-f]] [-m] [-l]"
-	echo "Options:"
-	echo  "-p		set the port number (default is 3260)."
-	echo  "-d		print debugging information"
-	echo  "-t		set transport (default is tcp)."
-	echo  "-f		force specific transport -disable the fallback to tcp (default is fallback enabled)."
-	echo  "			force the transport specified by the argument of the -t flag."
-	echo  "-m		manual startup - will set manual startup (default is automatic startup)."
-	echo  "-l		login to the new discovered nodes (default is false)."
-}
-
-dbg()
-{
-	$debug && echo $@
-}
-
-initialize()
-{
-	trap "exit" 2
-	debug=false
-	force="0"
-	log_out="1"
-	startup_manual="0"
-	#set default transport to tcp
-	transport=tcp
-	#set default port to 3260
-	port=3260;
-}
-
-parse_cmdline()
-{
-	if [ $# -lt 1 ]; then
-		usage
-		exit 1
-	fi
-
-	# check if the IP address is valid
-	ip=`echo $1 | awk -F'.' '$1 != "" && $1 <=255 && $2 != "" && $2 <= 255 && $3 != "" && $3 <= 255 && $4 != "" && $4 <= 255 {print $0}'`
-	if [ -z "$ip" ]; then
-		echo "$1 is not a vaild IP address!"
-		exit 1
-	fi
-	shift
-	while getopts "dfmlt:p:" options; do
-	 case $options in
-		d ) debug=true;;
-		f ) force="1";;
-		t ) transport=$OPTARG;;
-		p ) port=$OPTARG;;
-		m ) startup_manual="1";;
-		l ) log_out=0;;
-		\? ) usage
-			exit 1;;
-		* )  usage
-			exit 1;;
-	 esac
-	done
-}
-
-discover()
-{
-	# If open-iscsi is already logged in to the portal, exit
-	if [ $(iscsiadm -m session | grep -c ${ip}:${port}) -ne 0 ]; then
-		echo "Please logout from all targets on ${ip}:${port} before trying to run discovery on that portal"
-		exit 2
-	fi
-
-	connected=0
-	discovered=0
-
-	dbg "starting discovery to $ip"
-	disc="$(iscsiadm -m discovery --type sendtargets --portal ${ip}:${port})"
-	echo "${disc}" | while read portal target
-	do
-		portal=${portal%,*}
-		select_transport
-	done
-
-	discovered=$(echo "${disc}" | wc -l)
-	if [ ${discovered} = 0 ]; then
-		echo "failed to discover targets at ${ip}"
-		exit 2
-	else
-		echo "discovered ${discovered} targets at ${ip}"
-	fi
-}
-
-try_login()
-{
-	if [ "$startup_manual" != "1" ]; then
-		iscsiadm -m node --targetname ${target} --portal ${portal} --op update -n node.conn[0].startup -v automatic
-	fi
-	iscsiadm -m node --targetname ${target} --portal ${portal} --login >/dev/null 2>&1
-	ret=$?
-	if [ ${ret} = 0 ]; then
-		echo "Set target ${target} to automatic login over ${transport} to portal ${portal}"
-		((connected++))
-		if [ "$log_out" = "1" ]; then
-			iscsiadm -m node --targetname ${target} --portal ${portal} --logout
-		fi
-	else
-		echo "Cannot login over ${transport} to portal ${portal}"
-		iscsiadm -m node --targetname ${target} --portal ${portal} --op update -n node.conn[0].startup -v manual
-	fi
-	return ${ret}
-}
-
-set_transport()
-{
-	transport=$1
-	case "$transport" in
-	iser)
-		# iSER does not use digest
-		iscsiadm -m node --targetname ${target} --portal ${portal} \
-			--op update -n node.conn[0].iscsi.HeaderDigest -v None
-		iscsiadm -m node --targetname ${target} --portal ${portal} \
-			--op update -n node.conn[0].iscsi.DataDigest -v None
-		;;
-	cxgb3i)
-		# cxgb3i supports <= 16K packet (BHS + AHS + pdu payload + digests)
-		iscsiadm -m node --targetname ${target} --portal ${portal} \
-			--op update -n node.conn[0].iscsi.MaxRecvDataSegmentLength \
-			-v 8192
-		;;
-	esac
-	transport_name=`iscsiadm  -m node -p ${portal} -T ${target} |awk '/transport_name/ {print $1}'`
-	iscsiadm -m node --targetname ${target} --portal ${portal} \
-			--op update -n ${transport_name} -v ${transport}
-}
-
-select_transport()
-{
-	set_transport $transport
-	dbg "Testing $transport-login to target ${target} portal ${portal}"
-	try_login;
-	if [ $? != 0 -a  "$force" = "0" ]; then
-		set_transport tcp
-		dbg "starting to test tcp-login to target ${target} portal ${portal}"
-		try_login;
-	fi
-}
-
-check_iscsid()
-{
-	#check if iscsid is running
-	pidof iscsid &>/dev/null
-	ret=$?
-	if [ $ret -ne 0 ]; then
-		echo "iscsid is not running"
-		echo "Exiting..."
-		exit 1
-	fi
-}
-
-check_iscsid
-initialize
-parse_cmdline "$@"
-discover
diff -pruN 2.1.5-1/utils/iscsi_discovery.sh 2.1.7-2/utils/iscsi_discovery.sh
--- 2.1.5-1/utils/iscsi_discovery.sh	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/utils/iscsi_discovery.sh	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,195 @@
+#!/bin/bash
+#
+# Copyright (C) Voltaire Ltd. 2006.  ALL RIGHTS RESERVED.
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+# Author: Dan Bar Dov <danb@voltaire.com>
+
+# iscsi_discovery:
+#    * does a send-targets discovery to the given IP
+#    * set the transport type to the preferred transport (or tcp is -t flag is not used)
+#    * tries to login
+#    * if succeeds,
+#          o logout,
+#          o mark record autmatic (unless -m flag is used)
+#    * else
+#          o reset transport type to TCP
+#          o try to login
+#          o if succeeded
+#                + logout
+#                + mark record automatic (unless -m flag is used)
+#
+
+usage()
+{
+	echo "Usage: $0 <IP> [-p <port>] [-d] [-t <tcp|iser> [-f]] [-m] [-l]"
+	echo "Options:"
+	echo  "-p		set the port number (default is 3260)."
+	echo  "-d		print debugging information"
+	echo  "-t		set transport (default is tcp)."
+	echo  "-f		force specific transport -disable the fallback to tcp (default is fallback enabled)."
+	echo  "			force the transport specified by the argument of the -t flag."
+	echo  "-m		manual startup - will set manual startup (default is automatic startup)."
+	echo  "-l		login to the new discovered nodes (default is false)."
+}
+
+dbg()
+{
+	$debug && echo $@
+}
+
+initialize()
+{
+	trap "exit" 2
+	debug=false
+	force="0"
+	log_out="1"
+	startup_manual="0"
+	#set default transport to tcp
+	transport=tcp
+	#set default port to 3260
+	port=3260;
+}
+
+parse_cmdline()
+{
+	if [ $# -lt 1 ]; then
+		usage
+		exit 1
+	fi
+
+	# check if the IP address is valid
+	ip=`echo $1 | awk -F'.' '$1 != "" && $1 <=255 && $2 != "" && $2 <= 255 && $3 != "" && $3 <= 255 && $4 != "" && $4 <= 255 {print $0}'`
+	if [ -z "$ip" ]; then
+		echo "$1 is not a vaild IP address!"
+		exit 1
+	fi
+	shift
+	while getopts "dfmlt:p:" options; do
+	 case $options in
+		d ) debug=true;;
+		f ) force="1";;
+		t ) transport=$OPTARG;;
+		p ) port=$OPTARG;;
+		m ) startup_manual="1";;
+		l ) log_out=0;;
+		\? ) usage
+			exit 1;;
+		* )  usage
+			exit 1;;
+	 esac
+	done
+}
+
+discover()
+{
+	# If open-iscsi is already logged in to the portal, exit
+	if [ $(iscsiadm -m session | grep -c ${ip}:${port}) -ne 0 ]; then
+		echo "Please logout from all targets on ${ip}:${port} before trying to run discovery on that portal"
+		exit 2
+	fi
+
+	connected=0
+	discovered=0
+
+	dbg "starting discovery to $ip"
+	disc="$(iscsiadm -m discovery --type sendtargets --portal ${ip}:${port})"
+	echo "${disc}" | while read portal target
+	do
+		portal=${portal%,*}
+		select_transport
+	done
+
+	discovered=$(echo "${disc}" | wc -l)
+	if [ ${discovered} = 0 ]; then
+		echo "failed to discover targets at ${ip}"
+		exit 2
+	else
+		echo "discovered ${discovered} targets at ${ip}"
+	fi
+}
+
+try_login()
+{
+	if [ "$startup_manual" != "1" ]; then
+		iscsiadm -m node --targetname ${target} --portal ${portal} --op update -n node.conn[0].startup -v automatic
+	fi
+	iscsiadm -m node --targetname ${target} --portal ${portal} --login >/dev/null 2>&1
+	ret=$?
+	if [ ${ret} = 0 ]; then
+		echo "Set target ${target} to automatic login over ${transport} to portal ${portal}"
+		((connected++))
+		if [ "$log_out" = "1" ]; then
+			iscsiadm -m node --targetname ${target} --portal ${portal} --logout
+		fi
+	else
+		echo "Cannot login over ${transport} to portal ${portal}"
+		iscsiadm -m node --targetname ${target} --portal ${portal} --op update -n node.conn[0].startup -v manual
+	fi
+	return ${ret}
+}
+
+set_transport()
+{
+	transport=$1
+	case "$transport" in
+	iser)
+		# iSER does not use digest
+		iscsiadm -m node --targetname ${target} --portal ${portal} \
+			--op update -n node.conn[0].iscsi.HeaderDigest -v None
+		iscsiadm -m node --targetname ${target} --portal ${portal} \
+			--op update -n node.conn[0].iscsi.DataDigest -v None
+		;;
+	cxgb3i)
+		# cxgb3i supports <= 16K packet (BHS + AHS + pdu payload + digests)
+		iscsiadm -m node --targetname ${target} --portal ${portal} \
+			--op update -n node.conn[0].iscsi.MaxRecvDataSegmentLength \
+			-v 8192
+		;;
+	esac
+	transport_name=`iscsiadm  -m node -p ${portal} -T ${target} |awk '/transport_name/ {print $1}'`
+	iscsiadm -m node --targetname ${target} --portal ${portal} \
+			--op update -n ${transport_name} -v ${transport}
+}
+
+select_transport()
+{
+	set_transport $transport
+	dbg "Testing $transport-login to target ${target} portal ${portal}"
+	try_login;
+	if [ $? != 0 -a  "$force" = "0" ]; then
+		set_transport tcp
+		dbg "starting to test tcp-login to target ${target} portal ${portal}"
+		try_login;
+	fi
+}
+
+check_iscsid()
+{
+	#check if iscsid is running
+	pidof iscsid &>/dev/null
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		echo "iscsid is not running"
+		echo "Exiting..."
+		exit 1
+	fi
+}
+
+check_iscsid
+initialize
+parse_cmdline "$@"
+discover
diff -pruN 2.1.5-1/utils/iscsi_fw_login 2.1.7-2/utils/iscsi_fw_login
--- 2.1.5-1/utils/iscsi_fw_login	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/iscsi_fw_login	1970-01-01 00:00:00.000000000 +0000
@@ -1,12 +0,0 @@
-#!/bin/bash
-#
-# iscsi_fw_login -- login to iscsi firmware targets, if any
-#
-# This script is called when udev discovers a new iscsi
-# firmware target
-#
-
-ARGS="-m fw -l"
-ISCSIADM="/sbin/iscsiadm"
-
-$ISCSIADM $ARGS
diff -pruN 2.1.5-1/utils/iscsi_fw_login.sh.template 2.1.7-2/utils/iscsi_fw_login.sh.template
--- 2.1.5-1/utils/iscsi_fw_login.sh.template	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/utils/iscsi_fw_login.sh.template	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+# iscsi_fw_login -- login to iscsi firmware targets, if any
+#
+# This script is called when udev discovers a new iscsi
+# firmware target
+#
+
+ARGS="-m fw -l"
+ISCSIADM="@SBINDIR@/iscsiadm"
+
+$ISCSIADM $ARGS
diff -pruN 2.1.5-1/utils/iscsi-gen-initiatorname 2.1.7-2/utils/iscsi-gen-initiatorname
--- 2.1.5-1/utils/iscsi-gen-initiatorname	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/iscsi-gen-initiatorname	1970-01-01 00:00:00.000000000 +0000
@@ -1,73 +0,0 @@
-#!/bin/bash
-#
-# /sbin/iscsi-gen-initiatorname
-#
-# Generate a default iSCSI Initiatorname for SUSE installations.
-#
-# Copyright (c) 2011 Hannes Reinecke, SUSE Labs
-# This script is licensed under the GPL.
-#
-
-if [ "$1" ] ; then
-    if [ "$1" = "-f" ] ; then
-	FORCE=1
-    else
-	echo "Invalid option $1"
-	echo "Usage: $0 [-f]"
-	exit 1
-    fi
-fi
-
-if [ -d /sys/firmware/ibft/initiator ] ; then
-    read iSCSI_INITIATOR_NAME < /sys/firmware/ibft/initiator/initiator-name
-fi
-
-if [ -f /etc/iscsi/initiatorname.iscsi -a -z "$FORCE" ] ; then
-    if [ "$iSCSI_INITIATOR_NAME" ] ; then
-	eval $(cat /etc/iscsi/initiatorname.iscsi | sed -e '/^#/d')
-	if [ "$iSCSI_INITIATOR_NAME" != "$InitiatorName" ] ; then
-	    echo "iSCSI Initiatorname from iBFT is different from the current setting."
-	    echo "Please call '/sbin/iscsi-gen-initiatorname -f' to update the iSCSI Initiatorname."
-	    exit 1
-	fi
-    fi
-fi
-
-if [ "$iSCSI_INITIATOR_NAME" ] ; then
-    cat << EOF >> /etc/iscsi/initiatorname.iscsi
-##
-## /etc/iscsi/iscsi.initiatorname
-##
-## iSCSI Initiatorname taken from iBFT BIOS tables.
-##
-## DO NOT EDIT OR REMOVE THIS FILE! 
-## If you remove this file, the iSCSI daemon will not start.
-## Any change here will not be reflected to the iBFT BIOS tables.
-## If a different initiatorname is required please change the 
-## initiatorname in the BIOS setup and call
-## /sbin/iscsi-gen-initiatorname -f
-## to recreate an updated version of this file.
-##
-InitiatorName=$iSCSI_INITIATOR_NAME
-EOF
-fi
-
-if [ ! -f /etc/iscsi/initiatorname.iscsi ] ; then
-    cat << EOF >> /etc/iscsi/initiatorname.iscsi
-##
-## /etc/iscsi/iscsi.initiatorname
-##
-## Default iSCSI Initiatorname.
-##
-## DO NOT EDIT OR REMOVE THIS FILE! 
-## If you remove this file, the iSCSI daemon will not start.
-## If you change the InitiatorName, existing access control lists
-## may reject this initiator.  The InitiatorName must be unique
-## for each iSCSI initiator.  Do NOT duplicate iSCSI InitiatorNames.
-EOF
-	ISSUEDATE="1996-04"
-	INAME=$(/sbin/iscsi-iname -p iqn.$ISSUEDATE.de.suse:01)
-	printf "InitiatorName=$INAME\n"  >>/etc/iscsi/initiatorname.iscsi
-	chmod 0600 /etc/iscsi/initiatorname.iscsi
-fi
-
diff -pruN 2.1.5-1/utils/iscsi-gen-initiatorname.sh.template 2.1.7-2/utils/iscsi-gen-initiatorname.sh.template
--- 2.1.5-1/utils/iscsi-gen-initiatorname.sh.template	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/utils/iscsi-gen-initiatorname.sh.template	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,188 @@
+#!/bin/bash
+#
+# iscsi-gen-initiatorname
+#
+# Generate a default iSCSI Initiatorname for Linux installations.
+#
+# Copyright (c) 2022 Hannes Reinecke, SUSE Labs
+# This script is licensed under the GPL.
+#
+# external programs required:
+#   * iscsi-iname (if needed to generate a new InitiatorName)
+#
+
+NAME=${0##*/}
+INAME_DIR="@HOMEDIR@"
+INAME_FILE="$INAME_DIR/initiatorname.iscsi"
+
+# our default IQN prefix
+DEFAULT_IQN_PREFIX="iqn.1996-04.de.suse:01"
+
+#
+# set up comments for initiatorname files using variables
+# instead of HERE documents, since we may be running when
+# temp filename space is read-only
+#
+
+KERNEL_COMMENTS="\
+##
+## iSCSI Initiatorname taken from Kernel Command line.
+##
+## DO NOT EDIT OR REMOVE THIS FILE!
+## If you remove this file, the iSCSI daemon will not start.
+## Any change here may be overwritten at next boot, if
+## the kernel command-line parameter is passed in, again.
+## If a different initiatorname is required please change the
+## initiatorname on the kernel command line and call:
+##   # iscsi-gen-initiatorname -f
+## to recreate an updated version of this file.
+##"
+
+IBFT_COMMENTS="\
+##
+## iSCSI Initiatorname taken from iBFT BIOS tables.
+##
+## DO NOT EDIT OR REMOVE THIS FILE!
+## If you remove this file, the iSCSI daemon will not start.
+## Any change here will not be reflected to the iBFT BIOS tables.
+## If a different initiatorname is required please change the
+## initiatorname in the BIOS setup and call:
+##   # iscsi-gen-initiatorname -f
+## to recreate an updated version of this file.
+##"
+
+NORMAL_COMMENTS="\
+##
+## Default iSCSI Initiatorname.
+##
+## DO NOT EDIT OR REMOVE THIS FILE!
+## If you remove this file, the iSCSI daemon will not start.
+## If you change the InitiatorName, existing access control lists
+## may reject this initiator. The InitiatorName must be unique
+## for each iSCSI initiator. Do NOT duplicate iSCSI InitiatorNames."
+
+# where iBFT initiator name file would live, if present
+IBFT_SYSFS_DIR=/sys/firmware/ibft/initiator
+
+#
+# print usage and exit
+#
+# usage: usage_and_exit EXIT_VALUE
+#
+usage_and_exit()
+{
+    xit_val=$1
+
+    echo "Usage: $NAME [OPTIONS] -- generate an iSCSI initiatorname"
+    echo "Where OPTIONS are from:"
+    echo "   -h          print usage and exit"
+    echo "   -f          overwrite existing InitiatorName, if any"
+    echo "   -p IQN-PRE  set prefix for generated IQN (default ${DEFAULT_IQN_PREFIX})"
+    exit $xit_val
+}
+
+#
+# get kernel command-line-supplied initiatorname, if any
+#
+# usage: INAME=$(kernel_supplied_initiatorname)
+#
+kernel_supplied_initiatorname()
+{
+    kcl="$(</proc/cmdline)"
+    if [[ "$kcl" =~ rd.initiatorname ]] ; then
+	kcl=${kcl##*rd.initiatorname=}
+	echo ${kcl%% *}
+    else
+	echo ""
+    fi
+}
+
+#
+# start
+#
+
+while getopts "hfp:" o ; do
+    case "${o}" in
+	h) usage_and_exit 0 ;;
+	f) FORCE=1 ;;
+	p) IQN_PREFIX=${OPTARG} ;;
+	?) usage_and_exit 1 ;;
+    esac
+done
+shift $(($OPTIND-1))
+
+if [ "$#" -gt 0 ] ; then
+    echo "Error: Invalid argument(s): $*" 1>&2
+    usage_and_exit 1
+fi
+
+if [ "$EUID" -ne 0 ] ; then
+    echo "Error: You must be root to run this command" 1>&2
+    usage_and_exit 1
+fi
+
+# use prefix passed in, if any, else our default
+: ${IQN_PREFIX:=${DEFAULT_IQN_PREFIX}}
+
+# get kernel command-line-supplied initiator name, if any
+KERNEL_INAME="$(kernel_supplied_initiatorname)"
+
+# get the iBFT initiator name, if present
+[ -d $IBFT_SYSFS_DIR ] && read IBFT_INAME < $IBFT_SYSFS_DIR/initiator-name
+
+# get the systemd-supplied initiator name, if present (as InitiatorName)
+[ -r "$INAME_FILE" ] && . "$INAME_FILE"
+
+# if we have a local initiator name and "force" is not set end it now
+if [ "$InitiatorName" -a -z "$FORCE" ] ; then
+    echo "Error: you cannot overwrite the current InitiatorName unless 'force' is set." 1>&2
+    usage_and_exit 1
+fi
+
+# ensure we can write the initiator name file
+if [ -r "$INAME_FILE" ] ; then
+    if [ ! -w "$INAME_FILE" ] ; then
+	echo "Error: cannot update InitiatorName, write protected: $INAME_FILE" 1>&1
+	echo "Please ensure the filesystem is read/write." 1>&2
+	exit 1
+    fi
+    # the file exists but we can write over it
+elif [ ! -w "$INAME_DIR" ] ; then
+    echo "Error: no write permission in directory: $INAME_DIR" 1>&2
+    echo "Please ensure the filesystem is read/write." 1>&2
+    exit 1
+fi
+
+# if we have both iBFT and kernel command line initiator names that
+# do not match end it now
+if [ "$IBFT_INAME" -a "$KERNEL_INAME" -a "$IBFT_INAME" != "$KERNEL_INAME" ] ; then
+    echo "Error: Kernel cmdline Initiator Name: $KERNEL_INAME" 1>&2
+    echo "  does not match iBFT Initiator Name: $IBFT_INAME" 1>&2
+    echo "Please ensure they both match, or remove the kernel parameter, then" 1>&2
+    echo "  run '$NAME [-f]' to update iSCSI InitiatorName" 1>&2
+    exit 1
+fi
+
+# now we know we want to write the initiator name
+
+# handle a write failure on this first write attempt to the initiator name
+# file, in *case* it we somehow missed that it is not writable
+echo "##" > $INAME_FILE || exit 1
+
+if [ "$KERNEL_INAME" ] ; then
+    echo "## $INAME_FILE" >> $INAME_FILE
+    echo "$KERNEL_COMMENTS" >> $INAME_FILE
+    echo "InitiatorName=$KERNEL_INAME" >> $INAME_FILE
+elif [ "$IBFT_INAME" ] ; then
+    echo "## $INAME_FILE" >> $INAME_FILE
+    echo "$IBFT_COMMENTS" >> $INAME_FILE
+    echo "InitiatorName=$IBFT_INAME" >> $INAME_FILE
+else
+    echo "## $INAME_FILE" >> $INAME_FILE
+    echo "$NORMAL_COMMENTS" >> $INAME_FILE
+    # create a unique initiator name using iscsi-iname
+    INAME=$(@SBINDIR@/iscsi-iname -p "$IQN_PREFIX")
+    echo "InitiatorName=$INAME" >> $INAME_FILE
+fi
+
+chmod 0600 $INAME_FILE
diff -pruN 2.1.5-1/utils/iscsi_offload 2.1.7-2/utils/iscsi_offload
--- 2.1.5-1/utils/iscsi_offload	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/iscsi_offload	1970-01-01 00:00:00.000000000 +0000
@@ -1,384 +0,0 @@
-#!/bin/bash
-#
-# iscsi_offload
-#
-# Configure iSCSI offload engines for use with open-iscsi
-# Usage:
-#    iscsi_offload [-d | -f | -i <ipaddr> | -t ] <nic>
-#
-# Copyright (c) 2011 Hannes Reinecke, SUSE Labs
-# This script is licensed under the GPL.
-#
-# The script creates an open-iscsi interface definition
-# in the style <nic>-<module>, where <nic> matches the
-# network interface passed on the commandline.
-# If '-t' (test mode) is passed as an option, the script
-# will not create nor modify any setting but just print
-# the currently active ones.
-#
-# Currently the script works with Broadcom (bnx2i) and
-# Chelsio T3 (cxgbi) iSCSI offload engines.
-# Should work with Chelsio T4, but has not been tested.
-# ServerEngines (be2iscsi) and QLogic (qla4xxx) can only
-# be configured via BIOS, open-iscsi support is still in
-# development.
-#
-
-#
-# Return codes:
-#    0: Success
-#    1: Invalid command line parameter
-#    2: iSCSI offloading not supported
-#    3: Error during module loading
-#    4: Cannot configure interface via iscsiadm, use BIOS setup
-#    5: internal error running iscsiadm
-#
-# Output:
-#    <mac> [none|dhcp|ip <ipaddr>|ibft]
-# where
-#    <mac>: MAC Address of the iSCSI offload engine
-#    none:  No IP configuration set for the iSCSI offload engine
-#    dhcp:  iSCSI offload engine configured for DHCP
-#    ip:    iSCSI offload engine configured with static IP address <ipaddr>
-#    ibft:  iSCSI offload engine configured from iBFT values
-#
-
-#
-# Figure out the MAC address of the iSCSI offload engine
-# corresponding to a NIC from a given PCI device.
-# bnx2 is using one PCI device per port for both network and iSCSI offloading
-# cxgb3 is using one PCI device for everything.
-#
-iscsi_macaddress_from_pcidevice()
-{
-    local path=$1
-    local if=$2
-    local h
-    local host
-
-    for h in $path/host* ; do
-	if [ -d "$h" ] ; then
-	    host=${h##*/}
-	    read netdev < /sys/class/iscsi_host/$host/netdev
-	    if [ "$netdev" = "$IFNAME" ] ; then
-		read mac < /sys/class/iscsi_host/$host/hwaddress
-		if [ "$mac" != "00:00:00:00:00:00" ] ; then
-		    echo "$mac"
-		fi
-		break;
-	    fi
-	fi
-    done
-}
-
-#
-# Figure out the MAC address of the iSCSI offload engine
-# corresponding to a NIC from a given PCI function.
-# It is assumed that the MAC address of the iSCSI offload
-# engine is equal of the MAC address of the NIC plus one.
-# Suitable for be2iscsi and qla4xxx
-#
-iscsi_macaddress_from_pcifn()
-{
-    local path=$1
-    local if=$2
-    local h
-    local host
-    local ifmac
-    local olemacoffset=$3
-
-    ifmac=$(ip addr show dev $if | sed -n 's/ *link\/ether \(.*\) brd.*/\1/p')
-    m5=$(( 0x${ifmac##*:} ))
-    m5=$(( $m5 + $olemacoffset ))
-    ifmac=$(printf "%s:%02x" ${ifmac%:*} $m5)
-    for host in /sys/class/iscsi_host/host* ; do
-	if [ -L "$host" ] ; then
-	    read mac < $host/hwaddress
-	    if [ "$mac" = "$ifmac" ] ; then
-		echo "$mac"
-		break;
-	    fi
-	fi
-    done
-}
-
-update_iface_setting() {
-    local iface="$1"
-    local name="$2"
-    local value="$3"
-
-    iface_value=$(iscsiadm -m iface -I $iface | sed -n "s/$name = \(.*\)/\1/p")
-    if [ "$iface_value" = "<empty>" ] ; then
-	iface_value=
-    fi
-    if [ "$iface_value" != "$value" ] ; then
-	if ! iscsiadm -m iface -I $iface -o update -n "$name" -v "$value" ; then
-	    return 1
-	fi
-    fi
-    return 0
-}
-
-while getopts di:t options ; do
-    case $options in
-	d ) mode=dhcp;;
-	i ) mode=static
-	    optaddr=$OPTARG
-	    ;;
-	f ) mode=firmware;;
-	t ) dry_run=1;;
-	?)  printf "Usage: %s [-d|-t|-i ipaddr|-f] ifname\n" $0
-	    exit 1;;
-    esac
-done
-shift $(($OPTIND - 1))
-
-IFNAME=$1
-ibft_mode="none"
-
-if [ -z "$IFNAME" ] ; then
-    echo "No interface specified"
-    exit 1
-fi
-
-if [ "$dry_run" ] ; then
-    if [ "$mode" = "dhcp" ] ; then
-	echo "'-t' specified, ignoring '-d'"
-	mode=
-    elif [ "$mode" = "static" ] ; then
-	echo "'-t' specified, ignoring '-s'"
-	mode=
-    fi
-fi
-
-if [ ! -L /sys/class/net/$IFNAME ] ; then
-    echo "Interface $IFNAME not found"
-    exit 1
-fi
-
-if [ "$optaddr" ] && ! ip route get $optaddr ; then
-    echo "Invalid IP address $optaddr"
-    exit 1
-fi
-if [ "$dry_run" ] ; then
-    mode=
-fi
-
-
-ifpath=$(cd -P /sys/class/net/$IFNAME; echo $PWD)
-pcipath=$(cd -P $ifpath/device; echo $PWD)
-
-if [ -d $pcipath ] ; then
-    drvlink=$(readlink $pcipath/driver)
-    driver=${drvlink##*/}
-fi
-
-if [ -z "$driver" ] ; then
-    echo "No driver found for interface $IFNAME"
-    exit 1
-fi
-
-case "$driver" in
-    bnx2*)
-	mod=bnx2i
-	;;
-    cxgb*)
-	mod=cxgb3i
-	;;
-    be2*)
-	mod=be2iscsi
-	;;
-    qla*)
-	mod=qla4xxx
-	;;
-    qed*)
-	mod=qedi
-	;;
-esac
-
-if [ -z "$mod" ] ; then
-    echo "iSCSI offloading not supported on interface $IFNAME"
-    exit 2
-fi
-
-# Check if the required modules are already loaded
-loaded=$(sed -n "/^$mod/p" /proc/modules)
-if [ -z "$loaded" ] ; then
-    modprobe $mod
-fi
-
-loaded=$(sed -n "/^$mod/p" /proc/modules)
-if [ -z "$loaded" ] ; then
-    echo "Loading of $mod.ko failed, please check dmesg"
-    exit 3
-fi
-
-# Get the correct MAC address for the various devices
-if [ "$mod" = "bnx2i" ] ; then
-    mac=$(iscsi_macaddress_from_pcidevice $pcipath $IFNAME)
-elif [ "$mod" = "cxgb3i" ] ; then
-    mac=$(iscsi_macaddress_from_pcidevice $pcipath $IFNAME)
-elif [ "$mod" = "be2iscsi" ] ; then
-    mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME 1)
-elif [ "$mod" = "qla4xxx" ] ; then
-    mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME 1)
-elif [ "$mod" = "qede" -o "$mod" = "qedi" ] ; then
-    mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME 4)
-fi
-
-if [ -z "$mac" ] ; then
-    echo "iSCSI offloading not supported on interface $IFNAME"
-    exit 2
-fi
-
-gen_iface="$mod.$mac"
-ioe_iface="${IFNAME}-${mod}"
-
-# Get existing settings
-if iscsiadm -m iface -I $ioe_iface > /dev/null 2>&1 ; then
-    ioe_mac=$(iscsiadm -m iface -I $ioe_iface 2> /dev/null| sed -n "s/iface\.hwaddress = \(.*\)/\1/p")
-    ioe_mod=$(iscsiadm -m iface -I $ioe_iface 2> /dev/null| sed -n "s/iface\.transport_name = \(.*\)/\1/p")
-    ipaddr=$(iscsiadm -m iface -I $ioe_iface 2> /dev/null| sed -n "s/iface\.ipaddress = \(.*\)/\1/p")
-    if [ "$ipaddr" == "<empty>" ] ; then
-	ipaddr=
-    fi
-elif [ "$mod" = "be2iscsi" ] ; then
-    ioe_mac=$mac
-    ioe_mod=$mod
-else
-    # Create new interface
-    iscsiadm -m iface -I $ioe_iface --op=new 2> /dev/null
-    ioe_mac=
-    ioe_mod=
-    ipaddr=
-fi
-
-if [ -z "$dry_run" ] ; then
-    if [ "$ioe_mac" != "$mac" ] ; then
-	if [ -n "$ioe_mac" ] ; then
-	    echo "Warning: Updating MAC address on iface $ioe_iface"
-	fi
-	update_iface_setting $ioe_iface iface.hwaddress "$mac"
-    fi
-
-    if [ "$ioe_mod" != "$mod" ] ; then
-	if [ -n "$ioe_mod" ] ; then
-	    echo "Warning: Update transport on iface $ioe_iface"
-	fi
-	update_iface_setting $ioe_iface iface.transport_name "$mod"
-    fi
-elif [ -z "$ipaddr" ] ; then
-    ipaddr=$(iscsiadm -m iface -I $gen_iface 2> /dev/null| sed -n "s/iface\.ipaddress = \(.*\)/\1/p")
-    if [ "$ipaddr" = "<empty>" ] ; then
-	ipaddr=
-    fi
-elif [ "$ioe_mod" != "$mod" ] ; then
-    echo "Warning: Transport mismatch on iface $ioe_iface: $ioe_mod should be $mod"
-fi
-
-# Check iBFT setting
-for d in /sys/firmware/* ; do
-    [ -d $d ] || continue
-    [ -d $d/ethernet0 ] || continue
-    iboot_dir=$d
-done
-if [ -n "$iboot_dir" ] && [ -d "$iboot_dir" ] ; then
-    for if in ${iboot_dir}/ethernet* ; do
-	read ibft_mac < $if/mac
-	[ "$ibft_mac" = "$mac" ] || continue
-	ibft_origin=0
-	[ -f ${if}/origin ] && read ibft_origin < $if/origin
-	if [ "$ibft_origin" -eq 1 ] ; then
-	    ibft_mode="static"
-	elif [ "$ibft_origin" -eq 3 ] ; then
-	    ibft_mode="dhcp"
-	fi
-	[ -f $if/dhcp ] && read ibft_dhcp < $if/dhcp
-	if [ -n "$ibft_dhcp" -a "$ibft_mode" != "dhcp" ] ; then
-	    ibft_mode=dhcp
-	fi
-	if [ "$ibft_mode" = "dhcp" ] ; then
-	    ibft_ipaddr="0.0.0.0"
-	    ibft_gateway=
-	    ibft_mask=
-	    break
-	fi
-	[ -f $if/ip-addr ] && read ibft_ipaddr < $if/ip-addr
-	[ -f $if/gateway ] && read ibft_gateway < $if/gateway
-	[ -f $if/subnet-mask ] && read ibft_mask < $if/subnet-mask
-	break
-    done
-fi
-
-if [ -z "$optaddr" ] && [ "$ibft_ipaddr" ] ; then
-    optaddr=$ibft_ipaddr
-fi
-
-# Check if the interface needs to be configured
-if [ -z "$mode" ] ; then
-    if [ "$ibft_mode" != "none" ] ; then
-	echo "$mac ibft"
-	mode="ibft"
-    elif [ -z "$ipaddr" ] ; then
-	echo "$mac none"
-	mode="none"
-    elif [ "$ipaddr" = "0.0.0.0" ] ; then
-	echo "$mac dhcp"
-	ipaddr=
-	mode="dhcp"
-    else
-	echo "$mac ip $ipaddr"
-	mode="static"
-    fi
-    [ "$dry_run" ] && exit 0
-elif [ "$mode" = "dhcp" ] ; then
-    if [ "$ipaddr" = "0.0.0.0" ] ; then
-	echo "$mac dhcp"
-	exit 0
-    fi
-    optaddr="0.0.0.0"
-elif [ "$mode" = "static" ] && [ "$ipaddr" = "$optaddr" ] ; then
-    echo "$mac ip $ipaddr"
-    exit 0
-fi
-
-if [ "$mod" = "be2iscsi" ] ; then
-    exit 4
-fi
-
-if ! update_iface_setting $ioe_iface iface.ipaddress "$optaddr" ; then
-    echo "Failed to set IP address: $?"
-    exit 1
-fi
-if ! update_iface_setting $gen_iface iface.ipaddress "$optaddr" ; then
-    echo "Failed to set IP address for generic interface: $?"
-    exit 1
-fi
-
-if ! update_iface_setting $ioe_iface iface.gateway "$ibft_gateway" ; then
-    echo "Failed to set gateway address: $?"
-    exit 1
-fi
-
-if ! update_iface_setting $gen_iface iface.gateway "$ibft_gateway" ; then
-    echo "Failed to set gateway address for generic interface: $?"
-    exit 1
-fi
-
-if ! update_iface_setting $ioe_iface iface.subnet_mask "$ibft_mask" ; then
-    echo "Failed to set subnet mask: $?"
-    exit 1
-fi
-
-if ! update_iface_setting $gen_iface iface.subnet_mask "$ibft_mask" ; then
-    echo "Failed to set subnet mask for generic interface: $?"
-    exit 1
-fi
-
-if [ "$mod" = "qla4xxx" ] ; then
-    iscsiadm -m iface -H $mac -o applyall
-fi
-ip link set dev $IFNAME up
-
-exit 0
-
diff -pruN 2.1.5-1/utils/iscsi_offload.sh 2.1.7-2/utils/iscsi_offload.sh
--- 2.1.5-1/utils/iscsi_offload.sh	1970-01-01 00:00:00.000000000 +0000
+++ 2.1.7-2/utils/iscsi_offload.sh	2022-05-06 17:37:21.000000000 +0000
@@ -0,0 +1,384 @@
+#!/bin/bash
+#
+# iscsi_offload
+#
+# Configure iSCSI offload engines for use with open-iscsi
+# Usage:
+#    iscsi_offload [-d | -f | -i <ipaddr> | -t ] <nic>
+#
+# Copyright (c) 2011 Hannes Reinecke, SUSE Labs
+# This script is licensed under the GPL.
+#
+# The script creates an open-iscsi interface definition
+# in the style <nic>-<module>, where <nic> matches the
+# network interface passed on the commandline.
+# If '-t' (test mode) is passed as an option, the script
+# will not create nor modify any setting but just print
+# the currently active ones.
+#
+# Currently the script works with Broadcom (bnx2i) and
+# Chelsio T3 (cxgbi) iSCSI offload engines.
+# Should work with Chelsio T4, but has not been tested.
+# ServerEngines (be2iscsi) and QLogic (qla4xxx) can only
+# be configured via BIOS, open-iscsi support is still in
+# development.
+#
+
+#
+# Return codes:
+#    0: Success
+#    1: Invalid command line parameter
+#    2: iSCSI offloading not supported
+#    3: Error during module loading
+#    4: Cannot configure interface via iscsiadm, use BIOS setup
+#    5: internal error running iscsiadm
+#
+# Output:
+#    <mac> [none|dhcp|ip <ipaddr>|ibft]
+# where
+#    <mac>: MAC Address of the iSCSI offload engine
+#    none:  No IP configuration set for the iSCSI offload engine
+#    dhcp:  iSCSI offload engine configured for DHCP
+#    ip:    iSCSI offload engine configured with static IP address <ipaddr>
+#    ibft:  iSCSI offload engine configured from iBFT values
+#
+
+#
+# Figure out the MAC address of the iSCSI offload engine
+# corresponding to a NIC from a given PCI device.
+# bnx2 is using one PCI device per port for both network and iSCSI offloading
+# cxgb3 is using one PCI device for everything.
+#
+iscsi_macaddress_from_pcidevice()
+{
+    local path=$1
+    local if=$2
+    local h
+    local host
+
+    for h in $path/host* ; do
+	if [ -d "$h" ] ; then
+	    host=${h##*/}
+	    read netdev < /sys/class/iscsi_host/$host/netdev
+	    if [ "$netdev" = "$IFNAME" ] ; then
+		read mac < /sys/class/iscsi_host/$host/hwaddress
+		if [ "$mac" != "00:00:00:00:00:00" ] ; then
+		    echo "$mac"
+		fi
+		break;
+	    fi
+	fi
+    done
+}
+
+#
+# Figure out the MAC address of the iSCSI offload engine
+# corresponding to a NIC from a given PCI function.
+# It is assumed that the MAC address of the iSCSI offload
+# engine is equal of the MAC address of the NIC plus one.
+# Suitable for be2iscsi and qla4xxx
+#
+iscsi_macaddress_from_pcifn()
+{
+    local path=$1
+    local if=$2
+    local h
+    local host
+    local ifmac
+    local olemacoffset=$3
+
+    ifmac=$(ip addr show dev $if | sed -n 's/ *link\/ether \(.*\) brd.*/\1/p')
+    m5=$(( 0x${ifmac##*:} ))
+    m5=$(( $m5 + $olemacoffset ))
+    ifmac=$(printf "%s:%02x" ${ifmac%:*} $m5)
+    for host in /sys/class/iscsi_host/host* ; do
+	if [ -L "$host" ] ; then
+	    read mac < $host/hwaddress
+	    if [ "$mac" = "$ifmac" ] ; then
+		echo "$mac"
+		break;
+	    fi
+	fi
+    done
+}
+
+update_iface_setting() {
+    local iface="$1"
+    local name="$2"
+    local value="$3"
+
+    iface_value=$(iscsiadm -m iface -I $iface | sed -n "s/$name = \(.*\)/\1/p")
+    if [ "$iface_value" = "<empty>" ] ; then
+	iface_value=
+    fi
+    if [ "$iface_value" != "$value" ] ; then
+	if ! iscsiadm -m iface -I $iface -o update -n "$name" -v "$value" ; then
+	    return 1
+	fi
+    fi
+    return 0
+}
+
+while getopts di:t options ; do
+    case $options in
+	d ) mode=dhcp;;
+	i ) mode=static
+	    optaddr=$OPTARG
+	    ;;
+	f ) mode=firmware;;
+	t ) dry_run=1;;
+	?)  printf "Usage: %s [-d|-t|-i ipaddr|-f] ifname\n" $0
+	    exit 1;;
+    esac
+done
+shift $(($OPTIND - 1))
+
+IFNAME=$1
+ibft_mode="none"
+
+if [ -z "$IFNAME" ] ; then
+    echo "No interface specified"
+    exit 1
+fi
+
+if [ "$dry_run" ] ; then
+    if [ "$mode" = "dhcp" ] ; then
+	echo "'-t' specified, ignoring '-d'"
+	mode=
+    elif [ "$mode" = "static" ] ; then
+	echo "'-t' specified, ignoring '-s'"
+	mode=
+    fi
+fi
+
+if [ ! -L /sys/class/net/$IFNAME ] ; then
+    echo "Interface $IFNAME not found"
+    exit 1
+fi
+
+if [ "$optaddr" ] && ! ip route get $optaddr ; then
+    echo "Invalid IP address $optaddr"
+    exit 1
+fi
+if [ "$dry_run" ] ; then
+    mode=
+fi
+
+
+ifpath=$(cd -P /sys/class/net/$IFNAME; echo $PWD)
+pcipath=$(cd -P $ifpath/device; echo $PWD)
+
+if [ -d $pcipath ] ; then
+    drvlink=$(readlink $pcipath/driver)
+    driver=${drvlink##*/}
+fi
+
+if [ -z "$driver" ] ; then
+    echo "No driver found for interface $IFNAME"
+    exit 1
+fi
+
+case "$driver" in
+    bnx2*)
+	mod=bnx2i
+	;;
+    cxgb*)
+	mod=cxgb3i
+	;;
+    be2*)
+	mod=be2iscsi
+	;;
+    qla*)
+	mod=qla4xxx
+	;;
+    qed*)
+	mod=qedi
+	;;
+esac
+
+if [ -z "$mod" ] ; then
+    echo "iSCSI offloading not supported on interface $IFNAME"
+    exit 2
+fi
+
+# Check if the required modules are already loaded
+loaded=$(sed -n "/^$mod/p" /proc/modules)
+if [ -z "$loaded" ] ; then
+    modprobe $mod
+fi
+
+loaded=$(sed -n "/^$mod/p" /proc/modules)
+if [ -z "$loaded" ] ; then
+    echo "Loading of $mod.ko failed, please check dmesg"
+    exit 3
+fi
+
+# Get the correct MAC address for the various devices
+if [ "$mod" = "bnx2i" ] ; then
+    mac=$(iscsi_macaddress_from_pcidevice $pcipath $IFNAME)
+elif [ "$mod" = "cxgb3i" ] ; then
+    mac=$(iscsi_macaddress_from_pcidevice $pcipath $IFNAME)
+elif [ "$mod" = "be2iscsi" ] ; then
+    mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME 1)
+elif [ "$mod" = "qla4xxx" ] ; then
+    mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME 1)
+elif [ "$mod" = "qede" -o "$mod" = "qedi" ] ; then
+    mac=$(iscsi_macaddress_from_pcifn $pcipath $IFNAME 4)
+fi
+
+if [ -z "$mac" ] ; then
+    echo "iSCSI offloading not supported on interface $IFNAME"
+    exit 2
+fi
+
+gen_iface="$mod.$mac"
+ioe_iface="${IFNAME}-${mod}"
+
+# Get existing settings
+if iscsiadm -m iface -I $ioe_iface > /dev/null 2>&1 ; then
+    ioe_mac=$(iscsiadm -m iface -I $ioe_iface 2> /dev/null| sed -n "s/iface\.hwaddress = \(.*\)/\1/p")
+    ioe_mod=$(iscsiadm -m iface -I $ioe_iface 2> /dev/null| sed -n "s/iface\.transport_name = \(.*\)/\1/p")
+    ipaddr=$(iscsiadm -m iface -I $ioe_iface 2> /dev/null| sed -n "s/iface\.ipaddress = \(.*\)/\1/p")
+    if [ "$ipaddr" == "<empty>" ] ; then
+	ipaddr=
+    fi
+elif [ "$mod" = "be2iscsi" ] ; then
+    ioe_mac=$mac
+    ioe_mod=$mod
+else
+    # Create new interface
+    iscsiadm -m iface -I $ioe_iface --op=new 2> /dev/null
+    ioe_mac=
+    ioe_mod=
+    ipaddr=
+fi
+
+if [ -z "$dry_run" ] ; then
+    if [ "$ioe_mac" != "$mac" ] ; then
+	if [ -n "$ioe_mac" ] ; then
+	    echo "Warning: Updating MAC address on iface $ioe_iface"
+	fi
+	update_iface_setting $ioe_iface iface.hwaddress "$mac"
+    fi
+
+    if [ "$ioe_mod" != "$mod" ] ; then
+	if [ -n "$ioe_mod" ] ; then
+	    echo "Warning: Update transport on iface $ioe_iface"
+	fi
+	update_iface_setting $ioe_iface iface.transport_name "$mod"
+    fi
+elif [ -z "$ipaddr" ] ; then
+    ipaddr=$(iscsiadm -m iface -I $gen_iface 2> /dev/null| sed -n "s/iface\.ipaddress = \(.*\)/\1/p")
+    if [ "$ipaddr" = "<empty>" ] ; then
+	ipaddr=
+    fi
+elif [ "$ioe_mod" != "$mod" ] ; then
+    echo "Warning: Transport mismatch on iface $ioe_iface: $ioe_mod should be $mod"
+fi
+
+# Check iBFT setting
+for d in /sys/firmware/* ; do
+    [ -d $d ] || continue
+    [ -d $d/ethernet0 ] || continue
+    iboot_dir=$d
+done
+if [ -n "$iboot_dir" ] && [ -d "$iboot_dir" ] ; then
+    for if in ${iboot_dir}/ethernet* ; do
+	read ibft_mac < $if/mac
+	[ "$ibft_mac" = "$mac" ] || continue
+	ibft_origin=0
+	[ -f ${if}/origin ] && read ibft_origin < $if/origin
+	if [ "$ibft_origin" -eq 1 ] ; then
+	    ibft_mode="static"
+	elif [ "$ibft_origin" -eq 3 ] ; then
+	    ibft_mode="dhcp"
+	fi
+	[ -f $if/dhcp ] && read ibft_dhcp < $if/dhcp
+	if [ -n "$ibft_dhcp" -a "$ibft_mode" != "dhcp" ] ; then
+	    ibft_mode=dhcp
+	fi
+	if [ "$ibft_mode" = "dhcp" ] ; then
+	    ibft_ipaddr="0.0.0.0"
+	    ibft_gateway=
+	    ibft_mask=
+	    break
+	fi
+	[ -f $if/ip-addr ] && read ibft_ipaddr < $if/ip-addr
+	[ -f $if/gateway ] && read ibft_gateway < $if/gateway
+	[ -f $if/subnet-mask ] && read ibft_mask < $if/subnet-mask
+	break
+    done
+fi
+
+if [ -z "$optaddr" ] && [ "$ibft_ipaddr" ] ; then
+    optaddr=$ibft_ipaddr
+fi
+
+# Check if the interface needs to be configured
+if [ -z "$mode" ] ; then
+    if [ "$ibft_mode" != "none" ] ; then
+	echo "$mac ibft"
+	mode="ibft"
+    elif [ -z "$ipaddr" ] ; then
+	echo "$mac none"
+	mode="none"
+    elif [ "$ipaddr" = "0.0.0.0" ] ; then
+	echo "$mac dhcp"
+	ipaddr=
+	mode="dhcp"
+    else
+	echo "$mac ip $ipaddr"
+	mode="static"
+    fi
+    [ "$dry_run" ] && exit 0
+elif [ "$mode" = "dhcp" ] ; then
+    if [ "$ipaddr" = "0.0.0.0" ] ; then
+	echo "$mac dhcp"
+	exit 0
+    fi
+    optaddr="0.0.0.0"
+elif [ "$mode" = "static" ] && [ "$ipaddr" = "$optaddr" ] ; then
+    echo "$mac ip $ipaddr"
+    exit 0
+fi
+
+if [ "$mod" = "be2iscsi" ] ; then
+    exit 4
+fi
+
+if ! update_iface_setting $ioe_iface iface.ipaddress "$optaddr" ; then
+    echo "Failed to set IP address: $?"
+    exit 1
+fi
+if ! update_iface_setting $gen_iface iface.ipaddress "$optaddr" ; then
+    echo "Failed to set IP address for generic interface: $?"
+    exit 1
+fi
+
+if ! update_iface_setting $ioe_iface iface.gateway "$ibft_gateway" ; then
+    echo "Failed to set gateway address: $?"
+    exit 1
+fi
+
+if ! update_iface_setting $gen_iface iface.gateway "$ibft_gateway" ; then
+    echo "Failed to set gateway address for generic interface: $?"
+    exit 1
+fi
+
+if ! update_iface_setting $ioe_iface iface.subnet_mask "$ibft_mask" ; then
+    echo "Failed to set subnet mask: $?"
+    exit 1
+fi
+
+if ! update_iface_setting $gen_iface iface.subnet_mask "$ibft_mask" ; then
+    echo "Failed to set subnet mask for generic interface: $?"
+    exit 1
+fi
+
+if [ "$mod" = "qla4xxx" ] ; then
+    iscsiadm -m iface -H $mac -o applyall
+fi
+ip link set dev $IFNAME up
+
+exit 0
+
diff -pruN 2.1.5-1/utils/Makefile 2.1.7-2/utils/Makefile
--- 2.1.5-1/utils/Makefile	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/Makefile	2022-05-06 17:37:21.000000000 +0000
@@ -1,18 +1,78 @@
 # This Makefile will work only with GNU make.
+#
+# Make file for the util sub-directory
+#
+# This make file does not control the sysdeps
+# subdirectory, which is controlled
+# from the top-level make file.
+#
+
+SED = /usr/bin/sed
+INSTALL = install
+CHMOD = chmod
+
+DESTDIR ?=
+SBINDIR ?= /sbin
+etcdir = /etc
+HOMEDIR ?= $(etcdir)/iscsi
+
+RULESDIR ?= $(etcdir)/udev/rules.d
 
 CFLAGS ?= -O2 -fno-inline -g
 CFLAGS += -Wall -Wextra -Wstrict-prototypes
-PROGRAMS = iscsi-iname
 
-all: $(PROGRAMS)
+PROGRAMS	= iscsi-iname
+PROGRAMS_DEST	= $(addprefix $(DESTDIR)$(SBINDIR)/,$(PROGRAMS))
+
+SCRIPTS_SOURCES		= iscsi_discovery.sh iscsi_offload.sh
+SCRIPTS_TEMPLATES	= iscsi_fw_login.sh.template iscsi-gen-initiatorname.sh.template
+SCRIPTS_GENERATED	= $(SCRIPTS_TEMPLATES:.template=)
+SCRIPTS_DEST		= $(addprefix $(DESTDIR)$(SBINDIR)/,$(basename $(SCRIPTS_GENERATED))) \
+			  $(addprefix $(DESTDIR)$(SBINDIR)/,$(basename $(SCRIPTS_SOURCES)))
+
+RULESFILES_TEMPLATES	= 50-iscsi-firmware-login.rules.template
+RULESFILES_GENERATED	= $(RULESFILES_TEMPLATES:.template=)
+RULESFILES_DEST		= $(addprefix $(DESTDIR)$(RULESDIR)/,$(RULESFILES_GENERATED))
+
+OBJS = iscsi-iname.o md5.o
+
+all: $(PROGRAMS) $(SCRIPTS_GENERATED) $(RULESFILES_GENERATED)
+
+$(SCRIPTS_GENERATED): %.sh: %.sh.template
+	$(SED) -e 's:@SBINDIR@:$(SBINDIR):' -e 's:@HOMEDIR@:$(HOMEDIR):' $? > $@
+	$(CHMOD) 755 $@
+
+$(RULESFILES_GENERATED): %.rules: %.rules.template
+	$(SED) -e 's:@SBINDIR@:$(SBINDIR):' $? > $@
 
-iscsi-iname: md5.o iscsi-iname.o
+iscsi-iname: $(OBJS)
 	$(CC) $(CFLAGS) $(LDFLAGS) $^ $(DBM_LIB) -o $@
 
+install: $(DESTDIR)$(SBINDIR) $(DESTDIR)$(RULESDIR) \
+	$(PROGRAMS_DEST) $(SCRIPTS_DEST) $(RULESFILES_DEST)
+
+$(PROGRAMS_DEST): $(DESTDIR)$(SBINDIR)/%: %
+	$(INSTALL) -m 755 $? $@
+
+$(SCRIPTS_DEST): $(DESTDIR)$(SBINDIR)/%: %.sh
+	$(INSTALL) -m 755 $? $@
+
+install_udev_rules: $(RULESFILES_DEST)
+
+$(RULESFILES_DEST): $(DESTDIR)$(RULESDIR)/%: %
+	$(INSTALL) -m 644 $? $@
+
+$(DESTDIR)$(SBINDIR) $(DESTDIR)$(RULESDIR):
+	[ -d $@ ] || $(INSTALL) -d $@
+
 clean:
-	rm -f *.o $(PROGRAMS) .depend
+	$(RM) $(OBJS)
+	$(RM) $(PROGRAMS)
+	$(RM) $(SCRIPTS_GENERATED)
+	$(RM) $(RULESFILES_GENERATED)
+	$(RM) .depend
 
 depend:
-	gcc $(CFLAGS) -M `ls *.c` > .depend
+	$(CC) $(CFLAGS) -M `ls *.c` > .depend
 
 -include .depend
diff -pruN 2.1.5-1/utils/sysdeps/Makefile 2.1.7-2/utils/sysdeps/Makefile
--- 2.1.5-1/utils/sysdeps/Makefile	2021-09-05 23:32:54.000000000 +0000
+++ 2.1.7-2/utils/sysdeps/Makefile	2022-05-06 17:37:21.000000000 +0000
@@ -8,9 +8,9 @@ SYSDEPS_OBJS=sysdeps.o
 all: $(SYSDEPS_OBJS)
 
 clean:
-	rm -f *.o .depend
+	$(RM) *.o .depend
 
 depend:
-	gcc $(CFLAGS) -M `ls *.c` > .depend
+	$(CC) $(CFLAGS) -M `ls *.c` > .depend
 
 -include .depend
