#!/usr/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# bos72V src/bos/sbin/rc.boot/rc.boot.sh 1.58.14.28 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 1989,2019 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)62  1.58.14.28  src/bos/sbin/rc.boot/rc.boot.sh, bosboot, bos72V, v2019_39A1 9/12/19 12:21:01
#
# COMPONENT_NAME: (BOSBOOT) Base Operating System Boot
#
# FUNCTIONS: rc.boot.sh
#
# ORIGINS: 27
#
# (C) COPYRIGHT International Business Machines Corp. 1989, 1996
# All Rights Reserved
# Licensed Materials - Property of IBM
#
# US Government Users Restricted Rights - Use, duplication or
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
#

# local defines
ODMSTRNG="attribute=keylock and value=service"

# define local functions

loopled () {
	${SHOWLED} "$1" "$2"	# show a LED code
	while :			# loop forever
	do
		:
	done
# End of loopled function.
}

native_netboot_cfg() {
#
# Function: configure system for native network boot
#
# Read IPL control block for network addresses
${NIM_DEBUG}

eval $(bootinfo -c)		# gather the network boot parameters

# if VEND_GW is non-null, then it overrides BOOT_GATE_IP
[ -n "$VEND_GW" ] && BOOT_GATE_IP=$VEND_GW

if [ -n "$SUBMASK" ]; then
	OIFS="$IFS"
	IFS=.
	# separate the IP address octets for bitwise processing
	print $SUBMASK $BOOT_SERV_IP $CLIENT_IPADDR \
		| IFS=" " read S1 S2 S3 S4 B1 B2 B3 B4 C1 C2 C3 C4
	IFS="$OIFS"

	# unset BOOT_GATE_IP if bootp server (BOOT_SERV_IP) is on the same
	# subnet as bootp client (CLIENT_IPADDR)
	if [ $((${S1} & ${B1})).$((${S2} & ${B2})).$((${S3} \
			& ${B3})).$((${S4} & ${B4})) = \
		$((${S1} & ${C1})).$((${S2} & ${C2})).$((${S3} \
			& ${C3})).$((${S4} & ${C4})) ]; then
		unset BOOT_GATE_IP
	fi
	SUBMASK="netmask $SUBMASK"
fi

[ "$BOOT_GATE_IP" = 0 -o "$BOOT_GATE_IP" = 0.0.0.0 ] && unset BOOT_GATE_IP

# Get boot device
PHY_BOOT_DEV=`bootinfo -b`

# processing if VLAN is in use - VLAN_ID and VLAN_PCP come from bootinfo above
if [ -n "$VLAN_ID" ]; then
	BASE_DEV=$PHY_BOOT_DEV
	PHY_BOOT_DEV=$(/usr/lib/methods/define -n -c adapter -s vlan -t eth)
	/usr/lib/methods/chgvlan -l $PHY_BOOT_DEV -a \
		"base_adapter=$BASE_DEV vlan_tag_id=$VLAN_ID vlan_priority=$VLAN_PCP"
	/usr/lib/methods/cfgvlan -l $PHY_BOOT_DEV
	[ "$E802" -eq 1 ] && LDEV=et || LDEV=en
	LDEV=${LDEV}${PHY_BOOT_DEV##*([!0-9])}
	/usr/lib/methods/defif -c if -t en -s EN -w ${LDEV}
fi

# call the function to generate interface name
pdev_to_ldev

${SHOWLED} 0x606 "IFCONFIG BOOTDEV"
ifconfig lo0 inet 127.0.0.1 up

# determine ipv6 or ipv4 and call ifconfig accordingly
if [[ $CLIENT_IPADDR = *:* ]]; then
	# configure link-local (when a using global address)
	[[ $CLIENT_IPADDR != [Ff][Ee]80:* ]] && ifconfig $LDEV inet6 fe80:: eui64 up
	ifconfig $LDEV inet6 $CLIENT_IPADDR up || return 1
	[ "$BOOT_GATE_IP" ] && route -v add -inet6 -host $BOOT_SERV_IP $BOOT_GATE_IP
else
	ifconfig $LDEV inet $CLIENT_IPADDR up $SUBMASK || return 1
	[ "$BOOT_GATE_IP" ] && route -v add $BOOT_SERV_IP $BOOT_GATE_IP
fi

# set up route tables
[ -n "${ROUTES}" ] && {
	for route_args in $ROUTES
	do
		OIFS="$IFS"; IFS=':'
		set -- $route_args
		IFS="$OIFS"
		# verify that there are 3 arguments
		[ $# -ne 3 ] && continue
		route -v add -net $1 -netmask $2 $3 || return 2
	done
}

# build file name with client IP address if bootfile name is null
CLIENT_INFO_FILE=${BOOTFILE:-$CLIENT_IPADDR}.info
}

disknet_odm_init() {
#
# Function: initialize the ODM with basecust data
#
restbase	# extract basecust data
rc=$?
[ $rc -ne 0 ] && loopled 0x605 "NET RESTBASE BAD"	# fatal error

# save ATM data and reset ODM
odmget -q name=at0 CuAt > /tmp/odm_atm
odmget -q name=at0 CuDv >> /tmp/odm_atm
odmget -q "name=atm0 and attribute=uni_vers" CuAt >> /tmp/odm_atm
odmget -q name=inet0 CuAt >> /tmp/odm_atm
odmget -q name=inet0 CuDv >> /tmp/odm_atm
odmget -q"resource=ddins and value3=;" CuDvDr > /tmp/odm
odmdelete -o CuAt
odmdelete -o CuDv
odmdelete -o CuDvDr
odmadd /tmp/odm
}

config_ATM() {
#
# Function: configure ATM network services
#
odmadd /tmp/odm_atm
cd /
$(lsdev -Clatm0 -FConfigure) -2 -l atm0
/usr/lib/methods/cfgif.at -l at0
ifconfig lo0 inet 127.0.0.1 mtu 16896 up
ifconfig lo0 inet6 ::1 mtu 16896 up
/usr/lib/methods/cfginet
mkatmpvc
atmsvcd
muxatmd
sleep 60
BOOT_SERV_IP=$(odmget -q "name=at0 and \
	attribute=BSipaddr" CuAt | grep -w value | cut -d"\"" -f 2)
odmdelete -q "name=at0 and attribute=BSipaddr" -o CuAt
CLIENT_INFO_FILE=$(odmget -q "name=at0 and \
	attribute=CIfilename" CuAt | grep -w value | cut -d"\"" -f 2)
odmdelete -q "name=at0 and attribute=CIfilename" -o CuAt
}

pdev_to_ldev() {
#
# Function: generate interface name from physical device name and
# increase ifsize if interface count exceeds the default of 8.
#
	LDEV_NUM=${PHY_BOOT_DEV##*([!0-9])}
	case "$PHY_BOOT_DEV" in
		ent*)	[ "$E802" -eq 1 ] && \
				LDEV=et${LDEV_NUM} || \
				LDEV=en${LDEV_NUM};;
		fddi*)	LDEV=fi${LDEV_NUM};;
		hfi*)	LDEV=hf${LDEV_NUM};;
		tok*)	LDEV=tr${LDEV_NUM};;
		*)	# unknown network boot device
			loopled 0x605 "UNKNOWN NET DEV";;
	esac

	if [ "${LDEV_NUM}" -gt 7 ]; then
		(( IF_COUNT = LDEV_NUM + 1 ))
		no -o ifsize=${IF_COUNT}
	fi
}

