mkinitfs.in 7.07 KB
Newer Older
Natanael Copa's avatar
Natanael Copa committed
1
2
#!/bin/sh

3
VERSION=@VERSION@
4
5
6
sysconfdir=@sysconfdir@
datadir=@datadir@

7
config="$sysconfdir"/mkinitfs.conf
8
init="$datadir"/initramfs-init
9
fstab="$datadir"/fstab
10
11
12
passwd="$datadir"/passwd
group="$datadir"/group

13
startdir=$PWD
Natanael Copa's avatar
Natanael Copa committed
14

15
16
initfscomp=gzip

Natanael Copa's avatar
Natanael Copa committed
17
feature_files() {
18
19
	local dir="$1"
	local suffix="$2"
20
	local glob file fdir
Natanael Copa's avatar
Natanael Copa committed
21
	for f in $features; do
22
23
24
25
26
27
28
29
30
31
		for fdir in $features_dirs; do
			[ -f "$fdir/$f.$suffix" ] || continue
			for glob in $(sed -e '/^$/d' -e '/^#/d' -e "s|^/*|$dir|" "$fdir/$f.$suffix"); do
				for file in $glob; do
					if [ -d $file ]; then
						find $file -type f
					elif [ -e "$file" ]; then
						echo $file
					fi
				done
Natanael Copa's avatar
Natanael Copa committed
32
			done
33
			break
Natanael Copa's avatar
Natanael Copa committed
34
		done
35
	done
Natanael Copa's avatar
Natanael Copa committed
36
37
38
39
}

