]> git.pld-linux.org Git - projects/geninitrd.git/blob - geninitrd
Allow tuxonice snapshot device be device mapper device(LUKS, LVM, dmraid). Patch...
[projects/geninitrd.git] / geninitrd
1 #!/bin/sh
2
3 # geninitrd
4 #
5 #       by PLD Linux Team
6 #
7 # based on mkinitrd from RedHat Linux
8 #
9
10 RCSID='$Revision$ $Date$'
11 R=${RCSID#* *}; VERSION=${R%% *}
12 PROGRAM=${0##*/}
13
14 . /etc/rc.d/init.d/functions
15 . /lib/geninitrd/functions
16 . /etc/sysconfig/system
17
18 # list of geninitrd modules which need setup routine after commandline args parsing
19 GENINITRD_MODS=""
20 COMPRESS=yes
21 target=""
22 kernel=""
23 force=""
24 verbose=""
25 MODULES=""
26 img_vers=""
27 fstab=/etc/fstab
28 modext=.o
29 rootdev_nr=0
30 # device node for rootfs from fstab
31 rootdev=""
32
33 # internal variables
34 # is /dev on tmpfs
35 dev_mounted=no
36 # is /proc mounted
37 proc_mounted=no
38 # is /sys mounted
39 sys_mounted=no
40 # is /tmp mounted on tmpfs
41 tmp_mounted=no
42
43 # are /dev nodes already created from /proc/devices info?
44 proc_partitions=no
45
46 usage() {
47         echo "Usage: $PROGRAM [--version] [-v] [-f] [--ifneeded] [--preload <module>]"
48         echo "       [--with=<module>] [--image-version] [--fstab=<fstab>] [--nocompress]"
49         echo "       [--compress=yes|xz|lzma|bzip2|gzip|lzo]"
50         echo "       [--initrdfs=rom|initramfs|ext2|cram] [--modules-conf=<modules.conf>]"
51         echo "       [--with-bootsplash] [--without-bootsplash]"
52         echo "       [--with-fbsplash] [--without-fbsplash]"
53         echo "       [--with-fbcondecor] [--without-fbcondecor]"
54         echo "       [--lvmtoolsversion=1|2] [--with-udev] [--without-udev]"
55         echo "       [--with-suspend] [--without-suspend]"
56         echo "       [--with-tuxonice] [--without-tuxonice]"
57         echo "       [--without-dmraid]"
58         echo "       [--with-multipath=DEVPATH] [--without-multipath]"
59         echo "       [--without-blkid] [--without-luks]"
60         echo "       <initrd-image> <kernel-version>"
61         echo ""
62         echo "Example:"
63
64         local kdir kver
65         for kdir in /lib/modules/*; do
66                 [ -d $kdir ] || continue
67                 kver=${kdir##*/}
68                 echo "  $PROGRAM -f --initrdfs=rom /boot/initrd-$kver.gz $kver"
69         done
70         exit 0
71 }
72
73 msg() {
74         echo "$PROGRAM: $*"
75 }
76
77 warn() {
78         msg "WARNING: $*" >&2
79 }
80
81 debug() {
82         [ -n "$verbose" ] && msg "$*" >&2
83 }
84
85 # aborts program abnormally
86 die() {
87         local rc=${2:-1}
88         msg "ERROR: $1" >&2
89         exit $rc
90 }
91
92 # find program from specified paths
93 find_tool() {
94         local x
95         for x in "$@"; do
96                 if [ -x "$x" ]; then
97                         echo $x
98                         debug "find_tool: found $x"
99                         return 0
100                 fi
101         done
102         debug "find_tool: did not found any of: $@"
103         return 1
104 }
105
106 # loads geninitrd modules
107 geninitrd_load_mods() {
108         local mod
109         for mod in "$@"; do
110                 if [ ! -f /lib/geninitrd/mod-$mod.sh ]; then
111                         die "$mod geninitrd module can't be loaded"
112                 fi
113                 . /lib/geninitrd/mod-$mod.sh
114
115                 if type setup_mod_$mod > /dev/null; then
116                         # add to list which need init
117                         GENINITRD_MODS="$GENINITRD_MODS $mod"
118                 fi
119         done
120 }
121
122 # setup geninitrd modules
123 geninitrd_setup_mods() {
124         local mod
125
126         for mod in $GENINITRD_MODS; do
127                 eval setup_mod_$mod
128         done
129 }
130
131 # append text to /linuxrc
132 # takes STDIN as input
133 add_linuxrc() {
134         cat >> "$RCFILE"
135 }
136
137 # generate code to mount /dev on tmpfs and create initial nodes
138 # can be called multiple times. /dev is cleaned up (umounted) automatically at
139 # the end of script.
140 mount_dev() {
141     if [ "$INITRDFS" = "initramfs" ]; then
142                 # initramfs is read-write filesystem, no need for tmpfs
143                 return
144         fi
145
146         # we already generated tmpfs code; return
147         if is_yes "$dev_mounted"; then
148                 return
149         fi
150
151         dev_mounted=yes
152
153         busybox_applet mount mknod mkdir
154         add_linuxrc <<-EOF
155                 : 'Creating /dev'
156                 mount -o mode=0755 -t tmpfs none /dev
157                 mknod /dev/console c 5 1
158                 mknod /dev/null c 1 3
159                 mknod /dev/zero c 1 5
160                 mknod /dev/urandom c 1 9
161                 mkdir /dev/pts
162                 mkdir /dev/shm
163         EOF
164 }
165
166 # generate code to mount /proc on initrd
167 # can be called multiple times
168 mount_proc() {
169         if is_yes "$proc_mounted"; then
170                 return
171         fi
172
173         proc_mounted=yes
174     if [ "$INITRDFS" = "initramfs" ]; then
175                 # /proc is mounted with initramfs 2.6.22.14 kernel
176                 # XXX: remove when it is clear why proc was already mounted
177                 echo "[ -f /proc/cmdline ] || mount -t proc none /proc" | add_linuxrc
178         else
179                 echo "mount -t proc none /proc" | add_linuxrc
180         fi
181 }
182
183 # generate code to mount /sys on initrd
184 # can be called multiple times
185 mount_sys() {
186         if is_yes "$sys_mounted"; then
187                 return
188         fi
189
190         sys_mounted=yes
191         echo "mount -t sysfs none /sys" | add_linuxrc
192 }
193
194 # generate code to mount /tmp on initrd
195 # can be called multiple times
196 mount_tmp() {
197     if [ "$INITRDFS" = "initramfs" ]; then
198                 # initramfs is read-write filesystem, no need for tmpfs
199                 return
200         fi
201
202         if is_yes "$tmp_mounted"; then
203                 return
204         fi
205
206         tmp_mounted=yes
207         echo "mount -t tmpfs none /tmp" | add_linuxrc
208 }
209
210 # unmount all mountpoints mounted by geninitrd
211 umount_all() {
212
213         add_linuxrc <<-'EOF'
214         : Last shell before umounting all and giving control over to real init.
215         debugshell
216         EOF
217
218         if is_yes "$dev_mounted"; then
219                 echo 'umount /dev' | add_linuxrc
220                 dev_mounted=no
221         fi
222         if is_yes "$sys_mounted"; then
223                 echo 'umount /sys' | add_linuxrc
224                 sys_mounted=no
225         fi
226         if is_yes "$tmp_mounted"; then
227                 echo 'umount /tmp' | add_linuxrc
228                 tmp_mounted=no
229         fi
230         if is_yes "$proc_mounted"; then
231                 echo 'umount /proc' | add_linuxrc
232                 proc_mounted=no
233         fi
234 }
235
236
237 # Checks if busybox has support for APPLET(s)
238 # Exits from geninitrd if the support is not present.
239 #
240 # NB! XXX do not output to STDOUT, it will appear in initrd images in some cases!
241 busybox_applet() {
242         local err=0 applet
243
244         if [ -z "$busybox_functions" ]; then
245                 local tmp=$($busybox 2>&1)
246
247                 # BusyBox v1.1.3 says applet not found if it's not called 'busybox'.
248                 if [[ "$tmp" = *applet\ not\ found* ]]; then
249                         local t=$(mktemp -d)
250                         ln -s $busybox $t/busybox
251                         local tmp=$($t/busybox 2>&1)
252                         rm -rf $t
253                 fi
254
255                 busybox_functions=$(echo "$tmp" | \
256                         sed -ne '/Currently defined functions:/,$p' | \
257                         xargs | sed -e 's,.*Currently defined functions: ,,'
258                 )
259         fi
260         for applet in $*; do
261                 local have
262                 # try cache
263                 eval have='$'busybox_have_$applet
264                 if [ -z "$have" ]; then
265                         have=$(echo "$busybox_functions" | egrep -c "( |^)$applet(,|$)")
266                         if [ "$have" = 0 ]; then
267                                 warn "This setup requires busybox-initrd compiled with applet '$applet' support"
268                                 err=1
269                         fi
270                         eval busybox_have_$applet=$have
271                 fi
272         done
273         if [ $err = 1 ]; then
274                 die "Aborted"
275         fi
276 }
277
278 # extract-ikconfig - Extract the .config file from a kernel image
279 #
280 # The obscure use of the "tr" filter is to work around older versions of
281 # "grep" that report the byte offset of the line instead of the pattern.
282 #
283 # (c) 2009, Dick Streefland <dick@streefland.net>
284 # Licensed under the terms of the GNU General Public License.
285 #
286 # Ripped and adjusted for geninitrd from linux-2.6.34/scripts/extract-ikconfig
287 extract-ikconfig() {
288         local kofile=$(modinfo -k $kernel -n configs 2> /dev/null)
289         if [ -z "$kofile" ]; then
290                 return
291         fi
292         local img=$(mktemp)
293         case "$kofile" in
294         *.gz)
295                 gzip -dc "$kofile" > $img
296                 ;;
297         *)
298                 cat "$kofile" > $img
299                 ;;
300         esac
301
302         local cf1='IKCFG_ST\037\213\010'
303         local cf2='0123456789'
304         local pos
305
306         if pos=$(tr "$cf1\n$cf2" "\n$cf2=" < "$img" | grep -abo "^$cf2"); then
307                 pos=${pos%%:*}
308                 tail -c+$(($pos+8)) "$img" | gzip -dcq
309         fi
310         rm -f $img
311 }
312
313 # Finds module dependencies
314 #
315 # @param        $module
316 #
317 # Outputs full path to module and it's dependencies
318 find_depmod() {
319         local module="$1"
320         local skiperrors=0
321
322         # if module is prefixed with dash, we should ignore errors if the module
323         # can't be found.
324         if [ ${module#-} != $module ]; then
325                 skiperrors=1
326                 module=${module#-}
327         fi
328
329         # This works when user has module-init-tools installed even on 2.4 kernels
330         local modprobe
331         modprobe=$(modprobe --set-version $kernel --show-depends $module --ignore-install 2>&1)
332
333         if [ $? != 0 ]; then
334                 if [ $skiperrors = 1 ]; then
335                         return
336                 fi
337                 echo >&2 "$modprobe"
338
339                 if ! is_no "$EXIT_IF_MISSING"; then
340                         die "$module: module not found for $kernel kernel"
341                 fi
342
343                 warn "$module: module not found for $kernel kernel"
344                 warn "If $module isn't compiled in kernel then this initrd may not start your system."
345         fi
346
347         echo "$modprobe" | \
348         while read insmod modpath options; do
349                 [ "$insmod" = "insmod" ] && echo $modpath
350         done
351 }
352
353 find_firmware() {
354         local module="$1"
355
356         # no firmware support in 2.4 kernels
357         if [ "$kernel_version_long" -lt "002005048" ]; then
358                 return
359         fi
360         echo -n $(NEW_MODINFO=1 modinfo -k $kernel -F firmware $module 2>/dev/null | xargs)
361 }
362
363 # @param        $module
364 find_module() {
365         local mod depmod module=$1
366
367         depmod=$(find_depmod $module) || exit 1
368         for mod in $depmod; do
369                 mod=${mod#/lib/modules/$kernel/}
370
371                 # add each module only once
372                 local m have=0
373                 for m in $MODULES; do
374                         [ $m = $mod ] && have=1
375                 done
376                 if [ $have = 0 ]; then
377                         MODULES="$MODULES $mod"
378                 fi
379         done
380 }
381
382 # install a file to temporary mount image.
383 # it will operate recursively (copying directories)
384 # and will symlink destinations if source is symlink.
385 inst() {
386         if [ $# -lt 2 ]; then
387                 die 'Usage: inst <file> [<file>] <destination>'
388         fi
389
390         local src i=0 c=$(($# - 1))
391         while [ $i -lt $c ]; do
392                 src="$src $1"
393                 i=$((i + 1))
394                 shift
395         done
396         local dest=$1
397         set -- $src
398         parentDir=$(dirname $DESTDIR$dest)
399         [ ! -d "$parentDir" ] && (debug "+ mkdir -p $parentDir"; mkdir -p $parentDir)
400         debug "+ cp $* $DESTDIR$dest"
401         cp -HR "$@" "$DESTDIR$dest"
402 }
403
404 inst_d() {
405         if [ $# = 0 ]; then
406                 die 'Usage: inst_d <destination> <destination>'
407         fi
408         for dir in "$@"; do
409                 install -d "$DESTDIR$dir"
410         done
411 }
412
413 # install executable and it's shared libraries
414 inst_exec() {
415         if [ $# -lt 2 ]; then
416                 die "Invalid params ($@), Usage: inst_exec <file>[, <file>] <destination>"
417         fi
418         local src i=0 c=$(($# - 1))
419         while [ $i -lt $c ]; do
420                 src="$src $1"
421                 i=$((i + 1))
422                 shift
423         done
424         local dest=$1
425         set -- $src
426
427         inst "$@" $dest
428
429         local lib libs=$(ldd "$@" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
430         for lib in $libs; do
431                 if [ ! -f "$DESTDIR/$_lib/${lib##*/}" ]; then
432                         inst_d /$_lib
433                         inst_exec $lib /$_lib
434                 fi
435         done
436
437         # hack for uclibc linked binaries requiring this fixed path
438         # XXX: shouldn't rpath be used here instead so th
439         if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
440                 local lib=$DESTDIR/$_lib/libc.so.0
441                 lib=$(ldd "$lib" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
442                 local libdir=$(cd $(dirname "$lib"); pwd)
443                 if [ ! -e $DESTDIR$libdir ]; then
444                         libdir=$(dirname "$libdir")
445                         inst_d $libdir
446                         debug "+ ln -s /$_lib $DESTDIR$libdir"
447                         ln -s /$_lib $DESTDIR$libdir
448                 fi
449         fi
450 }
451
452 # output modules.conf / modprobe.conf
453 modprobe_conf() {
454         echo "$modprobe_conf_cache"
455 }
456
457 #
458 # defaults to modprobe -c if not told otherwise, this means include statements
459 # work from there.
460 cache_modprobe_conf() {
461         if [ "$kernel_version" -lt "002005" ]; then
462                 modulefile=/etc/modules.conf
463                 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
464                         modulefile=/etc/conf.modules
465                 fi
466         fi
467
468         if [ -n "$modulefile" ]; then
469                 debug "Using $modulefile for modules config"
470                 modprobe_conf_cache=$(cat $modulefile)
471         else
472                 debug "Using modprobe -c to get modules config"
473                 modprobe_conf_cache=$(modprobe -c --set-version $kernel)
474         fi
475 }
476
477 # find modules for $devpath
478 find_modules_for_devpath() {
479         local devpath="$1"
480         if [ -z "$devpath" ]; then
481                 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
482         fi
483
484         if [[ "$devpath" = /dev/dm-* ]]; then
485                 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
486                 devpath=$(dm_longname "$devpath")
487         fi
488
489         if [ -L "$devpath" ] && ! is_lvm "$devpath"; then
490                 # sanitize things like:
491                 # /dev/block/104:2 -> /dev/cciss/c0d0p2
492                 devpath=$(readlink -f "$devpath")
493         fi
494
495         debug "Finding modules for device path $devpath"
496
497         if is_luks "$devpath"; then
498                 find_modules_luks "$devpath"
499                 return
500         fi
501
502         if is_nfs "$devpath"; then
503                 find_modules_nfs "$devpath"
504                 return
505         fi
506
507         if is_md "$devpath"; then
508                 find_modules_md "$devpath"
509                 return
510         fi
511
512         if is_multipath "$devpath"; then
513                 if find_modules_multipath "$devpath"; then
514                         return
515                 fi
516
517                 # fallback
518         fi
519
520         if is_dmraid "$devpath"; then
521                 if find_modules_dmraid "$devpath"; then
522                         return
523                 fi
524                 # fallback
525         fi
526
527         if is_scsi "$devpath"; then
528                 find_modules_scsi "$devpath"
529                 return
530         fi
531
532         if is_ide "$devpath"; then
533                 find_modules_ide "$devpath"
534                 return
535         fi
536
537         if [[ "$devpath" == /dev/rd/* ]]; then
538                 find_module "DAC960"
539                 rootdev_add=/dev/rd/
540                 return
541         fi
542
543         if [[ "$devpath" == /dev/ida/* ]]; then
544                 find_module "cpqarray"
545                 rootdev_add=/dev/ida/
546                 return
547         fi
548
549         if [[ "$devpath" == /dev/cciss/* ]]; then
550                 find_module "cciss"
551                 rootdev_add=/dev/cciss/
552                 return
553         fi
554
555         if [[ "$devpath" == /dev/ataraid/* ]]; then
556                 find_modules_ide
557                 find_module "ataraid"
558                 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ && ! /^[\t ]*#/ { print $3; }')
559                 if [ -n "$ataraidmodules" ]; then
560                         # FIXME: think about modules compiled in kernel
561                         die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
562                 fi
563                 for n in $ataraidmodules; do
564                         find_module "$n"
565                 done
566                 rootdev_add=/dev/ataraid/
567                 return
568         fi
569
570         # check to see if we need to set up a loopback filesystem
571         if [[ "$devpath" == /dev/loop*  ]]; then
572                 die "Sorry, root on loop device isn't supported."
573                 # TODO: rewrite for bsp and make nfs ready
574                 if [ ! -x /sbin/losetup ]; then
575                         die "losetup is missing"
576                 fi
577                 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
578                 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
579                         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"
580                 fi
581
582                 line="`awk '/'$key'/ { print $0; }' $fstab`"
583                 loopDev="$(echo $line | awk '{print $3}')"
584                 loopFs="$(echo $line | awk '{print $4}')"
585                 loopFile="$(echo $line | awk '{print $5}')"
586
587                 BASICMODULES="$BASICMODULES -loop"
588                 find_module "-$loopFs"
589                 BASICMODULES="$BASICMODULES -${loopFs}"
590                 return
591         fi
592
593         if is_lvm "$devpath"; then
594                 find_modules_lvm "$devpath"
595                 return
596         fi
597 }
598
599 firmware_install_module() {
600         local module="$1"
601         local firmware_files="$2"
602
603         debug "Adding Firmwares ($firmware_files) to initrd for module $module"
604         # firmware not yet installed
605         if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
606                 inst_d /lib/firmware
607 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
608 #!/bin/sh -e
609 echo 1 > /sys$DEVPATH/loading
610 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
611 echo 0 > /sys$DEVPATH/loading
612 exit 0
613 EOF
614                 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
615         fi
616
617         for firmware in $firmware_files; do
618                 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
619                         FIRMWAREDIR=${firmware%/*}
620                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
621                         inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
622                 elif [ -f "/lib/firmware/$firmware" ]; then
623                         FIRMWAREDIR=${firmware%/*}
624                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
625                         inst /lib/firmware/$firmware /lib/firmware/$firmware
626                 else
627                         die "firmware file /lib/firmware/$firmware nor /lib/firmware/$kernel/$firmware found."
628                 fi
629         done
630
631         mount_sys
632         echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
633 }
634
635 modules_install() {
636         local modules="$1"
637         local mod
638
639         for mod in $modules; do
640                 MODULEDIR=${mod%/*}
641                 inst_d "/lib/modules/$kernel/$MODULEDIR"
642                 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
643                 gunzip "$DESTDIR/lib/modules/$kernel/$mod" 2> /dev/null
644         done
645 }
646
647 modules_add_linuxrc() {
648         local mod modpath
649
650         for mod in "$@"; do
651                 # module path without optional compression
652                 modpath=${mod%.gz}
653
654                 # name of the module
655                 local module=${modpath##*/}; module=${module%$modext}
656                 local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}' | xargs)
657                 local genericname=$(echo $module | tr - _)
658                 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
659                 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
660
661                 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
662                         options="scan=sync $options"
663                 fi
664
665                 if [ -n "$verbose" ]; then
666                         s=""
667                         if [ "$options" ]; then
668                                 s="$s with options [$options]"
669                         fi
670                         if [ "$usleep" ]; then
671                                 s="$s and $usleep usleep"
672                         fi
673                         debug "Loading module [$module]$s"
674                 fi
675
676                 if [ -n "$firmware" ]; then
677                         firmware_install_module "$module" "$firmware"
678                 else
679                         for file in $(find_firmware "$module"); do
680                                 firmware_install_module "$module" "$file"
681                         done
682                 fi
683
684                 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
685                 if [ -n "$usleep" ]; then
686                         echo "usleep $usleep" | add_linuxrc
687                 fi
688                 if [ "$module" = "scsi_wait_scan" ]; then
689                         if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
690                                 echo "rmmod scsi_wait_scan" | add_linuxrc
691                         fi
692                 fi
693
694         done
695 }
696
697 # Generates /dev nodes based on /proc/partitions information.
698 # Needs /proc mounted.
699 # Can be called multiple times.
700 initrd_gen_devices() {
701         if is_yes "$proc_partitions"; then
702                 return
703         fi
704         proc_partitions=yes
705
706         mount_dev
707         add_linuxrc <<-'EOF'
708                 : 'Making device nodes'
709                 cat /proc/partitions | (
710                         # ignore first two lines: header, empty line
711                         read b; read b
712
713                         while read major minor blocks dev rest; do
714                                 node=/dev/$dev
715                                 mkdir -p ${node%/*}
716                                 [ -e $node ] || mknod $node b $major $minor
717                         done
718                 )
719         EOF
720 }
721
722
723 initrd_gen_setrootdev() {
724         debug "Adding rootfs finding based on kernel cmdline root= option support."
725         add_linuxrc <<-'EOF'
726                 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
727                         rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
728                         if [ -n "$rootnr" ]; then
729                                 echo "$rootnr" > /proc/sys/kernel/real-root-dev
730                         fi
731                 fi
732         EOF
733 }
734
735 initrd_gen_initramfs_switchroot() {
736         inst_d /newroot
737         if [ "$rootdev" = "/dev/nfs" ]; then
738                 echo "rootfs on NFS root=/dev/nfs"
739         else
740                 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
741         fi
742
743         # parse 'root=xxx' kernel commandline
744         # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
745         add_linuxrc <<-'EOF'
746                 device=/dev/no_partition_found
747                 eval "$(busybox awk -v c="$ROOT" '
748                         BEGIN {
749                                 num_pattern_short = "[0-9a-f][0-9a-f][0-9a-f]";
750                                 num_pattern = "[0-9a-f]" num_pattern_short;
751                                 dev_pattern = "[hms][a-z][a-z]([0-9])+";
752                                 partition = "no_partition_found";
753                                 min = -1; maj = -1;
754
755                                 sub("^0x", "", c);
756                                 if (c ~ "^" num_pattern_short "$") sub("^", "0", c);
757                                 if (c ~ "^" num_pattern  "$") {
758                                         maj = sprintf("%s",substr(c,1,2));
759                                         min = sprintf("%s",substr(c,3));
760                                 }
761                                 if (c ~ "^\/dev\/" dev_pattern "$") sub("^/dev/","", c);
762                                 if (c ~ "^" dev_pattern "$") partition = c;
763                         }
764
765                         $4 ~ partition { maj = $1; min = $2; }
766                         $1 ~ maj && $2 ~ min { partition = $4; }
767
768                         END {
769                                 if (maj >= 0 && min >= 0) {
770                                         printf("device=/dev/%s; maj=%s; min=%s;\n", partition, maj, min);
771                                 }
772                         }
773                         ' /proc/partitions)"
774                 if [ "$device" != '/dev/no_partition_found' -a ! -b $device ]; then
775                         mknod $device b $maj $min
776                 fi
777         EOF
778
779         add_linuxrc <<-EOF
780                 rootdev=$rootdev
781                 rootfs=$rootFs
782         EOF
783
784         add_linuxrc <<-'EOF'
785                 if [ "$device" = '/dev/no_partition_found' ]; then
786                         device=$rootdev
787                 fi
788
789                 mount -t $rootfs -r $device /newroot
790                 init="$(echo "$CMDLINE" | busybox awk '/init=\// { gsub(/.*init=/,NIL,$0); gsub(/ .*/,NIL,$0); print }')"
791                 if [ -z "$init" -o ! -x "/newroot$init" ]; then
792                         init=/sbin/init
793                 fi
794         EOF
795
796         umount_all
797         busybox_applet switch_root
798         add_linuxrc <<-'EOF'
799                 exec switch_root /newroot $init ${1:+"$@"}
800
801                 echo "Error! initramfs should not reach this place."
802                 echo "It probably means you've got old version of busybox, with broken"
803                 echo "initramfs support. Trying to boot anyway, but won't promise anything."
804
805                 exec chroot /newroot $init ${1:+"$@"}
806
807                 echo "Failed to chroot!"
808         EOF
809         # we need /init being real file, not symlink, otherwise the initramfs will
810         # not be ran by pid 1 which is required for switch_root
811         mv $DESTDIR/linuxrc $DESTDIR/init
812         ln -s init $DESTDIR/linuxrc
813 }
814
815 # find if $symbol exists in System.map $mapfile
816 sym_exists() {
817         local mapfile="$1"
818         local symbol="$2"
819         if [ ! -f $mapfile ]; then
820                 # missing mapfile (not a pld kernel?)
821                 return 1
822         fi
823
824         awk -vc=1 -vsymbol="$symbol" '$2 == "T" && $3 == symbol {c = 0} END {exit c}' $mapfile
825 }
826
827 # find best compressor (or forced one) for initrd
828 find_compressor() {
829         local mode="$1"
830         # the best compressor list
831         local compressors='xz lzma bzip2 gzip lzo'
832
833         # a specified one, take it
834         if ! is_yes "$mode"; then
835                 compressors="$mode"
836         fi
837
838         debug "finding compressor: $compressors (via $mode)"
839         # check for compressor validity
840         local c prog map=/boot/System.map-$kernel
841         for c in $compressors; do
842                 case $c in
843                 xz)
844                         sym=unxz
845                         prog=/usr/bin/xz
846                         ;;
847                 lzma)
848                         sym=unlzma
849                         prog=/usr/bin/xz
850                         ;;
851                 bzip2)
852                         sym=bzip2
853                         prog=/usr/bin/bzip2
854                         ;;
855                 gzip)
856                         sym=gunzip
857                         prog=/bin/gzip
858                         ;;
859                 lzo)
860                         sym=unlzo
861                         prog=/usr/bin/lzop
862                         ;;
863                 *)
864                         die "Unknown compressor $c"
865                         ;;
866                 esac
867                 if sym_exists $map $sym && [ -x $prog ]; then
868                         echo $c
869                         return
870                 fi
871         done
872
873         debug "using gzip for compressor (fallback)"
874         echo gzip
875 }
876
877 # compresses kernel image image
878 # in function so we could retry with other compressor on failure
879 compress_image() {
880         local compressor="$1" IMAGE="$2" target="$3" tmp
881         tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
882
883         case "$compressor" in
884         xz)
885                 # don't use -9 here since kernel won't understand it
886                 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
887                 ;;
888         lzma)
889                 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
890                 ;;
891         bzip2)
892                 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
893                 ;;
894         gzip)
895                 gzip -9 < "$IMAGE" > "$tmp" || return $?
896                 ;;
897         lzo)
898                 lzop -9 < "$IMAGE" > "$tmp" || return $?
899                 ;;
900         esac
901
902         mv -f "$tmp" "$target"
903 }
904
905 if [ -r /etc/sysconfig/geninitrd ]; then
906         . /etc/sysconfig/geninitrd
907 fi
908
909 if [ ! -f /proc/mounts ]; then
910         warn "/proc filesystem not mounted, may cause wrong results or failure."
911 fi
912
913 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi
914
915 while [ $# -gt 0 ]; do
916         case $1 in
917         --fstab=*)
918                 fstab=${1#--fstab=}
919                 ;;
920         --fstab)
921                 fstab=$2
922                 shift
923                 ;;
924         --modules-conf=*)
925                 modulefile=${1#--modules-conf=}
926                 ;;
927         --modules-conf)
928                 modulefile=$2
929                 shift
930                 ;;
931         --with-bootsplash)
932                 BOOT_SPLASH=yes
933                 ;;
934         --without-bootsplash)
935                 BOOT_SPLASH=no
936                 ;;
937         --with-fbsplash)
938                 FB_SPLASH=yes
939                 ;;
940         --without-fbsplash)
941                 FB_SPLASH=no
942                 ;;
943         --with-fbcondecor)
944                 FB_CON_DECOR=yes
945                 ;;
946         --without-fbcondecor)
947                 FB_CON_DECOR=no
948                 ;;
949         --with-suspend)
950                 USE_SUSPEND=yes
951                 ;;
952         --without-suspend)
953                 USE_SUSPEND=no
954                 ;;
955         --with-suspend2 | --with-tuxonice)
956                 USE_TUXONICE=yes
957                 ;;
958         --without-suspend2 | --without-tuxonice)
959                 USE_TUXONICE=no
960                 ;;
961         --lvmversion=*)
962                 LVMTOOLSVERSION=${1#--lvmversion=}
963                 ;;
964         --lvmtoolsversion=*)
965                 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
966                 ;;
967         --lvmtoolsversion|--lvmversion)
968                 LVMTOOLSVERSION=$2
969                 shift
970                 ;;
971         --without-udev)
972                 USE_UDEV=no
973                 ;;
974         --with-udev)
975                 USE_UDEV=yes
976                 ;;
977         --without-dmraid)
978                 USE_DMRAID=no
979                 ;;
980         --without-multipath)
981                 USE_MULTIPATH=no
982                 ;;
983         --with-multipath=*)
984                 USE_MULTIPATH=${1#--with-multipath=}
985                 ;;
986         --without-blkid)
987                 USE_BLKID=no
988                 ;;
989         --without-luks)
990                 USE_LUKS=no
991                 ;;
992         --with=*)
993                 BASICMODULES="$BASICMODULES ${1#--with=}"
994                 ;;
995         --with)
996                 BASICMODULES="$BASICMODULES $2"
997                 shift
998                 ;;
999         --version)
1000                 echo "$PROGRAM: version $VERSION"
1001                 exit 0
1002                 ;;
1003         -v)
1004                 verbose=-v
1005                 ;;
1006         --compress)
1007                 COMPRESS=$2
1008                 ;;
1009         --compress=*)
1010                 COMPRESS="${1#--compress=}"
1011                 ;;
1012         --nocompress)
1013                 COMPRESS=no
1014                 ;;
1015         --ifneeded)
1016                 ifneeded=1
1017                 ;;
1018         -f)
1019                 force=1
1020                 ;;
1021         --preload=*)
1022                 PREMODS="$PREMODS ${1#--preload=}"
1023                 ;;
1024         --preload)
1025                 PREMODS="$PREMODS $2"
1026                 shift
1027                 ;;
1028         --fs=* | --fs)
1029                 die "--fs option is obsoleted. Use --initrdfs instead"
1030                 ;;
1031         --initrdfs=*)
1032                 INITRDFS=${1#--initrdfs=}
1033                 ;;
1034         --initrdfs)
1035                 INITRDFS=$2
1036                 shift
1037                 ;;
1038         --image-version)
1039                 img_vers=yes
1040                 ;;
1041         --ide-only-root)
1042                 ide_only_root="yes"
1043                 ;;
1044         *)
1045                 if [ -z "$target" ]; then
1046                         target="$1"
1047                 elif [ -z "$kernel" ]; then
1048                         kernel="$1"
1049                 else
1050                         usage >&2
1051                         exit 1
1052                 fi
1053                 ;;
1054         esac
1055
1056         shift
1057 done
1058
1059 if [ -z "$target" -o -z "$kernel" ]; then
1060         usage >&2
1061         exit 1
1062 fi
1063
1064 # main()
1065 if [ "$(id -u)" != 0 ]; then
1066         die "You need to be root to generate initrd"
1067 fi
1068
1069 if [ -d /lib64 -a -d /usr/lib64 ]; then
1070         _lib=lib64
1071 else
1072         _lib=lib
1073 fi
1074
1075 initrd_dir=/usr/$_lib/initrd
1076 kernel_version=$(echo "$kernel" | awk -F. '{print sprintf("%03d%03d",$1,$2)}')
1077 kernel_version_long=$(echo "$kernel" | awk -F. '{print sprintf("%03d%03d%03d",$1,$2,$3)}')
1078
1079 debug "# $RCSID"
1080 debug "Using _lib: $_lib"
1081 debug "Using initrd_dir: $initrd_dir"
1082
1083 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1084
1085 # we setup mods after parsing command line args
1086 geninitrd_setup_mods
1087
1088 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1089         warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1090 fi
1091
1092 if [ -z "$INITRDFS" ]; then
1093         if [ -n "$FS" ]; then
1094                 # FS= can came only via /etc/sysconfig/geninitrd likely?
1095                 die "FS configuration option is obsoleted. Use INITRDFS instead"
1096         fi
1097
1098         # default value
1099         if [ "$kernel_version" -ge "002005" ]; then
1100                 INITRDFS="initramfs"
1101         else
1102                 INITRDFS="rom"
1103         fi
1104 fi
1105
1106 case "$INITRDFS" in
1107   ext2)
1108         [ -x /sbin/mke2fs ] || die "/sbin/mke2fs is missing"
1109         ;;
1110   rom|romfs)
1111         [ -x /sbin/genromfs ] || die "/sbin/genromfs is missing"
1112         ;;
1113   cram|cramfs)
1114         [ -x /sbin/mkcramfs ] || die "/sbin/mkcramfs is missing"
1115         ;;
1116   initramfs)
1117         [ -x /bin/cpio ] || die "/bin/cpio is missing"
1118         [ -x /usr/bin/find ] || die "/usr/bin/find is missing"
1119         ;;
1120   *)
1121         die "Filesystem $INITRDFS on initrd is not supported"
1122         ;;
1123 esac
1124
1125 if [ -L "$target" ]; then
1126         target=$(readlink -f "$target")
1127 fi
1128
1129 if [ -n "$img_vers" ]; then
1130         target="$target-$kernel"
1131 fi
1132
1133 if [ -z "$force" -a -f "$target" ]; then
1134         die "$target already exists."
1135 fi
1136
1137 if [ ! -d "/lib/modules/$kernel" ]; then
1138         die "/lib/modules/$kernel is not a directory."
1139 fi
1140
1141 if [ "$kernel_version" -ge "002005" ]; then
1142         modext=".ko"
1143 fi
1144
1145 cache_modprobe_conf
1146
1147 for n in $PREMODS; do
1148         find_module "$n"
1149 done
1150
1151 if [ "$FBMODULE" ]; then
1152         find_module "$FBMODULE"
1153 fi
1154
1155 # allow forcing loading SCSI and/or IDE modules
1156 # XXX: where ADDSCSI cames from? drop?
1157 if is_yes "$ADDSCSI"; then
1158         find_modules_scsi
1159 fi
1160
1161 # autodetect SATA modules
1162 find_modules_sata
1163
1164 # XXX: where ADDIDE cames from? drop?
1165 if is_yes "$ADDIDE"; then
1166         find_modules_ide
1167 fi
1168
1169 if is_yes "$USE_SUSPEND"; then
1170         find_modules_suspend
1171 fi
1172
1173 find_root "$fstab" || exit
1174 debug "Using $rootdev as device for rootfs"
1175
1176 find_modules_for_devpath "$rootdev"
1177
1178 # if USE_MULTIPATH is path to device, scan that too
1179 # this is to bootstrap multipath setup into initrd.
1180 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1181         find_modules_multipath $USE_MULTIPATH
1182 fi
1183
1184 find_module "-$rootFs"
1185
1186 for n in $BASICMODULES; do
1187         find_module "$n"
1188 done
1189
1190 if is_yes "$USE_TUXONICE"; then
1191         find_module "-lzf"
1192 fi
1193
1194 find_modules_fbsplash
1195
1196 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1197         debug "No modules are needed -- not building initrd image."
1198         exit 0
1199 fi
1200
1201 debug "Building initrd..."
1202 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1203 RCFILE="$DESTDIR/linuxrc"
1204 > "$RCFILE"
1205 chmod a+rx "$RCFILE"
1206 ln -s linuxrc $DESTDIR/init
1207
1208 # create dirs that we really need
1209 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,sys}
1210
1211 modules_install "$MODULES"
1212
1213 # mknod'ing the devices instead of copying them works both with and
1214 # without devfs...
1215 mknod "$DESTDIR/dev/console" c 5 1
1216 mknod "$DESTDIR/dev/null" c 1 3
1217 mknod "$DESTDIR/dev/zero" c 1 5
1218 mknod "$DESTDIR/dev/urandom" c 1 9
1219
1220 inst_exec $busybox /bin/busybox
1221 ln -s busybox $DESTDIR/bin/sh
1222 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1223 ln -s busybox $DESTDIR/bin/initrd-busybox
1224
1225 add_linuxrc <<EOF
1226 #!/bin/sh
1227 # initrd generated by:
1228 # $RCSID
1229
1230 EOF
1231 mount_proc
1232 add_linuxrc <<-'EOF'
1233         read CMDLINE < /proc/cmdline; export CMDLINE
1234
1235         for arg in $CMDLINE; do
1236                 if [ "${arg}" = "debuginitrd" ]; then
1237                         DEBUGINITRD=yes
1238                 fi
1239                 if [ "${arg##debuginitrd=}" != "${arg}" ]; then
1240                         DEBUGINITRD=${arg##debuginitrd=}
1241                 fi
1242                 if [ "${arg##root=}" != "${arg}" ]; then
1243                         ROOT=${arg##root=}
1244                 fi
1245         done
1246
1247         # make debugshell() invoke subshell if $DEBUGINITRD=sh
1248         if [ "$DEBUGINITRD" = "sh" ]; then
1249                 debugshell() {
1250 EOF
1251 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1252 add_linuxrc <<-'EOF'
1253         echo "debug shell disabled by /etc/sysconfig/system:RUN_SULOGIN_ON_ERR setting"
1254 EOF
1255 else
1256 add_linuxrc <<-'EOF'
1257         sh
1258 EOF
1259 fi
1260 add_linuxrc <<-'EOF'
1261                 }
1262         else
1263                 debugshell() {
1264                         :
1265                 }
1266         fi
1267
1268         if [ "$DEBUGINITRD" ]; then
1269                 set -x
1270         fi
1271 EOF
1272
1273 modules_add_linuxrc $MODULES
1274
1275 # TODO: rewrite for busybox
1276 #if [ -n "$loopDev" ]; then
1277 #       if [ ! -d /initrd ]; then
1278 #               mkdir /initrd
1279 #       fi
1280 #
1281 #       cp -a "$loopDev" "$DESTDIR/dev"
1282 #       cp -a "$rootdev" "$DESTDIR/dev"
1283 #       echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1284 #       echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1285 #       echo "echo Setting up loopback device $rootdev" >> $RCFILE
1286 #       echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1287 #fi
1288
1289 if is_yes "$USE_UDEV"; then
1290         initrd_gen_udev
1291 fi
1292
1293 find_modules_uvesafb
1294 initrd_gen_uvesafb
1295
1296 if is_yes "$have_luks"; then
1297         initrd_gen_luks
1298 fi
1299
1300 if is_yes "$have_dmraid"; then
1301         initrd_gen_dmraid
1302 fi
1303
1304 if is_yes "$have_multipath"; then
1305         initrd_gen_multipath
1306 fi
1307
1308 if is_yes "$USE_BLKID"; then
1309         initrd_gen_blkid
1310 fi
1311
1312 if is_yes "$have_nfs"; then
1313         initrd_gen_nfs
1314 elif is_yes "$have_md"; then
1315         initrd_gen_md
1316         if is_yes "$have_lvm"; then
1317                 initrd_gen_lvm
1318         else
1319                 initrd_gen_setrootdev
1320         fi
1321 elif is_yes "$have_lvm"; then
1322         initrd_gen_lvm
1323 else
1324         initrd_gen_setrootdev
1325 fi
1326
1327 if is_yes "$USE_TUXONICE"; then
1328         initrd_gen_tuxonice
1329 fi
1330
1331 if is_yes "$USE_SUSPEND"; then
1332         initrd_gen_suspend
1333 fi
1334
1335 # additional devs always needed
1336 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1337
1338 if is_yes "$USE_UDEV"; then
1339         initrd_gen_stop_udevd
1340 fi
1341
1342 if [ "$INITRDFS" = "initramfs" ]; then
1343         initrd_gen_initramfs_switchroot
1344 else
1345         umount_all
1346 fi
1347
1348 if is_yes "$FB_SPLASH"; then
1349         initrd_gen_fbsplash
1350 fi
1351
1352 if is_yes "$FB_CON_DECOR"; then
1353         initrd_gen_fbcondecor
1354 fi
1355
1356 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1357
1358 debug "Creating $INITRDFS image $IMAGE"
1359 case "$INITRDFS" in
1360   ext2)
1361         dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1362         mke2fs -q -F -b 1024 -m 0 "$IMAGE" 2>/dev/null 1>&2
1363         tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1364
1365         local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1366         debug "Mounting ext2 image $IMAGE to $tmpmnt"
1367         mount -o loop -t ext2 "$IMAGE" "$tmpmnt"
1368         # We don't need this directory, so let's save space
1369         rm -rf "$tmpmnt"/lost+found
1370
1371         debug "Copy recursively $DESTDIR -> $tmpmnt"
1372         cp -a $DESTDIR/* $tmpmnt
1373         umount "$IMAGE"
1374         rmdir "$tmpmnt"
1375
1376         ;;
1377   rom|romfs)
1378         genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel initrd"
1379         ;;
1380   cram|cramfs)
1381         mkcramfs "$DESTDIR" "$IMAGE"
1382         ;;
1383   initramfs)
1384         (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1385         ;;
1386   *)
1387         die "Filesystem $INITRDFS not supported by $PROGRAM"
1388 esac
1389
1390 CONFIG_BLK_DEV_RAM_SIZE=$(extract-ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1391 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1392         CONFIG_BLK_DEV_RAM_SIZE=4096
1393 fi
1394
1395 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1396 debug   "image size: $IMAGESIZE KiB ($DESTDIR)"
1397 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1398         warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1399 fi
1400
1401 if ! is_no "$COMPRESS"; then
1402         compressor=$(find_compressor "$COMPRESS")
1403         debug "Compressing $target with $compressor"
1404
1405         # TODO: the image name (specified from kernel.spec) already contains
1406         # extension, which is .gz most of the time.
1407         compress_image "$compressor" "$IMAGE" "$target" || {
1408                 if [ $compressor != gzip ]; then
1409                         warn "Could not compress with $compressor, retrying with gzip"
1410                         compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1411                 else
1412                         die "Could not compress image with $compressor"
1413                 fi
1414         }
1415 else
1416         cp -a "$IMAGE" "$target"
1417 fi
1418
1419 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1420 if is_yes "$BOOT_SPLASH"; then
1421         initrd_gen_bootsplash "$target"
1422 fi
1423
1424 rm -rf "$DESTDIR" "$IMAGE"
1425
1426 # vim:ts=4:sw=4:noet:fdm=marker
This page took 0.565742 seconds and 4 git commands to generate.