#!/bin/sh # Generate an initramfs image, much like mkinitramfs(8) but simpler # # Copyright © 2021-2022 Guilhem Moulin # # 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 . set -eu PATH="/usr/sbin:/usr/bin:/sbin:/bin" export PATH unset DEBUG EXTRACT_DIR="$1" KERNEL_VERSION="$2" INITRD="$3" UTILS="$(dirname -- "$0")" DESTDIR="$(mktemp --directory -- "$INITRD.XXXXXXXXXX")" trap "rm -r${DEBUG:+v}f -- \"$DESTDIR\"" EXIT INT TERM # from /usr/sbin/mkinitramfs: create usr-merged filesystem layout, to # avoid duplicates if the host filesystem is usr-merged for d in /bin /lib* /sbin; do [ -d "$d" ] || continue mkdir -p "$DESTDIR/usr$d" ln -sT "usr$d" "$DESTDIR$d" done install -m0755 "$UTILS/init" "$DESTDIR/init" install -m0755 "$UTILS/debootstrap" "$DESTDIR/debootstrap" cat >"$DESTDIR/init.conf" <<- EOF HOSTNAME="$TESTNAME" export HOSTNAME PACKAGES="$PACKAGES" BOOT="$BOOT" CONSOLE="$CONSOLE" ARCH="$ARCH" MERGED_USR="$MERGED_USR" EOF for p in setup preinst postinst bottom; do # setup: sourced after creating the BIOS or EFI boot partition # preinst: run in chroot after debootstrap, but before installing extra packages # postinst: optionally run in chroot after installing extra packages # bottom: last thing to run before shutdown if [ -f "$TESTDIR/$TESTNAME.d/$p" ]; then install -m0755 "$TESTDIR/$TESTNAME.d/$p" "$DESTDIR/init.$p" fi done MODULES="dm_crypt ext4 btrfs raid0 raid1" if [ "$BOOT" = "efi" ]; then MODULES="$MODULES efivarfs nls_ascii nls_cp437 vfat" fi depmod -ab "$EXTRACT_DIR" "$KERNEL_VERSION" for kmod in virtio_console virtio_blk virtio_pci virtio_rng \ "$EXTRACT_DIR/lib/modules/$KERNEL_VERSION"/kernel/arch/*/crypto/*.ko* \ "$EXTRACT_DIR/lib/modules/$KERNEL_VERSION"/kernel/crypto/*.ko* \ $MODULES; do kmod="${kmod##*/}" modprobe -aid "$EXTRACT_DIR" -S "$KERNEL_VERSION" --show-depends "${kmod%%.*}" done | while read -r insmod kmod _; do [ "$insmod" = "insmod" ] || continue kmod_rel="${kmod#"$EXTRACT_DIR/lib/modules/$KERNEL_VERSION/"}" if [ ! -f "$kmod" ] || [ "${kmod_rel#kernel/}" = "$kmod_rel" ]; then echo "Error: Unexpected modprobe output: $insmod $kmod" >&2 exit 1 fi mkdir -p "$DESTDIR/lib/modules/$KERNEL_VERSION/${kmod_rel%/*}" ln -f${DEBUG:+v}T -- "$kmod" "$DESTDIR/lib/modules/$KERNEL_VERSION/$kmod_rel" done ln -t "$DESTDIR/lib/modules/$KERNEL_VERSION" -- \ "$EXTRACT_DIR/lib/modules/$KERNEL_VERSION/modules.order" \ "$EXTRACT_DIR/lib/modules/$KERNEL_VERSION/modules.builtin" depmod -wab "$DESTDIR" "$KERNEL_VERSION" verbose="${DEBUG-}" . /usr/share/initramfs-tools/hook-functions # for copy_exec() if [ -f "$TESTDIR/$TESTNAME.d/mkinitramfs" ]; then . "$TESTDIR/$TESTNAME.d/mkinitramfs" fi copy_exec /bin/cp copy_exec /bin/rm copy_exec /bin/chmod copy_exec /sbin/modprobe copy_exec /sbin/blkid copy_exec /sbin/sfdisk copy_exec /sbin/mkswap copy_exec /sbin/swapon copy_exec /sbin/swapoff copy_exec /sbin/cryptsetup copy_exec /sbin/dmsetup copy_exec /usr/bin/dpkg-deb copy_exec /bin/tar # assume ossl-modules/legacy.so is relative to the linked libcryptsetup.so libdir="$(env --unset=LD_PRELOAD ldd /sbin/cryptsetup | sed -nr '/.*=>\s*(\S+)\/libcryptsetup\.so\..*/ {s//\1/p;q}')" copy_exec "$libdir/ossl-modules/legacy.so" || true for p in /sbin/cryptsetup /sbin/lvm /sbin/mdadm /sbin/mke2fs /sbin/mkfs.btrfs /bin/btrfs; do if [ -x "$p" ]; then copy_exec "$p" fi done if [ "$BOOT" = "efi" ]; then if [ ! -x "/sbin/mkfs.vfat" ]; then echo "Couldn't find mkfs.vfat, is the 'dosfstools' package installed?" >&2 exit 1 fi copy_exec /sbin/mkfs.vfat fi cp -pLt "$DESTDIR/lib" /lib/klibc-*.so for cmd in cat chroot ln ls mkdir mount mv sh umount uname; do exe="/usr/lib/klibc/bin/$cmd" if [ ! -f "$exe" ] || [ ! -x "$exe" ]; then echo "No such executable: $exe" >&2 exit 1 fi copy_exec "$exe" /bin done # copy udevd and (some of) its rules copy_exec /lib/systemd/systemd-udevd copy_exec /bin/udevadm mkdir -p -- "$DESTDIR/etc/udev" "$DESTDIR/lib/udev/rules.d" cat >"$DESTDIR/etc/udev/udev.conf" <<-EOF udev_log=info resolve_names=never EOF for rules in 50-udev-default.rules 55-dm.rules 60-block.rules \ 60-persistent-storage.rules 60-persistent-storage-dm.rules \ 63-md-raid-arrays.rules 95-dm-notify.rules; do if [ -e "/lib/udev/rules.d/$rules" ]; then cp -T "/lib/udev/rules.d/$rules" "$DESTDIR/lib/udev/rules.d/$rules" fi done cd "$DESTDIR" find . -print0 | cpio -o0 -R 0:0 -H newc --quiet ${DEBUG:+--verbose} >"$INITRD"