undolt() {
#
# Function: verify a few things that are susceptible to doltism.
#	these changes target problems found in the real world
#
	# replace a couple of important symlinks if they're gone
	[[ -r /bin ]] || ln -s /usr/bin /bin
	[[ -r /lib ]] || ln -s /usr/lib /lib
	[[ -h /etc/init ]] || ln -fs /usr/sbin/init /etc/init
	# replace rc.boot if it has been removed
	[[ -s /sbin/rc.boot ]] || cp /../sbin/rc.boot /sbin
	# ensure that these files are executable
	chmod u+x /sbin/rc.boot /usr/sbin/init
}

ras_getattr() {
#
# Retrieve a value from the SWservAt base
#
# Argument: attribute name
#
# Return: attribute value
#
	odmget -q attribute=$1 SWservAt | awk -F'"' '/value/ {print $2}'
}

sh_setup() {
#
# Setup for System Hang Detection
# If the emergency login terminal is the console, then change the
# console mode to be 'share'
#
	if [ "`ras_getattr sh_pp`" = enable -a \
					"`ras_getattr sh_pp_login`" = enable ]
	then
		login_term=`ras_getattr sh_pp_lterm`
		if [ "$login_term" = /dev/console -o "$login_term" = `lscons` ]
		then
			pshare /dev/console
		fi
	fi
}

cfg_iscsi_sw() {
# configure tcp/ip and iSCSI SW protocol device and any iSCSI SW children

	set -x
	# loop for each ethernet interface
	lsdev -Cc if -s EN -F name | while read ifname; do
		# get this interface network address
		lsattr -El $ifname -a netaddr -F value | read addr
		if [ -n "$addr" ]; then
			# found an address
			# get subnetmask for this interface
			lsattr -El $ifname -a netmask -F value | read mask
			if [ -n "$mask" ]; then
				# found the subnetmask
				# extract mtu setting from ODM
				lsattr -El $ifname -a mtu -F value | read mtu
				# configure this interface
				ifconfig $ifname inet $addr arp netmask $mask mtu ${mtu:-1500} up
				print $?
			fi
		fi
	done

	# loop for each route that is associated with inet0
	lsattr -Elinet0 -aroute -Fvalue | while read data; do
		# the next four lines replace commas with spaces
		OIFS=$IFS
		IFS=','
		set -- $data
		IFS=$OIFS
		# store the resulting string in ROUTE_ARGS
		# and prepend it with a dash
		ROUTE_ARGS="-$@"
		route add $ROUTE_ARGS	# run the route command
	done

	# configure the iSCSI SW protocol devices
	lsdev -Cc driver -s node -t iscsi -F name | while read iscsiname
	do 
	    if [ -n "$iscsiname" ]; then
		if [ "$PHASE" -eq 1 ]; then
		    cfgmgr -fvl $iscsiname
		else
		    cfgmgr -vl $iscsiname
		fi
	    fi
        done
}

nim_mount() {
# create new mount function for nfs client access -- NIM

	typeset object=${1}
	typeset access_pnt=${2}

	if [ -n "${NIM_NFS4_MOUNTS}" ]; then
		# start lite versions of portmap and nfsrgyd
		portmap.min
		nfsrgyd.min
	fi

	# run the mount command
	mount ${NIM_SPOT_MOUNT_OPTS} ${NIM_MOUNT_OPTS} \
				${object} ${access_pnt} || return 1

	return 0
}

# End of rc.boot functions.

# Set environment
HOME=/
LIBPATH=/usr/lib:/lib
ODMDIR=/etc/objrepos
PATH=/usr/sbin:/etc:/usr/bin
SHOWLED=/usr/lib/methods/showled
SYSCFG_PHASE=BOOT
AIX_NO_SAVEBASE=1
CFGLOG=default
export HOME LIBPATH ODMDIR PATH SHOWLED SYSCFG_PHASE AIX_NO_SAVEBASE CFGLOG

umask 077
set -x

# Get config boot phase argument
PHASE=$1

PLATFORM=`bootinfo -p`
# verify that the correct bootinfo module exists
if [ ! -x "/usr/lib/boot/bin/bootinfo_${PLATFORM}" ]; then
	loopled 0xA10 "UNKNOWN PLATFORM"
fi

if [ "$PHASE" -eq 1 ]; then
	# save boot fs space by removing other platform modules
	for i in /usr/lib/boot/bin/!(*_${PLATFORM}); do
		init -c "unlink $i"
	done

	chramfs -t	# expand RAMFS
	init -c "unlink /usr/sbin/chramfs" >/dev/null
fi

# Start the boot process for a particular device.
BOOTYPE=`bootinfo -t`
[ "$?" -ne 0 ] && loopled 0xA06 "UNKNOWN BOOTTYPE"

[ -z "$BOOTYPE" ] && BOOTYPE=1

