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