2020-05-19 09:59:40 +05:30
|
|
|
#!/bin/sh
|
2020-01-05 23:31:39 +05:30
|
|
|
#
|
2021-05-10 17:12:11 +05:30
|
|
|
# Tiny initramfs
|
2020-04-15 22:20:45 +05:30
|
|
|
#
|
2021-05-10 17:12:11 +05:30
|
|
|
# https://www.shellcheck.net/wiki/SC2154
|
2020-06-28 10:14:36 +05:30
|
|
|
# shellcheck disable=2154
|
2020-01-05 23:31:39 +05:30
|
|
|
|
2020-04-21 20:05:55 +05:30
|
|
|
print()
|
|
|
|
{
|
2020-05-07 17:36:34 +05:30
|
|
|
printf "%b %s\n" "${2:-"\033[1;37m>>\033[m"}" "$1"
|
2020-04-21 20:05:55 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
panic()
|
|
|
|
{
|
2020-05-07 17:36:34 +05:30
|
|
|
print "${1:-unexpected error occurred}" \
|
2021-05-10 17:12:11 +05:30
|
|
|
"\033[1;31m!!\033[m"
|
|
|
|
|
|
|
|
exit 1
|
|
|
|
} >&2
|
2020-01-05 23:31:39 +05:30
|
|
|
|
2020-04-12 01:01:02 +05:30
|
|
|
usage()
|
|
|
|
{
|
2020-02-22 23:16:57 +05:30
|
|
|
cat << EOF
|
2021-05-10 17:12:11 +05:30
|
|
|
usage: ${0##*/} [option]...
|
2021-05-10 18:30:51 +05:30
|
|
|
-o, --output <file> set path to initramfs image
|
|
|
|
-c, --config <file> set path to config
|
|
|
|
-k, --kernel <ver> set kernel version
|
|
|
|
-m, --modules <dir> set path to modules
|
|
|
|
-H, --hooks <dir> set directory to hooks
|
|
|
|
-D, --helper <file> set path to device helper
|
|
|
|
-I, --init <file> set path to init script
|
|
|
|
-d, --debug enable debug mode
|
|
|
|
-f, --force overwrite initramfs image
|
2020-02-22 23:16:57 +05:30
|
|
|
EOF
|
|
|
|
}
|
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
parse_arguments()
|
2020-04-12 01:01:02 +05:30
|
|
|
{
|
2020-04-15 22:20:45 +05:30
|
|
|
while [ "$1" ]; do case "$1" in
|
|
|
|
-o | --output)
|
2020-06-28 09:28:57 +05:30
|
|
|
output="${2:?}"; shift 2
|
2020-04-15 22:20:45 +05:30
|
|
|
;;
|
|
|
|
-c | --config)
|
2020-06-28 09:28:57 +05:30
|
|
|
config="${2:?}"; shift 2
|
|
|
|
;;
|
2020-04-15 22:20:45 +05:30
|
|
|
-k | --kernel)
|
2020-06-28 09:28:57 +05:30
|
|
|
kernel="${2:?}"; shift 2
|
2020-04-15 22:20:45 +05:30
|
|
|
;;
|
2021-05-10 18:30:51 +05:30
|
|
|
-m | --modules)
|
|
|
|
moddir="${2:?}"; shift 2
|
|
|
|
;;
|
2020-06-28 09:28:57 +05:30
|
|
|
-H | --hooks)
|
|
|
|
hksdir="${2:?}"; shift 2
|
2020-04-15 22:20:45 +05:30
|
|
|
;;
|
2021-05-10 18:30:51 +05:30
|
|
|
-D | --helper)
|
|
|
|
helper="${2:?}"; shift 2
|
|
|
|
;;
|
|
|
|
-I | --init)
|
|
|
|
init="${2:?}"; shift 2
|
|
|
|
;;
|
2020-04-15 22:20:45 +05:30
|
|
|
-d | --debug)
|
2020-06-28 09:28:57 +05:30
|
|
|
debug=1; shift 1
|
2020-04-15 22:20:45 +05:30
|
|
|
;;
|
|
|
|
-f | --force)
|
2020-06-28 09:28:57 +05:30
|
|
|
force=1; shift 1
|
2020-04-15 22:20:45 +05:30
|
|
|
;;
|
|
|
|
-h | --help)
|
2020-05-07 17:36:34 +05:30
|
|
|
usage; exit 0
|
2020-04-15 22:20:45 +05:30
|
|
|
;;
|
|
|
|
*)
|
2021-05-10 17:12:11 +05:30
|
|
|
printf "invalid option: %s\n" "$1"
|
2020-05-07 17:36:34 +05:30
|
|
|
|
|
|
|
usage; exit 1
|
2020-04-15 22:20:45 +05:30
|
|
|
;;
|
|
|
|
esac; done
|
2020-02-22 23:16:57 +05:30
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# https://www.shellcheck.net/wiki/SC1090
|
2020-06-28 10:14:36 +05:30
|
|
|
# shellcheck disable=1090
|
2020-07-03 21:19:09 +05:30
|
|
|
. "${config:=/etc/tinyramfs/config}"
|
2020-03-08 06:48:07 +05:30
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
: "${kernel:=$(uname -r)}"
|
|
|
|
: "${moddir:=/lib/modules}"
|
2021-05-10 18:30:51 +05:30
|
|
|
: "${init:=/usr/share/tinyramfs/init}"
|
|
|
|
: "${helper:=/usr/share/tinyramfs/device-helper}"
|
|
|
|
: "${output:=${TMPDIR:-/tmp}/tinyramfs-${kernel}}"
|
2020-02-24 13:39:37 +05:30
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
mkdir -p "${tmpdir:=${TMPDIR:-/tmp}/tinyramfs.$$}"
|
2020-04-21 20:05:55 +05:30
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# https://www.shellcheck.net/wiki/SC2015
|
2020-07-03 21:19:09 +05:30
|
|
|
# shellcheck disable=2015
|
|
|
|
[ "$debug" = 1 ] && set -x || trap 'rm -rf $tmpdir' EXIT INT
|
2020-02-11 04:18:51 +05:30
|
|
|
}
|
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
prepare_initramfs()
|
2020-04-12 01:01:02 +05:30
|
|
|
{
|
2020-06-28 09:28:57 +05:30
|
|
|
print "preparing initramfs"
|
2020-04-21 20:05:55 +05:30
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# https://wikipedia.org/wiki/Filesystem_Hierarchy_Standard
|
2020-06-28 09:28:57 +05:30
|
|
|
mkdir -p \
|
|
|
|
"${tmpdir}/dev" \
|
|
|
|
"${tmpdir}/sys" \
|
|
|
|
"${tmpdir}/tmp" \
|
|
|
|
"${tmpdir}/run" \
|
|
|
|
"${tmpdir}/var" \
|
|
|
|
"${tmpdir}/proc" \
|
|
|
|
"${tmpdir}/root" \
|
|
|
|
"${tmpdir}/usr/lib" \
|
|
|
|
"${tmpdir}/usr/bin" \
|
|
|
|
"${tmpdir}/mnt/root" \
|
|
|
|
"${tmpdir}/etc/tinyramfs"
|
|
|
|
|
|
|
|
ln -s usr/lib "${tmpdir}/lib"
|
|
|
|
ln -s usr/bin "${tmpdir}/bin"
|
|
|
|
ln -s usr/bin "${tmpdir}/sbin"
|
|
|
|
ln -s ../run "${tmpdir}/var/run"
|
|
|
|
ln -s ../run/lock "${tmpdir}/var/lock"
|
|
|
|
ln -s bin "${tmpdir}/usr/sbin"
|
|
|
|
|
|
|
|
for _binary in \
|
2021-05-16 05:09:18 +05:30
|
|
|
\[ sh ln env mkdir sleep mount \
|
2021-05-10 18:30:51 +05:30
|
|
|
printf switch_root "$helper"
|
2020-05-07 17:36:34 +05:30
|
|
|
do
|
2020-06-28 09:28:57 +05:30
|
|
|
copy_binary "$_binary"
|
2020-02-25 16:21:20 +05:30
|
|
|
done
|
2020-04-12 01:01:02 +05:30
|
|
|
|
2020-09-11 01:23:39 +05:30
|
|
|
command -v blkid > /dev/null && copy_binary blkid
|
2020-07-16 00:53:12 +05:30
|
|
|
|
2021-05-10 18:30:51 +05:30
|
|
|
copy_file "$init" /init 755 0
|
|
|
|
copy_file "$config" /etc/tinyramfs/config 644 0
|
2020-01-30 19:23:17 +05:30
|
|
|
}
|
|
|
|
|
2020-08-30 01:03:12 +05:30
|
|
|
copy_file()
|
|
|
|
(
|
|
|
|
file="$1"; dest="$2"; mode="$3"; strip="$4"
|
|
|
|
|
2020-09-09 01:06:20 +05:30
|
|
|
[ -e "${tmpdir}${dest}" ] && return 0
|
2020-08-30 01:03:12 +05:30
|
|
|
|
2020-09-09 01:06:20 +05:30
|
|
|
mkdir -p "${tmpdir}${dest%/*}" || panic
|
2020-08-30 01:03:12 +05:30
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# Iterate throught symlinks and copy them
|
2020-08-30 01:03:12 +05:30
|
|
|
while [ -h "$file" ]; do
|
2020-09-09 02:02:54 +05:30
|
|
|
cp -P "$file" "${tmpdir}${dest%/*}/${file##*/}"
|
2020-08-30 01:03:12 +05:30
|
|
|
cd -P "${file%/*}"
|
|
|
|
|
|
|
|
symlink=$(ls -ld "$file")
|
2020-09-09 01:06:20 +05:30
|
|
|
symlink="${symlink##* -> }"
|
2020-08-30 01:03:12 +05:30
|
|
|
file="${PWD}/${symlink##*/}"
|
|
|
|
done
|
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# Handle case when file and dest have same basenames
|
2020-09-09 02:02:54 +05:30
|
|
|
[ -h "${tmpdir}${dest}" ] && dest="${dest%/*}/${file##*/}"
|
|
|
|
|
2020-08-30 01:03:12 +05:30
|
|
|
{
|
|
|
|
cp "$file" "${tmpdir}${dest}"
|
2020-09-09 01:06:20 +05:30
|
|
|
chmod "$mode" "${tmpdir}${dest}"
|
2020-08-30 01:03:12 +05:30
|
|
|
} || panic
|
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# https://www.shellcheck.net/wiki/SC2015
|
2020-08-30 01:03:12 +05:30
|
|
|
# shellcheck disable=2015
|
2020-09-09 01:06:20 +05:30
|
|
|
[ "$strip" = 1 ] && strip "${tmpdir}${dest}" > /dev/null 2>&1 || :
|
2020-08-30 01:03:12 +05:30
|
|
|
)
|
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
copy_binary()
|
2020-04-12 01:01:02 +05:30
|
|
|
{
|
2020-06-28 09:28:57 +05:30
|
|
|
binary=$(command -v "$1")
|
2020-04-15 22:20:45 +05:30
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# If output is
|
|
|
|
#
|
|
|
|
# empty, do panic
|
|
|
|
# external command, do nothing
|
|
|
|
# builtin command, try to find external alternative.
|
|
|
|
#
|
|
|
|
# https://www.shellcheck.net/wiki/SC2086
|
2020-07-03 21:19:09 +05:30
|
|
|
# shellcheck disable=2086
|
2020-06-28 09:28:57 +05:30
|
|
|
case "$binary" in */*) ;;
|
|
|
|
"")
|
|
|
|
panic "$1 does not exist"
|
2020-05-07 17:36:34 +05:30
|
|
|
;;
|
2020-06-28 09:28:57 +05:30
|
|
|
*)
|
|
|
|
IFS=:; set -- $PATH; unset IFS
|
2020-04-18 15:46:05 +05:30
|
|
|
|
2021-05-12 17:54:57 +05:30
|
|
|
_binary="$binary"
|
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
for _dir; do
|
2021-05-12 17:54:57 +05:30
|
|
|
binary="${_dir}/${_binary}"
|
2020-02-22 23:16:57 +05:30
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
[ -x "$binary" ] && break
|
2021-05-12 17:54:57 +05:30
|
|
|
done || panic "$_binary does not exist"
|
2020-05-07 17:36:34 +05:30
|
|
|
;;
|
2020-06-28 09:28:57 +05:30
|
|
|
esac
|
2020-05-07 17:36:34 +05:30
|
|
|
|
2020-09-09 01:06:20 +05:30
|
|
|
copy_file "$binary" "/bin/${binary##*/}" 755 1
|
2020-05-07 17:36:34 +05:30
|
|
|
|
2021-05-10 18:30:51 +05:30
|
|
|
# Skip copying binary dependencies if ldd not available.
|
2021-05-10 18:35:36 +05:30
|
|
|
command -v ldd > /dev/null || return 0
|
2021-05-10 18:30:51 +05:30
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# Copy binary dependencies if any exist.
|
2020-06-28 09:28:57 +05:30
|
|
|
ldd "$binary" 2> /dev/null |
|
2020-01-25 16:57:02 +05:30
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
while read -r _library || [ "$_library" ]; do
|
2020-02-09 23:15:10 +05:30
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
_library="${_library#* => }"
|
|
|
|
_library="${_library% *}"
|
2020-04-16 10:07:45 +05:30
|
|
|
|
2020-08-22 00:22:18 +05:30
|
|
|
[ -e "$_library" ] || continue
|
|
|
|
|
2020-09-09 01:06:20 +05:30
|
|
|
copy_file "$_library" "/lib/${_library##*/}" 755 1
|
2020-06-28 09:28:57 +05:30
|
|
|
done
|
2020-01-30 19:23:17 +05:30
|
|
|
}
|
2020-01-19 02:31:21 +05:30
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
copy_module()
|
2020-04-12 01:01:02 +05:30
|
|
|
{
|
|
|
|
module="$1"
|
2020-02-18 13:23:03 +05:30
|
|
|
|
2020-04-12 01:01:02 +05:30
|
|
|
modprobe -S "$kernel" -D "$module" 2> /dev/null |
|
2020-02-22 23:16:57 +05:30
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
while read -r _ module || [ "$module" ]; do
|
2020-02-27 23:47:05 +05:30
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# Skip builtin modules.
|
|
|
|
case "$module" in */*) ;; *) continue; esac
|
2020-04-18 21:15:24 +05:30
|
|
|
|
2020-09-09 01:06:20 +05:30
|
|
|
copy_file "$module" "$module" 644 0
|
2020-05-26 19:14:20 +05:30
|
|
|
done
|
2020-02-12 00:17:36 +05:30
|
|
|
}
|
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
copy_hook()
|
2020-04-12 01:01:02 +05:30
|
|
|
{
|
2020-06-28 09:28:57 +05:30
|
|
|
hook="$1"
|
2020-02-22 23:16:57 +05:30
|
|
|
|
2021-05-22 00:54:08 +05:30
|
|
|
for hook_dir in "$hksdir" /etc/tinyramfs/hooks /usr/share/tinyramfs/hooks; do
|
|
|
|
[ -f "${hook_dir}/${hook}/${hook}" ] && break
|
2020-09-06 19:16:46 +05:30
|
|
|
done || panic "could not find $hook hook"
|
|
|
|
|
|
|
|
print "running $hook hook"
|
2020-02-25 16:21:20 +05:30
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# https://www.shellcheck.net/wiki/SC1090
|
2020-09-06 19:16:46 +05:30
|
|
|
# shellcheck disable=1090
|
2021-05-22 00:54:08 +05:30
|
|
|
. "${hook_dir}/${hook}/${hook}"
|
2020-04-12 01:01:02 +05:30
|
|
|
|
2020-09-11 01:23:39 +05:30
|
|
|
for _type in init init.late; do
|
2021-05-22 00:54:08 +05:30
|
|
|
[ -f "${hook_dir}/${hook}/${hook}.${_type}" ] || continue
|
2020-02-05 19:28:58 +05:30
|
|
|
|
2020-09-11 01:23:39 +05:30
|
|
|
print "copying ${hook}.${_type}"
|
2020-05-07 17:36:34 +05:30
|
|
|
|
2021-05-22 00:54:08 +05:30
|
|
|
copy_file "${hook_dir}/${hook}/${hook}.${_type}" \
|
2020-09-11 01:23:39 +05:30
|
|
|
"/usr/share/tinyramfs/hooks/${hook}/${hook}.${_type}" 644 0
|
2020-09-06 19:16:46 +05:30
|
|
|
done
|
2020-02-06 21:51:00 +05:30
|
|
|
}
|
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
copy_modules()
|
2020-04-12 01:01:02 +05:30
|
|
|
{
|
2021-05-10 17:12:11 +05:30
|
|
|
# Skip this function if kernel
|
|
|
|
# compiled with builtin modules.
|
2020-06-28 09:28:57 +05:30
|
|
|
if [ "$monolith" = 1 ]; then
|
|
|
|
return 0
|
2020-05-07 17:36:34 +05:30
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
elif [ "$hostonly" = 1 ]; then
|
|
|
|
print "copying hostonly modules"
|
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# Perform autodetection of modules via /sys
|
|
|
|
# https://wiki.archlinux.org/index.php/Modalias
|
2020-06-28 09:28:57 +05:30
|
|
|
find /sys/devices -name modalias -exec sort -u {} + |
|
|
|
|
|
|
|
|
while read -r _module || [ "$_module" ]; do
|
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# Skip unneeded modules and skip modules which
|
|
|
|
# depends on them as well.
|
2020-06-28 09:28:57 +05:30
|
|
|
case $(modprobe -S "$kernel" -D "$_module") in
|
|
|
|
*wmi* | *gpu* | *net*) continue ;;
|
|
|
|
esac 2> /dev/null
|
|
|
|
|
|
|
|
copy_module "$_module"
|
|
|
|
done
|
|
|
|
|
|
|
|
if [ "$root_type" ]; then
|
|
|
|
copy_module "$root_type"
|
|
|
|
else
|
|
|
|
while read -r _ _dir _type _; do
|
2021-05-10 17:12:11 +05:30
|
|
|
[ "$_dir" = / ] && break
|
|
|
|
done < /proc/mounts || panic "failed to autodetect root fs module"
|
2020-06-28 09:28:57 +05:30
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
copy_module "$_type"
|
2020-06-28 09:28:57 +05:30
|
|
|
fi
|
2020-05-07 17:36:34 +05:30
|
|
|
else
|
2020-06-28 09:28:57 +05:30
|
|
|
print "copying all modules"
|
|
|
|
|
|
|
|
find \
|
|
|
|
"${moddir}/${kernel}/kernel/fs" \
|
|
|
|
"${moddir}/${kernel}/kernel/lib" \
|
|
|
|
"${moddir}/${kernel}/kernel/arch" \
|
|
|
|
"${moddir}/${kernel}/kernel/crypto" \
|
|
|
|
"${moddir}/${kernel}/kernel/drivers/md" \
|
|
|
|
"${moddir}/${kernel}/kernel/drivers/ata" \
|
|
|
|
"${moddir}/${kernel}/kernel/drivers/scsi" \
|
|
|
|
"${moddir}/${kernel}/kernel/drivers/block" \
|
|
|
|
"${moddir}/${kernel}/kernel/drivers/virtio" \
|
|
|
|
"${moddir}/${kernel}/kernel/drivers/usb/host" \
|
|
|
|
"${moddir}/${kernel}/kernel/drivers/usb/storage" \
|
|
|
|
-type f 2> /dev/null |
|
|
|
|
|
|
|
|
while read -r _module || [ "$_module" ]; do
|
2021-05-10 18:30:51 +05:30
|
|
|
copy_file "$_module" "/lib/modules/${_module#$moddir}" 644 0
|
2020-06-28 09:28:57 +05:30
|
|
|
done
|
2020-05-07 17:36:34 +05:30
|
|
|
fi
|
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
copy_binary modprobe
|
2020-05-07 17:36:34 +05:30
|
|
|
|
2021-05-10 18:30:51 +05:30
|
|
|
copy_file "${moddir}/${kernel}/modules.order" \
|
|
|
|
"/lib/modules/${kernel}/modules.order" 644 0
|
|
|
|
|
|
|
|
copy_file "${moddir}/${kernel}/modules.builtin" \
|
|
|
|
"/lib/modules/${kernel}/modules.builtin" 644 0
|
2020-05-07 17:36:34 +05:30
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
depmod -b "$tmpdir" "$kernel"
|
2020-01-30 19:23:17 +05:30
|
|
|
}
|
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
make_initramfs()
|
2020-05-07 17:36:34 +05:30
|
|
|
(
|
2020-06-28 09:28:57 +05:30
|
|
|
print "generating initramfs image"
|
2020-02-24 13:39:37 +05:30
|
|
|
|
2020-04-12 01:01:02 +05:30
|
|
|
[ "$force" != 1 ] && [ -e "$output" ] &&
|
2020-04-15 22:20:45 +05:30
|
|
|
panic "initramfs image already exist"
|
2020-02-18 13:23:03 +05:30
|
|
|
|
2020-06-28 09:28:57 +05:30
|
|
|
cd "$tmpdir"; find . |
|
|
|
|
cpio -oH newc 2> /dev/null |
|
|
|
|
${compress:-cat} > "$output" ||
|
|
|
|
panic "failed to generate initramfs image"
|
2020-06-02 16:56:42 +05:30
|
|
|
|
|
|
|
print "done! check out $output"
|
2020-05-07 17:36:34 +05:30
|
|
|
)
|
2020-01-30 19:23:17 +05:30
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
# Exit if command fails and disable globbing.
|
2020-09-11 01:23:39 +05:30
|
|
|
set -ef
|
2020-05-19 09:59:40 +05:30
|
|
|
|
2021-05-10 17:12:11 +05:30
|
|
|
parse_arguments "$@"
|
2020-09-11 01:23:39 +05:30
|
|
|
prepare_initramfs
|
2020-04-12 01:01:02 +05:30
|
|
|
|
2020-09-11 01:23:39 +05:30
|
|
|
for _hook in $hooks; do
|
|
|
|
copy_hook "$_hook"
|
|
|
|
done
|
2020-03-09 00:07:19 +05:30
|
|
|
|
2020-09-11 01:23:39 +05:30
|
|
|
copy_modules
|
|
|
|
make_initramfs
|