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