summaryrefslogtreecommitdiffstats
path: root/debian/tests/utils/init
diff options
context:
space:
mode:
Diffstat (limited to 'debian/tests/utils/init')
-rwxr-xr-xdebian/tests/utils/init273
1 files changed, 273 insertions, 0 deletions
diff --git a/debian/tests/utils/init b/debian/tests/utils/init
new file mode 100755
index 0000000..242a0c5
--- /dev/null
+++ b/debian/tests/utils/init
@@ -0,0 +1,273 @@
+#!/bin/sh
+
+# PID1 at initramfs stage
+#
+# Copyright © 2021-2022 Guilhem Moulin <guilhem@debian.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+set -eux
+PATH="/usr/sbin:/usr/bin:/sbin:/bin"
+export PATH
+
+trap "echo \"ALERT! Couldn't setup system, dropping to a shell.\" >&2; sh -i" 0
+
+# set VT100 autowrap mode again (QEMU might mess the terminal up)
+printf '\033[?7h'
+
+mount -t devtmpfs -o noexec,nosuid,mode=0755 udev /dev
+
+mkdir /dev/pts /proc /run /sys
+mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts
+mount -t proc -o nodev,noexec,nosuid proc /proc
+mount -t tmpfs -o nodev,noexec,nosuid,size=5%,mode=0755 tmpfs /run
+mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
+
+modprobe virtio_rng # /dev/hwrng (avoid entropy starvation)
+modprobe virtio_pci
+modprobe virtio_blk # /dev/vd[a-z]
+modprobe virtio_console # /dev/hvc[0-7]
+
+# start udevd
+/lib/systemd/systemd-udevd --daemon
+udevadm trigger --type=subsystems --action=add
+udevadm trigger --type=devices --action=add
+udevadm settle
+
+. /init.conf
+
+# https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs
+GUID_TYPE_MBR="024DEE41-33E7-11D3-9D69-0008C781F39F" # MBR partition scheme
+GUID_TYPE_EFI="C12A7328-F81F-11D2-BA4B-00A0C93EC93B" # EFI boot partition
+GUID_TYPE_BIOS_boot="21686148-6449-6E6F-744E-656564454649" # BIOS boot partition
+GUID_TYPE_Linux_FS="0FC63DAF-8483-4772-8E79-3D69D8477DE4" # Linux filesystem data
+GUID_TYPE_LUKS="CA7D7CCB-63ED-4C53-861C-1742536059CC" # LUKS partition
+GUID_TYPE_DMCRYPT="7FFEC5C9-2D00-49B7-8941-3EA10A5586B7" # Plain dm-crypt partition
+GUID_TYPE_LVM="E6D6D379-F507-44C2-A23C-238F2A3DF928" # Logical Volume Manager partition
+GUID_TYPE_RAID="A19D880F-05FC-4D3B-A006-743F0F84911E" # RAID partition
+
+if [ "$BOOT" = "bios" ]; then
+ BOOT_PARTITION_SIZE=2
+ BOOT_PARTITION_TYPE="$GUID_TYPE_BIOS_boot"
+elif [ "$BOOT" = "efi" ]; then
+ BOOT_PARTITION_SIZE=63
+ BOOT_PARTITION_TYPE="$GUID_TYPE_EFI"
+else
+ echo "ERROR unknown boot method '$BOOT'" >&2
+ exit 1
+fi
+
+# format the target disk and create a BIOS/EFI partition
+sfdisk /dev/vda <<-EOF
+ label: gpt
+ unit: sectors
+
+ start=$((1024*2)), size=$((BOOT_PARTITION_SIZE*1024*2)), type=$BOOT_PARTITION_TYPE
+EOF
+udevadm settle
+
+ROOT="/target"
+mkdir -m0755 "$ROOT"
+# /init.setup is expected to create the root filesystem of the target
+# system and mount it (alongside other filesystems) on $ROOT
+. /init.setup
+udevadm settle
+
+# inspired by debootstrap's /usr/share/debootstrap/functions
+if [ "$MERGED_USR" = "yes" ]; then
+ case "$ARCH" in
+ amd64) libdir="lib32 lib64 libx32";;
+ i386) libdir="lib64 libx32";;
+ mips|mipsel) libdir="lib32 lib64";;
+ mips64*|mipsn32*) libdir="lib32 lib64 libo32";;
+ loongarch64*) libdir="lib32 lib64";;
+ powerpc) libdir="lib64";;
+ ppc64) libdir="lib32 lib64";;
+ ppc64el) libdir="lib64";;
+ s390x) libdir="lib32";;
+ sparc) libdir="lib64";;
+ sparc64) libdir="lib32 lib64";;
+ x32) libdir="lib32 lib64 libx32";;
+ *) libdir="";;
+ esac
+ for dir in bin sbin lib $libdir; do
+ ln -s "usr/$dir" "$ROOT/$dir"
+ mkdir -p "$ROOT/usr/$dir"
+ done
+fi
+
+mkdir /media
+DEBIAN_DIST="$(blkid -l -t LABEL="debian_dist" -o device)"
+mount -t ext2 -o ro "$DEBIAN_DIST" /media
+for pkg in /media/__stage1__/*.deb; do
+ dpkg-deb --fsys-tarfile "$pkg" | tar -C "$ROOT" -xf - --keep-directory-symlink
+done
+
+# setup hosts(5) and hostname(5)
+echo "$HOSTNAME" >"$ROOT/etc/hostname"
+echo "127.0.0.1 localhost $HOSTNAME" >"$ROOT/etc/hosts"
+
+# EFI
+if [ "$BOOT" = "efi" ]; then
+ modprobe efivarfs
+ mount -t efivarfs efivarfs /sys/firmware/efi/efivars
+
+ mkfs.vfat -F 32 /dev/vda1
+ mkdir "$ROOT/boot/efi"
+ mount -t vfat /dev/vda1 "$ROOT/boot/efi"
+
+ cat >>"$ROOT/etc/fstab" <<-EOF
+ UUID=$(blkid -s UUID -o value /dev/vda1) /boot/efi auto defaults 0 2
+ EOF
+fi
+
+# bind mount pseudo and temporary filesystems to "$ROOT"
+mount -no bind /dev "$ROOT/dev"
+mount -no bind /proc "$ROOT/proc"
+mount -no bind /sys "$ROOT/sys"
+mount -t tmpfs -o nodev,noexec,nosuid,size=5%,mode=0755 tmpfs "$ROOT/run"
+
+# prevent any services from starting during package installation, taken
+# from debootstrap(8)
+cat >"$ROOT/usr/sbin/policy-rc.d" <<-EOF
+ #!/bin/sh
+ exit 101
+EOF
+chmod +x "$ROOT/usr/sbin/policy-rc.d"
+
+mv "$ROOT/sbin/start-stop-daemon" "$ROOT/sbin/start-stop-daemon.REAL"
+cat >"$ROOT/sbin/start-stop-daemon" <<-EOF
+ #!/bin/sh
+ echo
+ echo "Warning: Fake start-stop-daemon called, doing nothing"
+EOF
+chmod +x "$ROOT/usr/sbin/policy-rc.d" "$ROOT/sbin/start-stop-daemon"
+
+DEBIAN_FRONTEND="noninteractive"
+DEBCONF_NONINTERACTIVE_SEEN="true"
+export DEBIAN_FRONTEND DEBCONF_NONINTERACTIVE_SEEN
+
+# debootstrap the target system
+mkdir "$ROOT/media"
+mount -no move /media "$ROOT/media"
+cp -p /debootstrap "$ROOT/debootstrap"
+chroot "$ROOT" /debootstrap
+rm -f "$ROOT/debootstrap"
+
+# use MODULES=dep (if it works with fewer modules then it also works
+# with the default MODULES=most)
+mkdir -p "$ROOT/etc/initramfs-tools/conf.d"
+echo "MODULES=dep" >"$ROOT/etc/initramfs-tools/conf.d/modules"
+
+cp /init.preinst "$ROOT/init.preinst"
+chroot "$ROOT" /bin/sh -eux /init.preinst
+rm -f "$ROOT/init.preinst"
+udevadm settle
+
+# install extra packages
+chroot "$ROOT" apt-get -oAPT::Sandbox::User="root" install --yes $PACKAGES
+rm -f "$ROOT/etc/apt/sources.list"
+
+# configure and install GRUB
+cat >"$ROOT/etc/default/grub" <<-EOF
+ GRUB_DEFAULT=0
+ GRUB_TIMEOUT=0
+ GRUB_CMDLINE_LINUX_DEFAULT=""
+ GRUB_CMDLINE_LINUX="console=$CONSOLE,115200n8"
+ GRUB_DISABLE_RECOVERY=true
+ GRUB_TERMINAL="console serial"
+ GRUB_SERIAL_COMMAND="serial --speed=115200"
+EOF
+chroot "$ROOT" grub-install --no-floppy --modules=part_gpt /dev/vda
+chroot "$ROOT" update-grub
+
+chroot "$ROOT" busybox passwd -d root # make root account passwordless
+
+# show some system info right after login to ease troubleshooting
+cat >"$ROOT/root/.profile" <<-EOF
+ run_verbose() {
+ printf "\\\`%s\\\` output:\\\\n" "\$*"
+ "\$@"
+ }
+ stty cols 150
+ run_verbose dmsetup table
+ run_verbose lsblk
+ run_verbose df -h
+EOF
+
+cat >"$ROOT/root/.inputrc" <<-EOF
+ # disabled bracketed paste mode
+ set enable-bracketed-paste off
+EOF
+
+if [ -d "$ROOT/etc/systemd/system" ]; then
+ # systemd
+ if [ -c "$ROOT/dev/hvc0" ]; then
+ # serial-getty@ttyS0.service is automatically enabled due to the console= kernel parameter
+ ln -s "/dev/null" "$ROOT/etc/systemd/system/serial-getty@ttyS0.service"
+ ln -s "/lib/systemd/system/serial-getty@.service" \
+ "$ROOT/etc/systemd/system/getty.target.wants/serial-getty@hvc0.service"
+ fi
+
+ # mask all timer units
+ for t in "$ROOT"/lib/systemd/system/*.timer; do
+ test -f "$t" || continue
+ ln -s "/dev/null" "$ROOT/etc/systemd/system/${t##*/}"
+ done
+
+ # mask systemd-firstboot.service
+ ln -s "/dev/null" "/root/etc/systemd/system/systemd-firstboot.service"
+fi
+
+if [ -f "$ROOT/etc/inittab" ]; then
+ # sysvinit
+ if [ -c "$ROOT/dev/hvc0" ]; then
+ echo "h0:2345:respawn:/sbin/agetty -8 -L 115200 hvc0 linux"
+ else
+ echo "S0:23:respawn:/sbin/getty -8 -L 115200 $CONSOLE linux"
+ fi >>"$ROOT/etc/inittab"
+fi
+
+if [ -f /init.postinst ]; then
+ cp /init.postinst "$ROOT/init.postinst"
+ chroot "$ROOT" /bin/sh -eux /init.postinst
+ rm -f "$ROOT/init.postinst"
+fi
+
+# allow service startup again
+mv "$ROOT/sbin/start-stop-daemon.REAL" "$ROOT/sbin/start-stop-daemon"
+rm "$ROOT/usr/sbin/policy-rc.d"
+
+# unmount pseudo filesystems from the target system
+umount "$ROOT/dev"
+umount "$ROOT/proc"
+umount "$ROOT/sys"
+
+if [ "$BOOT" = "efi" ]; then
+ umount "$ROOT/boot/efi"
+fi
+umount "$ROOT/media"
+umount "$ROOT/run"
+
+# /init.bottom is expected to umount $ROOT and its submounts
+ROOT="$ROOT" sh -eux /init.bottom
+
+# stop udevd
+udevadm control --exit
+
+# exiting this script yields "Kernel panic - not syncing: Attempted to
+# kill init!", so give the asyncronous SysRq trigger a chance to power
+# off (sending a racy C-d would still trigger a panic but we don't care)
+echo o >/proc/sysrq-trigger
+exec cat >/dev/null