initfs_base() {
	local i= dirs= glob= file=
40
	for i in dev proc sys sbin bin run .modloop lib/modules media/cdrom \
41
	    etc/apk media/floppy media/usb newroot; do
Natanael Copa's avatar
Natanael Copa committed
42
43
		dirs="$dirs $tmpdir/$i"
	done
44
	mkdir -p $dirs
Natanael Copa's avatar
Natanael Copa committed
45

46
	local oldpwd="$PWD"
47
	cd "${basedir}"
48
49
50
51
	lddtree -R "$basedir" -l --no-auto-root \
		$(feature_files "$basedir" files) \
		\
		| sed -e "s|^$basedir||" | sort -u \
52
		| cpio --quiet -pdm "$tmpdir" || return 1
Natanael Copa's avatar
Natanael Copa committed
53
54

	# copy init
55
	cd "$startdir"
56
	install -m755 "$init" "$tmpdir"/init || return 1
57
58
59
60
61
	# copy modloop signature
	if [ -n "$modloop_sig" ]; then
		install -Dm644 "$modloop_sig" \
			"$tmpdir"/var/cache/misc/${modloop_sig##*/}
	fi
62
63
64
	for i in "$fstab" "$passwd" "$group"; do
		install -Dm644 "$i" "$tmpdir"/etc/${i##*/} || return 1
	done
65
	cd "$oldpwd"
Natanael Copa's avatar
Natanael Copa committed
66
67
68
}

find_kmod_deps() {
69
	awk -v prepend="/lib/modules/$kernel/" -v modulesdep="${basedir}lib/modules/$kernel/modules.dep" '
70
function recursedeps(k,		j, dep) {
Natanael Copa's avatar
Natanael Copa committed
71
72
73
74
75
76
	if (k in visited)
		return;
	visited[k] = 1;
	split(deps[k], dep, " ");
	for (j in dep)
		recursedeps(dep[j]);
77
	print(prepend k);
Natanael Copa's avatar
Natanael Copa committed
78
79
80
81
82
83
84
}

BEGIN {
	if (modulesdep == "")
		modulesdep="modules.dep";
	FS = ": ";
	while ( (getline < modulesdep) > 0) {
85
86
87
88
		if (substr($0,1,1) == "/") {
			gsub(prepend, "", $1);
			gsub(prepend, "", $2);
		}
Natanael Copa's avatar
Natanael Copa committed
89
90
91
92
93
		deps[$1] = $2;
	}
}

{
94
	mod[$0] = 1;
Natanael Copa's avatar
Natanael Copa committed
95
96
97
98
99
}

END {
	for (i in mod)
		recursedeps(i);
100
}'
Natanael Copa's avatar
Natanael Copa committed
101
102
}

103
find_kmods() {
104
	local oldpwd="$PWD"
Natanael Copa's avatar
Natanael Copa committed
105
	cd "$kerneldir" || return 1
106
	for file in $(feature_files "${kerneldir}/" modules); do
107
		echo ${file#${kerneldir%/}/}
108
	done | find_kmod_deps
109
	cd "$oldpwd"
110
111
112
}

initfs_kmods() {
113
	[ -z "$nokernel" ] || return 0
114
	local glob= file= files= dirs=
115
	rm -rf "$tmpdir"/lib/modules
116
117
	# make sure we have modules.dep
	if ! [ -f "$kerneldir"/modules.dep ]; then
118
		depmod -b "${basedir}" $kernel
119
	fi
120
	local oldpwd="$PWD"
121
	cd "${basedir}"
122
	for file in $(find_kmods); do
Natanael Copa's avatar
Natanael Copa committed
123
		echo "${file#/}"
124
125
	# DO NOT return with 1 if there are no custom modules for initramfs
	done | sort -u | cpio --quiet -pdm "$tmpdir"
126
	mkdir -p "$tmpdir"/lib/modules/$kernel/
127
128
129
130
131
	for file in modules.order modules.builtin; do
		if [ -f "$kerneldir"/$file ]; then
			cp "$kerneldir"/$file "$tmpdir"/lib/modules/$kernel/
		fi
	done
132
	depmod $kernel -b "$tmpdir"
133
	cd "$oldpwd"
Natanael Copa's avatar
Natanael Copa committed
134
135
}

136
initfs_firmware() {
137
	[ -z "$nokernel" ] || return 0
138
139
	rm -rf "$tmpdir"/lib/firmware
	mkdir -p "$tmpdir"/lib/firmware
140
141
142
	# Verify if there are initfs modules
	_modules=`find "$tmpdir"/lib/modules -type f -name "*.ko" -print -quit`
	[ -n "$_modules" ] || return 0
143
144
145
146
147
148
	find "$tmpdir"/lib/modules -type f -name "*.ko" | xargs modinfo -F firmware | sort -u | while read FW; do
		[ -e "${basedir}/lib/firmware/${FW}" ] && install -pD "${basedir}/lib/firmware/${FW}" "$tmpdir"/lib/firmware/$FW
	done
	return 0
}

149
150
initfs_apk_keys() {
	mkdir -p "$tmpdir"/etc/apk/keys
151
	[ "$hostkeys" ] && cp "/etc/apk/keys/"* "$tmpdir"/etc/apk/keys/
152
	cp "${basedir}etc/apk/keys/"* "$tmpdir"/etc/apk/keys/
153
154
}

155
156
157
158
159
160
161
162
163
initfs_custom_files() {
	for file in "$custom_files"; do
		if [ -f "$basedir"/$file ]; then
			mkdir -p "$tmpdir"/${file%/*}
			cp "$basedir"/$file "$tmpdir"/$file
		fi
	done
}

Natanael Copa's avatar
Natanael Copa committed
164
initfs_cpio() {
165
	if [ -n "$list_sources" ]; then
166
		(cd "$tmpdir" && find . | sort)
167
168
		return
	fi
169
	rm -f $outfile
kpcyrd's avatar
kpcyrd committed
170
171
172
173
174
175

	if [ -n "$SOURCE_DATE_EPOCH" ]; then
		# normalize timestamps
		find "$tmpdir" -exec touch -h -d "@$SOURCE_DATE_EPOCH" {} +
	fi

176
	umask 0077
177
178
179
180
181
182
183
184
185
	(cd "$tmpdir" && find . | sort | cpio --quiet -o -H newc | $comp) > $outfile
}

cmd_exists() {
	local cmd="$1"
	if ! command -v "$cmd" >/dev/null 2>&1; then
		echo "Command \"$cmd\" is not available."
		exit 1
	fi
Natanael Copa's avatar
Natanael Copa committed
186
187
188
189
}

usage() {
	cat <<EOF
190
usage: mkinitfs [-hkKLln] [-b basedir] [-c configfile] [-F features] [-f fstab]
191
192
		[-C initramfs compression] [-i initfile] [-o outfile]
		[-P featuresdir] [-t tempdir] [kernelversion]
Natanael Copa's avatar
Natanael Copa committed
193
194
195
options:
	-b  prefix files and kernel modules with basedir
	-c  use configfile instead of $config
omni's avatar
omni committed
196
	-C  initramfs compression (gzip|xz|zstd defaults to $initfscomp)
197
198
	-f  use fstab instead of $fstab
	-F  use specified features
Natanael Copa's avatar
Natanael Copa committed
199
200
201
	-h  print this help
	-i  use initfile as init instead of $init
	-k  keep tempdir
202
	-K  copy also host keys to initramfs
203
	-l  only list files that would have been used
Natanael Copa's avatar
Natanael Copa committed
204
	-L  list available features
205
	-n  don't include kernel modules or firmware
Natanael Copa's avatar
Natanael Copa committed
206
	-o  set another outfile
207
	-P  prepend features.d search path
208
	-q  Quiet mode
209
	-s  Include modloop signature
Natanael Copa's avatar
Natanael Copa committed
210
211
212
213
214
215
216
	-t  use tempdir when creating initramfs image

EOF
	exit 1
}

# main
217
features_dirs=${features_dir:-"${basedir%/:-}/${sysconfdir#/}/features.d"}
Natanael Copa's avatar
Natanael Copa committed
218

219
while getopts "b:c:C:f:F:hi:kKLlno:P:qs:t:" opt; do
Natanael Copa's avatar
Natanael Copa committed
220
221
222
	case "$opt" in
		b) basedir="$OPTARG";;
		c) config="$OPTARG";;
223
		C) initfscomp="$OPTARG";;
224
225
		F) myfeatures="$OPTARG";;
		f) fstab="$OPTARG";;
Natanael Copa's avatar
Natanael Copa committed
226
227
228
		h) usage;;
		i) init=$OPTARG;;
		k) keeptmp=1;;
229
		K) hostkeys=1;;
Natanael Copa's avatar
Natanael Copa committed
230
		L) list_features=1;;
231
		l) list_sources=1;;
232
		n) nokernel=1;;
Natanael Copa's avatar
Natanael Copa committed
233
		o) outfile="$OPTARG";;
234
		P) features_dirs="$OPTARG $features_dirs";;
235
		q) quiet=1;;
236
		s) modloop_sig="$OPTARG";;
Natanael Copa's avatar
Natanael Copa committed
237
238
239
240
241
242
		t) tmpdir="$OPTARG";;
		*) usage;;
	esac
done
shift $(( $OPTIND - 1 ))

243
. $(readlink -f "$config")
244
[ -n "$myfeatures" ] && features="$myfeatures"
Natanael Copa's avatar
Natanael Copa committed
245
246

if [ -n "$list_features" ]; then
247
248
249
	for dir in $features_dirs; do
		for i in $dir/*.files $dir/*.modules; do
			[ -e "$i" ] || continue
250
			file=${i##*/}
251
252
			echo ${file%.*}
		done
253
	done | sort -u
Natanael Copa's avatar
Natanael Copa committed
254
255
256
	exit 0
fi

257
258
259
260
basedir="${basedir%/}/"
[ "${basedir}" = "${basedir#/}" ] && basedir="${PWD}/${basedir}"


261
262
263
264
if [ -z "$nokernel" ]; then
	[ -n "$1" ] && kernel="$1"
	[ -z "$kernel" ] && kernel=$(uname -r)
	kerneldir="${basedir}lib/modules/$kernel"
265

266
267
268
269
270
	kflavor=${kernel##*-}
	[ "$kflavor" = "$kernel" ] && kflavor=vanilla
else
	kflavor=generic
fi
271

Natanael Copa's avatar
Natanael Copa committed
272
if [ -z "$outfile" ]; then
273
	outfile="${basedir}boot/initramfs-${kflavor}"
Natanael Copa's avatar
Natanael Copa committed
274
275
fi

276
if [ -z "$nokernel" ] && [ ! -d "$kerneldir" ]; then
Natanael Copa's avatar
Natanael Copa committed
277
278
279
280
	echo "$kerneldir does not exist or is not a directory"
	exit 1
fi

281
282
283
284
285
if [ -n "$DEBUG_KMOD" ]; then
	find_kmods
	exit 0
fi

Natanael Copa's avatar
Natanael Copa committed
286
287
288
289
290
291
292
293
294
295
if [ -z "$tmpdir" ]; then
	tmpdir=$(mktemp -d /tmp/mkinitfs.XXXXXX)
else
	mkdir -p "$tmpdir"
fi

if [ -z "$keeptmp" ]; then
	[ -d "$tmpdir" ] && rm -rf "$tmpdir"/*
fi

296
297
if [ -z "$list_sources" ] && [ -z "$quiet" ]; then
	echo "==> initramfs: creating $outfile"
Natanael Copa's avatar
Natanael Copa committed
298
fi
Natanael Copa's avatar
Natanael Copa committed
299

300
case "$initfscomp" in
301
	gzip) comp="$(command -v pigz 2>/dev/null || echo gzip) -9" ;;
302
	xz) cmd_exists xz; comp="xz -C crc32 -T 0" ;;
Iggy Jackson's avatar
Iggy Jackson committed
303
	zstd) cmd_exists zstd; comp="zstd -19" ;;
304
305
306
	*) echo "Initramfs compression \"$initfscomp\" not supported!"; exit 1 ;;
esac

Natanael Copa's avatar
Natanael Copa committed
307
308
initfs_base \
	&& initfs_kmods \
309
	&& initfs_firmware \
Natanael Copa's avatar
Natanael Copa committed
310
	&& initfs_apk_keys \
311
	&& initfs_custom_files \
Natanael Copa's avatar
Natanael Copa committed
312
313
	&& initfs_cpio
rc=$?
314

Natanael Copa's avatar
Natanael Copa committed
315
316
317
318
319
# cleanup
if [ -z "$keeptmp" ]; then
	[ -d "$tmpdir" ] && rm -rf "$tmpdir"
fi

Natanael Copa's avatar
Natanael Copa committed
320
exit $rc