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