case "$BOOTYPE" in

	1)	# Disk boot

		unset pdev_to_ldev native_netboot_cfg
		unset disknet_odm_init config_ATM

		case "$PHASE" in

			1)	# Phase 1 boot - disk

			echo "\n\n_______________________________________"\
				"_____________________________________" \
				"\nrc.boot: starting disk boot process" \
				>/tmp/boot_log

			# Also log an informational message to the cfg log
			echo "B1 Starting Disk Boot" > /tmp/cfg_log

			ln /usr/lib/lib* /lib

			# Call restore base
			echo "rc.boot: executing \"restbase\"" \
				>>/tmp/boot_log
			restbase
			rc=$?
			[ $rc -eq 1 ] && ${SHOWLED} 0x548 "RESTBASE FAILED" #fatal error
			[ $rc -eq 2 ] && >/no_sbase	#non-fatal error

			${SHOWLED} 0x510 "DEV CFG 1 START"
			# Call config manager phase 1
			echo "rc.boot: executing \"cfgmgr -f -v\"" \
				>>/tmp/boot_log
			cfgmgr -f -v

			# if booted from iscsi, configure tcp and iscsi sw
			if [ "$(bootinfo -i)" -eq 1 ]; then
				cfg_iscsi_sw
			fi

			${SHOWLED} 0x511 "DEV CFG 1 END"

			dvc=`bootinfo -b`
			if [ ! "${dvc}" ]; then
				if [ "$(bootinfo -U)" -eq 1 ]; then
					# VRM reserve failures were detected
					loopled 0x2702 "INSUFFICIENT ENTITLED MEMORY"
				fi
				loopled 0x554 "UNKNOWN BOOTDISK"
			fi
			echo "rc.boot: boot device is $dvc" \
				>>/tmp/boot_log
			ln /dev/r$dvc /dev/ipldevice
			exit 0
			;;


			2)	# Phase 2 boot - disk

			${SHOWLED} 0x551 "VARYON IPL DEV"
			# Bring up the root volume group
			echo "rc.boot: executing \"ipl_varyon -v\"" \
				>>/tmp/boot_log
			ipl_varyon -v
			rc=$?
			case $rc in
				0 )     ;;  # do nothing
				7 | 8 ) loopled 0x554 "BOOTDEV ACC FAIL";;
				4 | 9 ) loopled 0x556 "LVM_QUERY ERROR";;
				* )     loopled 0x552 "IPLVARYON ERROR";;
			esac

			ln /usr/sbin/mount /etc/umount

			${SHOWLED} 0x517 "MOUNT ROOT"
			echo "rc.boot: executing \"fsck -fp /\"" \
				>>/tmp/boot_log
			{ fsck -fp / 2>&1; print $? >/tmp/rc; } | \
						tee -a /tmp/boot_log
			read rc </tmp/rc
			[ "$rc" -ne 0 ] && loopled 0x555 "FSCK ERROR"

			echo "rc.boot: executing \"mount /\"" \
				>>/tmp/boot_log
			{ mount -f / 2>&1; print $? >/../tmp/rc; } | \
						tee -a /../tmp/boot_log
			read rc </../tmp/rc
			[ "$rc" -ne 0 ] && loopled 0x557 "ROOT MNT FAILED"

			# Recover /dev directory from any maintenance work.
			if [ -d /dev.org ]
			then
				/../usr/bin/rm -fr /dev
				/../usr/sbin/mvdir /dev.org /dev
			fi

			# Copy /dev special files from RAM filesystem to disk
			# based filesystem, including /dev/ipldevice.
			# The mounted root filesystem contains a symlink
			# /usr/lib that points to /../usr/lib, and that is how
			# we can find mergedev with the root fs mounted
			/usr/lib/boot/mergedev 2>&1 | \
					/../usr/bin/tee -a /../tmp/boot_log

			# Mount /usr
			/../usr/lib/methods/showled 0x517 "MOUNT /USR"
			echo "rc.boot: executing \"fsck -fp /usr\"" \
				>>/../tmp/boot_log
			/../usr/sbin/fsck -fp /usr 2>&1 | \
				/../usr/bin/tee -a /../tmp/boot_log
			echo "rc.boot: executing \"mount /usr\"" \
				>>/../tmp/boot_log
			{ /../usr/sbin/mount /usr 2>&1; \
				print $? >/../tmp/rc; } | \
				/../usr/bin/tee -a /../tmp/boot_log
			read rc </../tmp/rc
			[ "$rc" -ne 0 ] && loopled 0x518 "/USR MNT FAILED"

			# If secure boot is enabled, download the
			#  TSD into the  security kernel table

			# use this libc.a to find the one that is
			# listed in the RAM fs TSD file.  After this call,
			# trustchk starts using the disk filesystem TSD file.
			LIBPATH=/usr/ccs/lib:/usr/lib /usr/sbin/trustchk -b 4

			# trusted boot processing, as needed
			if [ "$(bootinfo -V)" -eq 1 -a \
					-f /../etc/rc.teboot ]; then
				/../etc/rc.teboot 2>> /../tmp/boot_log \
						1> /../tmp/teboot_log
			fi

			echo "The \"date\" command is now available: " \
				"`date`" >>/../tmp/boot_log

			if [ -f /etc/rc.B1 ]; then
				/etc/rc.B1 start
			fi

			# Mount /var for copycore
			${SHOWLED} 0x517 "MOUNT /VAR"
			echo "rc.boot: executing \"fsck -fp /var\"" \
				>>/../tmp/boot_log
			/usr/sbin/fsck -fp /var 2>&1 | \
						tee -a /../tmp/boot_log
			echo "rc.boot: executing \"mount /var\"" \
				>>/../tmp/boot_log
			{ mount /var 2>&1; print $? >/../tmp/rc; } | \
						tee -a /../tmp/boot_log
			read rc </../tmp/rc
			[ $rc -ne 0 ] && loopled 0x518 "/VAR MNT FAILED"
			# retrieve dump
			echo "rc.boot: executing \"copycore\"" \
				>>/../tmp/boot_log
			copycore
			umount /var

			# Error Recovery if customized data is zero
			[ -f /../no_sbase ] && {
			echo "rc.boot: executing savebase recovery procedures" \
				>>/../tmp/boot_log
				X=`ODMDIR=/etc/objrepos odmshow CuDv |\
					fgrep population`
				count=`echo $X | cut -f2 -d' '`
				[ $count -ne 0 ] && {
					unset AIX_NO_SAVEBASE # allow savebase to run
					/usr/sbin/savebase
					[ $? -ne 0 ] && loopled 0x546 "SAVEBASE FAILED"
					mount /var	# so that reboot can log
					echo "savebase recovery reboot" \
						>>/../tmp/boot_log
					cat /../tmp/boot_log | alog -q -t boot
					reboot
				}
			}

			# Copy LVM information to the hardfile
			cp /../etc/vg/* /etc/vg 2>/dev/null

			# Copy ram filesystem ODM customized data to disk
			cp /../etc/objrepos/Cu* /etc/objrepos

			# Empty the CuAtSav ODM file.
			odmdelete -o CuAtSav >/dev/null 2>&1

			# Start paging if no dump - find first auto paging dev
			lsps -t lv | while read lvname junk vgname junk junk \
					junk autoflag junk; do
				if [ "$vgname" = "rootvg" -a \
						"$autoflag" = "yes" ]; then
					break
				fi
			done

			# ensure that lvname is not null
			if [ -z "$lvname" ]; then
				lvname=hd6
			fi

			# get size (in MB) of kernel startup pagespace
			# it is always a multiple of 32 MB
			PGSP_SZ=$(bootinfo -A)
			# get size (in MB) and count of default
			# paging logical volume partitions
			lslv -L $lvname | awk '
				$4 == "PP" && $5 == "SIZE:" && $6 ~ /^[0-9]+$/ {
					PPSZ=$6
				}
				$1 == "LPs:" && $2 ~ /^[0-9]+$/ {
					LPC=$2
				}
			END { print PPSZ " " LPC }
			' | read PART_SZ PART_CNT

			# compare startup pagespace size to
			# paging logical volume size.
			# non-null values are required for all fields.
			if [ "$PGSP_SZ" -a "$PART_SZ" -a "$PART_CNT" ]; then
				# logical volume size is the product
				# of partition size and count.
				if [ "$PGSP_SZ" -gt \
					$(( "$PART_SZ" * "$PART_CNT" )) ]; then
					# how many more partitions required?
					# divide startup size by partition size,
					# then subtract existing count
					REQD_PARTS=$(("$PGSP_SZ" / "$PART_SZ" -
								"$PART_CNT"))
					if [ $((PGSP_SZ % PART_SZ)) -ne 0 ]
					then
						# handle case where bitmap size
						# modulo partition size != 0
						(( REQD_PARTS +=1 ))
					fi
					echo "adding $REQD_PARTS partition(s) to $lvname" >>/../tmp/boot_log
					chps -s $REQD_PARTS $lvname
					rc=$?
					if [ $rc -ne 0 ]; then
						echo "chps failed with $rc" \
							>>/../tmp/boot_log
					fi
				fi
			fi

			[ ! -f /needcopydump ] && swapon /dev/"$lvname" 2>&1 | \
						tee -a /../tmp/boot_log

			ls32 -i /dev/ipl_blv 2>/dev/null | \
					read PREV_BLV_INODE junk
			BOOTLV=/dev/r$(bootinfo -v)
			ls32 -i $BOOTLV 2>/dev/null | read CURR_BLV_INODE junk
			if [ "$CURR_BLV_INODE" -ne "$PREV_BLV_INODE" ]; then
				# update link
				ln -f "$BOOTLV" /dev/ipl_blv
				# determine if TCB is enabled
				odmget -q attribute=TCB_STATE \
					PdAt 2>/dev/null | \
					grep -q tcb_disabled 2>/dev/null
				TCB_ENABLED=$?	# 1 indicates TCB is enabled
				if [ $TCB_ENABLED -eq 1 ]; then
					PREV_BLVPATH=$(find /dev -inum \
							$PREV_BLV_INODE -print)
					tcbck -a $PREV_BLVPATH links=
					tcbck -a "$BOOTLV" links=/dev/ipl_blv
				fi
			fi

			sync; sync; sync	# flush to disk

			# allow service if there is a dump or
			#  need diag/maintenance
			KEYPOS=`odmget -q"$ODMSTRNG" CuAt`
			if [ -n "$KEYPOS" -o -f /needcopydump ]
			then
			echo "rc.boot: initiating service procedures" \
				>>/../tmp/boot_log
				export KEYPOS
				mv /needcopydump /../ >/dev/null 2>&1
				/usr/lib/boot/srvboot
				[ $? -ne 0 ] && {
					if [ `bootinfo -L` = "1" ]; then
						# yes, the box has LED display
						loopled 0x549 "SRVBOOT FAILED"
					fi
					# else there's no LED for us to
					# indicate that the dump image could
					# not be retrieved.
					# log it and move along
					echo "\nrc.boot: NOTICE: the dump image could not be saved." >>/../tmp/boot_log
					echo "Increase the size of the dump copy directory.\n" >>/../tmp/boot_log
					/usr/bin/sysdumpdev -z
				}
			fi

			#
			# If this is the first reboot since an update,
			# we need to move the new odm commands
			# and library into the proper place.
			#
			if [ -f /etc/rc.update ]
			then
				/etc/rc.update
				rm /etc/rc.update
			fi
			${SHOWLED} 0x517 "MOUNT /VAR"

			echo "rc.boot: run time mount of /var" \
				>>/../tmp/boot_log
			{ mount /var 2>&1; print $? >/../tmp/rc; } | \
						tee -a /../tmp/boot_log
			read rc </../tmp/rc
			[ "$rc" -ne 0 ] && loopled 0x518 "/VAR MNT FAILED"

			# Copy secure boot log from RAMFS to /var file system
			# if secure boot is on in logonly mode

			/usr/sbin/trustchk -b 5

			cat /../tmp/boot_log | alog -q -t boot
			rm -f /../tmp/boot_log
			chmod go-w,g+r /var/adm/ras/bootlog

			if [ -f /../tmp/teboot_log ]; then
				mv /../tmp/teboot_log /var/adm/ras/teboot.log
				chmod go-w,g+r /var/adm/ras/teboot.log
			fi

			# Write ramfs cfg log to the real cfg log
			cat /../tmp/cfg_log | alog -q -t cfg
			alog -of /../tmp/cfglog | alog -q -t cfg
			rm -f /../tmp/cfg_log /../tmp/cfglog
			chmod go-w,g+r /var/adm/ras/cfglog
			echo "B1" `date -u +"%D %r %Z"` \
				"Disk Boot Phase 1 Complete" | alog -q -t cfg

			undolt		# a function that tries to fix things

			# loop for max of 250 seconds if any
			# files exist in /busy
			busy_timeout=250
			while [ $busy_timeout -gt 0 -a -f /../busy/* ]; do
				sleep 1
				(( busy_timeout-=1 ))
			done

			${SHOWLED} 0x553 "PHASE 1 COMPLETE"
			exit 0
			# Exit to kernel newroot
			;;


			3)	# Phase 3 inittab finish boot - disk

			echo "rc.boot: run time mount of /tmp" \
				| alog -q -t boot
			${SHOWLED} 0x517 "MOUNT /TMP"
			if [ -r /etc/filesystems ]
			then
				fsck -fp /tmp
				mount /tmp
			fi
			[ "$?" -ne 0 ] && loopled 0x518 "/TMP MNT FAILED"

			# update boot logical volume label
			primary_bootlv=$(bootinfo -v)
			lsvg -l rootvg | while read lvname lvtype junk; do
				if [ "$lvtype" = "boot" -a \
					"$lvname" != "$primary_bootlv" ]; then
						chlv -L standby_bootlv "$lvname"
				fi
			done
			chlv -L primary_bootlv "$primary_bootlv"

			# delete any WPAR objects
			ODMDIR=/etc/objrepos /usr/bin/odmdelete -o CuWxt

			# Volume group sync.
			${SHOWLED} 0x517 "SYNCVG ROOTVG"
			LVMTMPPVDIR=/tmp syncvg -v rootvg &

			# fall through to bottom - phase 3 common code
			;;

			*)	exit 0 ;;

		esac
		;;

	3)	# CDROM boot

		unset pdev_to_ldev undolt native_netboot_cfg
		unset disknet_odm_init config_ATM
		case "$PHASE" in

			1)	# Phase 1 boot - CDROM
			${SHOWLED} 0x510 "DEV CFG 1 START"
			# Run config manager first phase
			cfgmgr -f -v

			bootdev=$(bootinfo -b)
			if [ ! "${bootdev}" ]; then
				loopled 0x518 "UNKNOWN BOOTDEV"
			fi

			bootdev=/dev/${bootdev}

			boot_fs=$(bootinfo -f ${bootdev})
			if [ ! "${boot_fs}" ]; then
				loopled 0x518 "UNKNOWN BOOT FS"
			fi

			# create /etc/filesystems
			>/etc/filesystems
			${SHOWLED} 0x517 "MOUNT ${boot_fs}"
			mount -rv ${boot_fs} ${bootdev} /SPOT
			[ "$?" -ne 0 ] && loopled 0x518 \
					"MOUNT ${boot_fs} FAIL"
			${SHOWLED} 0x512 "PREPARE RAM FS"

			# remove stuff from the boot RAM fs
			/SPOT/usr/bin/rm -r /etc/init /usr/bin /usr/lib/boot \
				/usr/lib/drivers/* /usr/lib/methods/* /usr/sbin


			# recreate and populate RAM fs /usr/bin and /usr/sbin
			/SPOT/usr/bin/mkdir /usr/bin /usr/sbin
			/SPOT/usr/bin/ln -s /SPOT/usr/bin/* /usr/bin
			ln -s /SPOT/usr/sbin/* /usr/sbin
			cd /usr/bin
			rm ksh tee cat odmget copydumpmenu sh
			cd /SPOT/usr/bin
			cp ksh tee cat odmget copydumpmenu /usr/bin
			ln /usr/bin/ksh /usr/bin/sh
			cd /usr/sbin
			rm umount mount bootinfo lsdev mvdir
			cd /SPOT/usr/sbin
			cp mount bootinfo lsdev mvdir /usr/sbin
			ln /usr/sbin/mount /usr/sbin/umount

			# finish populating /usr in the boot RAM fs
			cd /
			mkdir -p /usr/ccs/bin /usr/lib/boot /usr/lib/nls \
				/usr/lib/objrepos /usr/lpp /usr/share/lib
			ln -s /SPOT/usr/lib/instl /usr/lib
			cp -p /SPOT/usr/ccs/bin/* /usr/ccs/bin
			cp -Rp /SPOT/usr/lib/boot/* /usr/lib/boot
			rm /usr/lib/boot/bin/!(*_${PLATFORM})
			cp -Rp /SPOT/usr/lib/nls/* /usr/lib/nls
			cp -p /SPOT/usr/lib/objrepos/* /usr/lib/objrepos
			cp -p /SPOT/usr/lib/* /usr/lib
			cp -Rp /SPOT/usr/lpp/* /usr/lpp
			cp -p /SPOT/* /

			# populate RAM fs directories with links that
			# point to the files in the optical filesystem
			ln -s /SPOT/usr/lib/drivers/* /usr/lib/drivers
			ln -s /SPOT/usr/lib/methods/* /usr/lib/methods
			ln -s /SPOT/usr/share/lib/* /usr/share/lib
			cp -p /SPOT/usr/lib/microcode/* /usr/lib/microcode

			ln -s /SPOT/usr/lib/boot/ssh /etc/init
			ln -s /usr/lib/objrepos/* /etc/objrepos

			# Enable device package name generation
			DEV_PKGNAME=ALL
			export DEV_PKGNAME

			strload -f /dev/null
			# Run config manager for remaining devices
			${SHOWLED} 0x510 "DEV CFG 2 START"
			cfgmgr -p3 -v
			${SHOWLED} 0x511 "DEV CFG 2 END"

			exit 0
			;;

			2)	# Phase 2 boot - CDROM

			rm -f /sbin/rc.boot

			unset loopled
			shift $#

			# copy diagnostic /etc/objrepos files to boot
			# RAM filesystem so that diags can write to them
			cp /SPOT/root/etc/objrepos/* /etc/objrepos

			${SHOWLED} 0x513 "EXECUTE BI_MAIN"
			exec /usr/lpp/bosinst/bi_main
			exit 0
			;;

			*)	exit 0 ;;

		esac
		;;

	4)	# Tape boot

		unset pdev_to_ldev undolt native_netboot_cfg
		unset disknet_odm_init config_ATM
		case "$PHASE" in

			1)	# Phase 1 boot - tape

			${SHOWLED} 0x510 "STRLOAD"
			strload -f /dev/null
			# Run config manager first phase
			cfgmgr -f -v

			# Enable device package name generation
			DEV_PKGNAME=ALL
			export DEV_PKGNAME

			${SHOWLED} 0x510 "DEV CFG 2 START"
			# Run config manager second phase
			cfgmgr -p3 -v

			${SHOWLED} 0x512 "PREPARE RAM FS"
			# Ensure that all tape drives are
			# configured to block size 512.
			lsdev -Cc tape -F name | while read tapename
			do
				`lsdev -Cl$tapename -FChange` -l $tapename \
					-a block_size=512
			done

			# Cleanup
			for i in /usr/lib/drivers/*/* /usr/lib/drivers/* \
				/usr/lib/methods/cfglft \
				/usr/lib/methods/startlft \
				/usr/lib/methods/starttty \
				/usr/lib/microcode/* \
				/usr/lib/nls/loc/C.lftkeymap /usr/lpp/fonts/* \
				/usr/sbin/strload
			do
				init -c "unlink $i" >/dev/null
			done

			exit 0
			;;


			2)	# Phase 2 boot - tape

			init -c "unlink /sbin/rc.boot" >/dev/null
			unset loopled
			shift $#
			${SHOWLED} 0x513 "EXECUTE BI_MAIN"

			if [ -f /etc/rc.B1 ]; then
				/etc/rc.B1 install
			fi

			exec /usr/lpp/bosinst/bi_main
			exit 0
			;;

			*)	exit 0 ;;

		esac
		;;


	5)	# Network boot

		unset NIM_DEBUG		# make sure this is null if not used
		# export NIM_DEBUG='set -x'
		case "$PHASE" in

			1)	# Phase 1 boot - network
			${NIM_DEBUG}
			${SHOWLED} 0x600 "NET BOOT START"

			if [ "$(bootinfo -b)" = "atm0" ]; then
				disknet_odm_init
			fi

			# configure the network boot device and parent devices
			${SHOWLED} 0x600 "CONFIG NETBOOT"
			cfgmgr -fv

			# set up env variable for local name resolution
			export NSORDER=local
			# configure network - NOTE:  we assume that the
			#	"ROUTES" env variable is undefined at this
			#	point.  It may be defined for subsequent calls.

			if [ "$(bootinfo -b)" = "atm0" ]; then
				config_ATM
				[ $? -ne 0 ] && loopled 0x607 "IFCONFIG FAILED"
			else
				native_netboot_cfg
				[ $? -ne 0 ] && loopled 0x607 "IFCONFIG FAILED"
			fi

			# tftp read client miniroot mount point file
			${SHOWLED} 0x608 "GET CLIENT FILE"
			until tftp -go /SPOT/niminfo \
					$BOOT_SERV_IP $CLIENT_INFO_FILE image
			do
				${SHOWLED} 0xfff
				${SHOWLED} 0x608 "RETRY CLIENTFILE"
			done

			# dot execute the /SPOT/niminfo file to load variables
			if [ -s "/SPOT/niminfo" ]
			then
				. /SPOT/niminfo
			else
				loopled 0x609 "NIMINFO FAILED"
			fi

			# set nfso reserved port option for nfs client
			if [ "${NFS_RESERVED_PORT}" = "yes" ]
			then
				nfso -o nfs_use_reserved_ports=1
				[ $? -ne 0 ] && loopled 0x2026 "NFSO FAILED"
			fi

			# create /etc/hosts for the RAM filesystem
			for host_lines in $NIM_HOSTS
			do
				OIFS="$IFS"; IFS=':'
				set -- $host_lines
				IFS="$OIFS"
				echo $* >> /etc/hosts
			done

			# IPv6 hosts entries need a different delimiter,
			#  since the IPv6 address uses colons
			NEW_IPADDR=
			[ -n "${NIM_IPV6_HOSTS}" ] && {
				for host_lines in $NIM_IPV6_HOSTS
				do
					OIFS="$IFS"; IFS='|'
					set -- $host_lines
					IFS="$OIFS"
					echo $* >> /etc/hosts

					# save client's IP /etc/hosts address
					[[ $NIM_HOSTNAME = $2 ]] &&
						NEW_IPADDR=$1
				done

				# firmware might use link-local address to
				# boot, but we need the global address
				# ... convert hex digits to uppercase
				typeset -u NEW_IP_UPPER=$NEW_IPADDR
				typeset -u CLIENT_IP_UPPER=$CLIENT_IPADDR
				if [[ -n $NEW_IP_UPPER &&
					$NEW_IP_UPPER != $CLIENT_IP_UPPER ]]
				then
					ifconfig $LDEV detach
					ifconfig $LDEV inet6 $NEW_IPADDR up
				fi
			}

			# set up route tables
			[ -n "${ROUTES}" ] && {
				if [ "$(bootinfo -b)" = "atm0" ]; then
					route -v flush
				fi
				for route_args in $ROUTES
				do
					OIFS="$IFS"; IFS=':'
					set -- $route_args
					IFS="$OIFS"
					# verify that there are 3 arguments
					[ $# -ne 3 ] && continue
					route -v add -net $1 -netmask $2 $3 ||
						loopled 0x613 "ADD ROUTE FAILED"
				done
			}

			for route_args in $NIM_IPV6_ROUTES
			do
				OIFS="$IFS"; IFS='|'
				set -- $route_args
				IFS="$OIFS"
				# verify that there are 3 arguments
				[ $# -ne 3 ] && continue
				# if the install is link-local, don't set
				# anymore routes, the existing link route
				# is sufficient
				[[ $CLIENT_IPADDR = [Ff][Ee]80:* ]] && continue
				# ifconfig now creates routes that may
				# conflict with the new routes... delete
				# those routes first before proceeding
				if [[ "$2" = "0" ]]
				then
					route -v delete -inet6 -net $1
					route -v add -inet6 -net $1 $3 ||
					loopled 0x613 "ADD ROUTE FAILED"
				else
					route -v delete -inet6 -net $1 -netmask $2
					route -v add -inet6 -net $1 -netmask $2 $3 ||
					loopled 0x613 "ADD ROUTE FAILED"
				fi
			done


			> /etc/filesystems

			# Tell the NIM master that we are about to mount
			# the SPOT.
			nimclient -o change -a force=yes -a ignore_lock=yes \
			  -a info="LED 610: mount ${NIM_MOUNT_OPTS} -r $SPOT /SPOT/usr"

			# NFS mount the spot
			${SHOWLED} 0x610 "MOUNT /SPOT/USR"
			nim_mount $SPOT /SPOT/usr

			if [[ "$?" -ne 0 ]]
			then
				nimclient -o change -a force=yes \
				  -a ignore_lock=yes \
				  -a info="LED 611: failure: mount -r $SPOT /SPOT/usr"
				loopled 0x611 "/SPOT MNT FAILED"
			fi
			# Clear out the info field on the client so it will
			# not look like the mount hung.
			nimclient -o change -a force=yes \
			  -a ignore_lock=yes -a info=""

			${SHOWLED} 0x612 "CP RCCONF FILE"
			cp /SPOT/usr/lib/boot/network/$RC_CONFIG /etc
			RC_CONFIG=/etc/$RC_CONFIG
			. $RC_CONFIG
			exit 0
			;;

			2)	# Phase 2 boot - network

			${NIM_DEBUG}
			export NSORDER=local
			PHY_BOOT_DEV=`bootinfo -b`
			. /SPOT/niminfo
			RC_CONFIG=/etc/$RC_CONFIG
			. $RC_CONFIG

			# Kill portmap.min and nfsrgyd.min if they're running.
			# This is done here because init cannot wait for
			# inherited processes.
			PIDS=`ps -A |
				awk '$NF == "portmap.min" ||
				$NF == "nfsrgyd.min" { PIDS = PIDS $1 " " }
				END { print PIDS }'`

			if [ -n "$PIDS" ]
			then
				kill -s KILL $PIDS
				while ps -p "$PIDS"
				do
					sleep 1
				done
			fi

			exit 0
			# Exit to kernel newroot
			;;

			3)	# Phase 3 inittab finish boot - network

			# Set the shell debugging if NIM asked.
			${NIM_DEBUG}
			. /etc/niminfo

			# fall through to bottom - phase 3 common code
			;;

			*)	exit 0 ;;

		esac
		;;

	*)
		loopled 0xA06 "UNKNOWN BOOTTYPE"
		;;

esac

unset SYSCFG_PHASE

echo "rc.boot: checking free space in /tmp" | alog -q -t boot
# this removes enough files to create 1024 K free space in /tmp
# if that much space is already free, it does nothing
/usr/lib/boot/bootutil -d /tmp -s 1024 | alog -t boot

# Load the streams modules
echo "rc.boot: executing \"strload\"" | alog -t boot
strload 2>&1 | alog -t boot

# A thinserver having at least one NFS4-mounted FS must have
# nfsrgyd and portmap running in order to resolve the string->id or
# id->string for user/group id/names that are not cached.
# So, start them with the srcmstr and then, kill the srcmstr because it
# will be spawned by /etc/init later in the boot process.
if [ $BOOTYPE -eq 5 -a -n "${NIM_NFS4_MOUNTS}" ]
then
	/usr/sbin/portmap &
	/usr/sbin/nfsrgyd &
fi

# Don't configure the secondary dump device if it's a paging space
# other than hd6.
# Note:  The primary should be hd6 if it's a paging space.
# Get odm entry for the secondary dump device.
dumpparm=
dev=`odmget -q "attribute = 'tsecondary'" SWservAt |\
	awk -F'"' '/value/ {print $2}'`

# See if it's a paging space other than hd6
[[ -n "$dev" ]] && dev=`basename $dev`
if [[ -n "$dev" && "$dev" != "hd6" ]]
then	# Check for paging space.
	lsps $dev >/dev/null 2>&1
	if [[ $? = 0 ]]
	then	# secondary is paging, don't set it now.
		dumpparm='-s /dev/sysdumpnull'
	fi
fi

# For the Remote Dump
# Configure the iSCSI subsystem if the primary dump device is an iSCSI disk

# get current primary dump device
# must be called before current value is overwriten by permanent value
primary=`odmget -q "attribute = 'primary'" SWservAt |\
	awk -F'"' '/value/ {sub(/\/dev\//, ""); print $2}'`

found=`lsdev -l $primary -c disk -s iscsi`
if [ -n "$found" ]
then
    #configure tcp and iscsi sw
    cfg_iscsi_sw

    # configure current primary dump device
    cfgmgr -l $primary | alog -t boot
fi

sysdumpdev -q $dumpparm

# Allow 64-bit apps
echo "rc.boot: allow 64-bit apps" | alog -t boot
/usr/lib/methods/cfg64 | alog -t boot

# Configure live dump
echo "rc.boot: executing \"cfglivedump -c\"" | alog -t boot
/usr/lib/methods/cfglivedump -c | alog -t boot

# Taking firmware-assisted dump if there is one in progress
/usr/sbin/copy_inmem_dump -f | alog -t boot

# Run the configuration manager
echo "rc.boot: executing \"cfgmgr\"" | alog -t boot

/usr/bin/rm -f /.bootsequence /etc/locks/* >/dev/null 2>&1

set +x
KEYPOS=`odmget -q"$ODMSTRNG" CuAt`
if [ -n "$KEYPOS" ]
then
	cfgmgr -p3 -v 2>&1 | alog -t boot	# key is in service position
	/usr/lib/methods/cfgcon
	# this call to swcons disables controlling tty
	swcons -c
else
	# This is for alt_disk_install, to define the console correctly
	if [ -s /etc/inst_info/alt_cons.add1 ]; then
		ODMDIR=/etc/objrepos odmdelete -q \
			"name=sys0 and attribute = tmpcons" -o CuAt
		ODMDIR=/etc/objrepos odmdelete -q \
			"name=sys0 and attribute = altcons" -o CuAt
		ODMDIR=/etc/objrepos odmadd /etc/inst_info/alt_cons.add2
		rm -f /etc/inst_info/alt_cons.add2
	fi

	cfgmgr -p2 -v 2>&1 | alog -t boot	# key is in normal position

	if [ -s /etc/inst_info/alt_cons.add1 ]; then
		ODMDIR=/etc/objrepos odmdelete -q \
			"name=sys0 and attribute = tmpcons" -o CuAt
		ODMDIR=/etc/objrepos odmdelete -q \
			"name=sys0 and attribute = altcons" -o CuAt
		CONS=`grep value /etc/inst_info/alt_cons.add1 | cut -d"\"" -f2`
		chcons $CONS
		rm -f /etc/inst_info/alt_cons.add1
	fi

	/usr/lib/methods/cfgcon
	# this call to swcons disables controlling tty
	swcons -c

	# Setup for System Hang Detection
	# If the emergency login terminal is the console, then change the
	# console mode to be 'share'
	sh_setup

	#
	# If desktop to be started in inittab, then start graphical boot
	#
	RLEVEL=`/usr/bin/cat /etc/.init.state 2>/dev/null`
	DTRUN=`/usr/bin/grep "^dt:" /etc/inittab | /usr/bin/cut -d: -f2`
	DTACT=`/usr/bin/grep "^dt:" /etc/inittab | /usr/bin/cut -d: -f3`
	if [ -n "$DTRUN" -a -s "/etc/rc.dt" -a -s "/usr/bin/X11/aixconsole" \
		-a "$RLEVEL" != "S" -a "$DTACT" != "off" ]
	then
		RUNINFO=`/usr/bin/grep ":initdefault:" /etc/inittab \
			| /usr/bin/cut -d: -f2`
		if [ "$DTRUN" = "$RUNINFO" ] ; then
			>/.bootsequence
			/etc/rc.dt boot | alog -t boot -q
			/usr/bin/sleep 8
		fi
	fi
	#
	# End of Graphical Boot Startup
	#
fi

# Inform kernel of boot progress for VRM entitlement
/usr/lib/boot/bootutil -p

sysdumpdev -q $dumpparm

# Save base customize
# (this must be done AFTER system console setup)

unset AIX_NO_SAVEBASE		# Allow savebase to save data.
echo "\nSaving Base Customize Data to boot disk" | alog -t boot
# savebase for disk booted systems
[ "$BOOTYPE" -eq 1 ] && savebase
# savebase for net boot systems
[ "$BOOTYPE" -eq 5 ] && savebase -d /etc/basecust

# Remove unavailable ttys from inittab
# also remove ttyx if it is serving as the console
/usr/lib/methods/cleantty
sync; sync

if [ -f /etc/rc.B1 ]; then
	/etc/rc.B1 label
fi

echo "Starting the sync daemon" | alog -t boot
nohup /usr/sbin/syncd 60 > /dev/null 2>&1 &

# deleting error notification objects that should not survive reboot
odmdelete -o errnotify -q "en_persistenceflg=0" >/dev/null 2>&1

# prepare diagnostics Service Event queue file for diagela
# error notifications prior to starting the interface to SFP
if [ -x /usr/lpp/diagnostics/bin/diagServiceEvent ]
then
	touch /etc/lpp/diagnostics/data/diagSE_queue
fi

# Get the platform dump directory.
dir=`odmget -q "attribute = 'fwdump_dir'" SWservAt |\
	awk -F'"' '/value/ {print $2}'`
if [[ -n "$dir" ]]
then	# See if FS is defined
	lsfs $dir >/dev/null 2>&1
	if [[ $? = 0 ]]
	then	# mount the fs
		echo "Mounting the platform dump file system, $dir" | alog -t boot
		mount $dir 2>&1 | alog -t boot
	fi
fi

if [ -x /usr/lib/errdemon ]
then
	echo "Starting the error daemon" | alog -t boot
	/usr/bin/rm -f /tmp/errdemon.$$
	/usr/lib/errdemon >/tmp/errdemon.$$ 2>&1
	if [ $? -ne 0 ]
	then
		cat /tmp/errdemon.$$ | alog -t boot
		echo "Starting the errdemon with the system default" \
			"log file, /var/adm/ras/errlog." | alog -t boot
		/usr/lib/errdemon -i /var/adm/ras/errlog
	fi
	/usr/bin/rm -f /tmp/errdemon.$$
fi

#Update etrace kernel variables with ODM values
if [ -x "/usr/bin/probevctrl" ]
then
	/usr/bin/probevctrl -i | alog -t boot
fi

${SHOWLED} 0xFFF

# If shutdown did not end gracefully
rm -f /etc/nologin

# start the mirrod if it exists
[ -x /usr/sbin/mirrord ] && /usr/sbin/mirrord mir_modem

# Configuration check, if it exists
[ -x /usr/lib/methods/cfgchk ] && /usr/lib/methods/cfgchk | alog -t boot

# do diagnostic stuff if this particular machine supports it

bootinfo -M > /dev/null
rc=$?
if [ $rc -eq 101 -o $rc -eq 103 ]; then
	diag_ok=1	# diagnostics are supported
else
	diag_ok=0	# diagnostics are not supported
fi

if [ $diag_ok = 1 ]; then
	# Setup Service boot and display message for missing devices.
	if [ -n "$KEYPOS" ]; then
		# this call to swcons enables controlling tty
		swcons +c
		DIAGD=/usr/lpp/diagnostics/bin
		[ -s $DIAGD/diagsrv ] && \
			$DIAGD/diagsrv -b </dev/console >/dev/console 2>&1
		# diagnostics exits by doing a shutdown, so we should
		#	never get back to this point
	fi
fi

# Complete end of boot tasks
/usr/lib/boot/bootutil -e

# Check for pending power events
/etc/rc.powerfail -p & > /dev/console 2>&1

# Restoring secure NLSPATH value, if it exists
nlspath=`ODMDIR=/usr/lib/objrepos /usr/bin/odmget -q \
	attribute=SEC_NLSPATH PdAt | /usr/bin/awk -F '"' '/deflt/ {print $2}'`

if [ -n "$nlspath" ]
then
	/usr/sbin/chnlspath $nlspath
fi

# Suspend initialization until fw-assisted system dump has completed
/usr/sbin/copy_inmem_dump -s
sysdumpdev -q $dumpparm

echo "System initialization completed." | alog -t boot
echo "B1" `date -u +"%D %r %Z"` "rc.boot complete." | alog -qt cfg

exit 0
