]> git.pld-linux.org Git - projects/geninitrd.git/blob - geninitrd
make romfs comment shorter so that "file" would display most significant info
[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]"
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 img=$(mktemp)
289         local kofile=$(modinfo -k $kernel -n configs)
290         case "$kofile" in
291         '')
292                 return
293                 ;;
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'
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                 *)
860                         die "Unknown compressor $c"
861                         ;;
862                 esac
863                 if sym_exists $map $sym && [ -x $prog ]; then
864                         echo $c
865                         return
866                 fi
867         done
868
869         debug "using gzip for compressor (fallback)"
870         echo gzip
871 }
872
873 if [ -r /etc/sysconfig/geninitrd ]; then
874         . /etc/sysconfig/geninitrd
875 fi
876
877 if [ ! -f /proc/mounts ]; then
878         warn "/proc filesystem not mounted, may cause wrong results or failure."
879 fi
880
881 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi
882
883 while [ $# -gt 0 ]; do
884         case $1 in
885         --fstab=*)
886                 fstab=${1#--fstab=}
887                 ;;
888         --fstab)
889                 fstab=$2
890                 shift
891                 ;;
892         --modules-conf=*)
893                 modulefile=${1#--modules-conf=}
894                 ;;
895         --modules-conf)
896                 modulefile=$2
897                 shift
898                 ;;
899         --with-bootsplash)
900                 BOOT_SPLASH=yes
901                 ;;
902         --without-bootsplash)
903                 BOOT_SPLASH=no
904                 ;;
905         --with-fbsplash)
906                 FB_SPLASH=yes
907                 ;;
908         --without-fbsplash)
909                 FB_SPLASH=no
910                 ;;
911         --with-fbcondecor)
912                 FB_CON_DECOR=yes
913                 ;;
914         --without-fbcondecor)
915                 FB_CON_DECOR=no
916                 ;;
917         --with-suspend)
918                 USE_SUSPEND=yes
919                 ;;
920         --without-suspend)
921                 USE_SUSPEND=no
922                 ;;
923         --with-suspend2 | --with-tuxonice)
924                 USE_TUXONICE=yes
925                 ;;
926         --without-suspend2 | --without-tuxonice)
927                 USE_TUXONICE=no
928                 ;;
929         --lvmversion=*)
930                 LVMTOOLSVERSION=${1#--lvmversion=}
931                 ;;
932         --lvmtoolsversion=*)
933                 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
934                 ;;
935         --lvmtoolsversion|--lvmversion)
936                 LVMTOOLSVERSION=$2
937                 shift
938                 ;;
939         --without-udev)
940                 USE_UDEV=no
941                 ;;
942         --with-udev)
943                 USE_UDEV=yes
944                 ;;
945         --without-dmraid)
946                 USE_DMRAID=no
947                 ;;
948         --without-multipath)
949                 USE_MULTIPATH=no
950                 ;;
951         --with-multipath=*)
952                 USE_MULTIPATH=${1#--with-multipath=}
953                 ;;
954         --without-blkid)
955                 USE_BLKID=no
956                 ;;
957         --without-luks)
958                 USE_LUKS=no
959                 ;;
960         --with=*)
961                 BASICMODULES="$BASICMODULES ${1#--with=}"
962                 ;;
963         --with)
964                 BASICMODULES="$BASICMODULES $2"
965                 shift
966                 ;;
967         --version)
968                 echo "$PROGRAM: version $VERSION"
969                 exit 0
970                 ;;
971         -v)
972                 verbose=-v
973                 ;;
974         --compress)
975                 COMPRESS=$2
976                 ;;
977         --compress=*)
978                 COMPRESS="${1#--compress=}"
979                 ;;
980         --nocompress)
981                 COMPRESS=no
982                 ;;
983         --ifneeded)
984                 ifneeded=1
985                 ;;
986         -f)
987                 force=1
988                 ;;
989         --preload=*)
990                 PREMODS="$PREMODS ${1#--preload=}"
991                 ;;
992         --preload)
993                 PREMODS="$PREMODS $2"
994                 shift
995                 ;;
996         --fs=* | --fs)
997                 die "--fs option is obsoleted. Use --initrdfs instead"
998                 ;;
999         --initrdfs=*)
1000                 INITRDFS=${1#--initrdfs=}
1001                 ;;
1002         --initrdfs)
1003                 INITRDFS=$2
1004                 shift
1005                 ;;
1006         --image-version)
1007                 img_vers=yes
1008                 ;;
1009         --ide-only-root)
1010                 ide_only_root="yes"
1011                 ;;
1012         *)
1013                 if [ -z "$target" ]; then
1014                         target="$1"
1015                 elif [ -z "$kernel" ]; then
1016                         kernel="$1"
1017                 else
1018                         usage >&2
1019                         exit 1
1020                 fi
1021                 ;;
1022         esac
1023
1024         shift
1025 done
1026
1027 if [ -z "$target" -o -z "$kernel" ]; then
1028         usage >&2
1029         exit 1
1030 fi
1031
1032 # main()
1033 if [ "$(id -u)" != 0 ]; then
1034         die "You need to be root to generate initrd"
1035 fi
1036
1037 if [ -d /lib64 -a -d /usr/lib64 ]; then
1038         _lib=lib64
1039 else
1040         _lib=lib
1041 fi
1042
1043 initrd_dir=/usr/$_lib/initrd
1044 kernel_version=$(echo "$kernel" | awk -F. '{print sprintf("%03d%03d",$1,$2)}')
1045 kernel_version_long=$(echo "$kernel" | awk -F. '{print sprintf("%03d%03d%03d",$1,$2,$3)}')
1046
1047 debug "# $RCSID"
1048 debug "Using _lib: $_lib"
1049 debug "Using initrd_dir: $initrd_dir"
1050
1051 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1052
1053 # we setup mods after parsing command line args
1054 geninitrd_setup_mods
1055
1056 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1057         warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1058 fi
1059
1060 if [ -z "$INITRDFS" ]; then
1061         if [ -n "$FS" ]; then
1062                 # FS= can came only via /etc/sysconfig/geninitrd likely?
1063                 die "FS configuration option is obsoleted. Use INITRDFS instead"
1064         fi
1065
1066         # default value
1067         if [ "$kernel_version" -ge "002005" ]; then
1068                 INITRDFS="initramfs"
1069         else
1070                 INITRDFS="rom"
1071         fi
1072 fi
1073
1074 case "$INITRDFS" in
1075   ext2)
1076         [ -x /sbin/mke2fs ] || die "/sbin/mke2fs is missing"
1077         ;;
1078   rom|romfs)
1079         [ -x /sbin/genromfs ] || die "/sbin/genromfs is missing"
1080         ;;
1081   cram|cramfs)
1082         [ -x /sbin/mkcramfs ] || die "/sbin/mkcramfs is missing"
1083         ;;
1084   initramfs)
1085         [ -x /bin/cpio ] || die "/bin/cpio is missing"
1086         [ -x /usr/bin/find ] || die "/usr/bin/find is missing"
1087         ;;
1088   *)
1089         die "Filesystem $INITRDFS on initrd is not supported"
1090         ;;
1091 esac
1092
1093 if [ -L "$target" ]; then
1094         target=$(readlink -f "$target")
1095 fi
1096
1097 if [ -n "$img_vers" ]; then
1098         target="$target-$kernel"
1099 fi
1100
1101 if [ -z "$force" -a -f "$target" ]; then
1102         die "$target already exists."
1103 fi
1104
1105 if [ ! -d "/lib/modules/$kernel" ]; then
1106         die "/lib/modules/$kernel is not a directory."
1107 fi
1108
1109 if [ "$kernel_version" -ge "002005" ]; then
1110         modext=".ko"
1111 fi
1112
1113 cache_modprobe_conf
1114
1115 for n in $PREMODS; do
1116         find_module "$n"
1117 done
1118
1119 if [ "$FBMODULE" ]; then
1120         find_module "$FBMODULE"
1121 fi
1122
1123 # allow forcing loading SCSI and/or IDE modules
1124 # XXX: where ADDSCSI cames from? drop?
1125 if is_yes "$ADDSCSI"; then
1126         find_modules_scsi
1127 fi
1128
1129 # autodetect SATA modules
1130 find_modules_sata
1131
1132 # XXX: where ADDIDE cames from? drop?
1133 if is_yes "$ADDIDE"; then
1134         find_modules_ide
1135 fi
1136
1137 if is_yes "$USE_SUSPEND"; then
1138         find_modules_suspend
1139 fi
1140
1141 find_root "$fstab" || exit
1142 debug "Using $rootdev as device for rootfs"
1143
1144 find_modules_for_devpath "$rootdev"
1145
1146 # if USE_MULTIPATH is path to device, scan that too
1147 # this is to bootstrap multipath setup into initrd.
1148 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1149         find_modules_multipath $USE_MULTIPATH
1150 fi
1151
1152 find_module "-$rootFs"
1153
1154 for n in $BASICMODULES; do
1155         find_module "$n"
1156 done
1157
1158 if is_yes "$USE_TUXONICE"; then
1159         find_module "-lzf"
1160 fi
1161
1162 find_modules_fbsplash
1163
1164 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1165         debug "No modules are needed -- not building initrd image."
1166         exit 0
1167 fi
1168
1169 debug "Building initrd..."
1170 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1171 RCFILE="$DESTDIR/linuxrc"
1172 > "$RCFILE"
1173 chmod a+rx "$RCFILE"
1174 ln -s linuxrc $DESTDIR/init
1175
1176 # create dirs that we really need
1177 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,sys}
1178
1179 modules_install "$MODULES"
1180
1181 # mknod'ing the devices instead of copying them works both with and
1182 # without devfs...
1183 mknod "$DESTDIR/dev/console" c 5 1
1184 mknod "$DESTDIR/dev/null" c 1 3
1185 mknod "$DESTDIR/dev/zero" c 1 5
1186 mknod "$DESTDIR/dev/urandom" c 1 9
1187
1188 inst_exec $busybox /bin/busybox
1189 ln -s busybox $DESTDIR/bin/sh
1190 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1191 ln -s busybox $DESTDIR/bin/initrd-busybox
1192
1193 add_linuxrc <<EOF
1194 #!/bin/sh
1195 # initrd generated by:
1196 # $RCSID
1197
1198 EOF
1199 mount_proc
1200 add_linuxrc <<-'EOF'
1201         read CMDLINE < /proc/cmdline; export CMDLINE
1202
1203         for arg in $CMDLINE; do
1204                 if [ "${arg}" = "debuginitrd" ]; then
1205                         DEBUGINITRD=yes
1206                 fi
1207                 if [ "${arg##debuginitrd=}" != "${arg}" ]; then
1208                         DEBUGINITRD=${arg##debuginitrd=}
1209                 fi
1210                 if [ "${arg##root=}" != "${arg}" ]; then
1211                         ROOT=${arg##root=}
1212                 fi
1213         done
1214
1215         # make debugshell() invoke subshell if $DEBUGINITRD=sh
1216         if [ "$DEBUGINITRD" = "sh" ]; then
1217                 debugshell() {
1218 EOF
1219 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1220 add_linuxrc <<-'EOF'
1221         echo "debug shell disabled by /etc/sysconfig/system:RUN_SULOGIN_ON_ERR setting"
1222 EOF
1223 else
1224 add_linuxrc <<-'EOF'
1225         sh
1226 EOF
1227 fi
1228 add_linuxrc <<-'EOF'
1229                 }
1230         else
1231                 debugshell() {
1232                         :
1233                 }
1234         fi
1235
1236         if [ "$DEBUGINITRD" ]; then
1237                 set -x
1238         fi
1239 EOF
1240
1241 modules_add_linuxrc $MODULES
1242
1243 # TODO: rewrite for busybox
1244 #if [ -n "$loopDev" ]; then
1245 #       if [ ! -d /initrd ]; then
1246 #               mkdir /initrd
1247 #       fi
1248 #
1249 #       cp -a "$loopDev" "$DESTDIR/dev"
1250 #       cp -a "$rootdev" "$DESTDIR/dev"
1251 #       echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1252 #       echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1253 #       echo "echo Setting up loopback device $rootdev" >> $RCFILE
1254 #       echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1255 #fi
1256
1257 if is_yes "$USE_UDEV"; then
1258         initrd_gen_udev
1259 fi
1260
1261 if is_yes "$USE_TUXONICE"; then
1262         initrd_gen_tuxonice
1263 fi
1264
1265 find_modules_uvesafb
1266 initrd_gen_uvesafb
1267
1268 if is_yes "$have_luks"; then
1269         initrd_gen_luks
1270 fi
1271
1272 if is_yes "$have_dmraid"; then
1273         initrd_gen_dmraid
1274 fi
1275
1276 if is_yes "$have_multipath"; then
1277         initrd_gen_multipath
1278 fi
1279
1280 if is_yes "$USE_BLKID"; then
1281         initrd_gen_blkid
1282 fi
1283
1284 if is_yes "$have_nfs"; then
1285         initrd_gen_nfs
1286 elif is_yes "$have_md"; then
1287         initrd_gen_md
1288         if is_yes "$have_lvm"; then
1289                 initrd_gen_lvm
1290         else
1291                 initrd_gen_setrootdev
1292         fi
1293 elif is_yes "$have_lvm"; then
1294         initrd_gen_lvm
1295 else
1296         initrd_gen_setrootdev
1297 fi
1298
1299 if is_yes "$USE_SUSPEND"; then
1300         initrd_gen_suspend
1301 fi
1302
1303 # additional devs always needed
1304 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1305
1306 if is_yes "$USE_UDEV"; then
1307         initrd_gen_stop_udevd
1308 fi
1309
1310 if [ "$INITRDFS" = "initramfs" ]; then
1311         initrd_gen_initramfs_switchroot
1312 else
1313         umount_all
1314 fi
1315
1316 if is_yes "$FB_SPLASH"; then
1317         initrd_gen_fbsplash
1318 fi
1319
1320 if is_yes "$FB_CON_DECOR"; then
1321         initrd_gen_fbcondecor
1322 fi
1323
1324 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1325
1326 debug "Creating $INITRDFS image $IMAGE"
1327 case "$INITRDFS" in
1328   ext2)
1329         dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1330         mke2fs -q -F -b 1024 -m 0 "$IMAGE" 2>/dev/null 1>&2
1331         tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1332
1333         local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1334         debug "Mounting ext2 image $IMAGE to $tmpmnt"
1335         mount -o loop -t ext2 "$IMAGE" "$tmpmnt"
1336         # We don't need this directory, so let's save space
1337         rm -rf "$tmpmnt"/lost+found
1338
1339         debug "Copy recursively $DESTDIR -> $tmpmnt"
1340         cp -a $DESTDIR/* $tmpmnt
1341         umount "$IMAGE"
1342         rmdir "$tmpmnt"
1343
1344         ;;
1345   rom|romfs)
1346         genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel initrd"
1347         ;;
1348   cram|cramfs)
1349         mkcramfs "$DESTDIR" "$IMAGE"
1350         ;;
1351   initramfs)
1352         (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1353         ;;
1354   *)
1355         die "Filesystem $INITRDFS not supported by $PROGRAM"
1356 esac
1357
1358 CONFIG_BLK_DEV_RAM_SIZE=$(extract-ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1359 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1360         CONFIG_BLK_DEV_RAM_SIZE=4096
1361 fi
1362
1363 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1364 debug   "image size: $IMAGESIZE KiB ($DESTDIR)"
1365 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1366         warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1367 fi
1368
1369 if ! is_no "$COMPRESS"; then
1370         tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1371         compressor=$(find_compressor "$COMPRESS")
1372         debug "Compressing $target with $compressor"
1373
1374         # TODO: the image name (specified from kernel.spec) already contains
1375         # extension, which is .gz most of the time.
1376         case "$compressor" in
1377         xz)
1378                 # don't use -9 here since kernel won't understand it
1379                 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp"
1380                 ;;
1381         lzma)
1382                 xz --format=lzma -9 < "$IMAGE" > "$tmp"
1383                 ;;
1384         bzip2)
1385                 bzip2 -9 < "$IMAGE" > "$tmp"
1386                 ;;
1387         gzip)
1388                 gzip -9 < "$IMAGE" > "$tmp"
1389                 ;;
1390         esac
1391         mv -f "$tmp" "$target"
1392 else
1393         cp -a "$IMAGE" "$target"
1394 fi
1395
1396 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1397 if is_yes "$BOOT_SPLASH"; then
1398         initrd_gen_bootsplash "$target"
1399 fi
1400
1401 rm -rf "$DESTDIR" "$IMAGE"
1402
1403 # vim:ts=4:sw=4:noet:fdm=marker
This page took 0.153508 seconds and 4 git commands to generate.