-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinitramfs.sh
executable file
·245 lines (190 loc) · 5.86 KB
/
initramfs.sh
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#!/bin/bash
copy() {
local file
[ "$2" == "lib" ] && file=$(PATH=/lib:/usr/lib type -p $1) || file=$(type -p $1)
[ -n $file ] && cp $file $WDIR/$2 || {
echo "Missing required file: $1 for directory $2";
rm -rf $WDIR;
exit 1;
}
}
[ -z $1 ] && INITRAMFS_FILE=initrd.img-no-kmods || {
KERNEL_VERSION=$1;
INITRAMFS_FILE=initrd.img-$KERNEL_VERSION;
}
[ -n "$KERNEL_VERSION" ] && [ -d "/lib/modules/$1" ] || { echo "No modules directory named $1"; exit 1; }
printf "Creating ${INITRAMFS_FILE}..."
binfiles="sh cat cp dd killall ls mkdir mknod mount umount sed sleep ln rm uname"
# Systemd puts udevadm in /bin...
[ -x /bin/udevadm ] && binfiles+=" udevadm";
sbinfiles="modprobe blkid switch_root"
# optional...
for f in mdadm mdmon udevd udevadm; do
[ -x /sbin/${f} ] && sbinfiles+=" ${f}"
done
unset f
unsorted=$(mktemp /tmp/unsorted.XXXXXXXXXX)
WDIR=$(mktemp -d /tmp/initrd-work.XXXXXXXXXX)
mkdir -p $WDIR/{bin,dev,lib/firmware,run,sbin,sys,proc}
mkdir -p $WDIR/etc/{modprobe.d,udev/rules.d}
touch $WDIR/etc/modprobe.d/modprobe.conf
ln -s lib $WDIR/lib64
mknod -m 640 $WDIR/dev/console c 5 1
mknod -m 664 $WDIR/dev/null c 1 3
[ -f /etc/udev/udev.conf ] && cp /etc/udev/udev.conf $WDIR/etc/udev/udev.conf
for file in $(find /etc/udev/rules.d/ -type f); do
cp "${file}" $WDIR/etc/udev/rules.d
done
unset file
cp -a /lib/firmware $WDIR/lib
[ -f /etc/mdadm.conf ] && cp /etc/mdadm.conf $WDIR/etc/mdadm.conf
cat > $WDIR/init << EOFINIT
#!/bin/sh
PATH=/bin:/usr/bin:/sbin:/usr/sbin
export PATH
problem() {
printf "Encountered a problem!\n\nDropping you into a shell.\n\n"
sh
}
no_device() {
printf "The device %s, which is supposed to contain the\n" $1
printf "root filesystem, does not exist.\n"
printf "Please fix this problem and exit this shell.\n"
}
no_mount() {
printf "Could not mount device %s\n" $1
printf "Sleeping forever. Please reboot and fix the kernel command line.\n\n"
printf "Maybe thie device is formatted with an unsupported file system?\n\n"
printf "Or maybe the filesystem type autodetection went wrong, in which case\n"
printf "you should add the rootfstype=... parameter to the kernel command line.\n\n"
printf "Available partitions:\n"
}
do_mount_root() {
mkdir /.root
[ -n "$rootflags" ] && rootflags="$rootflags,"
rootflags+="$ro"
case "$root" in
/dev/* ) device=$root ;;
UUID=* ) eval $root; device=/dev/disk/by-uuid/$UUID ;;
LABEL=* ) eval $root; device=/dev/disk/by-label/$LABEL ;;
"" ) echo "No root device specified."; problem ;;
esac
while [ -b "$device" ]; do
no_device $device
problem
done
if ! mount -n -t "rootfstype" -o "$rootflags" "$device" /.root ; then
no_mount $device
cat /proc/partitions
while true ; do sleep 10000; done
else
echo "Successfully mounted device $root"
fi
}
init=/sbin/init
root=
rootdelay
rootfstype=auto
ro="ro"
rootflags=
device=
mount -n -t devtmpfs devtmpfs /dev
mount -n -t proc proc /proc
mount -n -t sysfs sysfs /sys
mount -n -t tmpfs tmpfs /run
read -r cmdline < /proc/cmdline
for param in $cmdline ; do
case $param in
init=* ) init=${param#init=} ;;
root=* ) root=${param#root=} ;;
rootdelay=* ) rootdelay=${param#rootdelay=} ;;
rootfstype=* ) rootfstype=${param#rootfstype=} ;;
rootflags=* ) rootflags=${param#rootflags=} ;;
ro ) ro="ro" ;;
rw ) ro="rw" ;;
esac
done
# udevd locations...
[ -x /sbin/udevd ] && UDEVD=/sbin/udevd || {
[ -x /lib/udev/udevd ] && UDEVD=/lib/udev/udevd || {
[ -x /lib/systemd/systemd-udevd ] && UDEVD=/lib/systemd/systemd-udevd || {
echo "Cannot find udevd nor systemd-udevd"; problem;
}
}
}
${UDEVD} --daemon --resolve-names=never
udevadm trigger
udevadm settle
[ -f /etc/mdadm.conf ] && mdadm -As
[ -x /sbin/vgchange ] && /sbin/vgchange -a y > /dev/null
[ -n "$rootdelay" ] && sleep "$rootdelay"
do_mount_root
killall -w ${UDEVD##*/}
exec switch_root /.root "$init" "$@"
EOFINIT
chmod 0755 $WDIR/init
[ -n "$KERNEL_VERSION" ] && {
[ -x /bin/kmod ] && binfiles+=" kmod" || {
binfiles+=" lsmod";
sbinfiles+=" insmod";
}
}
# Install binaries
for f in $binfiles; do
ldd /bin/$f | sed "s/\t//" | cut -d " " -f1 >> $unsorted
copy $f bin
done
unset f
# Add lvm
[ -x /sbin/lvm ] && sbinfiles+=" lvm dmsetup"
for f in $sbinfiles; do
ldd /sbin/$f | sed "s/\t//" | cut -d " " -f1 >> $unsorted
copy $f sbin
done
unset f
# Add udevd libs if not in /sbin
[ -x /lib/udev/udevd ] && {
ldd /lib/udev/udevd | sed "s/\t//" | cut -d " " -f1 >> $unsorted;
} || [ -x /lib/systemd/systemd-udevd ] && {
ldd /lib/systemd/systemd-udevd | sed "s/\t//" | cut -d " " -f1 >> $unsorted;
}
# mod sylinks
[ -n "$KERNEL_VERSION" ] && [ -x /bin/kmod ] && {
ln -s kmod $WDIR/bin/lsmod;
ln -s kmod $WDIR/bin/insmod;
}
# lvm.conf and lvm symlinks
[ -x /sbin/lvm ] && {
for l in change rename extend create display scan; do
ln -s lvm $WDIR/sbin/lv${l};
done
for p in change ck create display scan; do
ln -s lvm $WDIR/sbin/pv${p};
done
for v in change create scan rename ck; do
ln -s lvm $WDIR/sbin/vg${v};
done
unset l p v
cp -a /etc/lvm $WDIR/etc
}
# install libs
sort $unsorted | uniq | while read libr; do
[ "$libr" == "linux-vdso.so.1" -o "$libr" == "linux-gate.so.1" ] && continue
copy $libr lib
done
[ -d /lib/udev ] && cp -a /lib/udev $WDIR/lib
[ -d /lib/systemd ] && cp -a /lib/systemd $WDIR/lib
# install kernel modules if requested
[ -n "$KERNEL_VERSION" ] && {
find \
/lib/modules/$KERNEL_VERSION/kernel/{crypto,fs,lib} \
/lib/modules/$KERNEL_VERSION/kernel/drivers/{block,ata,md,firewire} \
/lib/modules/$KERNEL_VERSION/kernel/drivers/{scsi,message,pcmcia,virtio} \
/lib/modules/$KERNEL_VERSION/kernel/drivers/usb/{host,storage} \
-type f 2> /dev/null | cpio --make-directories -p --quiet $WDIR
cp /lib/modules/$KERNEL_VERSION/modules.{builtin,order} $WDIR/lib/modules/$KERNEL_VERSION
depmod -b $WDIR $KERNEL_VERSION
}
( cd $WDIR && find . | cpio -o -H newc --quiet | gzip -9 ) > $INITRAMFS_FILE
rm -rf $WDIR $unsorted
printf "done. \n"