2008-03-07 22:48:01 +03:00
#!/bin/sh
2008-03-07 19:03:47 +03:00
PROG=mkmodpack
VERSION=0.1
CATCHED=
Exit()
{
local rc=$?
[ -z "$1" ] || rc="$1"
CATCHED=1
exit $rc
}
Warning()
{
echo "$PROG: warning: $*" >&2
}
Fatal()
{
echo "$PROG: $*" >&2
Exit 1
}
KERNEL=
OUTPUT=
WORKDIR=
TEMPLATE=
pattern=
uname_r="$(uname -r)"
exit_handler()
{
local rc=$?
trap - EXIT
[ -n "$CATCHED" -o $rc -eq 0 ] ||
echo "$PROG: unhandled error, exiting..."
[ -z "$WORKDIR" ] || rm -rf "$WORKDIR"
[ -z "$TEMPLATE" ] || rm -f "$TEMPLATE"
exit $rc
}
signal_handler()
{
echo 'Interrupted!' >&2
Exit 1
}
trap exit_handler EXIT
trap signal_handler SIGHUP SIGPIPE SIGINT SIGTERM SIGQUIT
FIRMWARE_DIRS="/lib/firmware /usr/lib/hotplug/firmware"
Usage()
{
cat >&2 <<EOF
mkmodpack - creates an cpio archive, containing subset of kernel modules.
mkmodpack is free software, covered by the GNU General Public License.
mkmodpack comes with ABSOLUTELY NO WARRANTY, see license for details.
Usage: $PROG [options]
Valid options are:
--version print version number and exit.
-k, --kernel assume given kernel version, instead of uname -r.
-o, --output output filename, stdout if omitted.
-p, --pattern place into archive only modules which match one of pattern from given file.
-h, --help show this text.
Example: $PROG -o modpack -k $uname_r
EOF
[ -n "$1" ] && Exit "$1" || Exit
}
#---------------------------------------------------------------
ListModules()
{
if [ -s "$pattern" ]; then
2012-08-10 14:23:37 +04:00
find /lib/modules/$KERNEL -type f 2>/dev/null |grep -wf "$pattern"
2008-03-07 19:03:47 +03:00
else
2012-08-10 14:23:37 +04:00
find /lib/modules/$KERNEL -type f 2>/dev/null
2008-03-07 19:03:47 +03:00
fi
}
ListModuleFiles()
{
2012-08-10 14:23:37 +04:00
modprobe --set-version="$KERNEL" --show-depends "$@" 2>/dev/null
2008-03-07 19:03:47 +03:00
}
AddUniqueModule()
{
local path="$1" modules=
modules="$MODULES
$path"
modules="$(echo "$modules" |sort)"
if [ -z "$(echo "$modules" |uniq -d)" ]; then
echo "$modules"
fi
}
AddModuleFile()
{
local path="$1" name="$1" modules=
name="${name##*/}"
name="${name%.gz}"
2012-01-06 00:00:50 +04:00
name="${name%.xz}"
2008-03-07 19:03:47 +03:00
name="${name%.ko}"
modules=$(AddUniqueModule "$path")
if [ -n "$modules" ]; then
MODULES="$modules"
AddModuleFirmware "$name" "$path"
fi
}
AddModuleFirmware()
{
local mod_name="$1" && shift
local mod_path="$1" && shift
2010-04-01 17:32:10 +04:00
local fw_list fw_name fw_dir fw_file fw_privdir
2008-03-07 19:03:47 +03:00
fw_list="$(modinfo -F firmware "$mod_path")" || return
[ -n "$fw_list" ] || return
for fw_name in $fw_list; do
fw_file=
for fw_dir in $FIRMWARE_DIRS; do
if [ -r "$fw_dir/$fw_name" ]; then
fw_file="$fw_dir/$fw_name"
break
fi
done
[ -n "$fw_file" ] || {
Warning "Firmware file \"$fw_name\" for module \"$mod_name\" not found"
continue
}
2021-07-21 18:22:16 +03:00
fw_privdir=$fw_name
while [ ! "$fw_privdir" = "${fw_name%%/*}" ]; do
fw_privdir="${fw_privdir%/*}"
FILES="$FILES
2010-04-01 17:32:10 +04:00
dir /lib/firmware/$fw_privdir 0755 0 0"
2021-07-21 18:22:16 +03:00
done
2008-03-07 19:03:47 +03:00
FILES="$FILES
file /lib/firmware/$fw_name $fw_file 0644 0 0"
done
}
AddModule()
{
local path="$1" name="$1" m list
name="${name##*/}"
name="${name%.gz}"
2012-01-06 00:00:50 +04:00
name="${name%.xz}"
2008-03-07 19:03:47 +03:00
name="${name%.ko}"
list=`ListModuleFiles "$name"`
for m in $list; do
[ -z "${m##/lib/modules/*}" ] || continue
AddModuleFile "$m"
done
}
TEMP=`getopt -n "$0" -o k:,o:,p:,h -l kernel:,output:,pattern:,help,version -- "$@"` || exit 1
eval set -- "$TEMP"
while :; do
case "$1" in
-k|--kernel)
shift
KERNEL="$1"
;;
-o|--output)
shift
OUTPUT="$1"
;;
-p|--pattern*)
shift
pattern="$1"
;;
-h|--help)
Usage 0
;;
--version)
echo "$PROG: version $VERSION"
exit 0
;;
--) shift; break
;;
*) Fatal "Unrecognized option: $1"
;;
esac
shift
done
2008-03-07 22:48:01 +03:00
[ -n "$KERNEL" ] || KERNEL="$uname_r"
2008-03-07 19:03:47 +03:00
[ -d "/lib/modules/$KERNEL" ] || Fatal "Directory /lib/modules/$KERNEL does not exists."
2012-10-15 16:06:07 +04:00
# modprobe from kmod-9+ *requires* modules.dep.bin (ALT #27640)
if [ ! -f /lib/modules/$KERNEL/modules.dep.bin ]; then
2012-08-13 21:38:25 +04:00
depmod -a -F "/boot/System.map-$KERNEL" "$KERNEL" ||
Fatal "Failed to create modules dependencies (full)."
fi
2008-03-07 19:03:47 +03:00
#---------------------------------------------------------------
2009-06-25 19:15:54 +04:00
FIRMWARE_DIRS="$FIRMWARE_DIRS /lib/firmware/$KERNEL"
2008-03-07 19:03:47 +03:00
MODULES=
FILES=
for m in $(ListModules); do
AddModule "$m"
done
WORKDIR=`mktemp -td mkmodpack.XXXXXXXXXX` || Fatal "Failed to create working directory."
TEMPLATE=`mktemp -t mkmodpack.XXXXXXXXXX` || Fatal "Failed to create temporary file."
echo "$MODULES" |cpio -pmd "$WORKDIR" 2>/dev/null || Fatal "Failed to copy modules to working directory."
2008-03-07 22:48:01 +03:00
depmod -a -F "/boot/System.map-$KERNEL" -b "$WORKDIR" "$KERNEL" || Fatal "Failed to create modules dependencies."
2008-03-07 19:03:47 +03:00
(
cd "$WORKDIR"
find "lib/modules/$KERNEL" -type d |sed -e 's,^.\+$,dir\t/&\t0755\t0 0,g'
find "lib/modules/$KERNEL" -type f |sed -e "s,^.\+$,file\t/&\t$WORKDIR/&\t0644\t0 0,g"
2021-07-21 18:22:16 +03:00
echo "$FILES"|sort -k2|uniq
2008-03-07 19:03:47 +03:00
) > "$TEMPLATE"
if [ -n "$OUTPUT" ]; then
gencpio "$TEMPLATE" |gzip -c > "$OUTPUT"
else
gencpio "$TEMPLATE" |gzip -c
fi
2020-12-18 19:38:54 +03:00
if [ -s "$pattern" ]; then
for m in `grep -v '#' "$pattern" | sort -u`; do
name="${m##*/}"
name="${name%.gz}"
name="${name%.xz}"
name="${name%.ko}"
# Omit built-in modules whose names match in modprobe output and in "pattern"
ListModuleFiles "$name" | grep "builtin" | grep -q "$name" 2>/dev/null && continue
echo "$MODULES" | grep -qw "$m" 2>/dev/null || Warning "Module pattern \"$m\" doesn't match anything."
done
fi
2008-03-07 19:03:47 +03:00
Exit 0