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