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