# -*- shell-script -*-

catenate_cpiogz() {
	# Sanity check
	if [ ! -e "${1}" ]; then
		echo "W:catenate_cpiogz: arg1='${1}' does not exist." >&2
		return
	fi

	cat "${1}" >>"${__TMPCPIOGZ}"
}

force_load()
{
		manual_add_modules ${@}
		echo "${@}" >>"${DESTDIR}/conf/modules"
}

# Takes a file containing a list of modules to be added as an
# argument, figures out dependancies, and adds them.
#
# Input file syntax:
#
#   # comment
#   modprobe_module_name [args ...]
#   [...]
#
add_modules_from_file()
{
	# Sanity check
	if [ ! -e "${1}" ]; then
		echo "W:add_modules_from_file: arg1='${1}' does not exist." >&2
		return
	fi

	sed -e '/^#/d' ${1} | while read module rest; do
		force_load "${module}" "${rest}"
	done
}

manual_add_modules()
{
	for mam_x in $(modprobe --set-version="${version}" --ignore-install \
	--show-depends "${1}" 2>/dev/null | awk '/^insmod/ { print $2 }'); do
		# Prune duplicates
		if [ -e "${DESTDIR}/${mam_x}" ]; then
			continue
		fi

		mkdir -p "${DESTDIR}/$(dirname "${mam_x}")"
		ln -s "${mam_x}" "${DESTDIR}/$(dirname "${mam_x}")"
		if [ -n "${verbose}" ] && [ "${verbose}" = "y" ]; then
			echo "Adding module ${mam_x}"
		fi
	done
}

manual_add_firmware()
{
	for x_firm in $(find "/lib/firmware/${version}" -name "${1}" -print 2>/dev/null); do
		if [ -e "${DESTDIR}/${x_firm}" ]; then
			continue
		fi

		mkdir -p "${DESTDIR}/$(dirname "${x_firm}")"
		ln -s "${x_firm}" "${DESTDIR}/$(dirname "${x_firm}")"
		if [ -n "${verbose}" -a "${verbose}" = "y" ]; then
			echo "Adding firmware ${x_firm}"
		fi
        done
}

