mkinitfs.in 6.46 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
	done | sort -u | cpio --quiet -pdm "$tmpdir" || return 1
125
	mkdir -p "$tmpdir"/lib/modules/$kernel/
126 127 128 129 130
	for file in modules.order modules.builtin; do
		if [ -f "$kerneldir"/$file ]; then
			cp "$kerneldir"/$file "$tmpdir"/lib/modules/$kernel/
		fi
	done
131
	depmod $kernel -b "$tmpdir"
132
	cd "$oldpwd"
Natanael Copa's avatar
Natanael Copa committed
133 134
}

135
initfs_firmware() {
136
	[ -z "$nokernel" ] || return 0
137 138 139 140 141 142 143 144
	rm -rf "$tmpdir"/lib/firmware
	mkdir -p "$tmpdir"/lib/firmware
	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
}

145 146
initfs_apk_keys() {
	mkdir -p "$tmpdir"/etc/apk/keys
147
	[ "$hostkeys" ] && cp "/etc/apk/keys/"* "$tmpdir"/etc/apk/keys/
148
	cp "${basedir}etc/apk/keys/"* "$tmpdir"/etc/apk/keys/
149 150
}

Natanael Copa's avatar
Natanael Copa committed
151
initfs_cpio() {
152
	if [ -n "$list_sources" ]; then
153
		(cd "$tmpdir" && find . | sort)
154 155
		return
	fi
156
	rm -f $outfile
157
	umask 0077
158 159 160 161 162 163 164 165 166
	(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
167 168 169 170
}

usage() {
	cat <<EOF
171
usage: mkinitfs [-hkKLln] [-b basedir] [-c configfile] [-F features] [-f fstab]
172 173
		[-C initramfs compression] [-i initfile] [-o outfile]
		[-P featuresdir] [-t tempdir] [kernelversion]
Natanael Copa's avatar
Natanael Copa committed
174 175 176
options:
	-b  prefix files and kernel modules with basedir
	-c  use configfile instead of $config
177
	-C  initramfs compression (gzip|xz defaults to $initfscomp)
178 179
	-f  use fstab instead of $fstab
	-F  use specified features
Natanael Copa's avatar
Natanael Copa committed
180 181 182
	-h  print this help
	-i  use initfile as init instead of $init
	-k  keep tempdir
183
	-K  copy also host keys to initramfs
184
	-l  only list files that would have been used
Natanael Copa's avatar
Natanael Copa committed
185
	-L  list available features
186
	-n  don't include kernel modules or firmware
Natanael Copa's avatar
Natanael Copa committed
187
	-o  set another outfile
188
	-P  prepend features.d search path
189
	-q  Quiet mode
190
	-s  Include modloop signature
Natanael Copa's avatar
Natanael Copa committed
191 192 193 194 195 196 197
	-t  use tempdir when creating initramfs image

EOF
	exit 1
}

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

200
while getopts "b:c:C:f:F:hi:kKLlno:P:qs:t:" opt; do
Natanael Copa's avatar
Natanael Copa committed
201 202 203
	case "$opt" in
		b) basedir="$OPTARG";;
		c) config="$OPTARG";;
204
		C) initfscomp="$OPTARG";;
205 206
		F) myfeatures="$OPTARG";;
		f) fstab="$OPTARG";;
Natanael Copa's avatar
Natanael Copa committed
207 208 209
		h) usage;;
		i) init=$OPTARG;;
		k) keeptmp=1;;
210
		K) hostkeys=1;;
Natanael Copa's avatar
Natanael Copa committed
211
		L) list_features=1;;
212
		l) list_sources=1;;
213
		n) nokernel=1;;
Natanael Copa's avatar
Natanael Copa committed
214
		o) outfile="$OPTARG";;
215
		P) features_dirs="$OPTARG $features_dirs";;
216
		q) quiet=1;;
217
		s) modloop_sig="$OPTARG";;
Natanael Copa's avatar
Natanael Copa committed
218 219 220 221 222 223
		t) tmpdir="$OPTARG";;
		*) usage;;
	esac
done
shift $(( $OPTIND - 1 ))

224
. $(readlink -f "$config")
225
[ -n "$myfeatures" ] && features="$myfeatures"
Natanael Copa's avatar
Natanael Copa committed
226 227

if [ -n "$list_features" ]; then
228 229 230
	for dir in $features_dirs; do
		for i in $dir/*.files $dir/*.modules; do
			[ -e "$i" ] || continue
231
			file=${i##*/}
232 233
			echo ${file%.*}
		done
234
	done | sort -u
Natanael Copa's avatar
Natanael Copa committed
235 236 237
	exit 0
fi

238 239 240 241
basedir="${basedir%/}/"
[ "${basedir}" = "${basedir#/}" ] && basedir="${PWD}/${basedir}"


242 243 244 245
if [ -z "$nokernel" ]; then
	[ -n "$1" ] && kernel="$1"
	[ -z "$kernel" ] && kernel=$(uname -r)
	kerneldir="${basedir}lib/modules/$kernel"
246

247 248 249 250 251
	kflavor=${kernel##*-}
	[ "$kflavor" = "$kernel" ] && kflavor=vanilla
else
	kflavor=generic
fi
252

Natanael Copa's avatar
Natanael Copa committed
253
if [ -z "$outfile" ]; then
254
	outfile="${basedir}boot/initramfs-${kflavor}"
Natanael Copa's avatar
Natanael Copa committed
255 256
fi

257
if [ -z "$nokernel" ] && [ ! -d "$kerneldir" ]; then
Natanael Copa's avatar
Natanael Copa committed
258 259 260 261
	echo "$kerneldir does not exist or is not a directory"
	exit 1
fi

262 263 264 265 266
if [ -n "$DEBUG_KMOD" ]; then
	find_kmods
	exit 0
fi

Natanael Copa's avatar
Natanael Copa committed
267 268 269 270 271 272 273 274 275 276
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

277 278
if [ -z "$list_sources" ] && [ -z "$quiet" ]; then
	echo "==> initramfs: creating $outfile"
Natanael Copa's avatar
Natanael Copa committed
279
fi
Natanael Copa's avatar
Natanael Copa committed
280

281 282 283 284 285 286
case "$initfscomp" in
	gzip) comp="gzip -9" ;;
	xz) cmd_exists xz; comp="xz -C crc32 -T 0" ;;
	*) echo "Initramfs compression \"$initfscomp\" not supported!"; exit 1 ;;
esac

Natanael Copa's avatar
Natanael Copa committed
287 288
initfs_base \
	&& initfs_kmods \
289
	&& initfs_firmware \
Natanael Copa's avatar
Natanael Copa committed
290 291 292
	&& initfs_apk_keys \
	&& initfs_cpio
rc=$?
293

Natanael Copa's avatar
Natanael Copa committed
294 295 296 297 298
# cleanup
if [ -z "$keeptmp" ]; then
	[ -d "$tmpdir" ] && rm -rf "$tmpdir"
fi

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