tinyramfs/init

212 lines
5.0 KiB
Plaintext
Raw Normal View History

2020-04-12 01:01:02 +05:30
#!/bin/sh -ef
2020-01-30 20:10:13 +05:30
#
2020-04-12 01:01:02 +05:30
# tiny init
#
# word splitting is safe by design
# shellcheck disable=2068,2046,2086
#
# false positive
# shellcheck disable=2154,2163,1091
2020-01-05 23:31:39 +05:30
2020-04-21 20:05:55 +05:30
print()
{
printf "%b %s\n" "${2:-"\033[1;37m>>\033[m"}" "$1"
2020-04-21 20:05:55 +05:30
}
panic()
{
print "${1:-unexpected error occurred}" \
"\033[1;31m!!\033[m" >&2; sh
2020-01-30 20:10:13 +05:30
}
2020-01-28 20:43:42 +05:30
2020-04-12 01:01:02 +05:30
findfs()
{
count=0; device=
2020-04-12 01:01:02 +05:30
case "${1%%=*}" in
/dev/*) device="$1" ;;
UUID) device="/dev/disk/by-uuid/${1##*=}" ;;
LABEL) device="/dev/disk/by-label/${1##*=}" ;;
PARTUUID) device="/dev/disk/by-partuuid/${1##*=}" ;;
2020-04-12 01:01:02 +05:30
esac
# prevent race condition
while [ ! -e "$device" ]; do sleep 1
2020-05-26 19:14:20 +05:30
[ "$(( count += 1 ))" != 30 ] || {
panic "failed to lookup partition"
break
}
2020-05-26 19:14:20 +05:30
done
2020-02-21 14:27:07 +05:30
}
2020-01-05 23:31:39 +05:30
2020-04-12 01:01:02 +05:30
prepare_environment()
{
. /etc/tinyramfs/config
2020-04-12 01:01:02 +05:30
export \
PATH=/bin TERM=linux SHELL=/bin/sh \
LANG=C LC_ALL=C PS1="# " HOME=/root \
2020-03-08 08:59:14 +05:30
mount -t proc -o nosuid,noexec,nodev proc /proc
mount -t sysfs -o nosuid,noexec,nodev sys /sys
mount -t tmpfs -o nosuid,nodev,mode=0755 run /run
2020-04-12 01:01:02 +05:30
mount -t devtmpfs -o nosuid,noexec,mode=0755 dev /dev
2020-03-08 08:59:14 +05:30
mkdir -p \
/run/cryptsetup \
/run/lock \
/run/lvm
2020-04-12 01:01:02 +05:30
ln -s /proc/self/fd /dev/fd
ln -s fd/0 /dev/stdin
ln -s fd/1 /dev/stdout
ln -s fd/2 /dev/stderr
2020-04-17 23:11:54 +05:30
trap panic EXIT
[ ! "$modules" ] || modprobe -a "$modules"
2020-04-12 01:01:02 +05:30
}
parse_cmdline()
{
read -r cmdline < /proc/cmdline
for line in $cmdline; do case "$line" in
debug | debug=1) set -x ;;
2020-05-26 19:14:20 +05:30
rootfstype=*) root_type="${line##*=}" ;;
rootflags=*) root_opts="${line##*=}" ;;
ro | rw) rorw="-o $line" ;;
--) init_args="${cmdline##*--}"; break ;;
*=*) export "$line" ;;
*) export "${line}=1" ;;
esac; done
2020-01-30 20:10:13 +05:30
}
2020-01-05 23:31:39 +05:30
2020-04-12 01:01:02 +05:30
setup_devmgr()
{
[ "$break" = devmgr ] && { print "break before setup_devmgr()"; sh; }
2020-04-12 01:01:02 +05:30
2020-02-26 01:13:25 +05:30
case "$devmgr" in
udev)
udevd -N never & devmgr_pid="$!"
2020-02-26 01:13:25 +05:30
udevadm trigger -c add -t subsystems
udevadm trigger -c add -t devices
udevadm settle
2020-04-12 01:01:02 +05:30
;;
2020-02-26 01:13:25 +05:30
mdev)
mdev -s
mdev -df & devmgr_pid="$!"
[ "$monolith" = 1 ] && return 0
2020-04-12 01:01:02 +05:30
2020-05-26 19:14:20 +05:30
find /sys/devices -name uevent |
while read -r uevent; do
printf add > "$uevent"
done
2020-04-12 01:01:02 +05:30
;;
2020-02-26 01:13:25 +05:30
mdevd)
mdevd & devmgr_pid="$!"
2020-02-26 01:13:25 +05:30
mdevd-coldplug
2020-04-12 01:01:02 +05:30
;;
esac 2> /dev/null
2020-01-30 20:10:13 +05:30
}
2020-01-05 23:31:39 +05:30
2020-04-12 01:01:02 +05:30
unlock_luks()
{
[ "$break" = luks ] && { print "break before unlock_luks()"; sh; }
2020-02-26 01:13:25 +05:30
{ IFS=,; set -- $luks_opts; unset IFS; }
2020-02-16 01:03:13 +05:30
for opt; do case "$opt" in
discard | discard=1) luks_discard="--allow-discards" ;;
header=*) luks_header="--${opt}" ;;
name=*) luks_name="${opt##*=}" ;;
key=*) luks_key="-d ${opt##*=}" ;;
esac; done
2020-02-16 01:03:13 +05:30
2020-04-12 01:01:02 +05:30
findfs "$luks_root"
set -- \
2020-05-26 19:14:20 +05:30
"$luks_key" "$luks_header" "$luks_discard" \
"$device" "${luks_name:-luks-${device##*/}}"
2020-04-12 01:01:02 +05:30
cryptsetup open $@ || panic "failed to unlock LUKS"
}
2020-04-12 01:01:02 +05:30
trigger_lvm()
{
[ "$break" = lvm ] && { print "break before trigger_lvm()"; sh; }
{ IFS=,; set -- $lvm_opts; unset IFS; }
2020-04-12 01:01:02 +05:30
for opt; do case "$opt" in
discard | discard=1) lvm_discard="--config=devices{issue_discards=1}" ;;
config=0) : > /etc/lvm/lvm.conf ;;
group=*) lvm_group="${opt##*=}" ;;
name=*) lvm_name="/${opt##*=}" ;;
tag=*) lvm_tag="@${opt##*=}" ;;
esac; done
2020-04-12 01:01:02 +05:30
set -- "--sysinit" "-qq" "-aay" "$lvm_discard"
2020-01-25 16:57:02 +05:30
2020-02-21 14:27:07 +05:30
if [ "$lvm_group" ] && [ "$lvm_name" ]; then
lvm lvchange $@ "${lvm_group}${lvm_name}"
2020-02-21 14:27:07 +05:30
elif [ "$lvm_group" ]; then
lvm vgchange $@ "$lvm_group"
2020-04-12 01:01:02 +05:30
elif [ "$lvm_tag" ]; then
lvm lvchange $@ "$lvm_tag"
2020-02-21 14:27:07 +05:30
else
lvm vgchange $@
2020-02-21 14:27:07 +05:30
fi
2020-05-26 19:30:30 +05:30
[ "$?" = 0 ] || panic "failed to trigger LVM"
2020-01-28 20:43:42 +05:30
}
2020-01-05 23:31:39 +05:30
2020-04-12 01:01:02 +05:30
mount_root()
{
[ "$break" = root ] && { print "break before mount_root()"; sh; }
2020-04-12 01:01:02 +05:30
findfs "$root"
set -- \
"${rorw:--o ro}${root_opts:+,$root_opts}" \
2020-05-26 19:14:20 +05:30
"${root_type:+-t $root_type}" "$device" "/mnt/root"
2020-04-12 01:01:02 +05:30
mount $@ || panic "failed to mount root"
2020-01-30 20:10:13 +05:30
}
2020-01-05 23:31:39 +05:30
2020-05-26 19:14:20 +05:30
boot_system()
2020-04-12 01:01:02 +05:30
{
2020-05-26 19:14:20 +05:30
[ "$break" = boot ] && { print "break before boot_system()"; sh; }
2020-04-12 01:01:02 +05:30
kill "$devmgr_pid"
# temporary workaround until util-linux release a new version
2020-04-12 01:01:02 +05:30
# see https://github.com/karelzak/util-linux/issues/997
for dir in run dev sys proc; do
mount -o move "$dir" "/mnt/root/${dir}" ||
mount --move "$dir" "/mnt/root/${dir}"
2020-04-12 01:01:02 +05:30
done
2020-01-05 23:31:39 +05:30
2020-05-26 19:14:20 +05:30
set -- \
"/mnt/root" "${init:-/sbin/init}" "$init_args"
2020-01-30 20:10:13 +05:30
2020-05-26 19:14:20 +05:30
exec switch_root $@ || panic "failed to boot system"
2020-04-12 01:01:02 +05:30
}
2020-01-30 20:58:03 +05:30
2020-04-12 01:01:02 +05:30
# int main()
{
prepare_environment
parse_cmdline
setup_devmgr
2020-02-26 01:13:25 +05:30
# trigger lvm twice to handle both LUKS on LVM and LVM on LUKS
[ "$lvm" = 1 ] && trigger_lvm
2020-04-12 01:01:02 +05:30
[ "$luks" = 1 ] && unlock_luks
[ "$lvm" = 1 ] && trigger_lvm
2020-02-26 01:13:25 +05:30
2020-04-12 01:01:02 +05:30
mount_root
boot_system
}