Removed s390 special case for image selection; we will be using the default mechanism...
[opensuse:mkinitrd-old.git] / bonked / mkinitrd
1 #! /bin/bash
2
3 # mkinitrd - create the inital ramdisk images
4 # usage: see below usage() or call with -h
5 #
6 # Copyright (C) 1999-2003 SuSE Linux AG, Nuernberg, Germany
7 #
8 # This program is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU General Public License
10 # as published by the Free Software Foundation; either version 2
11 # of the License, or (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
21 # USA.
22
23 # This file is kept in the following CVS repository:
24 #
25 # $Source: /suse/yast2/cvsroot/mkinitrd/bonked/Attic/mkinitrd,v $
26 # $Revision: 1.36 $
27
28 #
29 # Print usage and exit
30 #
31 usage() {
32     cat<<EOM
33         Create initial ramdisk images that contain all kernel modules
34         needed in the early boot process, before the root file system
35         becomes available. This usually includes SCSI and/or RAID
36         modules, a file system module for the root file system, or
37         a network interface driver module for dhcp.
38
39         mkinitrd [options] [root_dir]
40
41         options:
42           -h               This Text.
43           -k "kernel list" List of kernel images for which initrd files
44                            are created. Defaults to all kernels found
45                            in /boot.
46           -i "initrd list" List of file names for the initrd; position
47                            have match to "kernel list". Defaults to all
48                            all kernels found in /boot.
49           -m "module list" Modules to include in initrd. Defaults to the
50                            INITRD_MODULES variable in /etc/sysconfig/kernel.
51           -b boot_dir      Boot directory. Defaults to /boot.
52           -d root_device   Root device. Defaults to the device from which
53                            the root_dir is mounted. Overrides the rootdev
54                            enviroment variable if set.
55           -s size          Add splash animation and bootscreen to initrd.
56           -t tmp_dir       Temporary directory. Defaults to $root_dir/var/tmp.
57           -D interface     Run dhcp on the specified interface.
58           -a acpi_dsdt     Attach compiled ACPI DSDT (Differentiated System
59                            Description Table) to initrd. This replaces the
60                            DSDT of the BIOS. Defaults to the ACPI_DSDT
61                            variable in /etc/sysconfig/kernel.
62           -S               Load policy file for SELinux if exist.
63         root_dir:          The directory the root partition is mounted on.
64                            Defaults to "/".
65 EOM
66     exit
67 }
68
69 # Readlink is not present on some older distributions: emulate it.
70 readlink() {
71     local path=$1 ll
72
73     ll="$(LC_ALL=C ls -l "$path" 2>&1)"
74     echo "${ll/* -> }"
75 }
76
77 default_kernel_images () {
78         local regex kernel_image kernel_version version_version initrd_image
79         local qf='%{NAME}-%{VERSION}-%{RELEASE}\n'
80
81         case "$arch" in
82                 s390*)  regex='image'
83                         ;;
84                 ppc)    regex='vmlinu[xz]\(64\)\?'
85                         ;;
86                 *)      regex='vmlinuz'
87                         ;;
88         esac
89
90         kernel_images=""
91         initrd_images=""
92         for kernel_image in $(ls $root_dir/boot \
93                 | sed -ne "\|^$regex\(-[0-9.]\+-[0-9]\+-[a-z0-9]\+$\)\?|p") ; do
94
95                 # Note that we cannot check the RPM database here -- this
96                 # script is itself called from within the binary kernel
97                 # packages, and rpm does not allow recursive calls.
98
99                 [ -L "$root_dir/boot/$kernel_image" ] && continue
100                 kernel_version=$(/sbin/get_kernel_version \
101                                  $root_dir/boot/$kernel_image 2> /dev/null)
102                 initrd_image=$(echo $kernel_image | sed -e "s|${regex}|initrd|")
103                 if [ "$kernel_image" != "$initrd_image" -a \
104                      -n "$kernel_version" -a \
105                      -d "$root_dir/lib/modules/$kernel_version" ]; then
106                         kernel_images="$kernel_images /boot/$kernel_image"
107                         initrd_images="$initrd_images /boot/$initrd_image"
108                 fi
109         done
110 }
111
112 # You can specify the root device via the environment variable rootdev (e.g.
113 # "rootdev=/dev/hda mkinitrd").
114
115 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
116 # general configurable parameters
117
118 kernel_images=
119 initrd_images=
120 modules=
121 modules_set=
122 boot_dir=
123 splash="auto"
124 use_pivot_root=
125 use_static_binaries=1
126 acpi_dsdt=
127 use_selinux=
128
129 # architecture dependend changes:
130 arch=`uname -m`
131 arch=${arch/ppc64/ppc}
132 arch=${arch/s390x/s390}
133
134 case $arch in
135 s390)
136     splash=off
137     ;;
138 esac
139
140 while getopts :hk:i:m:b:d:o:s:St:D:a: a ; do
141     case $a in
142         \:|\?)  case $OPTARG in
143                 k)  echo "-k requires kernel list parameter"
144                     ;;
145                 i)  echo "-i requires initrd list parameter"
146                     ;;
147                 m)  echo "-m requires module list parameter"
148                     ;;
149                 b)  echo "-b requires boot dir parameter"
150                     ;;
151                 d)  echo "-d requires root device parameter"
152                     ;;
153                 s)  echo "-s requires image size(s)"
154                     ;;
155                 t)  echo "-t requires tmp dir parameter"
156                     ;;
157                 D)  echo "-D requires dhcp interface parameter"
158                     ;;
159                 a)  echo "-a requires a DSDT parameter"
160                     ;;
161                 *)  echo "Unknown option: -$OPTARG"
162                     echo "Try mkinitrd -h"
163                     ;;
164             esac
165             exit 1
166             ;;
167         k)  kernel_images=$OPTARG
168             ;;
169         i)  initrd_images=$OPTARG
170             ;;
171         m)  modules=$OPTARG
172             modules_set=1
173             ;;
174         b)  boot_dir=$OPTARG
175             ;;
176         d)  rootdev=$OPTARG
177             ;;
178         s)  splash=$OPTARG
179             ;;
180         t)  tmp_dir=$OPTARG
181             ;;
182         D)  dhcp_interface=$OPTARG
183             dhcp_interface=${dhcp_interface#/dev/}
184             use_pivot_root=1
185             ;;
186         a)  acpi_dsdt="$OPTARG"
187             ;;
188         S)  use_selinux=1
189             ;;
190         h)  usage
191             ;;
192     esac
193 done
194 shift `expr $OPTIND - 1`
195
196 if [ -n "$1" ]; then
197     root_dir=${1%/}  # strip trailing slash
198 else
199     root_dir=
200 fi
201
202 if [ -n "$boot_dir" ]; then
203     boot_dir="${boot_dir#/}"
204     boot_dir="/${boot_dir%/}"
205 else
206     boot_dir="/boot"
207 fi
208 if [ ! -d "$boot_dir" ]; then
209     echo "$boot_dir is not a directory" >&2
210     exit 1
211 fi
212
213 # FIXME agruen: tmp_dir is the full, absolute path to a temporary directory
214 # that must not be a tmpfs file system. This was not consistently used in
215 # the previous version of mkinitrd.
216
217 if [ -n "$tmp_dir" ]; then
218     tmp_dir="/${tmp_dir#/}"  # make sure it is an absolute path
219 else
220     tmp_dir=$root_dir/var/tmp
221 fi
222 if [ ! -d "$tmp_dir" ]; then
223     echo "$tmp_dir is not a directory" >&2
224     exit 1
225 fi
226
227 # FIXME agruen: tmp_dir defaults to $root_dir/var/tmp. Not very nice
228 # to write into a directory of another installation without explicitly
229 # being asked to.
230 #
231 # If tmp_dir is unspecified, find a non-tmpfs temporary directory:
232 # /var/tmp, $root_dir/var/tmp, /tmp, $root_dir/tmp, etc.
233
234 # Check if the -k and -i settings are valid.
235 if [ $(set -- $kernel_images ; echo $#) -ne \
236      $(set -- $initrd_images ; echo $#) ]; then
237     echo "You have to specify -k and -i, or none of both. The -k" \
238          "and -i options must each contain the same number of items." >&2
239     exit 1
240 fi
241
242 if [ -z "$kernel_images" -o -z "$initrd_images" ]; then
243     default_kernel_images
244 fi
245
246
247 # Check which shell and insmod binaries to use in initrd.
248 [ -x $root_dir/bin/ash ] \
249     && initrd_shell_dynamic=$root_dir/bin/ash
250 if [ -n "$use_static_binaries" ]; then
251     if [ -x $root_dir/bin/ash.static ]; then
252         initrd_shell=$root_dir/bin/ash.static
253     else
254         initrd_shell=/bin/ash.static
255     fi
256 else
257     initrd_shell=$initrd_shell_dynamic
258 fi
259
260 # The shell-bang line to use inside initrd.
261 shebang=${initrd_shell#$root_dir}
262 shebang=${shebang%.static}
263
264 [ -x $root_dir/sbin/insmod ] \
265     && initrd_insmod_dynamic=$root_dir/sbin/insmod
266 if [ -n "$use_static_binaries" ]; then
267     if [ -x $root_dir/sbin/insmod.static ]; then
268         initrd_insmod=$root_dir/sbin/insmod.static
269     else
270         initrd_insmod=/sbin/insmod.static
271     fi
272 else
273     initrd_insmod=$initrd_insmod_dynamic
274 fi
275
276 # FIXME agruen: Is is really necessary to fall back to /bin/ash.static
277 # and /sbin/initrd.static outside the $root_dir?
278
279 # maximum initrd size
280 image_blocks=20480
281 image_inodes=2048
282
283 # handle splash screen
284 [ "x$splash" = xoff ] && splash=
285 if [ "x$splash" = xauto ] ; then
286     splash=
287     vgascan=/dev/null
288     [ -f $root_dir/etc/lilo.conf ] \
289         && vgascan="$vgascan $root_dir/etc/lilo.conf"
290     [ -f $root_dir/boot/grub/menu.lst ] \
291         && vgascan="$vgascan $root_dir/boot/grub/menu.lst"
292     for vga in `cat $vgascan \
293                 | sed -ne '/^[ \t]*#/d' \
294                       -e 's/^.*[ \t]*vga[ \t]*=[ \t]*\([0-9]\+\|0[xX][0-9a-fA-F]\+\).*$/\1/p'` ; do
295         splashsize=
296         case $vga in
297             785|786|0x311|0x312|0x0311|0x0312) splashsize=640x480   ;;
298             788|789|0x314|0x315|0x0314|0x0315) splashsize=800x600   ;;
299             791|792|0x317|0x318|0x0317|0x0318) splashsize=1024x768  ;;
300             794|0x31a|0x31A|0x031a)     splashsize=1280x1024 ;;
301             795|0x31b|0x31B|0x031b)     splashsize=1280x1024 ;;
302             *)
303                 vgahex=`printf 0x%04x "$[$vga]"`
304                 splashsize=`hwinfo debug=0 -all +bios.vbe \
305                             | sed -ne 's/^.*Mode '$vgahex': \([^ ][^ ]*\) .*$/\1/p' 2>/dev/null`
306                 ;;
307         esac
308         [ -n "$splashsize" -a "x${splash/$splashsize/}" = "x$splash" ] \
309             && splash="$splash,$splashsize"
310     done
311     splash=${splash#,}
312 fi
313
314 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
315 # should be nothing to change below...
316
317 PATH=/sbin:/usr/sbin:$PATH
318
319 work_dir=`mktemp -qd $tmp_dir/mkinitrd.XXXXXX`
320 if [ $? -ne 0 ]; then
321         echo "$0: Can't create temp dir, exiting." >&2
322         exit 1
323 fi
324 is_mounted=
325 is_mounted_small=
326
327 umount_proc() {
328     [ "$mounted_proc" ] && umount $mounted_proc
329     mounted_proc=
330 }
331
332 cleanup () {
333     [ "$is_mounted" ] && umount $tmp_mnt
334     is_mounted=
335     [ "$is_mounted_small" ] && umount $tmp_mnt_small
336     is_mounted_small=
337     rm -f $tmp_initrd $tmp_initrd.gz $tmp_msg tmp_initrd_small \
338           $tmp_initrd_small.gz
339     [ -d "$tmp_mnt" ] && rmdir $tmp_mnt
340     [ -d "$tmp_mnt_small" ] && rmdir $tmp_mnt_small
341 }
342
343 cleanup_finish () {
344     umount_proc
345     [ -d "$work_dir" ] && rmdir $work_dir
346 }
347
348 handle_terminate () {
349     echo "(received signal)
350
351 Interrupted, cleaning up." >&2
352     cleanup
353     cleanup_finish
354     exit 255
355 }
356
357 trap handle_terminate 1 2 3 15
358
359 error () {
360     echo "$2" >&2
361     cleanup
362     cleanup_finish
363     exit $1
364 }
365
366 oops () {
367     exit_code=$1
368     shift
369     echo "$@" >&2
370 }
371
372 # Check if module $1 is listed in $modules.
373 has_module () {
374     case " $modules " in
375         *" $1 "*)   return 0 ;;
376     esac
377     return 1
378 }
379
380 # Check if any of the modules in $* are listed in $modules.
381 has_any_module () {
382     local module
383     for module in "$@"; do
384         has_module "$module" && return 0
385     done
386 }
387
388 # Add module $1 at the end of the module list.
389 add_module () {
390     local module
391     for module in "$@"; do
392         has_module "$module" || modules="$modules $module"
393     done
394 }
395
396 enable_module () {
397     add_module "$1"
398     echo "
399 Automatically adding module $1.
400
401 If you want to add $2 support for later mkinitrd calls where
402 possibly no $2 is found, add $1 to INITRD_MODULES
403 in /etc/sysconfig/kernel
404 "
405 }
406
407 # Install a binary file
408 cp_bin () {
409     cp -a "$@"
410
411     # Remember the binaries installed. We need the list for checking
412     # for dynamic libraries.
413     while [ $# -gt 1 ]; do
414         initrd_bins[${#initrd_bins[@]}]=$1
415         shift
416    done
417 }
418
419 # Resolve dynamic library dependencies. Returns a list of symbolic links
420 # to shared objects and shared object files for the binaries in $*. The
421 # binaries must be relative to $root_dir.
422 shared_object_files () {
423     local LDD CHROOT initrd_libs lib_files lib_links lib link
424
425     LDD=/usr/bin/ldd
426     if [ ! -x $root_dir$LDD ]; then
427         error 2 "I need $root_dir$LDD."
428     fi
429
430     if [ -n "$root_dir" ]; then
431         CHROOT=/usr/bin/chroot
432         if [ ! -x $CHROOT ]; then
433             error 2 "I need $CHROOT."
434         fi
435         DO_CHROOT="$CHROOT $root_dir"
436     else
437         DO_CHROOT=
438     fi
439
440     initrd_libs=( $(
441         $DO_CHROOT $LDD "${@#$root_dir}" \
442         | sed -e '\: => :!d' -e 's:.* => \([^ ]*\).*:\1:'
443     ) )
444
445     # Evil hack: On some systems we have generic as well as optimized
446     # libraries, but the optimized libraries may not work with all
447     # kernel versions (e.g., the NPTL glibc libraries don't work with
448     # a 2.4 kernel). Use the generic versions of the libraries in the
449     # initrd (and guess the name).
450     local n optimized
451     for ((n=0; $n<${#initrd_libs[@]}; n++)); do
452         lib=${initrd_libs[$n]}
453         optimized="$(echo "$lib" | sed -e 's:.*/\([^/]\+/\)[^/]\+$:\1:')"
454         lib=${lib/$optimized/}
455         if [ "${optimized:0:3}" != "lib" -a -f "$lib" ]; then
456             #echo "[Using $lib instead of ${initrd_libs[$n]}]" >&2
457             initrd_libs[$n]="${lib/$optimized/}"
458         fi
459     done
460
461     for lib in "${initrd_libs[@]}"; do
462         case "$lib" in
463         linux-gate*)
464             # This library is mapped into the process by the kernel
465             # for vsyscalls (i.e., syscalls that don't need a user/
466             # kernel address space transition) in 2.6 kernels.
467             continue ;;
468         /*)
469             lib="${lib:1}" ;;
470         *)
471             # Library could not be found.
472             oops 7 "Dynamic library $lib not found"
473             continue ;;
474         esac
475
476         while [ -L "$root_dir/$lib" ]; do
477             echo $lib
478             link="$(readlink "$root_dir/$lib")"
479             if [ x"${link:0:1}" == x"/" ]; then
480                 lib=${link#/}
481             else
482                 lib="${lib%/*}/$link"
483             fi
484         done
485         echo $lib
486     done \
487     | sort -u
488 }
489
490 # Resolve module dependencies and parameters. Returns a list of modules and
491 # their parameters. The module names returned are relative to $root_dir.
492 resolve_modules () {
493     local kernel_version=$1 module
494     shift
495
496     if [ -n "$root_dir" ]; then
497         CHROOT=/usr/bin/chroot
498         if [ ! -x $CHROOT ]; then
499             error 2 "I need $CHROOT."
500         fi
501         DO_CHROOT="$CHROOT $root_dir"
502     else
503         DO_CHROOT=
504     fi
505
506     for module in "$@"; do
507         module=${module#.o}  # strip trailing ".o" just in case.
508         module=${module#.ko}  # strip trailing ".ko" just in case.
509         case $kernel_version in
510         2.4.*)
511             # Really old systems don't have modprobe.old.
512             local modprobe
513             if [ -e $root_dir/sbin/modprobe.old ]; then
514                modprobe=$root_dir/sbin/modprobe.old
515             else
516                modprobe=$root_dir/sbin/modprobe
517             fi
518             tmp_conf="$(mktemp $root_dir/tmp/mkinitrd.XXXXXX)"
519             {   echo "depfile=/lib/modules/$kernel_version/modules.dep"
520                 sed -e '/^[ \t]*depfile=/d' $root_dir/etc/modules.conf
521             } > "$tmp_conf"
522             module_list=$( $DO_CHROOT \
523                 ${modprobe#$root_dir} -C "${tmp_conf#$root_dir}" \
524                                       -v -n $module 2> /dev/null \
525                 | sed -ne 's:.*insmod /\?::p' )
526             rm -f "$tmp_conf"
527             ;;
528         *)
529             local with_modprobe_conf
530             if [ -e /etc/modprobe.conf ]; then
531                 with_modprobe_conf="-C /etc/modprobe.conf"
532             fi
533             module_list=$( $DO_CHROOT \
534                /sbin/modprobe $with_modprobe_conf \
535                               --set-version $kernel_version \
536                               --show-depends $module 2> /dev/null \
537                | sed -ne 's:.*insmod /\?::p' )
538             ;;
539         esac
540         if [ -z "$module_list" ]; then
541             case $module in
542             scsi_mod|sd_mod|md)  # modularized in 2.4.21
543                 # These modules were previously compiled into the kernel,
544                 # and were modularized later. They will be missing in older
545                 # kernels; ignore error messages.
546                 ;;
547             xfs_dmapi|xfs_support)  # gone in 2.4.20
548                 # These modules do no longer exist. Do not produce an error
549                 # message, but warn that they should be removed manually.
550                 echo -n "Warning: Module $module no longer exists, and" \
551                      "should be removed " >&2
552                 if [ -e $root_dir/etc/sysconfig/kernel ]; then
553                     echo "from /etc/sysconfig/kernel." >&2
554                 elif [ -e $root_dir/etc/rc.config ]; then
555                     echo "from /etc/rc.config." >&2
556                 else
557                     echo "." >&2
558                 fi
559                 ;;
560             *)
561                 oops 7 "Cannot determine dependencies of module $module." \
562                        "Is modules.dep up to date?"
563                 ;;
564             esac
565         fi
566         echo "$module_list"
567     done \
568     | awk ' # filter duplicates: we must not reorder modules here!
569         $1 in seen  { next }
570                     { seen[$1]=1
571                       print
572                     }
573     '
574     rm -f $temp
575 }
576
577 # Test if file $1 is smaller than file $2 (kilobyte granularity)
578 smaller_file () {
579     local size1=$(ls -l "$1" |awk '{print $5}')
580     local size2=$(ls -l "$2" |awk '{print $5}')
581     [ $size1 -lt $size2 ]
582 }
583
584 # Cat from stdin to linuxrc, removing leading whitespace up to pipe symbol.
585 # Note that here documents can only be indented with tabs, not with spaces.
586 cat_linuxrc () {
587     sed 's/^[ \t]*|//' >> $linuxrc
588     echo >> $linuxrc
589 }
590
591 # Attach ACPI DSDT if necessary.
592 attach_dsdt () {
593     local initrd_image=$1
594
595     if [ -z "$acpi_dsdt" ]; then
596         if [ -f "$root_dir/etc/sysconfig/kernel" ]; then
597             . $root_dir/etc/sysconfig/kernel
598             acpi_dsdt="$ACPI_DSDT"
599         fi
600     fi
601     if [ -z "$acpi_dsdt" ]; then
602         return
603     fi
604     if [ ! -f "$acpi_dsdt" ]; then
605         oops 2 "ACPI DSDT $acpi_dsdt does not exist."
606         return
607     fi
608     if ! grep -q "DSDT" "$acpi_dsdt" ; then
609         oops 2 "File $acpi_dsdt is not a valid ACPI DSDT. Ignoring."
610     elif grep -qE 'DefinitionBlock|char|dsl|aml' "$acpi_dsdt" ; then
611         oops 2 "ACPI DSDT $acpi_dsdt does not seem to be in binary form." \
612                "Will not attach this to $initrd_image."
613     else
614         {   echo -ne "INITRDDSDT123DSDT123\0"
615             cat "$acpi_dsdt"
616             echo -ne "INITRDDSDT321DSDT321\0"
617         } >> $initrd_image
618         echo -e "ACPI DSDT:\t$acpi_dsdt"
619     fi
620 }
621
622 # Create the initrd image $2 for kernel $1 (both are absolute path names).
623 mkinitrd_kernel () {
624     local kernel_image=$1 initrd_image=$2
625     local kernel_version need_mount sysfs_root
626
627     tmp_mnt=$work_dir/mnt
628     tmp_mnt_small=${tmp_mnt}_small
629     tmp_msg=$work_dir/msg$$
630     linuxrc=$tmp_mnt/linuxrc
631
632     if ! [ -f "$root_dir$kernel_image" ] ; then
633         echo "No kernel image $root_dir$kernel_image found" >&2
634         return
635     fi
636
637     kernel_version=$(/sbin/get_kernel_version $root_dir$kernel_image)
638
639     echo -e "Kernel version:\t$kernel_version ($HOSTTYPE)"
640     echo -e "Kernel image:\t$root_dir$kernel_image"
641     echo -e "Initrd image:\t$root_dir$initrd_image"
642
643     if [ ! -d "$root_dir/lib/modules/$kernel_version/misc" -a \
644          ! -d "$root_dir/lib/modules/$kernel_version/kernel" ]; then
645         oops 2 "No modules found for kernel $kernel_version"
646         return
647     fi
648
649     # create an empty initrd
650     mkdir $tmp_mnt || error 1 "could not create temporary directory"
651     dd if=/dev/zero of=$tmp_initrd bs=1k count=$image_blocks 2>/dev/null
652     mke2fs -q -F -b 1024 -m 0 -N $image_inodes $tmp_initrd 2>/dev/null 1>&2
653     tune2fs -i 0 $tmp_initrd >/dev/null 2>&1
654
655     # check for loop device
656     grep -q loop /proc/devices
657     if [ $? != 0 ] ; then
658         if [ -f /lib/loop.o ] ; then
659             insmod /lib/loop.o
660         else
661             modprobe loop
662         fi
663     fi
664     # mount it
665     if ! mount -t ext2 -oloop $tmp_initrd $tmp_mnt ; then
666         error 3 "failed to mount image"
667     fi
668     is_mounted=1
669     # fill the initrd
670     rmdir $tmp_mnt/lost+found
671     mkdir -p $tmp_mnt/{sbin,bin,dev}
672     initrd_devices=$(echo dev/{zero,null,ram0,ram1,ram2,ram,ramdisk} \
673                           dev/{console,md0})
674     case $arch in
675         s390*)
676             ;;
677         *)  initrd_devices="$initrd_devices $(echo dev/{fb0,tty1,tty2})"
678             ;;
679     esac
680     (cd ${root_dir:-/} ; cp -R --parents $initrd_devices $tmp_mnt )
681     cp_bin $initrd_shell $tmp_mnt$shebang 2>/dev/null \
682         || error 4 "no static shell"
683     cp_bin $initrd_insmod $tmp_mnt/sbin/insmod 2>/dev/null \
684         || error 5 "no static insmod"
685
686     # If exists, copy also insmod.static.old, it is created by modutils for
687     # 2.5.47+ kernels and it is needed by these to work with older kernels.
688     if [ -r $initrd_insmod.old ] ; then
689       cp_bin $initrd_insmod.old $tmp_mnt/sbin/insmod.old 2>/dev/null
690     fi
691
692    # SELinux: Binary policy file and load_policy utility for loading it.
693    if [ -n "$use_selinux" ] ; then
694         if [ -f $root_dir/etc/security/selinux/policy.15 -a -f $root_dir/usr/sbin/load_policy ] ; then
695            echo -e "SELinux policy:\tadded"
696            mkdir -p $tmp_mnt/selinux
697            mkdir -p $tmp_mnt/etc/security/selinux
698            cp -p $root_dir/etc/security/selinux/policy.15 $tmp_mnt/etc/security/selinux
699            cp_bin $root_dir/usr/sbin/load_policy $tmp_mnt/sbin/load_policy
700         else
701            echo -e "SELinux policy:\tnot found"
702         fi
703     fi
704
705     case "$kernel_version" in
706     2.6*)
707         sysfs_root=1
708         ;;
709     esac
710
711     if [ -n "$sysfs_root" ]; then
712         mkdir -p $tmp_mnt/sys
713         cp_bin $root_dir/usr/bin/expr $tmp_mnt/bin
714         cp_bin $root_dir/bin/cat $tmp_mnt/bin
715         need_mount=1
716     fi
717
718     if [ -n "$root_lvm" ] ; then
719         echo "Including LVM support"
720         mkdir -p $tmp_mnt/etc/lvmtab.d
721         cp -a $root_dir/dev/lvm  $tmp_mnt/dev
722         cp_bin $root_dir/sbin/{vgscan,vgchange} $tmp_mnt/sbin
723         cp_bin $root_dir/bin/cat $tmp_mnt/bin
724         need_mount=1
725     fi
726
727     if [ -n "$use_pivot_root" ] ; then
728         echo "Including pivot root support"
729         cp_bin $root_dir/sbin/pivot_root $tmp_mnt/bin
730         cp_bin $root_dir/bin/cat $tmp_mnt/bin
731         echo "#! $shebang" > $tmp_mnt/bin/init
732         echo 'echo initrd failed, goodbye...' >> $tmp_mnt/bin/init
733         chmod 755 $tmp_mnt/bin/init
734         mkdir -p $tmp_mnt/mnt
735         need_mount=1
736     fi
737
738     if [ -n "$dhcp_interface" ] ; then
739         echo " Using dhcp on $dhcp_interface"
740         cp_bin $root_dir/sbin/dhcpcd $tmp_mnt/bin
741         cp_bin $root_dir/bin/kill $tmp_mnt/bin
742         mkdir -p $tmp_mnt/var/lib/dhcpcd
743         mkdir -p $tmp_mnt/var/run
744         need_mount=1
745     fi
746
747     if has_module jfs ; then
748         echo "Including JFS recovery support"
749         cp_bin $root_dir/sbin/fsck $tmp_mnt/bin
750         cp_bin $root_dir/sbin/fsck.jfs $tmp_mnt/bin
751         need_mount=1
752     fi
753
754     if has_module scsi_mod ; then
755         cp_bin $root_dir/bin/cat $tmp_mnt/bin
756         need_mount=1
757     fi
758
759     if [ -n "$need_mount" ] ; then
760         mkdir -p $tmp_mnt/{etc,proc,mnt}
761         echo 'none /proc proc defaults 0 0' > $tmp_mnt/etc/fstab
762         if [ "$sysfs_root" ] ; then
763             echo 'sysfs /sys sysfs defaults 0 0' > $tmp_mnt/etc/fstab
764         fi
765         cp_bin $root_dir/bin/{mount,umount} $tmp_mnt/bin
766         if [ -z "$use_pivot_root" -a -b "$root_dir/$rootdev" ] ; then
767             mkdir -p $tmp_mnt/${rootdev%/*}
768             cp -a $root_dir/$rootdev $tmp_mnt/${rootdev%/*}
769         fi
770     fi
771
772     # DEBUG: cp_bin /bin/ls $tmp_mnt/bin
773
774     echo -ne "Shared libs:\t"
775     # Only check those binaries against dynamic libraries that were
776     # taken from the root_dir: We don't want to go into library
777     # hell by adding libraries in different versions!
778     bin_files=$(
779         for bin in "${initrd_bins[@]}" ; do
780             case $bin in
781                 ($root_dir*)
782                     echo "${bin#$root_dir}"
783                     ;;
784             esac
785         done )
786
787     # Copy all required shared libraries and the symlinks that
788     # refer to them.
789     lib_files=$(shared_object_files $bin_files)
790     if [ -n "$lib_files" ]; then
791         for lib in $lib_files; do
792             [ -L $root_dir/$lib ] || echo -n "$lib "
793             ( cd ${root_dir:-/} ; cp -dp --parents $lib $tmp_mnt )
794         done
795         echo
796     else
797         echo "none"
798     fi
799
800     if [ -n "$lib_files" -a -n "$initrd_shell_dynamic" ]; then
801         # If we have already have all dynamic libraries that
802         # $initrd_shell_dynamic is using, and if $initrd_shell_dynamic
803         # is smaller than $initrd_shell, we can save a little space
804         # by using the dynamic version. The benefit is marginal, though.
805
806         if smaller_file $initrd_shell_dynamic $initrd_shell ; then
807             for lib in $(shared_object_files $initrd_shell_dynamic) ; do
808                 case $lib_files in
809                     *$lib*) ;;
810                     *)  initrd_shell_dynamic=
811                         break ;;
812                 esac
813             done
814             if [ -n "$initrd_shell_dynamic" ]; then
815                 #echo " - Using dynamically linked $shebang"
816                 cp_bin $initrd_shell_dynamic $tmp_mnt$shebang
817             fi
818         fi
819     fi
820
821     if [ -n "$lib_files" -a -n "$initrd_insmod_dynamic" ]; then
822         # If we have already have all dynamic libraries that
823         # $initrd_insmod_dynamic is using, and if $initrd_insmod_dynamic
824         # is smaller than $initrd_insmod, we can save a little space
825         # by using the dynamic version. The benefit is marginal, though.
826
827         if smaller_file $initrd_insmod_dynamic $initrd_insmod ; then
828             for lib in $(shared_object_files $initrd_insmod_dynamic); do
829                 case $lib_files in
830                     *$lib*) ;;
831                     *)  initrd_insmod_dynamic=
832                         break ;;
833                 esac
834             done
835             if [ -n "$initrd_insmod_dynamic" ]; then
836                 #echo " - Using dynamically linked /sbin/insmod"
837                 cp_bin $initrd_insmod_dynamic $tmp_mnt/sbin/insmod
838             fi
839         fi
840     fi
841
842     cat /dev/null > $linuxrc
843     chmod 755 $linuxrc
844
845     # Note that the in-place documents must be indented with tabs, not spaces.
846
847     cat_linuxrc <<-EOF
848         |#! $shebang
849         |
850         |export PATH=/sbin:/bin:/usr/bin
851         EOF
852
853     resolved_modules="$(resolve_modules $kernel_version $modules)"
854
855     # If a SCSI module is loaded, we will have a dependency on scsi_mod
856     # for kernels which don't have this built in. In that case, assume
857     # that the root file system is on a SCSI device, and also include
858     # sd_mod.
859     local have_scsi have_sd
860     case "$resolved_modules" in
861         */scsi_mod.*)   have_scsi=1
862                         ;;
863     esac
864     case "$resolved_modules" in
865         */sd_mod.*)     have_sd=1
866                         ;;
867     esac
868     if [ -n "$have_scsi" -a -z "$have_sd" ]; then
869         modules="sd_mod $modules"
870         # Re-evaluate module dependencies
871         resolved_modules="$(resolve_modules $kernel_version $modules)"
872     fi
873
874     # Copy the modules to the initrd
875     echo -ne "Modules:\t"
876     initrd_is_using_modules=
877     while read module params ; do
878         [ -z "$module" ] && continue
879         echo -n "${module#lib/modules/$kernel_version/} "
880         if [ ! -r $root_dir/$module ]; then
881             oops 9 "Module $module not found."
882             continue
883         fi
884         if ! ( cd ${root_dir:-/} ; cp -p --parents $module $tmp_mnt ) ; then
885             oops 6 "Failed to add module $module. Initrd too small?"
886             return
887         fi
888
889         case "$module" in
890             */dasd_mod.*)
891                 # kernel cmdline dasd parameter is placed into the environment.
892                 # all we need to do is to have it evaluated at insmod time....:
893                 params="dasd=\$dasd"
894                 ;;
895             */zfcp.*)
896                 # FIXME hare: Check against 2.6 whether configuration is
897                 # still the same ...
898                 if [ "$zfcp_param" ]; then
899                         params="map=\"$zfcp_param\""
900                 fi
901                 ;;
902             */scsi_mod*)
903                 # We may have SCSI parameters on the kernel command line,
904                 # but because scsi_mod is a module, those would be ignored.
905                 # Hack around this by scanning /proc/cmdline in linuxrc.
906                 params="\$extra_scsi_params${params:+ $params}"
907
908                 cat_linuxrc <<-EOF
909                 |# check for SCSI parameters in /proc/cmdline
910                 |mount -n -tproc none /proc
911                 |for p in \`cat /proc/cmdline\` ; do
912                 |  case \$p in
913                 |    scsi*|*_scsi_*|llun_blklst=*|max_report_luns=*)
914                 |      extra_scsi_params="\$extra_scsi_params \$p"
915                 |      ;;
916                 |  esac
917                 |done
918                 |umount -n /proc
919                 EOF
920         esac
921
922         mp="/$module${params:+ $params}"
923         cat_linuxrc <<-EOF
924         |echo "Loading ${mp#/lib/modules/$kernel_version/}"
925         |insmod $mp
926         EOF
927         initrd_is_using_modules=1
928     done < <(echo "$resolved_modules")
929     echo
930
931     if [ -z "$initrd_is_using_modules" ]; then
932         echo "none"
933     fi
934
935     if has_any_module raid0 raid1 raid5 linear multipath ; then
936         echo "Including raidautorun"
937         cat_linuxrc <<-EOF
938         |echo "raidautorun ..."
939         |raidautorun
940         |echo "done..."
941         EOF
942     fi
943
944     if [ -n "$root_lvm" ] ; then
945         # need dummy entry so fsck doesn't complain
946         cat_linuxrc <<-EOF
947         |# scan for lvm devices
948         |mount -n -tproc none /proc
949         |createpartitiondevs
950         |#need space for lvm data
951         |mount -n -tshm none /etc/lvmtab.d
952         |vgscan
953         |vgchange -a y
954         |umount -n /etc/lvmtab.d
955         |# set the right root device if user specified a lvm root
956         |root=
957         |for o in \`cat /proc/cmdline\` ; do
958         |  case \$o in
959         |    root=*) root="\$o" ;;
960         |  esac
961         |done
962         |if test -n "\$root"; then
963         |  echo "\$root" > /.root
964         |  oifs="\$IFS"
965         |  IFS="="
966         |  read dummy rootdev < /.root
967         |  IFS="\$oifs"
968         |  rootdevn=\`devnumber \$rootdev 2>/dev/null\`
969         |  if test -n "\$rootdevn" -a "\$rootdevn" -ge 14848 -a \\
970         |          "\$rootdevn" -lt 15104 ; then
971         |    echo "\$rootdevn" > /proc/sys/kernel/real-root-dev
972         |  fi
973         |fi
974         |umount -n /proc
975         EOF
976     fi
977
978     if [ -n "$sysfs_root" ]; then
979         cat_linuxrc <<-'EOF'
980         |sh_basename () {
981         |       local path="$1" IFS="/"
982         |
983         |       set -- $path
984         |       while test "$#" -gt 1; do shift; done
985         |       echo "$1"
986         |}
987         |
988         |sysfs_set_root_dir () {
989         |       local entry name major minor dev_t dir="$1" search="$2"
990         |
991         |       name="$(sh_basename $dir)"
992         |       if test -f "$dir/dev" -a "$name" = "$search"; then
993         |               IFS=: read major minor < "$dir/dev"
994         |               dev_t=`expr "$major" "*" "256" "+" "$minor"`
995         |               echo "rootfs: /dev/$name major=$major minor=$minor dev_t=$dev_t"
996         |               echo "$dev_t" > /proc/sys/kernel/real-root-dev
997         |       fi
998         |       for entry in "$dir/"*; do
999         |               test -L "$entry" && continue
1000         |               test -d "$entry" || continue
1001         |               sysfs_set_root_dir "$entry" "$search"
1002         |       done
1003         |}
1004         |
1005         |sysfs_set_root () {
1006         |       local root="$1"
1007         |
1008         |       sysfs_set_root_dir /sys/block $root
1009         |}
1010         |
1011         |mount -n -tproc none /proc
1012         |mount -n -tsysfs sysfs /sys > /dev/null 2>&1
1013         |for item in $(cat /proc/cmdline); do
1014         |       case "$item" in
1015         |               root=/dev/*)
1016         |                       sysfs_set_root `expr substr $item 11 99` ;;
1017         |       esac
1018         |done
1019         |umount -n /sys
1020         |umount -n /proc
1021         EOF
1022     fi
1023
1024     if [ -n "$use_pivot_root" ] ; then
1025         cat_linuxrc <<-EOF
1026         |# create missing devices
1027         |mount -n -tproc none /proc
1028         |createpartitiondevs
1029         |umount -n /proc
1030         EOF
1031     fi
1032
1033     if [ -n "$dhcp_interface" ] ; then
1034         cat_linuxrc <<-EOF
1035         |mount -n -tproc none /proc
1036         |root=
1037         |for o in \`cat /proc/cmdline\` ; do
1038         |  case \$o in
1039         |    root=*:*) root="\$o" ;;
1040         |    root=*) root="\$o" ; no_dhcp=true ;;
1041         |  esac
1042         |done
1043         |# run dhcp
1044         |if test -z "\$no_dhcp" ; then
1045         |  dhcp_mode=1
1046         |  rootdev=
1047         |  # ifconfig lo 127.0.0.1 netmask 255.0.0.0 broadcast 127.255.255.255 up
1048         |  # portmap
1049         |  echo "running dhcpcd on interface $dhcp_interface"
1050         |  dhcpcd -R -Y -N -t 100000000 $dhcp_interface
1051         |  test -s /var/lib/dhcpcd/dhcpcd-$dhcp_interface.info || {
1052         |    echo "no response from dhcp server."
1053         |    echo 256 > /proc/sys/kernel/real-root-dev
1054         |    exit 0
1055         |  }
1056         |  . /var/lib/dhcpcd/dhcpcd-$dhcp_interface.info
1057         |  kill -9 \`cat /var/run/dhcpcd-$dhcp_interface.pid\`
1058         |  if test -n "\$DNS" ; then
1059         |    oifs="\$IFS"
1060         |    IFS=","
1061         |    for ns in \$DNS ; do
1062         |      echo "nameserver \$ns" >> /etc/resolv.conf
1063         |    done
1064         |    IFS="\$oifs"
1065         |    test -n "\$DOMAIN" \\
1066         |      && echo "search \$DOMAIN" >> /etc/resolv.conf
1067         |    echo 'hosts: dns' > /etc/nsswitch.conf
1068         |  fi
1069         |fi
1070         |if test -z "\$root" ; then
1071         |  if test -z "\$ROOTPATH" ; then
1072         |    echo "no root= kernel option given and no rootpath" \
1073         |         "set by the dhcp server."
1074         |    echo 256 > /proc/sys/kernel/real-root-dev
1075         |    exit 0
1076         |  fi
1077         |  case \$ROOTPATH in
1078         |    *:*)
1079         |      rootdev="\$ROOTPATH"
1080         |      ;;
1081         |    *)
1082         |      if test -n "\$DHCPSIADDR" ; then
1083         |        rootdev="\$DHCPSIADDR:\$ROOTPATH"
1084         |      elif test -n "\$DHCPSNAME" ; then
1085         |        rootdev="\$DHCPSNAME:\$ROOTPATH"
1086         |      else
1087         |        echo "no root= kernel option given and no root" \
1088         |             "server set by the dhcp server."
1089         |        echo 256 > /proc/sys/kernel/real-root-dev
1090         |        exit 0
1091         |      fi
1092         |  esac
1093         |fi
1094         |umount -n /proc
1095         EOF
1096     fi
1097
1098     if has_module jfs && [ -n "$rootdev" ] ; then
1099         cat_linuxrc <<-EOF
1100         |# check filesystem if it is of type jfs
1101         |mount -n -tproc none /proc
1102         |test -z "\$dhcp_mode" && fsck -t jfs "$rootdev"
1103         |umount -n /proc
1104         EOF
1105     fi
1106
1107     if [ -n "$use_selinux" -a -d $tmp_mnt/selinux ]; then
1108         cat_linuxrc <<-EOF
1109         |echo -n "Loading SELinux policy        "
1110         |if mount -n -t selinuxfs none /selinux >/dev/null 2>/dev/null ; then
1111         |  /sbin/load_policy /etc/security/selinux/policy.15
1112         |  umount /selinux
1113         |  echo "successful"
1114         |else
1115         |  echo "skipped"
1116         |fi
1117         EOF
1118     fi
1119
1120     if [ -n "$use_pivot_root" ] ; then
1121         cat_linuxrc <<-EOF
1122         |# mount root with pivot_root call
1123         |opt="-oro"
1124         |test -n "\$dhcp_mode" && opt=-oro,nolock
1125         |test -z "\$dhcp_mode" && rootdev="$rootdev"
1126         |root=
1127         |nopivot=
1128         |mount -n -tproc none /proc
1129         |# bug in some kernels, need cat
1130         |for o in \`cat /proc/cmdline\` ; do
1131         |  test "\$o" = rw && opt=
1132         |  test "\$o" = rw -a -n "\$dhcp_mode" && opt=-onolock
1133         |  case \$o in
1134         |    root=ROOT=*) root="\$o" ;;
1135         |    root=LABEL=*) root="\$o" ;;
1136         |    root=*) root="\$o" ; nopivot=1 ;;
1137         |  esac
1138         |done
1139         |if test -n "\$nopivot" -a -z "\$dhcp_mode" ; then
1140         |  umount -n /proc
1141         |  exit 0
1142         |fi
1143         |
1144         |if test -n "\$root" ; then
1145         |  # sed free programming
1146         |  echo "\$root" > /.root
1147         |  oifs="\$IFS"
1148         |  IFS="="
1149         |  read dummy rootdev < /.root
1150         |  IFS="\$oifs"
1151         |fi
1152         |
1153         |# tell kernel root is /dev/ram0, prevents remount after initrd
1154         |echo 256 > /proc/sys/kernel/real-root-dev
1155         |# mount the actual root device below /mnt
1156         |echo "Mounting root \$rootdev"
1157         |mount -n \$opt \$rootdev /mnt || exit 1
1158         |umount -n /proc
1159         |# do pivot-root call
1160         |cd /mnt
1161         |exec <dev/console >dev/console 2>&1
1162         |if test -d initrd ; then
1163         |   exec pivot_root . initrd
1164         |elif test -d mnt ; then
1165         |   pivot_root . mnt
1166         |   exec /bin/umount -n /mnt
1167         |else
1168         |   pivot_root . tmp
1169         |   exec /bin/umount -n /tmp
1170         |fi
1171         EOF
1172     fi
1173
1174
1175     # Now create a second initrd with minimal size
1176
1177     #echo "Creating minimum size initrd image"
1178     img_size=`expr \`df -kP $tmp_mnt | sed '1d' | awk '{print $3}'\` + 2000`
1179     mkdir $tmp_mnt_small
1180
1181     dd if=/dev/zero of=$tmp_initrd_small bs=1k count=$img_size 2>/dev/null
1182     mke2fs -q -F -b 1024 -m 0 -N $image_inodes $tmp_initrd_small \
1183         2>/dev/null 1>&2
1184     tune2fs -i 0 $tmp_initrd_small >/dev/null 2>&1
1185
1186     if ! mount -t ext2 -oloop $tmp_initrd_small $tmp_mnt_small ; then
1187         error 3 "failed to mount image"
1188     fi
1189     is_mounted_small=1
1190
1191     rmdir $tmp_mnt_small/lost+found
1192     cp -a $tmp_mnt/* $tmp_mnt_small \
1193         || error 6 "copy big image to small image failed"
1194     chown -R 0:0 $tmp_mnt
1195
1196     umount $tmp_mnt_small
1197     is_mounted_small=
1198
1199     umount $tmp_mnt
1200     is_mounted=
1201
1202     gzip -9 $tmp_initrd_small
1203
1204     if ! cp -f $tmp_initrd_small.gz $initrd_image ; then
1205         oops 8 "Failed to install initrd"
1206         return
1207     fi
1208
1209     splash_bin=
1210     [ -x /sbin/splash.bin ] && splash_bin=/sbin/splash.bin
1211     [ -x /bin/splash ] && splash_bin=/bin/splash
1212     if [ -n "$splash" -a -n "$splash_bin" ]; then
1213         if [ -f /etc/sysconfig/bootsplash ]; then
1214             . /etc/sysconfig/bootsplash
1215         fi
1216
1217         themes_dir=
1218         if [ -d "$root_dir/etc/bootsplash/themes" ]; then
1219             themes_dir="$root_dir/etc/bootsplash/themes"
1220         elif [ -d "$root_dir/usr/share/splash/themes" ]; then
1221             themes_dir="$root_dir/usr/share/splash/themes"
1222         fi
1223
1224         echo -ne "Bootsplash:\t"
1225         if [ -n "$themes_dir" -a \
1226              -d "$themes_dir/$THEME" -o -L "$themes_dir/$THEME" ]; then
1227             for size in ${splash//,/ }; do
1228                 bootsplash_picture="$themes_dir/$THEME/images/bootsplash-$size.jpg"
1229                 cfgname="$themes_dir/$THEME/config/bootsplash-$size.cfg"
1230                 if [ ! -r $cfgname ] ; then
1231                     echo "disabled for resolution $size"
1232                 elif [ ! -r $bootsplash_picture ] ; then
1233                     echo "no image for resolution $size"
1234                 else
1235                     echo "$THEME ($size)"
1236                     $splash_bin -s -f $cfgname >> $initrd_image
1237                 fi
1238             done
1239         else
1240             echo "no theme selected"
1241         fi
1242     fi
1243 }
1244
1245 ###################################################################
1246
1247 # working directories
1248 tmp_initrd=$work_dir/initrd
1249 tmp_initrd_small=${tmp_initrd}_small
1250
1251 mounted_proc=
1252 if [ ! -r /proc/mounts ]; then
1253   mounted_proc=/proc
1254   mount -t proc proc $mounted_proc
1255 fi
1256
1257 if [ -z "$rootdev" ] ; then
1258   # no rootdev specified, get current root from /etc/fstab
1259   while read fstab_device fstab_mountpoint fstab_type fstab_options dummy ; do
1260     if [ "$fstab_mountpoint" = "/" ]; then
1261       rootdev="$fstab_device"
1262       rootfstype="$fstab_type"
1263       break
1264     fi
1265   done < <( sed -e '/^[         ]*#/d' < $root_dir/etc/fstab)
1266 else
1267   # get type from /etc/fstab or /proc/mounts (actually not needed)
1268   x1=$(cat $root_dir/etc/fstab /proc/mounts 2>/dev/null \
1269        | grep -E "$rootdev[[:space:]]" | tail -n 1)
1270   rootfstype=`echo $x1 | cut -f 3 -d " "`
1271 fi
1272
1273 if [ -z "$dhcp_interface" ]; then
1274     [ -z "$rootdev" ] \
1275         && error 1 "No '/' mountpoint specified in $root_dir/etc/fstab"
1276 else
1277     rootdev=
1278     rootfstype=nfs
1279 fi
1280
1281 realrootdev="$rootdev"
1282 case "$rootdev" in
1283     LABEL=*|UUID=*)
1284         use_pivot_root=1
1285         # get real root via fsck hack
1286         realrootdev=$(fsck -N "$rootdev" \
1287                       | sed -ne '2s/.* \/dev/\/dev/p' \
1288                       | sed -e 's/  *//g')
1289         [ -z "$realrootdev" ] \
1290             && error 1 "Could not expand $rootdev to real device"
1291         ;;
1292 esac
1293
1294 # check if the root device is an lvm device
1295 root_lvm=
1296 if [ -n "$realrootdev" -a -b "$realrootdev" ] ; then
1297     major=$(ls -l "$realrootdev" \
1298             | sed -e "s/.* \\([0-9]\+\\), *[0-9]\+.*/\\1/")
1299     [ "$major" -eq 58 ] && root_lvm=1
1300 fi
1301
1302 s390_zfcp() {
1303    zfcp_param=
1304    if [ ! -s $root_dir/etc/zfcp.conf ] && cat /proc/modules | grep -q "^zfcp"
1305    then
1306         fcpconf=`cat /proc/scsi/zfcp/map`
1307         if [ -n "$fcpconf" ]; then
1308             echo "$fcpconf" > $root_dir/etc/zfcp.conf
1309             chmod 644 $root_dir/etc/zfcp.conf
1310         fi
1311    fi
1312    if [ -s $root_dir/etc/zfcp.conf ]; then
1313         add_module zfcp
1314
1315         zfcp_param=$(sed -e 's,#.*,,' -e '/^[[:blank:]]*$/d' \
1316                      $root_dir/etc/zfcp.conf)
1317
1318         if [ -z "$zfcp_param" ]; then
1319             zfcp_param=`modprobe -v -n zfcp|sed -n '/map=/s/.*zfcp.o //p'`
1320         fi
1321
1322         if [ -z "$zfcp_param" ]; then
1323             error 1 "\
1324 zfcp module loaded but root_dir/etc/zfcp.conf empty.
1325 don't know how to configure zfcp in initrd.
1326
1327 you can save the current configuration with this command:
1328
1329     cat /proc/scsi/zfcp/map >> root_dir/etc/zfcp.conf
1330 "
1331         fi
1332     fi
1333 }
1334
1335 s390_dasd() {
1336     if [ -f $root_dir/etc/zipl.conf ]; then
1337         if grep -q '^[[:space:]]*parameters=' $root_dir/etc/zipl.conf; then
1338             zipl_conf_with_dasd=1
1339         fi
1340     fi
1341
1342     if grep -q '^[[:space:]]*options[[:space:]]\+dasd_mod'\
1343                 $root_dir/etc/modules.conf; then
1344         dasd_modules_conf=1
1345     fi
1346
1347     if cat /proc/modules | grep -q -e "^dasd" \
1348         || [ -n "$zipl_conf_with_dasd" ] \
1349         || [ -n "$dasd_modules_conf" ] \
1350         || has_module dasd_mod ; then
1351
1352         if [ ! "$zipl_conf_with_dasd" -a ! "$dasd_modules_conf" ]; then
1353             error 1 "\
1354 The dasd module is required, but no dasd configuration was found in
1355 root_dir/etc/zipl.conf or root_dir/etc/modules.conf."
1356         fi
1357
1358         if grep -q ECKD /proc/dasd/devices ; then
1359             enable_module dasd_eckd_mod 'ECKD dasd'
1360         fi
1361
1362         if grep -q FBA  /proc/dasd/devices ; then
1363             enable_module dasd_fba_mod  'FBA dasd'
1364         fi
1365
1366         if grep -q DIAG /proc/dasd/devices ; then
1367             enable_module dasd_diag_mod 'DIAG dasd'
1368         fi
1369     fi
1370 }
1371
1372 ###################################################################
1373
1374 x="$rootdev"
1375 [ -n "$dhcp_interface" ] && x="nfs-root"
1376 [ "$rootdev" != "$realrootdev" ] && x="$x ($realrootdev)"
1377 echo -e "Root device:\t$x (mounted on ${root_dir:-/} as $rootfstype)"
1378
1379 if [ -z "$modules_set" ]; then
1380     # get INITRD_MODULES from system configuration
1381     if [ -e $root_dir/etc/sysconfig/kernel ]; then
1382         . $root_dir/etc/sysconfig/kernel
1383         modules="$INITRD_MODULES"
1384     elif [ -e $root_dir/etc/rc.config ]; then
1385         . $root_dir/etc/sysconfig/kernel
1386         modules="$INITRD_MODULES"
1387     fi
1388 fi
1389
1390 ###################################################################
1391 # add modules required by features
1392 if [ -n "$root_lvm" ] ; then
1393     add_module lvm-mod
1394 fi
1395
1396 if [ "$arch" = s390 ]; then
1397     # Check if zfcp or dasd modules need to be added automatically:
1398     s390_zfcp
1399     s390_dasd
1400 fi
1401
1402 # check if an initrd is needed at all.
1403 #
1404 # on s390 the initrd is always needed as long as we don't set the
1405 # initrd flag in /etc/zipl.conf with YaST.
1406 if [ -z "$modules" -a -z "$root_lvm" -a -z "$use_pivot_root" -a \
1407      -z "$splash" -a "$arch" != s390 -a -z "$use_selinux" ]; then
1408     ( cd $boot_dir
1409       rm -f $initrd_images )
1410     error 0 "No initrd required"
1411 fi
1412
1413 ###################################################################
1414
1415 exit_code=0
1416
1417 initrd_images=( $initrd_images )
1418 kernel_images=( $kernel_images )
1419
1420 echo -e "Module list:\t$modules"
1421 for ((i=0 ; $i<${#kernel_images[@]} ; i++)); do
1422     kernel_image=${kernel_images[$i]}
1423     [ ${kernel_image:0:1} != '/' ] \
1424         && kernel_image=$boot_dir/$kernel_image
1425
1426     initrd_image=${initrd_images[$i]}
1427     [ ${initrd_image:0:1} != '/' ] \
1428         && initrd_image=$boot_dir/$initrd_image
1429
1430     mkinitrd_kernel $kernel_image $initrd_image
1431     attach_dsdt $initrd_image
1432
1433     # Hack: Previous kernels have had a symlink vmlinuz -> vmlinuz-$VERSION,
1434     # but initrd was a plain file. Try to detect that case, and replace
1435     # old initrd files with symlinks.
1436     if [ -L $root_dir/$boot_dir/vmlinuz -a \
1437          "$(readlink $root_dir/$boot_dir/vmlinuz)" == \
1438          "${kernel_image#$boot_dir/}" ]; then
1439         rm -f $root_dir/$boot_dir/initrd
1440         ln -s "${initrd_image#$boot_dir/}" $root_dir/$boot_dir/initrd
1441     fi
1442     cleanup
1443 done
1444
1445
1446 cleanup_finish
1447
1448 if [ -e $root_dir/etc/sysconfig/bootloader ]; then
1449     . $root_dir/etc/sysconfig/bootloader
1450 fi
1451 case $LOADER_TYPE in
1452   lilo)
1453     echo "
1454 Run lilo now to update the boot loader configuration."
1455     ;;
1456   elilo)
1457     if [ -x /sbin/elilo ]; then
1458       /sbin/elilo
1459     else
1460       echo "
1461 You may now have to update the elilo boot loader configuration."
1462     fi
1463     ;;
1464   grub)
1465     ;;
1466   *)
1467     if [ -f "$root_dir/etc/zipl.conf" ]; then
1468         echo -e "\ninitrd updated, zipl needs to update the IPL record before IPL!"
1469     else
1470         echo "
1471 You may now have to update your boot loader configuration."
1472     fi
1473     ;;
1474 esac
1475
1476 exit $exit_code