-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathminimal-init
More file actions
executable file
·204 lines (188 loc) · 6.61 KB
/
minimal-init
File metadata and controls
executable file
·204 lines (188 loc) · 6.61 KB
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
#!/bin/sh
set -u
busybox mount -n -t proc proc /proc
busybox mount -n -t devtmpfs devtmpfs /dev
busybox mount -n -t sysfs sysfs /sys
busybox --install -s
if [ ! -x "/dev/pts" ]; then mkdir /dev/pts; fi
if [ ! -x "/dev/shm" ]; then mkdir /dev/shm; fi
busybox mount -n -t devpts devpts /dev/pts -o gid=5,mode=620,ptmxmode=000
cmdline_arg() {
local name="$1"
local value="${2-}"
for arg in $(cat /proc/cmdline); do
if [[ "${arg%%=*}" == "${name}" ]]; then
value="${arg#*=}"
fi
done
echo "${value}"
}
emergency() {
echo "ERROR: The early initrd has failed. To activate debug shell breakpoints, boot with rd.earlyshell in the kernel cmdline, and to activate tracing, boot with rd.earlytrace" >&2
if read -s -p "Press Enter for emergency shell or wait 60 seconds for reboot." -t 60; then
echo >&2; echo "Entering emergency mode. Exit the shell to retry /init (you might need to clean up mounts first) or reboot with 'reboot -f'." >&2
busybox sh || true
exec /init
else
echo >&2; echo "INFO: Rebooting" >&2
exec reboot -f
fi
}
trap 'emergency' ERR
# Custom debug breakpoint
debug_sh() {
if [ "$(cmdline_arg rd.earlyshell)" != "" ]; then
echo "INFO: Entering debug shell breakpoint ($*), exit to continue booting (reboot with 'reboot -f')">&2
busybox sh || true
fi
}
debug_sh 1/4: before mdev
if [ "$(cmdline_arg rd.earlytrace)" != "" ]; then
set -x
fi
loadmodules() {
# Coldplugging but with using /sbin/modprobe (which is kmod) instead of busybox's modprobe
# because busybox doesn't properly support the globs in modules.alias
find /sys/ -name modalias -print0 | xargs -0 sort -u | tr '\n' '\0' | xargs -0 /sbin/modprobe -abq || true
}
mdev -d
mdev -s
loadmodules
# Required to access disks, but not autoloaded:
/sbin/modprobe sd_mod
debug_sh 2/4: before verity
find_drive() {
local search="$1"
local ueventline=
local blkidmatch=
local drive=
local waitingmsg=
local starttime=
local timeoutsecs=
local now=
case "${search}" in
LABEL=*)
blkidmatch="${search#LABEL=}"
# Needs " around the value
blkidmatch="LABEL=\"${blkidmatch}\""
;;
UUID=*)
blkidmatch="${search#UUID=}"
# Needs " around the value
blkidmatch="UUID=\"$(echo "${blkidmatch}" | tr "[:upper:]" "[:lower:]")\""
;;
PARTUUID=*)
ueventline="${search#PARTUUID=}"
ueventline="PARTUUID=$(echo "${ueventline}" | tr "[:upper:]" "[:lower:]")"
;;
PARTLABEL=*)
ueventline="PARTNAME=${search#PARTLABEL=}"
;;
*)
echo "${search}"
return
;;
esac
starttime=$(date +%s)
# Default to 5 minutes
timeoutsecs=$(cmdline_arg rd.earlytimeout 300)
while [ "${drive}" = "" ]; do
now=$(date +%s)
# Timeout of 5 minutes for finding the device
# NOTE: Only mdev -d runs as this point and the kernel also can spawn modprobe to load modules.
# If problems arise, first make sure that required modules and their deps are actually in the initrd,
# but if that's not enough we might even have to trigger the find /sys ... xargs coldplugging
# here again every now and then? (Last resort would be to run proper udev, possibly without systemd.)
if [ $((now - starttime)) -gt "${timeoutsecs}" ]; then
echo "ERROR: Timeout waiting for drive: ${ueventline}${blkidmatch}" >&2
return 1 # Throw error
fi
if [ $((now - starttime)) -gt 10 ]; then
sleep 5
echo "Still waiting for drive..." >&2
loadmodules
fi
# No "sleep 0.1", so this is rather busy polling but normally it works on first try
# and after some time we stop busy polling and have the longer sleep above
if [ "${ueventline}" != "" ]; then
drive="$({ grep -s -l -m 1 -r "${ueventline}" /sys/class/block/*/uevent || true; } | cut -d / -f 5)"
else
drive="$(blkid | { grep -m 1 "${blkidmatch}" || true ; } | cut -d : -f 1 | cut -d / -f 3-)"
fi
if [ "${drive}" = "" ] && [ "${waitingmsg}" = "" ]; then
echo "Waiting for drive..." >&2
waitingmsg=1
fi
done
drive="/dev/${drive}"
echo "${drive}"
}
# Ported code from the generators
verityusr=$(cmdline_arg verity.usr)
usrhash=$(cmdline_arg verity.usrhash)
verityusr=$(find_drive "${verityusr}")
# Only proceed if the source is a path and we have sufficient parameters.
if echo "${verityusr}" | grep -q "^/" && [ "${usrhash}" != "" ]; then
# Hardcoded expected value from the image GPT layout
veritysetup --panic-on-corruption --hash-offset=1065345024 open "${verityusr}" usr "${verityusr}" "${usrhash}"
# If there's a hash mismatch during table initialization,
# veritysetup reports it on stderr but still exits 0.
# Manually check the target status and fail if invalid.
status=$(dmsetup status usr | cut -d " " -f 4)
if [ "${status}" != V ]; then
echo "Verity setup failed" >&2
false # Throw error
fi
fi
usr=$(cmdline_arg mount.usr $(cmdline_arg usr))
usrfstype=$(cmdline_arg mount.usrfstype $(cmdline_arg usrfstype auto))
usrflags=$(cmdline_arg mount.usrflags $(cmdline_arg usrflags ro))
usr=$(find_drive "${usr}")
if [ "${usr}" = "" ] && [ -f /usr.squashfs ]; then
usr=/usr.squashfs
usrfstype=squashfs
elif [ "${usrfstype}" = btrfs ] || [ "${usrfstype}" = auto ]; then
if [ "$(echo ",${usrflags}," | grep -v -F ',ro,')" != "" ]; then
true # Don't set "norecovery" when mounting rw
else
usrflags="${usrflags},rescue=nologreplay"
fi
fi
# Only proceed if the source is a path.
case "${usr}" in
/*) : ;;
*) echo "No mountable /usr partition given (usr='${usr}')" >&2
false # Throw error
;;
esac
debug_sh 3/4: before /sysusr mount
echo "Mounting /usr from ${usr}" >&2
# mount -t auto only works if btrfs is already loaded
/sbin/modprobe btrfs
mkdir -p /sysusr/usr
mount -t "${usrfstype}" -o "${usrflags}" "${usr}" /sysusr/usr
# Busybox doesn't load this for us
/sbin/modprobe loop
LOOP=$(losetup -f)
losetup -r "${LOOP}" /sysusr/usr/lib/flatcar/bootengine.img
mkdir /underlay /work
mount -t tmpfs tmpfs /work
mkdir /work/realinit /work/work
mount -t squashfs "${LOOP}" /underlay
mkdir -p /realinit
mount -t overlay -o rw,lowerdir=/underlay,upperdir=/work/realinit,workdir=/work/work overlay /realinit
mkdir -p /realinit/sysusr/usr
mount -o move /sysusr/usr /realinit/sysusr/usr
if [ "${usr}" = /usr.squashfs ]; then
# Move either /oem (preferred) or /usr/share/oem (legacy) into the new root.
mv /oem /realinit || mv /usr/share/oem /realinit || true
mv /usr.squashfs /realinit
fi
debug_sh 4/4: before switch_root to /realinit
killall mdev || true
umount /proc
umount /sys
umount /dev/pts
# Lazy unmount because /dev/console is held by the current process
umount -l /dev
exec switch_root /realinit /init