summaryrefslogtreecommitdiffstats
path: root/debian/tests/utils/mkinitramfs
blob: 6bc70f471a496b9e71f1c04e19d7ae81e3460afd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/bin/sh

# Generate an initramfs image, much like mkinitramfs(8) but simpler
#
# 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 -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 and libgcc_s.so are 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
copy_libgcc "$libdir"

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"