]> git.pld-linux.org Git - projects/geninitrd.git/blame - geninitrd
Allow usage of UUID/LABEL in /etc/crypttab.
[projects/geninitrd.git] / geninitrd
CommitLineData
bb529f94
JK
1#!/bin/sh
2
3# geninitrd
4#
45d4d8cb 5# by PLD Linux Team
bb529f94 6#
9e1ceabe 7# based on mkinitrd from RedHat Linux
e4b07ddc 8#
c31050f3 9
b7114dde 10VERSION='devel'
ca2c2012 11PROGRAM=${0##*/}
bb529f94
JK
12
13. /etc/rc.d/init.d/functions
ded87775 14. /lib/geninitrd/functions
e2405b29 15. /etc/sysconfig/system
bb529f94 16
c124d0cf
ER
17# list of geninitrd modules which need setup routine after commandline args parsing
18GENINITRD_MODS=""
c3667d07 19COMPRESS=yes
897d14b7 20STRIP=/usr/bin/strip
bb529f94
JK
21target=""
22kernel=""
23force=""
24verbose=""
25MODULES=""
26img_vers=""
c3667d07 27fstab=/etc/fstab
c3667d07 28modext=.o
4e9eb79c 29rootdev_nr=0
738c05d8
ER
30# device node for rootfs from fstab
31rootdev=""
bb529f94 32
8bd582f1
ER
33# internal variables
34# is /dev on tmpfs
b64f015b
ER
35dev_mounted=no
36# is /proc mounted
37proc_mounted=no
38# is /sys mounted
39sys_mounted=no
40# is /tmp mounted on tmpfs
41tmp_mounted=no
42
43# are /dev nodes already created from /proc/devices info?
8bd582f1 44proc_partitions=no
6b013929 45
b64f015b 46usage() {
46768f45 47 echo "Usage: $PROGRAM [--version] [-v] [-f] [--ifneeded] [--preload <module>]"
ac085800 48 echo " [--with=<module>] [--image-version] [--fstab=<fstab>] [--nocompress]"
8a6f083b 49 echo " [--compress=yes|xz|lzma|bzip2|gzip|lzo]"
76a48507 50 echo " [--nostrip ] [--strip PATH/strip] [--strip=PATH/strip]"
92ed99b6 51 echo " [--initrdfs=rom|initramfs|ext2|cram] [--modules-conf=<modules.conf>]"
ba5d09f0 52 echo " [--with-bootsplash] [--without-bootsplash]"
6c69a2d4
ER
53 echo " [--with-fbsplash] [--without-fbsplash]"
54 echo " [--with-fbcondecor] [--without-fbcondecor]"
e4b07ddc 55 echo " [--lvmtoolsversion=1|2] [--with-udev] [--without-udev]"
ba5d09f0 56 echo " [--with-suspend] [--without-suspend]"
1cd2aabd 57 echo " [--with-tuxonice] [--without-tuxonice]"
ecd7bf46
ER
58 echo " [--without-dmraid]"
59 echo " [--with-multipath=DEVPATH] [--without-multipath]"
3ef3d717 60 echo " [--without-blkid] [--without-luks]"
ac085800 61 echo " <initrd-image> <kernel-version>"
553786c4 62 echo ""
46768f45
ER
63 echo "Example:"
64
0ad676eb 65 local kdir kver dir=${target:-/boot}
46768f45
ER
66 for kdir in /lib/modules/*; do
67 [ -d $kdir ] || continue
68 kver=${kdir##*/}
dfe1a27c 69 echo " $0 -f --initrdfs=initramfs $dir/initrd-$kver.gz $kver $verbose"
63514069 70 done | sort -V
bb529f94
JK
71}
72
779a218a 73msg() {
f4010f7f
AM
74 echo "$PROGRAM: $*"
75}
76
77warn() {
4a60c01f 78 msg "WARNING: $*" >&2
779a218a
AM
79}
80
02ba8ab7 81verbose() {
34f3f0e9 82 [ -n "$verbose" ] && msg "$*" >&3
02ba8ab7
ER
83}
84
94769f11 85debug() {
02ba8ab7 86 [ x"$verbose" = x"-v -v" ] && msg "$*" >&3
94769f11 87}
aa69da6e 88
2b945b6b
ER
89# add initrd code to print to kmsg
90# @param string message
91# @param int loglevel. defaults to "6" (info)
92# Log levels can be:
93# Name String Meaning
94# KERN_EMERG "0" Emergency messages, system is about to crash or is unstable
95# KERN_ALERT "1" Something bad happened and action must be taken immediately
96# KERN_CRIT "2" A critical condition occurred like a serious hardware/software failure
97# KERN_ERR "3" An error condition, often used by drivers to indicate difficulties with the hardware
98# KERN_WARNING "4" A warning, meaning nothing serious by itself but might indicate problems
99# KERN_NOTICE "5" Nothing serious, but notably nevertheless. Often used to report security events.
100# KERN_INFO "6" Informational message e.g. startup information at driver initialization
101# KERN_DEBUG "7" Debug messages
102# KERN_CONT "c" "continued" line of log printout (only done after a line that had no enclosing \n)
103kmsg() {
104 local msg="$1" level=${2:-6}
105 echo "echo '<$level>$msg' > /dev/kmsg" | add_linuxrc
106}
107
bf6c3fcb
ER
108# aborts program abnormally
109die() {
b5f5c089 110 local rc=${2:-1}
046c68c9 111 msg "ERROR: $1" >&2
bf6c3fcb
ER
112 exit $rc
113}
114
684d5d2a
ER
115# find program from specified paths
116find_tool() {
27442691 117 local x p b n
c45a111c 118 local paths="$initrd_dirs /bin /sbin /usr/bin /usr/sbin"
684d5d2a 119 for x in "$@"; do
5493388d 120 debug "find_tool: checking $x"
684d5d2a
ER
121 if [ -x "$x" ]; then
122 echo $x
02ba8ab7 123 verbose "find_tool: found $x"
684d5d2a
ER
124 return 0
125 fi
27442691
JR
126 n="$x"
127 for p in $paths; do
128 b=$(basename $x)
5493388d 129 debug "find_tool: checking $p/$b"
27442691
JR
130 if [ -x "$p/$b" ]; then
131 echo $p/$b
132 verbose "find_tool: found $p/$b"
133 return 0
134 fi
135 n="$n $p/$b"
136 done
684d5d2a 137 done
27442691 138 debug "find_tool: did not find any of: $n"
684d5d2a
ER
139 return 1
140}
141
c124d0cf
ER
142# loads geninitrd modules
143geninitrd_load_mods() {
144 local mod
145 for mod in "$@"; do
146 if [ ! -f /lib/geninitrd/mod-$mod.sh ]; then
147 die "$mod geninitrd module can't be loaded"
148 fi
149 . /lib/geninitrd/mod-$mod.sh
150
c34c6a69 151 GENINITRD_MODS="$GENINITRD_MODS $mod"
c124d0cf
ER
152 done
153}
154
155# setup geninitrd modules
156geninitrd_setup_mods() {
b7114dde 157 local mod
c124d0cf
ER
158
159 for mod in $GENINITRD_MODS; do
b7114dde 160 debug "# $mod"
c34c6a69
ER
161
162 # some mods want init
163 if type setup_mod_$mod > /dev/null; then
164 eval setup_mod_$mod
165 fi
c124d0cf
ER
166 done
167}
168
c6c6ce01
ER
169# append text to /linuxrc
170# takes STDIN as input
171add_linuxrc() {
b64f015b 172 cat >> "$RCFILE"
c6c6ce01
ER
173}
174
b64f015b
ER
175# generate code to mount /dev on tmpfs and create initial nodes
176# can be called multiple times. /dev is cleaned up (umounted) automatically at
177# the end of script.
178mount_dev() {
b64f015b
ER
179 # we already generated tmpfs code; return
180 if is_yes "$dev_mounted"; then
181 return
182 fi
183
184 dev_mounted=yes
185
186 busybox_applet mount mknod mkdir
187 add_linuxrc <<-EOF
188 : 'Creating /dev'
621695f6
AF
189 if ! mount -t devtmpfs -o mode=0755,nosuid devtmpfs /dev > /dev/null 2>&1; then
190 mount -o mode=0755,nosuid -t tmpfs tmpfs /dev
13659675
AM
191 mknod -m 600 /dev/console c 5 1
192 mknod -m 666 /dev/null c 1 3
193 mknod -m 666 /dev/zero c 1 5
194 mknod -m 666 /dev/random c 1 8
195 mknod -m 600 /dev/snapshot c 10 231
196 mknod -m 666 /dev/urandom c 1 9
197 mknod -m 666 /dev/ptmx c 5 2
198 mknod -m 644 /dev/kmsg c 1 11
621695f6 199 fi
b64f015b
ER
200 mkdir /dev/pts
201 mkdir /dev/shm
202 EOF
203}
204
ff9aded5
AM
205# load font
206load_font() {
207 local font
208 [ ! -r /etc/sysconfig/console ] && return
209 . /etc/sysconfig/console
210 if [ -n "$CONSOLEFONT" ]; then
211 font=$(ls -1 /lib/kbd/consolefonts/${CONSOLEFONT}*.gz 2> /dev/null)
212 if [ -n "$font" ]; then
213 verbose "Loading font $font"
214 busybox_applet loadfont
215 inst_d "/lib/kbd/consolefonts"
216 cp -a "$font" "$DESTDIR/lib/kbd/consolefonts/"
217 gunzip ${DESTDIR}/lib/kbd/consolefonts/${CONSOLEFONT}*.gz
218 font=${font%.gz}
219 echo "loadfont < $font" | add_linuxrc
220 fi
221 fi
222}
223
b64f015b
ER
224# generate code to mount /proc on initrd
225# can be called multiple times
226mount_proc() {
227 if is_yes "$proc_mounted"; then
228 return
229 fi
230
231 proc_mounted=yes
2bface63
ER
232 if [ "$INITRDFS" = "initramfs" ]; then
233 # /proc is mounted with initramfs 2.6.22.14 kernel
234 # XXX: remove when it is clear why proc was already mounted
235 echo "[ -f /proc/cmdline ] || mount -t proc none /proc" | add_linuxrc
236 else
237 echo "mount -t proc none /proc" | add_linuxrc
238 fi
b64f015b
ER
239}
240
241# generate code to mount /sys on initrd
242# can be called multiple times
243mount_sys() {
244 if is_yes "$sys_mounted"; then
245 return
246 fi
247
248 sys_mounted=yes
249 echo "mount -t sysfs none /sys" | add_linuxrc
250}
251
252# generate code to mount /tmp on initrd
253# can be called multiple times
254mount_tmp() {
255 if [ "$INITRDFS" = "initramfs" ]; then
256 # initramfs is read-write filesystem, no need for tmpfs
257 return
258 fi
259
260 if is_yes "$tmp_mounted"; then
261 return
262 fi
263
264 tmp_mounted=yes
265 echo "mount -t tmpfs none /tmp" | add_linuxrc
266}
267
d63131e0
AF
268# generate code to mount /run on initrd
269# can be called multiple times
270mount_run() {
271 if is_yes "$run_mounted"; then
272 return
273 fi
274
275 run_mounted=yes
276 echo "mount -t tmpfs run /run" | add_linuxrc
277}
278
b64f015b 279# unmount all mountpoints mounted by geninitrd
c6d164fb 280# try to move pseudo filesystems to newroot if possible
b64f015b 281umount_all() {
ec49b7e6
ER
282
283 add_linuxrc <<-'EOF'
903f21ea 284 : Last shell before umounting all and giving control over to real init.
ec49b7e6
ER
285 debugshell
286 EOF
5b70f84d 287
d63131e0 288 if is_yes "$run_mounted"; then
c6d164fb
ER
289 add_linuxrc <<-EOF
290 mount --bind /run /newroot/run
291 umount /run
292 EOF
d63131e0
AF
293 run_mounted=no
294 fi
b64f015b 295 if is_yes "$dev_mounted"; then
c6d164fb
ER
296 add_linuxrc <<-EOF
297 mount --bind /dev /newroot/dev
298 umount /dev
299 EOF
b64f015b
ER
300 dev_mounted=no
301 fi
b64f015b 302 if is_yes "$sys_mounted"; then
c6d164fb
ER
303 add_linuxrc <<-EOF
304 mount --bind /sys /newroot/sys
305 umount /sys
306 EOF
b64f015b
ER
307 sys_mounted=no
308 fi
c6d164fb
ER
309 if is_yes "$proc_mounted"; then
310 add_linuxrc <<-EOF
311 mount --bind /proc /newroot/proc
312 umount /proc
313 EOF
314 proc_mounted=no
315 fi
b64f015b
ER
316 if is_yes "$tmp_mounted"; then
317 echo 'umount /tmp' | add_linuxrc
318 tmp_mounted=no
319 fi
320}
321
9299682f
ER
322# Checks if busybox has support for APPLET(s)
323# Exits from geninitrd if the support is not present.
324#
325# NB! XXX do not output to STDOUT, it will appear in initrd images in some cases!
326busybox_applet() {
30495bbf 327 local err=0 applet
9299682f
ER
328
329 if [ -z "$busybox_functions" ]; then
684d5d2a 330 local tmp=$($busybox 2>&1)
9b1373fb
ER
331
332 # BusyBox v1.1.3 says applet not found if it's not called 'busybox'.
333 if [[ "$tmp" = *applet\ not\ found* ]]; then
334 local t=$(mktemp -d)
684d5d2a 335 ln -s $busybox $t/busybox
9b1373fb
ER
336 local tmp=$($t/busybox 2>&1)
337 rm -rf $t
338 fi
339
340 busybox_functions=$(echo "$tmp" | \
9299682f
ER
341 sed -ne '/Currently defined functions:/,$p' | \
342 xargs | sed -e 's,.*Currently defined functions: ,,'
343 )
344 fi
345 for applet in $*; do
346 local have
347 # try cache
348 eval have='$'busybox_have_$applet
349 if [ -z "$have" ]; then
e871f497 350 have=$(echo "$busybox_functions" | grep -Ec "( |^)$applet(,|$)")
9299682f 351 if [ "$have" = 0 ]; then
f4010f7f 352 warn "This setup requires busybox-initrd compiled with applet '$applet' support"
9299682f
ER
353 err=1
354 fi
355 eval busybox_have_$applet=$have
356 fi
357 done
358 if [ $err = 1 ]; then
00eaa938 359 die "Aborted"
9299682f
ER
360 fi
361}
362
755e5cdc
ER
363# Extract the .config file from a kernel image
364# uses extract-ikconfig from kernel sources (scripts/extract-ikconfig)
365ikconfig() {
61d20b49 366 local kofile=$(modinfo -k $kernel -n configs 2> /dev/null)
755e5cdc
ER
367 if [ -n "$kofile" ]; then
368 /lib/geninitrd/extract-ikconfig $kofile
7283bf35 369 return
25cb53df 370 fi
7283bf35
ER
371
372 # see if config available as separate file
373 if [ -f /boot/config-$kernel ]; then
374 cat /boot/config-$kernel
375 return
376 fi
377
378 # finally try vmlinuz itself
379 /lib/geninitrd/extract-ikconfig /boot/vmlinuz-$kernel
25cb53df
ER
380}
381
faee129c
AM
382# @param $module
383basename_module() {
384 local module=$1
385
386 module=${module##*/}
387 module=${module%$modext*}
388 echo $module
389}
390
7ffba534
ER
391# Finds module dependencies
392#
7ffba534
ER
393# @param $module
394#
046c68c9 395# Outputs full path to module and it's dependencies
7ffba534 396find_depmod() {
fe280785 397 local module="$1"
046c68c9
ER
398 local skiperrors=0
399
400 # if module is prefixed with dash, we should ignore errors if the module
401 # can't be found.
402 if [ ${module#-} != $module ]; then
403 skiperrors=1
404 module=${module#-}
405 fi
406
046c68c9
ER
407 # This works when user has module-init-tools installed even on 2.4 kernels
408 local modprobe
409 modprobe=$(modprobe --set-version $kernel --show-depends $module --ignore-install 2>&1)
410
411 if [ $? != 0 ]; then
412 if [ $skiperrors = 1 ]; then
0c7e9123 413 return 0
7cac5014 414 fi
046c68c9 415 echo >&2 "$modprobe"
7cac5014 416
7ffba534 417 if ! is_no "$EXIT_IF_MISSING"; then
046c68c9 418 die "$module: module not found for $kernel kernel"
7ffba534 419 fi
046c68c9
ER
420
421 warn "$module: module not found for $kernel kernel"
422 warn "If $module isn't compiled in kernel then this initrd may not start your system."
7ffba534
ER
423 fi
424
faee129c
AM
425 local smodule
426
046c68c9 427 echo "$modprobe" | \
c25765ed 428 while read insmod modpath options; do
faee129c
AM
429 if [ "$insmod" = "insmod" ]; then
430
431 # XXX: find a away to autodetect
432 smodule=$(basename_module $modpath)
433 case "$smodule" in
b771ab7f
AM
434 btrfs)
435 find_depmod "-libcrc32c"
436 ;;
bb0ca032 437 crc-t10dif)
e7d76a06 438 find_depmod "-crct10dif-pclmul"
bb0ca032
AM
439 find_depmod "-crct10dif"
440 ;;
faee129c
AM
441 libcrc32c)
442 find_depmod "-crc32c-intel"
443 find_depmod "-crc32c"
444 ;;
dd1e5379
AM
445 virtio_blk|virtio_scsi)
446 find_depmod "-virtio_pci"
447 find_depmod "-virtio_mmio"
448 ;;
faee129c
AM
449 esac
450
451 echo $modpath
452 fi
7ffba534 453 done
0c7e9123 454 return 0
7ffba534
ER
455}
456
4a60c01f
AM
457find_firmware() {
458 local module="$1"
601127ea
ER
459
460 # no firmware support in 2.4 kernels
461 if [ "$kernel_version_long" -lt "002005048" ]; then
462 return
463 fi
464 echo -n $(NEW_MODINFO=1 modinfo -k $kernel -F firmware $module 2>/dev/null | xargs)
4a60c01f
AM
465}
466
046c68c9
ER
467# @param $module
468find_module() {
469 local mod depmod module=$1
ac085800 470
046c68c9 471 depmod=$(find_depmod $module) || exit 1
fe280785 472 for mod in $depmod; do
7ffba534 473 mod=${mod#/lib/modules/$kernel/}
fe280785
ER
474
475 # add each module only once
476 local m have=0
477 for m in $MODULES; do
478 [ $m = $mod ] && have=1
479 done
480 if [ $have = 0 ]; then
c2eb7d4f 481 MODULES="$MODULES $mod"
fe280785 482 fi
10c3df06 483 done
bb529f94
JK
484}
485
034fdd5d
ER
486# install a file to temporary mount image.
487# it will operate recursively (copying directories)
488# and will symlink destinations if source is symlink.
bb529f94 489inst() {
17e97aec 490 if [ $# -lt 2 ]; then
a9ace64a 491 die 'Usage: inst <file> [<file>] <destination>'
c31050f3 492 fi
17e97aec
ER
493
494 local src i=0 c=$(($# - 1))
495 while [ $i -lt $c ]; do
496 src="$src $1"
497 i=$((i + 1))
498 shift
499 done
500 local dest=$1
501 set -- $src
ce40ba21 502 local parentDir=$(dirname $DESTDIR$dest)
02ba8ab7 503 if [ ! -d "$parentDir" ]; then
7f5eccc0 504 verbose "+ mkdir -p DESTDIR${parentDir#$DESTDIR}"
02ba8ab7
ER
505 mkdir -p $parentDir
506 fi
7f5eccc0 507 verbose "+ cp $* DESTDIR$dest"
b9c1a1c5 508 cp -HRp "$@" "$DESTDIR$dest"
bb529f94
JK
509}
510
dab92b1d 511inst_d() {
17e97aec 512 if [ $# = 0 ]; then
a9ace64a 513 die 'Usage: inst_d <destination> <destination>'
034fdd5d 514 fi
7c239866 515 local dir
034fdd5d 516 for dir in "$@"; do
9b557a09 517 install -d "$DESTDIR$dir"
034fdd5d
ER
518 done
519}
520
209061e3
ER
521# install executable and it's shared libraries
522inst_exec() {
17e97aec 523 if [ $# -lt 2 ]; then
3601c2fa 524 die "Invalid params ($@), Usage: inst_exec <file>[, <file>] <destination>"
17e97aec 525 fi
209061e3
ER
526 local src i=0 c=$(($# - 1))
527 while [ $i -lt $c ]; do
528 src="$src $1"
529 i=$((i + 1))
530 shift
531 done
9b532fe6 532 local dest=$1
209061e3
ER
533 set -- $src
534
9b532fe6
ER
535 inst "$@" $dest
536
c45a111c 537 local obj lib libs libdir
10e8125f 538 for obj in "$@"; do
66aec48b 539 case "$obj" in
68c2e3b2 540 /lib/ld-linux.so.2 | /lib64/ld-linux-x86-64.so.2 | /libx32/ld-linux-x32.so.2)
66aec48b
ER
541 continue
542 esac
543
544 libs=$(ldd "$obj" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
545 for lib in $libs; do
1be24d6e
ER
546 libdir=$(cd $(dirname "$lib"); pwd)
547 if [ ! -f "$DESTDIR/$lib" ]; then
548 inst_d $libdir
549 inst_exec $lib $libdir
66aec48b
ER
550 fi
551 done
209061e3 552 done
c7ade647
ER
553
554 # hack for uclibc linked binaries requiring this fixed path
555 # XXX: shouldn't rpath be used here instead so th
54c9f5ee
AM
556 for _lib in $(get_libdir LIBDIR); do
557 if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
558 lib=$DESTDIR/$_lib/libc.so.0
559 lib=$(ldd "$lib" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
560 libdir=$(cd $(dirname "$lib"); pwd)
561 if [ ! -e $DESTDIR$libdir ]; then
562 libdir=$(dirname "$libdir")
563 inst_d $libdir
564 verbose "+ ln -s /$_lib $DESTDIR$libdir"
565 ln -s /$_lib $DESTDIR$libdir
566 break
567 fi
c7ade647 568 fi
54c9f5ee 569 done
209061e3
ER
570}
571
82474db9
ER
572# output modules.conf / modprobe.conf
573modprobe_conf() {
574 echo "$modprobe_conf_cache"
575}
576
38ac83a5
ER
577# return options for MODULE
578# @param $1 module name
579modprobe_options() {
580 local module=$1
915ff812 581 local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
38ac83a5
ER
582 echo ${options# }
583}
584
82474db9
ER
585#
586# defaults to modprobe -c if not told otherwise, this means include statements
587# work from there.
588cache_modprobe_conf() {
707f5e60 589 if [ "$kernel_version" -lt "002005" ]; then
82474db9
ER
590 modulefile=/etc/modules.conf
591 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
592 modulefile=/etc/conf.modules
593 fi
594 fi
595
596 if [ -n "$modulefile" ]; then
d8056591 597 debug "Using $modulefile for modules config"
99e7251e
ER
598 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
599
82474db9 600 else
d8056591 601 debug "Using modprobe -c to get modules config"
99e7251e 602 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
82474db9
ER
603 fi
604}
605
bc0d6f2d 606# find modules for $devpath
d8056591 607find_modules_for_devpath() {
bc0d6f2d
ER
608 local devpath="$1"
609 if [ -z "$devpath" ]; then
d8056591 610 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
f6536797 611 fi
ac085800 612
c2eb7d4f
ER
613 if [[ "$devpath" = /dev/dm-* ]]; then
614 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
d2cb46cf 615 devpath=$(dm_node "$devpath")
c2eb7d4f
ER
616 fi
617
336018a5 618 if [ -L "$devpath" ] && ! is_lvm "$devpath" && ! is_luks "$devpath"; then
c2eb7d4f
ER
619 # sanitize things like:
620 # /dev/block/104:2 -> /dev/cciss/c0d0p2
621 devpath=$(readlink -f "$devpath")
622 fi
623
02ba8ab7 624 verbose "Finding modules for device path $devpath"
bc0d6f2d 625
3ef3d717
ER
626 if is_luks "$devpath"; then
627 find_modules_luks "$devpath"
628 return
629 fi
630
74d45ce1
ER
631 if is_nfs "$devpath"; then
632 find_modules_nfs "$devpath"
d9179777
ER
633 return
634 fi
635
e16414d9 636 if is_md "$devpath"; then
df738638 637 find_modules_md "$devpath"
d9179777
ER
638 return
639 fi
640
c3b54060 641 if is_multipath "$devpath"; then
07137fe3 642 if find_modules_multipath "$devpath"; then
9baf4f3f 643 return
9baf4f3f 644 fi
ecd7bf46 645
9baf4f3f
ER
646 # fallback
647 fi
648
36523626 649 if is_dmraid "$devpath"; then
c083ae23
ER
650 if find_modules_dmraid "$devpath"; then
651 return
652 fi
653 # fallback
654 fi
655
35043b20
ER
656 if is_scsi "$devpath"; then
657 find_modules_scsi "$devpath"
d9179777
ER
658 return
659 fi
660
30ca4815 661 if is_ide "$devpath"; then
bc0d6f2d 662 find_modules_ide "$devpath"
d9179777
ER
663 return
664 fi
665
0bdde1a1
ER
666 if [[ "$devpath" == /dev/bcache* ]]; then
667 find_modules_bcache "$devpath"
668 return
669 fi
670
07b09cf9 671 if [[ "$devpath" == /dev/rd/* ]]; then
046c68c9 672 find_module "DAC960"
c3313cd6 673 rootdev_add=/dev/rd/
d9179777
ER
674 return
675 fi
676
07b09cf9 677 if [[ "$devpath" == /dev/ida/* ]]; then
046c68c9 678 find_module "cpqarray"
c3313cd6 679 rootdev_add=/dev/ida/
d9179777
ER
680 return
681 fi
682
08651ad1 683 if [[ "$devpath" == /dev/cciss/* ]]; then
c3313cd6 684 rootdev_add=/dev/cciss/
df11fbe8
ER
685
686 # load hpsa for future kernels, cciss for backwards compat
687 if [ "$kernel_version_long" -ge "003000000" ]; then
688 find_module "hpsa" "-cciss"
649df3de 689 find_modules_scsi "$devpath"
df11fbe8
ER
690 else
691 find_module "cciss"
692 fi
693
d9179777
ER
694 return
695 fi
696
07b09cf9 697 if [[ "$devpath" == /dev/ataraid/* ]]; then
ac085800 698 find_modules_ide
046c68c9 699 find_module "ataraid"
99e7251e 700 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
9ae446b9 701 if [ -n "$ataraidmodules" ]; then
7c38b114 702 # FIXME: think about modules compiled in kernel
82474db9 703 die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
7c38b114
AF
704 fi
705 for n in $ataraidmodules; do
046c68c9 706 find_module "$n"
7c38b114 707 done
c3313cd6 708 rootdev_add=/dev/ataraid/
d9179777
ER
709 return
710 fi
711
7c38b114 712 # check to see if we need to set up a loopback filesystem
07b09cf9 713 if [[ "$devpath" == /dev/loop* ]]; then
00eaa938 714 die "Sorry, root on loop device isn't supported."
7c38b114
AF
715 # TODO: rewrite for bsp and make nfs ready
716 if [ ! -x /sbin/losetup ]; then
00eaa938 717 die "losetup is missing"
7c38b114 718 fi
bc0d6f2d 719 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
82474db9 720 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
42820142 721 die "The root filesystem is on a $devpath, but there is no magic entry in $fstab for this device. Consult the $PROGRAM man page for more information"
7c38b114
AF
722 fi
723
724 line="`awk '/'$key'/ { print $0; }' $fstab`"
725 loopDev="$(echo $line | awk '{print $3}')"
726 loopFs="$(echo $line | awk '{print $4}')"
727 loopFile="$(echo $line | awk '{print $5}')"
728
729 BASICMODULES="$BASICMODULES -loop"
046c68c9 730 find_module "-$loopFs"
7c38b114 731 BASICMODULES="$BASICMODULES -${loopFs}"
d9179777
ER
732 return
733 fi
734
67aa84bd
ER
735 if is_lvm "$devpath"; then
736 find_modules_lvm "$devpath"
d9179777 737 return
7c38b114
AF
738 fi
739}
740
b64f015b 741firmware_install_module() {
c3667d07 742 local module="$1"
c6c6ce01 743 local firmware_files="$2"
9ed6e1db 744
02ba8ab7 745 verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
9ed6e1db 746 # firmware not yet installed
9b557a09 747 if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
034fdd5d 748 inst_d /lib/firmware
9b557a09 749cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
9ed6e1db 750#!/bin/sh -e
45294dc1
ER
751# handle only firmware add requests
752if [ "$SUBSYSTEM" != "firmware" ]; then
753 exit 0
754fi
755if [ "$ACTION" != "add" ]; then
756 exit 0
757fi
8639f99a
AM
758echo 1 > /sys$DEVPATH/loading
759cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
760echo 0 > /sys$DEVPATH/loading
761exit 0
9ed6e1db 762EOF
9b557a09 763 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
63cb815e
ER
764
765 # setup firmware loader agent
766 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
9ed6e1db
AM
767 fi
768
769 for firmware in $firmware_files; do
80b23733 770 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
486d26a5 771 FIRMWAREDIR=${firmware%/*}
4a9920e7 772 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
80b23733
ER
773 inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
774 elif [ -f "/lib/firmware/$firmware" ]; then
c661b23c 775 FIRMWAREDIR=${firmware%/*}
776 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
80b23733 777 inst /lib/firmware/$firmware /lib/firmware/$firmware
c661b23c 778 else
6652b089 779 warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
4a60c01f 780 fi
9ed6e1db
AM
781 done
782
b64f015b 783 mount_sys
9ed6e1db
AM
784}
785
2a5bcca9 786modules_install() {
c3667d07
ER
787 local modules="$1"
788 local mod
2a5bcca9
AM
789
790 for mod in $modules; do
fe280785 791 MODULEDIR=${mod%/*}
4a9920e7 792 inst_d "/lib/modules/$kernel/$MODULEDIR"
9b557a09 793 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
5d62840e
AM
794 case $mod in
795 *.gz)
b657b865 796 gunzip "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress gz"
5d62840e
AM
797 mod=${mod%.gz}
798 ;;
799 *.xz)
b657b865 800 xz -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress xz"
5d62840e
AM
801 mod=${mod%.xz}
802 ;;
803 *.bz2)
b657b865 804 bzip2 -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress bz2"
5d62840e
AM
805 mod=${mod%.bz2}
806 ;;
807 esac
897d14b7 808 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
5d62840e 809 $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod}"
ccd1f65f 810 fi
2a5bcca9
AM
811 done
812}
813
814modules_add_linuxrc() {
fe280785 815 local mod modpath
ac085800 816
fe280785
ER
817 for mod in "$@"; do
818 # module path without optional compression
819 modpath=${mod%.gz}
5d62840e
AM
820 modpath=${modpath%.xz}
821 modpath=${modpath%.bz2}
fe280785
ER
822
823 # name of the module
8011a76c 824 local module=${modpath##*/}; module=${module%$modext}
38ac83a5 825 local options=$(modprobe_options "$module")
8011a76c
ER
826 local genericname=$(echo $module | tr - _)
827 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
828 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
2a5bcca9 829
3e1d0df9
AM
830 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
831 options="scan=sync $options"
832 fi
833
02ba8ab7 834 if [ x"$verbose" = x"-v" ]; then
8a47b72c
ER
835 s=""
836 if [ "$options" ]; then
837 s="$s with options [$options]"
838 fi
8011a76c
ER
839 if [ "$usleep" ]; then
840 s="$s and $usleep usleep"
8a47b72c 841 fi
02ba8ab7 842 verbose "Loading module [$module]$s"
ac085800
ER
843 fi
844
8011a76c
ER
845 if [ -n "$firmware" ]; then
846 firmware_install_module "$module" "$firmware"
4a60c01f 847 else
06e481d7
ER
848 for file in $(find_firmware "$module"); do
849 firmware_install_module "$module" "$file"
850 done
9ed6e1db 851 fi
4a60c01f 852
18ece493 853 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
8011a76c
ER
854 if [ -n "$usleep" ]; then
855 echo "usleep $usleep" | add_linuxrc
8e598759 856 fi
e00dcfcb 857 if [ "$module" = "scsi_wait_scan" ]; then
d29583e0
ER
858 if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
859 echo "rmmod scsi_wait_scan" | add_linuxrc
860 fi
e00dcfcb
AM
861 fi
862
2a5bcca9
AM
863 done
864}
865
82b2dba2
ER
866# Generates /dev nodes based on /proc/partitions information.
867# Needs /proc mounted.
868# Can be called multiple times.
869initrd_gen_devices() {
870 if is_yes "$proc_partitions"; then
871 return
872 fi
873 proc_partitions=yes
335cd101 874
82b2dba2
ER
875 mount_dev
876 add_linuxrc <<-'EOF'
877 : 'Making device nodes'
878 cat /proc/partitions | (
8d4aba01 879 # ignore first two lines: header, empty line
82b2dba2 880 read b; read b
2cc3ae8b 881
82b2dba2
ER
882 while read major minor blocks dev rest; do
883 node=/dev/$dev
884 mkdir -p ${node%/*}
6b45dd6c 885 [ -e $node ] || mknod -m 660 $node b $major $minor
82b2dba2
ER
886 done
887 )
888 EOF
889}
bb529f94 890
82b2dba2 891
4828c787 892initrd_gen_setrootdev() {
02ba8ab7 893 verbose "Adding rootfs finding based on kernel cmdline root= option support."
71b2d771 894 busybox_applet ls
b7114dde 895 debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
82b2dba2 896 add_linuxrc <<-'EOF'
dcdf6b49
ER
897 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
898 rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
94da85db
ER
899 # fallback to ls, try two different formats
900 # http://lists.pld-linux.org/mailman/pipermail/pld-devel-en/2014-May/023915.html
901 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
902 # busybox up to 1.22
5efa9a2e 903 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
71b2d771 904 fi
94da85db
ER
905 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
906 # busybox 1.22 and upwards
907 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $5 + $6; }}')"
908 fi
909 if [ "${rootnr:-0}" -gt 0 ]; then
82b2dba2
ER
910 echo "$rootnr" > /proc/sys/kernel/real-root-dev
911 fi
912 fi
b64f015b 913 EOF
1606e343
AM
914}
915
4671d086
ER
916initrd_gen_initramfs_switchroot() {
917 inst_d /newroot
918 if [ "$rootdev" = "/dev/nfs" ]; then
919 echo "rootfs on NFS root=/dev/nfs"
920 else
921 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
922 fi
5845b321
ER
923
924 # parse 'root=xxx' kernel commandline
4671d086 925 # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
ec21900e
ER
926
927 # from lilo-23.2/readme/README:
928 # root=<device> changes the root device. This overrides settings that may
929 # have been made in the boot image and on the LILO command line. <device> is
930 # either the hexadecimal device number or the full path name of the device,
931 # e.g. /dev/hda3 [*]
932 #
933 # * The device names are hard-coded in the kernel. Therefore, only the
934 # "standard" names are supported and some less common devices may not be
935 # recognized. In those cases, only numbers can be used.
5436b31f 936 busybox_applet cat
4671d086 937 add_linuxrc <<-'EOF'
7f187a08 938 device=
3564e6b6 939 eval "$(busybox awk -v root="$ROOT" '
f9194b15
ER
940 # http://9fans.net/archive/2006/09/261
941 function h2d(str, hstr, res, num, n, digit, i) {
942 hstr = "0123456789abdcef";
943 res = 0;
944 n = split(tolower(str), digit, "");
945
946 for (i = 1; i <= n; i++) {
947 num = index(hstr, digit[i]) - 1;
948 res = res + (num * 16 ^ (n - i));
949 }
950
951 return res;
952 }
4671d086 953 BEGIN {
f9194b15
ER
954
955 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
956 num_pattern = "[0-9a-fA-F]" num_pattern_short;
4671d086 957 dev_pattern = "[hms][a-z][a-z]([0-9])+";
7f187a08 958 partition = "";
4671d086
ER
959 min = -1; maj = -1;
960
3564e6b6
ER
961 # see if we have /dev/hdX or hdX, we can just take partition name
962 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") {
963 partition = root
964 sub("^/dev/", "", partition);
965
966 } else {
967 # unify values first
968 if (root ~ "^" num_pattern_short "$") {
969 # change "303" => "0x0303"
970 root = "0x0" root
971 } else if (root ~ "^" num_pattern "$") {
972 # change "0303" => "0x0303"
973 root = "0x" root
974 }
975
f9194b15
ER
976 maj = h2d(substr(root, 3, 2));
977 min = h2d(substr(root, 5, 2));
4671d086 978 }
4671d086
ER
979 }
980
7f187a08 981 partition && $4 == partition { maj = $1; min = $2; }
afa32d0e 982 $1 == maj && $2 == min { partition = $4; }
4671d086
ER
983
984 END {
fa3a5452 985 if (maj >= 0 && min >= 0) {
7f187a08
ER
986 printf("maj=%s; min=%s;\n", maj, min);
987 }
988 if (partition) {
989 printf("device=/dev/%s;\n", partition);
fa3a5452 990 }
4671d086
ER
991 }
992 ' /proc/partitions)"
4671d086 993
7f187a08 994 if [ -z "$device" ]; then
5436b31f
AM
995 if [ "$DEBUGINITRD" ]; then
996 cat /proc/partitions
997 fi
0fb9dda3 998 device=$ROOT
4671d086
ER
999 fi
1000
481bdb77 1001 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
6b45dd6c 1002 mknod -m 660 $device b $maj $min
7f187a08
ER
1003 fi
1004
dad8bc39
AM
1005 # XXX hack, fallback to rootdev from geninitrd time
1006 if [ ! -e "$device" ]; then
1007 device="$rootdev"
1008 echo "DEVICE set to $device based on fstab entry from initrd gen time"
1009 fi
1010
86aa389f
ER
1011 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
1012 if [ ! -e "$device" ]; then
1013 rrd=$(cat /proc/sys/kernel/real-root-dev)
1014 major=$(($rrd / 256))
1015 minor=$(($rrd % 256))
1016
1017 while read pmajor pminor blocks dev rest; do
1018 # skip header and empty line
1019 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
1020
1021 if [ $pmajor = $major -a $pminor = $minor ]; then
1022 device=/dev/$dev
1023 echo "DEVICE set to $device based on real-root-dev"
1024 fi
1025 done < /proc/partitions
1026 fi
1027
144396dd 1028 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
41d3645c 1029
144396dd 1030 mount -t $ROOTFS -r $device $ROOTFLAGS /newroot || echo "Mount of rootfs failed."
0fb9dda3 1031 init=$INIT
4671d086
ER
1032 if [ -z "$init" -o ! -x "/newroot$init" ]; then
1033 init=/sbin/init
1034 fi
1035 EOF
1036
b1ae7c80
AM
1037 busybox_applet dmesg
1038 busybox_applet tail
1039 add_linuxrc <<-'EOF'
1040 if [ "$DEBUGINITRD" ]; then
1041 echo "Last 20 lines of dmesg:"
1042 dmesg | tail -n 20
1043 fi
2b945b6b 1044
b1ae7c80
AM
1045 EOF
1046
2b945b6b
ER
1047 kmsg "geninitrd/$VERSION switching root"
1048
4671d086 1049 umount_all
0273c2c4 1050 busybox_applet switch_root usleep
4671d086 1051 add_linuxrc <<-'EOF'
278e5013 1052 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
0273c2c4
ER
1053
1054 # switch root to empty dir will make kernel panic, so sleep 10s before it
1055 # switch_root needs to be pid 1, so there's no other way to recover from here
1056 # if /dev is missing, switch root will likely fail, give debug shell before that
1057 if [ ! -d /newroot/dev ]; then
1058 echo "/dev is missing, switch_root will likely fail"
1059 echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
1060 debugshell
1061 [ "$DEBUGINITRD" ] || usleep 10000000
1062 fi
1063
72a1b0ef
ER
1064 # systemd[1]: /usr appears to be on its own filesytem and is not
1065 # already mounted. This is not a supported setup. Some things will
1066 # probably break (sometimes even silently) in mysterious ways. Consult
1067 # http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
1068 # for more information.
1069 echo trying to mount /usr
1070 chroot /newroot mount -n /usr
1071
f8ea6a63 1072 exec switch_root /newroot $init ${1:+"$@"}
4671d086 1073
0273c2c4
ER
1074 # FIXME: this code is never executed, as "exec" does not return!
1075
4671d086
ER
1076 echo "Error! initramfs should not reach this place."
1077 echo "It probably means you've got old version of busybox, with broken"
1078 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1079
f8ea6a63 1080 exec chroot /newroot $init ${1:+"$@"}
4671d086
ER
1081
1082 echo "Failed to chroot!"
b61aa273 1083 debugshell
4671d086
ER
1084 EOF
1085 # we need /init being real file, not symlink, otherwise the initramfs will
1086 # not be ran by pid 1 which is required for switch_root
1087 mv $DESTDIR/linuxrc $DESTDIR/init
1088 ln -s init $DESTDIR/linuxrc
1089}
1090
c552503c
ER
1091# find if $symbol exists in System.map $mapfile
1092sym_exists() {
1093 local mapfile="$1"
1094 local symbol="$2"
1095 if [ ! -f $mapfile ]; then
1096 # missing mapfile (not a pld kernel?)
1097 return 1
1098 fi
1099
1100 awk -vc=1 -vsymbol="$symbol" '$2 == "T" && $3 == symbol {c = 0} END {exit c}' $mapfile
1101}
1102
1103# find best compressor (or forced one) for initrd
1104find_compressor() {
1105 local mode="$1"
1b89c904
AM
1106 # fastest initrd decompression speed is first
1107 local compressors='lzo gzip xz lzma bzip2'
c552503c
ER
1108
1109 # a specified one, take it
55aaf2fe
AM
1110 if ! is_yes "$mode"; then
1111 compressors="$mode"
c552503c
ER
1112 fi
1113
02ba8ab7 1114 verbose "finding compressor: $compressors (via $mode)"
c552503c
ER
1115 # check for compressor validity
1116 local c prog map=/boot/System.map-$kernel
1117 for c in $compressors; do
1118 case $c in
66d146a5 1119 xz)
29f7d622
AM
1120 sym=unxz
1121 prog=/usr/bin/xz
1122 ;;
1123 lzma)
c552503c 1124 sym=unlzma
66d146a5 1125 prog=/usr/bin/xz
c552503c
ER
1126 ;;
1127 bzip2)
1128 sym=bzip2
c42692d4 1129 prog=/usr/bin/bzip2
c552503c
ER
1130 ;;
1131 gzip)
1132 sym=gunzip
c42692d4 1133 prog=/bin/gzip
c552503c 1134 ;;
8a6f083b
AM
1135 lzo)
1136 sym=unlzo
1137 prog=/usr/bin/lzop
1138 ;;
5fcc3d04
AM
1139 none|no)
1140 # any existing sym will work
1141 sym=initrd_load
1142 prog=/bin/cat
1143 ;;
c552503c
ER
1144 *)
1145 die "Unknown compressor $c"
1146 ;;
1147 esac
c454c66e 1148 if sym_exists $map $sym && [ -x $prog ]; then
c552503c
ER
1149 echo $c
1150 return
1151 fi
1152 done
1153
02ba8ab7 1154 verbose "using gzip for compressor (fallback)"
c552503c
ER
1155 echo gzip
1156}
1157
97f51b6e
ER
1158# compresses kernel image image
1159# in function so we could retry with other compressor on failure
1160compress_image() {
1161 local compressor="$1" IMAGE="$2" target="$3" tmp
1162 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1163
1164 case "$compressor" in
1165 xz)
1166 # don't use -9 here since kernel won't understand it
1167 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1168 ;;
1169 lzma)
1170 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1171 ;;
1172 bzip2)
1173 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1174 ;;
1175 gzip)
1176 gzip -9 < "$IMAGE" > "$tmp" || return $?
1177 ;;
8a6f083b
AM
1178 lzo)
1179 lzop -9 < "$IMAGE" > "$tmp" || return $?
1180 ;;
5fcc3d04
AM
1181 none|no)
1182 cat < "$IMAGE" > "$tmp" || return $?
1183 ;;
97f51b6e
ER
1184 esac
1185
1186 mv -f "$tmp" "$target"
1187}
1188
82b2dba2
ER
1189if [ -r /etc/sysconfig/geninitrd ]; then
1190 . /etc/sysconfig/geninitrd
1191fi
2cc3ae8b 1192
c215292c
AG
1193if [ ! -f /proc/mounts ]; then
1194 warn "/proc filesystem not mounted, may cause wrong results or failure."
1195fi
1196
2d769917 1197geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
c124d0cf 1198
82b2dba2
ER
1199while [ $# -gt 0 ]; do
1200 case $1 in
1201 --fstab=*)
1202 fstab=${1#--fstab=}
1203 ;;
1204 --fstab)
1205 fstab=$2
1206 shift
1207 ;;
1208 --modules-conf=*)
1209 modulefile=${1#--modules-conf=}
1210 ;;
1211 --modules-conf)
1212 modulefile=$2
1213 shift
1214 ;;
82b2dba2
ER
1215 --with-bootsplash)
1216 BOOT_SPLASH=yes
1217 ;;
1218 --without-bootsplash)
1219 BOOT_SPLASH=no
1220 ;;
1221 --with-fbsplash)
1222 FB_SPLASH=yes
1223 ;;
1224 --without-fbsplash)
1225 FB_SPLASH=no
1226 ;;
6c69a2d4
ER
1227 --with-fbcondecor)
1228 FB_CON_DECOR=yes
1229 ;;
1230 --without-fbcondecor)
1231 FB_CON_DECOR=no
1232 ;;
82b2dba2
ER
1233 --with-suspend)
1234 USE_SUSPEND=yes
1235 ;;
1236 --without-suspend)
1237 USE_SUSPEND=no
1238 ;;
1239 --with-suspend2 | --with-tuxonice)
1240 USE_TUXONICE=yes
1241 ;;
1242 --without-suspend2 | --without-tuxonice)
1243 USE_TUXONICE=no
1244 ;;
80b1ed79 1245 --lvmversion=*)
7308edee 1246 LVMTOOLSVERSION=${1#--lvmversion=}
82b2dba2 1247 ;;
80b1ed79 1248 --lvmtoolsversion=*)
1249 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1250 ;;
82b2dba2
ER
1251 --lvmtoolsversion|--lvmversion)
1252 LVMTOOLSVERSION=$2
1253 shift
1254 ;;
1255 --without-udev)
1256 USE_UDEV=no
1257 ;;
1258 --with-udev)
1259 USE_UDEV=yes
1260 ;;
1261 --without-dmraid)
1262 USE_DMRAID=no
1263 ;;
1264 --without-multipath)
ecd7bf46
ER
1265 USE_MULTIPATH=no
1266 ;;
1267 --with-multipath=*)
1268 USE_MULTIPATH=${1#--with-multipath=}
82b2dba2 1269 ;;
af075488 1270 --without-blkid)
1271 USE_BLKID=no
289fbc9b 1272 ;;
3ef3d717
ER
1273 --without-luks)
1274 USE_LUKS=no
1275 ;;
82b2dba2
ER
1276 --with=*)
1277 BASICMODULES="$BASICMODULES ${1#--with=}"
1278 ;;
1279 --with)
1280 BASICMODULES="$BASICMODULES $2"
1281 shift
1282 ;;
1283 --version)
1284 echo "$PROGRAM: version $VERSION"
1285 exit 0
1286 ;;
1287 -v)
02ba8ab7
ER
1288 if [ x"$verbose" = x"-v" ]; then
1289 verbose="-v -v"
1290 else
1291 verbose="-v"
1292 fi
11ab0dea 1293 exec 3>&1
82b2dba2 1294 ;;
c552503c
ER
1295 --compress)
1296 COMPRESS=$2
1297 ;;
1298 --compress=*)
1299 COMPRESS="${1#--compress=}"
1300 ;;
82b2dba2
ER
1301 --nocompress)
1302 COMPRESS=no
1303 ;;
ccd1f65f 1304 --nostrip)
76a48507
ER
1305 STRIP=
1306 ;;
1307 --strip=*)
1308 STRIP="${1#--strip=}"
1309 ;;
1310 --strip)
1311 STRIP=$2
1312 shift
ccd1f65f 1313 ;;
82b2dba2
ER
1314 --ifneeded)
1315 ifneeded=1
1316 ;;
1317 -f)
1318 force=1
1319 ;;
1320 --preload=*)
1321 PREMODS="$PREMODS ${1#--preload=}"
1322 ;;
1323 --preload)
1324 PREMODS="$PREMODS $2"
1325 shift
1326 ;;
2965cab9 1327 --fs=* | --fs)
bbbc32d0 1328 die "--fs option is obsoleted. Use --initrdfs instead"
82b2dba2
ER
1329 ;;
1330 --initrdfs=*)
1331 INITRDFS=${1#--initrdfs=}
1332 ;;
1333 --initrdfs)
1334 INITRDFS=$2
1335 shift
1336 ;;
1337 --image-version)
1338 img_vers=yes
1339 ;;
1340 --ide-only-root)
1341 ide_only_root="yes"
1342 ;;
1343 *)
1344 if [ -z "$target" ]; then
1345 target="$1"
1346 elif [ -z "$kernel" ]; then
1347 kernel="$1"
1348 else
7f6e5359 1349 usage
36523626 1350 exit 1
82b2dba2
ER
1351 fi
1352 ;;
1353 esac
f5db170b 1354
82b2dba2
ER
1355 shift
1356done
1357
1358if [ -z "$target" -o -z "$kernel" ]; then
7f6e5359 1359 usage
36523626 1360 exit 1
82b2dba2
ER
1361fi
1362
93a38d1a
ER
1363# main()
1364if [ "$(id -u)" != 0 ]; then
1365 die "You need to be root to generate initrd"
1366fi
1367
c45a111c
ER
1368for dir in libx32 lib64 lib; do
1369 initrd_dir=/usr/$dir/initrd
1370 if [ -d "$initrd_dir" ]; then
1371 initrd_dirs="$initrd_dirs $initrd_dir"
1372 fi
1373done
1374
e4487862
AM
1375kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1376kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
82b2dba2 1377
b7114dde 1378verbose "# geninitrd $VERSION"
c124d0cf
ER
1379debug "Using initrd_dir: $initrd_dir"
1380
6ec4aea6 1381busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
c124d0cf
ER
1382
1383# we setup mods after parsing command line args
1384geninitrd_setup_mods
1385
1386if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1387 warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1388fi
1389
82b2dba2 1390if [ -z "$INITRDFS" ]; then
bbbc32d0
ER
1391 if [ -n "$FS" ]; then
1392 # FS= can came only via /etc/sysconfig/geninitrd likely?
1393 die "FS configuration option is obsoleted. Use INITRDFS instead"
f5db170b 1394 fi
f5db170b 1395
bbbc32d0
ER
1396 # default value
1397 if [ "$kernel_version" -ge "002005" ]; then
1398 INITRDFS="initramfs"
1399 else
1400 INITRDFS="rom"
1401 fi
82b2dba2 1402fi
966c32cc 1403
82b2dba2 1404case "$INITRDFS" in
4877276e
ER
1405 ext2)
1406 [ -x /sbin/mke2fs ] || die "/sbin/mke2fs is missing"
1407 ;;
1408 rom|romfs)
1409 [ -x /sbin/genromfs ] || die "/sbin/genromfs is missing"
1410 ;;
1411 cram|cramfs)
1412 [ -x /sbin/mkcramfs ] || die "/sbin/mkcramfs is missing"
1413 ;;
1414 initramfs)
1415 [ -x /bin/cpio ] || die "/bin/cpio is missing"
1416 [ -x /usr/bin/find ] || die "/usr/bin/find is missing"
1417 ;;
1418 *)
1419 die "Filesystem $INITRDFS on initrd is not supported"
1420 ;;
82b2dba2 1421esac
f5db170b 1422
9323ada3 1423if [ -L "$target" ]; then
1424 target=$(readlink -f "$target")
1425fi
1426
82b2dba2
ER
1427if [ -n "$img_vers" ]; then
1428 target="$target-$kernel"
1429fi
8bd582f1 1430
82b2dba2
ER
1431if [ -z "$force" -a -f "$target" ]; then
1432 die "$target already exists."
1433fi
c6c6ce01 1434
82b2dba2
ER
1435if [ ! -d "/lib/modules/$kernel" ]; then
1436 die "/lib/modules/$kernel is not a directory."
1437fi
2ffb1734 1438
bbbc32d0
ER
1439if [ "$kernel_version" -ge "002005" ]; then
1440 modext=".ko"
1441fi
1442
82b2dba2
ER
1443cache_modprobe_conf
1444
1445for n in $PREMODS; do
046c68c9 1446 find_module "$n"
82b2dba2
ER
1447done
1448
ed30e3a8 1449if [ "$FBMODULE" ]; then
046c68c9 1450 find_module "$FBMODULE"
ed30e3a8
ER
1451fi
1452
cefcd7bb
AM
1453# autodetect USB keyboards
1454find_modules_usbkbd
1455
82b2dba2 1456# allow forcing loading SCSI and/or IDE modules
35043b20 1457# XXX: where ADDSCSI cames from? drop?
82b2dba2
ER
1458if is_yes "$ADDSCSI"; then
1459 find_modules_scsi
1460fi
1461
3f53322c 1462# autodetect SATA modules
1463find_modules_sata
e2d6ca6c 1464
35043b20 1465# XXX: where ADDIDE cames from? drop?
82b2dba2
ER
1466if is_yes "$ADDIDE"; then
1467 find_modules_ide
1468fi
1469
4c16dac4
ER
1470if is_yes "$USE_SUSPEND"; then
1471 find_modules_suspend
1472fi
1473
82b2dba2 1474find_root "$fstab" || exit
02ba8ab7 1475verbose "Using $rootdev as device for rootfs"
82b2dba2 1476
d8056591 1477find_modules_for_devpath "$rootdev"
ac085800 1478
ecd7bf46
ER
1479# if USE_MULTIPATH is path to device, scan that too
1480# this is to bootstrap multipath setup into initrd.
1481if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1482 find_modules_multipath $USE_MULTIPATH
1483fi
1484
046c68c9 1485find_module "-$rootFs"
ac085800 1486
82b2dba2 1487for n in $BASICMODULES; do
046c68c9 1488 find_module "$n"
82b2dba2 1489done
4e9eb79c 1490
82b2dba2 1491if is_yes "$USE_TUXONICE"; then
046c68c9 1492 find_module "-lzf"
82b2dba2 1493fi
33d24e12 1494
2d769917 1495find_modules_uvesafb
bf6d9c64 1496find_modules_fbsplash
2968c9dd 1497
82b2dba2 1498if [ -n "$ifneeded" -a -z "$MODULES" ]; then
02ba8ab7 1499 verbose "No modules are needed -- not building initrd image."
82b2dba2
ER
1500 exit 0
1501fi
c6c6ce01 1502
02ba8ab7 1503verbose "Building initrd..."
d8056591 1504DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
9b557a09 1505RCFILE="$DESTDIR/linuxrc"
82b2dba2
ER
1506> "$RCFILE"
1507chmod a+rx "$RCFILE"
9b557a09 1508ln -s linuxrc $DESTDIR/init
e8d178ff 1509
82b2dba2 1510# create dirs that we really need
d63131e0 1511inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys}
e8d178ff 1512
82b2dba2 1513modules_install "$MODULES"
b64f015b 1514
82b2dba2
ER
1515# mknod'ing the devices instead of copying them works both with and
1516# without devfs...
6b45dd6c
AM
1517mknod -m 600 "$DESTDIR/dev/console" c 5 1
1518mknod -m 666 "$DESTDIR/dev/null" c 1 3
1519mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1520mknod -m 666 "$DESTDIR/dev/random" c 1 8
1521mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
2b945b6b 1522mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
be2f3ecc 1523
6ec4aea6
JR
1524inst_exec $busybox /bin/busybox
1525ln -s busybox $DESTDIR/bin/sh
1526# for older busyboxes who had /bin/initrd-busybox as EXEPATH
1527ln -s busybox $DESTDIR/bin/initrd-busybox
2ffb1734 1528
82b2dba2
ER
1529add_linuxrc <<EOF
1530#!/bin/sh
b7114dde 1531# initrd generated by geninitrd/$VERSION
8938f33d 1532# on $(LC_ALL=C date)
c6c6ce01 1533
82b2dba2 1534EOF
ff9aded5 1535load_font
82b2dba2 1536mount_proc
2b945b6b
ER
1537
1538kmsg "geninitrd/$VERSION starting"
1539
0fb9dda3
ER
1540add_linuxrc <<-EOF
1541 # builtin defaults from geninitrd
1542 ROOT=$rootdev
1543 ROOTFS=$rootFs
1544EOF
82b2dba2 1545add_linuxrc <<-'EOF'
48d98595 1546 read CMDLINE < /proc/cmdline
c6c6ce01 1547
82b2dba2 1548 for arg in $CMDLINE; do
04bffd7a 1549 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
82b2dba2
ER
1550 DEBUGINITRD=yes
1551 fi
04bffd7a
ER
1552 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1553 DEBUGINITRD=${arg##debug*rd=}
82b2dba2 1554 fi
fc787d45 1555 if [ "${arg##root=}" != "${arg}" ]; then
1556 ROOT=${arg##root=}
1557 fi
144396dd
AM
1558 if [ "${arg##rootflags=}" != "${arg}" ]; then
1559 ROOTFLAGS=${arg##rootflags=}
db795d06 1560 fi
41d3645c
AM
1561 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1562 ROOTFSFLAGS=${arg##rootfsflags=}
1563 fi
0fb9dda3
ER
1564 if [ "${arg##init=}" != "${arg}" ]; then
1565 INIT=${arg##init=}
1566 fi
82b2dba2 1567 done
c6c6ce01 1568
144396dd
AM
1569 # handling of invalid, rootfsflags, option
1570 if [ -n "$ROOTFSFLAGS" ]; then
1571 if [ -n "$ROOTFLAGS" ]; then
1572 ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1573 else
1574 ROOTFLAGS="$ROOTFSFLAGS"
1575 fi
1576 fi
1577
82b2dba2 1578 if [ "$DEBUGINITRD" = "sh" ]; then
8938f33d 1579 # export some vars to subshell for debug to work
144396dd 1580 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
4569a02c
ER
1581 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1582 export rootnr attrs majmin major minor device
1583
1584 # make debugshell() invoke subshell if $DEBUGINITRD=sh
82b2dba2 1585 debugshell() {
e2405b29
AM
1586EOF
1587if is_yes "$RUN_SULOGIN_ON_ERR"; then
1588add_linuxrc <<-'EOF'
0273c2c4 1589 echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
e2405b29
AM
1590EOF
1591else
1592add_linuxrc <<-'EOF'
1593 sh
1594EOF
1595fi
1596add_linuxrc <<-'EOF'
82b2dba2
ER
1597 }
1598 else
1599 debugshell() {
1600 :
1601 }
1602 fi
e934d044 1603
82b2dba2
ER
1604 if [ "$DEBUGINITRD" ]; then
1605 set -x
cff3058d 1606 fi
82b2dba2 1607EOF
2df2e995 1608
fe280785 1609modules_add_linuxrc $MODULES
82b2dba2
ER
1610
1611# TODO: rewrite for busybox
1612#if [ -n "$loopDev" ]; then
1613# if [ ! -d /initrd ]; then
1614# mkdir /initrd
1615# fi
1616#
9b557a09
ER
1617# cp -a "$loopDev" "$DESTDIR/dev"
1618# cp -a "$rootdev" "$DESTDIR/dev"
82b2dba2
ER
1619# echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1620# echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1621# echo "echo Setting up loopback device $rootdev" >> $RCFILE
1622# echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1623#fi
2b1a3707 1624
1606e343
AM
1625if is_yes "$USE_UDEV"; then
1626 initrd_gen_udev
382ce856
AM
1627else
1628 initrd_gen_mdev
1606e343
AM
1629fi
1630
3dd50160 1631initrd_gen_uvesafb
1b481849
ER
1632initrd_gen_luks
1633initrd_gen_dmraid
1634initrd_gen_multipath
1635initrd_gen_blkid
289fbc9b 1636
69b1e935 1637if is_yes "$have_nfs"; then
2df2e995 1638 initrd_gen_nfs
1b481849
ER
1639else
1640 initrd_gen_md
1641 initrd_gen_lvm
2d769917 1642 initrd_gen_bcache
d222b474 1643 initrd_gen_blkid
1b481849 1644 initrd_gen_luks
4828c787 1645 initrd_gen_setrootdev
7c38b114
AF
1646fi
1647
5101a385 1648# additional devs always needed
9b557a09 1649[ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
5101a385 1650
1b481849 1651initrd_gen_stop_udevd
382ce856 1652initrd_gen_stop_mdev
6fadace4 1653initrd_gen_stop_uvesafb
82de999f 1654
4a362aea
ER
1655# resume after killing local processes
1656initrd_gen_tuxonice
1657initrd_gen_suspend
1658
52a92a2a
ER
1659# clean up env
1660add_linuxrc <<-'EOF'
4569a02c 1661if [ ! "$DEBUGINITRD" ]; then
52a92a2a
ER
1662 ifs=$IFS
1663 IFS="
1664 "
1665 for i in $(export -p); do
1666 i=${i#declare -x } # ksh/bash
1667 i=${i#export } # busybox
1668
1669 case "$i" in
1670 *=*)
1671 : ;;
1672 *)
1673 continue ;;
1674 esac
1675
1676 i=${i%%=*}
1677
1678 [ -z "$i" ] && continue
1679
1680 case "$i" in
62028605 1681 ROOT|PATH|HOME|TERM)
52a92a2a
ER
1682 :
1683 ;;
1684 *)
62028605 1685 unset $i
52a92a2a
ER
1686 ;;
1687 esac
1688 done
1689 IFS=$ifs
4569a02c 1690fi
52a92a2a
ER
1691EOF
1692
f8f9e56d 1693if [ "$INITRDFS" = "initramfs" ]; then
4671d086 1694 initrd_gen_initramfs_switchroot
b64f015b 1695else
b64f015b 1696 umount_all
f8f9e56d
AM
1697fi
1698
1b481849
ER
1699initrd_gen_fbsplash
1700initrd_gen_fbcondecor
6c69a2d4 1701
b7114dde 1702debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
2990ac33 1703
d8056591 1704IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
51dc1fe6 1705
5c7359e3 1706IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
02ba8ab7 1707verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
5c7359e3 1708
02ba8ab7 1709verbose "Creating $INITRDFS image $IMAGE"
2ad94d8a 1710case "$INITRDFS" in
4877276e 1711 ext2)
4877276e 1712 dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
c091a192
ER
1713 # NOTE: ext2 label is max 16 chars
1714 mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
4877276e
ER
1715 tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1716
1717 local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1718 debug "Mounting ext2 image $IMAGE to $tmpmnt"
5c7359e3 1719 mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
4877276e
ER
1720 # We don't need this directory, so let's save space
1721 rm -rf "$tmpmnt"/lost+found
1722
1723 debug "Copy recursively $DESTDIR -> $tmpmnt"
1724 cp -a $DESTDIR/* $tmpmnt
1725 umount "$IMAGE"
1726 rmdir "$tmpmnt"
1727
1728 ;;
1729 rom|romfs)
c091a192 1730 genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
4877276e
ER
1731 ;;
1732 cram|cramfs)
1733 mkcramfs "$DESTDIR" "$IMAGE"
1734 ;;
1735 initramfs)
1736 (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1737 ;;
1738 *)
93a38d1a 1739 die "Filesystem $INITRDFS not supported by $PROGRAM"
c31050f3 1740esac
bb529f94 1741
755e5cdc 1742CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
25cb53df
ER
1743if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1744 CONFIG_BLK_DEV_RAM_SIZE=4096
3fbd853a 1745 warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
25cb53df 1746fi
e3bc44e2 1747
e3bc44e2
ER
1748if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1749 warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1750fi
1751
c552503c 1752if ! is_no "$COMPRESS"; then
c552503c 1753 compressor=$(find_compressor "$COMPRESS")
02ba8ab7 1754 verbose "Compressing $target with $compressor"
c552503c
ER
1755
1756 # TODO: the image name (specified from kernel.spec) already contains
1757 # extension, which is .gz most of the time.
97f51b6e
ER
1758 compress_image "$compressor" "$IMAGE" "$target" || {
1759 if [ $compressor != gzip ]; then
1760 warn "Could not compress with $compressor, retrying with gzip"
1761 compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1762 else
1763 die "Could not compress image with $compressor"
1764 fi
1765 }
bb529f94 1766else
7d2fc5eb 1767 cp -a "$IMAGE" "$target"
bb529f94 1768fi
5b71959c 1769
7992356a 1770# XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1b481849 1771initrd_gen_bootsplash "$target"
5b71959c 1772
d8056591 1773rm -rf "$DESTDIR" "$IMAGE"
ac085800
ER
1774
1775# vim:ts=4:sw=4:noet:fdm=marker
This page took 1.095498 seconds and 4 git commands to generate.