#!/bin/sh -efu

. sh-functions
. shell-error

ignore_missing=
if [ "${1-}" = '--optional' ]; then
	ignore_missing=1
	shift
fi

list_module_files() {
	local l f m a
	for a; do
		l="$(/sbin/modprobe --set-version="$kernel" --show-depends --ignore-all-commands "$a" 2>/dev/null |
			cut -d' ' -f2)"

		for m in ${blacklist-}; do
			for f in "$@" $l; do
				f="${f##*/}"
				f="$(normalize_modname "${f%.ko*}")"
				[ "$f" = "$m" ] ||
					continue
				verbose "Module '$a' is ignored because the '$m' is blacklisted"
				return 1
			done
		done

		printf '%s\n' "$l"
	done
}

add_module_firmware() {
	local mod_name mod_path list name d fwfile

	mod_name="$1"; shift
	mod_path="$1"; shift

	list="$(modinfo -F firmware "$mod_path")" ||
		return 0

	for name in $list; do
		fwfile=
		for d in $FIRMWARE_DIRS; do
			if [ -r "$d/$name" ]; then
				fwfile="$d/$name"
				break
			fi
		done

		if [ -z "$fwfile" ]; then
			message "Firmware file \"$name\" for module \"$mod_name\" not found"
			continue
		fi
		[ ! -f "$rootdir/lib/firmware/$name" ] ||
			continue

		verbose "Adding firmware file \"$fwfile\" for module \"$mod_name\""
		install -pD -- "$fwfile" "$rootdir/lib/firmware/$name"
	done
}

add_module_file() {
	local path="$1" name="$1"
	name="${name##*/}"
	name="${name%.ko*}"

	[ ! -f "$rootdir/$path" ] ||
		return 0

	verbose "Adding module \"$name.ko\""
	put-file "$path"

	add_module_firmware "$name" "$path"
}

add_module() {
	local blocked_module= m list name="$1"
	name="${name##*/}"
	name="${name%.ko*}"

	list="$(list_module_files "$name")" ||
		blocked_module=1

	[ -n "$list" -o -n "$blocked_module" -o -n "$ignore_missing" ] ||
		fatal "No module \"$name\" found for kernel $kernel"

	printf '%s\n' "$list" |
	while read m; do
		[ -n "$m" ] ||
			continue
		add_module_file "$m"
	done
}

for n; do
	if [ -n "${n##*[/\[\].*&^\$\\\\/]*}" ]; then
		add_module "$n"

	elif [ -n "${KERNEL_MODULES-}" ]; then
		find "$KERNEL_MODULES" -type f |egrep -e "$n" |
		while read m; do
			add_module "$m"
		done
	else
		fatal "Unable to handle pattern: $n"
	fi
done