# $1 is source
# $2 is relative destination
copy_exec() {
	final_destination=${DESTDIR}/${2}/`basename ${1}`
	if [ -L "$final_destination" ]; then
		if ! [ `readlink ${final_destination}` = "${1}" ]; then
			echo "W:copy_exec: Not copying ${1} to \$DESTDIR${2}/`basename ${1}`, which is already a copy of `readlink ${final_destination}`" >&2
			return
		fi
	else
		ln -s ${1} ${DESTDIR}/${2}
		if [ -n "${verbose}" ] && [ "${verbose}" = "y" ]; then
			echo "Adding binary ${1}"
		fi
	fi

	# Copy the dependant libraries
	for x in $(ldd ${1} 2>/dev/null | sed -e '
	    /\//!d;
	    /linux-gate/d;
	    /=>/ {s/.*=>[[:blank:]]*\([^[:blank:]]*\).*/\1/};
	    s/[[:blank:]]*\([^[:blank:]]*\) (.*)/\1/' 2>/dev/null); do

		# Try to use non-optimised libraries where possible.
		# We assume that all HWCAP libraries will be in tls.
		nonoptlib=$(echo ${x} | sed -e 's#/lib/tls.*/\(lib.*\)#/lib/\1#')

		if [ -e ${nonoptlib} ]; then
			x=${nonoptlib}
		fi

		libname=$(basename ${x})
		dirname=$(dirname ${x})

		mkdir -p ${DESTDIR}/${dirname}
		if [ ! -e ${DESTDIR}/${dirname}/${libname} ]; then
			ln -s ${x} ${DESTDIR}/${dirname}
			if [ -n "${verbose}" ] && [ "${verbose}" = "y" ]; then
				echo "Adding library ${x}"
			fi
		fi
	done
}

# Copy entire subtrees to the initramfs
copy_modules_dir()
{
	if ! [ -d "${MODULESDIR}/${1}" ]; then
		return;
	fi
	if [ -n "${verbose}" ] && [ "${verbose}" = "y" ]; then
		echo "Copying module directory ${1}"
	fi
	for x_mod in $(find "${MODULESDIR}/${1}" -name '*.ko' -print); do
		manual_add_modules `basename ${x_mod} .ko`
	done
}

dep_add_modules()
{

	# Things that are too hard to autodetect.
	for x in md raid0 raid1 raid5 raid6 ext2 ext3 isofs jfs nfs reiserfs udf xfs af_packet dm_mod; do
		manual_add_modules ${x}
	done

	for x in /sys/bus/pci/devices/*; do
		if [ -e "${x}/modalias" ]; then
			manual_add_modules $(cat "${x}/modalias")
		fi
	done

	for x in /sys/bus/usb/devices/*; do
		if [ -e "${x}/modalias" ]; then
			manual_add_modules $(cat "${x}/modalias")
		fi
	done

	if [ -e /proc/ide ]; then
		for x in ide-generic ide-disk ide-cd; do
			manual_add_modules "${x}"
		done
	fi

	if [ -e /sys/bus/scsi/devices/ ]; then
		manual_add_modules sd_mod
		if [ -e /sys/module/qla2xxx/ ]; then
			for x in 100 200 300 322 400; do
				manual_add_firmware "ql2${x}_fw.bin"
			done
		fi
		if [ -e /sys/module/aic94xx/ ]; then
			manual_add_modules sd_mod
			manual_add_firmware "aic94xx-seq.fw"
		fi
	fi

	if [ -e /sys/bus/i2o/devices/ ]; then
		manual_add_modules i2o_block
	fi

	if [ -e /sys/bus/ps3_system_bus/ ]; then
		for x in ps3disk ps3rom ps3-gelic ps3_storage gelic_net ohci-hcd ehci-hcd; do
			manual_add_modules "${x}"
		done
	fi

	if [ -e /sys/bus/vio/ ]; then
		for x in sunvnet sunvdc; do
			manual_add_modules "${x}"
		done
	fi
}


auto_add_firmware()
{
	case "$1" in
	scsi)
		for x in 100 200 300 322 400; do
			manual_add_firmware "ql2${x}_fw.bin"
		done
		manual_add_firmware "aic94xx-seq.fw"
	;;
	*)
		auto_add_firmware scsi
	;;
	esac
}

# The modules "most" classes added per default to the initramfs
auto_add_modules()
{
	case "$1" in
	base)
		for x in ehci-hcd ohci-hcd uhci-hcd usbhid usb-storage ext2 \
		ext3 isofs jfs nfs reiserfs udf xfs af_packet atkbd i8042 \
		virtio_pci vfat nls_cp437 nls_iso8859-1; do
			manual_add_modules "${x}"
		done
	;;
	net)
		for x in 3c59x 8139cp 8139too 8390 b44 bmac bnx2 defxx \
		dl2k e1000 e100 ehea epic100 ep93xx_eth eql fealnx \
		famachi forcedeth  hp100 mace mv643xx_eth myri10ge \
		natsemi ne2k-pci netconsole ns83820 pcnet32 qla3xxx \
		r8169 s2io sis900 skge slhc smc911x starfire \
		sundance sungem sungem_phy sunhme sunvnet tg3 tlan de2104x \
		de4x5 dmfe tulip winbond-840 xircom_cb xircom_tulip_cb \
		typhon via-rhine via-velocity yellowfin gelic_net; do
			manual_add_modules "${x}"
		done
	;;
	ide)
		copy_modules_dir kernel/drivers/ide
	;;
	scsi)
		copy_modules_dir kernel/drivers/scsi
		for x in mptfc mptsas mptscsih mptspi; do
			manual_add_modules "${x}"
		done
		auto_add_firmware scsi
	;;
	ata)
		copy_modules_dir kernel/drivers/ata
	;;
	block)
		copy_modules_dir kernel/drivers/block
	;;
	ieee1394)
		for x in ohci1394 sbp2; do
			manual_add_modules "${x}"
		done
	;;
	i2o)
		for x in i2o_block; do
			manual_add_modules "${x}"
		done
	;;
	dasd)
		for x in dasd_eckd_mod dasd_fba_mod; do
			manual_add_modules "${x}"
		done
	;;
	*)
		auto_add_modules base
		auto_add_modules net
		auto_add_modules ide
		auto_add_modules scsi
		auto_add_modules ata
		auto_add_modules i2o
		auto_add_modules dasd
		auto_add_modules ieee1394
		auto_add_modules block
	;;
	esac
}

usage()
{
	cat >&2 << EOF

Usage: ${0} [OPTION]... <-o outfile> [version]

Options:
  -d confdir  Specify an alternative configuration directory.
  -k          Keep temporary directory used to make the image.
  -o outfile  Write to outfile.
  -r root     Override ROOT setting in mkinitrd.conf.

See mkinitramfs(8) for further details.
EOF
	exit 1

}

# minimal supported kernel version
check_minkver()
{
	curversion=${1}
	initdir=${2}
	if [ -z ${initdir} ]; then
		DPKG_ARCH=`dpkg --print-installation-architecture`
		case ${DPKG_ARCH} in
			ia64|hppa)
				minversion="2.6.15"
			;;
			*)
				minversion="2.6.12"
			;;
		esac
		if dpkg --compare-versions "${curversion}" lt "${minversion}"; then
			echo "W: kernel ${curversion} too old for initramfs on ${DPKG_ARCH}" >&2
			echo "W: not generating requested initramfs for kernel ${curversion}" >&2
			exit 2
		fi
		return 0
	fi
	set_initlist
	for cm_x in ${initlist}; do
		tmp=$(eval echo $(grep ^MINKVER ${initdir}/${cm_x} | cut -d'=' -f2))
		if dpkg --compare-versions "${curversion}" lt "${tmp}"; then
			echo "W: ${cm_x} hook script requires at least kernel version ${tmp}" >&2
			echo "W: not generating requested initramfs for kernel ${curversion}" >&2
			exit 2
		fi
	done
}
