]> git.pld-linux.org Git - projects/geninitrd.git/blob - geninitrd
- variable cosmetics, localize
[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|xz|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                 local module=${modpath##*/}; module=${module%$modext}
616                 local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}' | xargs)
617                 local genericname=$(echo $module | tr - _)
618                 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
619                 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
620
621                 if [ -n "$verbose" ]; then
622                         s=""
623                         if [ "$options" ]; then
624                                 s="$s with options [$options]"
625                         fi
626                         if [ "$usleep" ]; then
627                                 s="$s and $usleep usleep"
628                         fi
629                         debug "Loading module [$module]$s"
630                 fi
631
632                 if [ -n "$firmware" ]; then
633                         firmware_install_module "$module" "$firmware"
634                 else
635                         firmware_files=$(find_firmware "$module")
636                         if [ -n "$firmware_files" ]; then
637                                 for file in $firmware_files; do
638                                         firmware_install_module "$module" "$file"
639                                 done
640                         fi
641                 fi
642
643                 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
644                 if [ -n "$usleep" ]; then
645                         echo "usleep $usleep" | add_linuxrc
646                 fi
647                 if [ "$module" = "scsi_wait_scan" ]; then
648                         if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
649                                 echo "rmmod scsi_wait_scan" | add_linuxrc
650                         fi
651                         # HACK HACK HACK until we get proper solution like waiting untill rootfs device appears
652                         if [ -z "$usleep" -a "$kernel_version_long" -ge "002006030" ]; then
653                                 echo "usleep 15000000" | add_linuxrc
654                         fi
655                 fi
656
657         done
658 }
659
660 # Generates /dev nodes based on /proc/partitions information.
661 # Needs /proc mounted.
662 # Can be called multiple times.
663 initrd_gen_devices() {
664         if is_yes "$proc_partitions"; then
665                 return
666         fi
667         proc_partitions=yes
668
669         mount_dev
670         add_linuxrc <<-'EOF'
671                 : 'Making device nodes'
672                 cat /proc/partitions | (
673                         # ignore first two lines: header, empty line
674                         read b; read b
675
676                         while read major minor blocks dev rest; do
677                                 node=/dev/$dev
678                                 mkdir -p ${node%/*}
679                                 [ -e $node ] || mknod $node b $major $minor
680                         done
681                 )
682         EOF
683 }
684
685
686 initrd_gen_setrootdev() {
687         debug "Adding rootfs finding based on kernel cmdline root= option support."
688         add_linuxrc <<-'EOF'
689                 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
690                         rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
691                         if [ -n "$rootnr" ]; then
692                                 echo "$rootnr" > /proc/sys/kernel/real-root-dev
693                         fi
694                 fi
695         EOF
696 }
697
698 initrd_gen_initramfs_switchroot() {
699         inst_d /newroot
700         if [ "$rootdev" = "/dev/nfs" ]; then
701                 echo "rootfs on NFS root=/dev/nfs"
702         else
703                 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
704         fi
705
706         # parse 'root=xxx' kernel commandline
707         # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
708         add_linuxrc <<-'EOF'
709                 device=/dev/no_partition_found
710                 eval "$(busybox awk -v c="$ROOT" '
711                         BEGIN {
712                                 num_pattern_short = "[0-9a-f][0-9a-f][0-9a-f]";
713                                 num_pattern = "[0-9a-f]" num_pattern_short;
714                                 dev_pattern = "[hms][a-z][a-z]([0-9])+";
715                                 partition = "no_partition_found";
716                                 min = -1; maj = -1;
717
718                                 sub("^0x", "", c);
719                                 if (c ~ "^" num_pattern_short "$") sub("^", "0", c);
720                                 if (c ~ "^" num_pattern  "$") {
721                                         maj = sprintf("%s",substr(c,1,2));
722                                         min = sprintf("%s",substr(c,3));
723                                 }
724                                 if (c ~ "^\/dev\/" dev_pattern "$") sub("^/dev/","", c);
725                                 if (c ~ "^" dev_pattern "$") partition = c;
726                         }
727
728                         $4 ~ partition { maj = $1; min = $2; }
729                         $1 ~ maj && $2 ~ min { partition = $4; }
730
731                         END {
732                                 if (maj >= 0 && min >= 0) {
733                                         printf("device=/dev/%s; maj=%s; min=%s;\n", partition, maj, min);
734                                 }
735                         }
736                         ' /proc/partitions)"
737                 if [ "$device" != '/dev/no_partition_found' -a ! -b $device ]; then
738                         mknod $device b $maj $min
739                 fi
740         EOF
741
742         add_linuxrc <<-EOF
743                 rootdev=$rootdev
744                 rootfs=$rootFs
745         EOF
746
747         add_linuxrc <<-'EOF'
748                 if [ "$device" = '/dev/no_partition_found' ]; then
749                         device=$rootdev
750                 fi
751
752                 mount -t $rootfs -r $device /newroot
753                 init="$(echo "$CMDLINE" | busybox awk '/init=\// { gsub(/.*init=/,NIL,$0); gsub(/ .*/,NIL,$0); print }')"
754                 if [ -z "$init" -o ! -x "/newroot$init" ]; then
755                         init=/sbin/init
756                 fi
757         EOF
758
759         umount_all
760         busybox_applet switch_root
761         add_linuxrc <<-'EOF'
762                 exec switch_root /newroot $init ${1:+"$@"}
763
764                 echo "Error! initramfs should not reach this place."
765                 echo "It probably means you've got old version of busybox, with broken"
766                 echo "initramfs support. Trying to boot anyway, but won't promise anything."
767
768                 exec chroot /newroot $init ${1:+"$@"}
769
770                 echo "Failed to chroot!"
771         EOF
772         # we need /init being real file, not symlink, otherwise the initramfs will
773         # not be ran by pid 1 which is required for switch_root
774         mv $DESTDIR/linuxrc $DESTDIR/init
775         ln -s init $DESTDIR/linuxrc
776 }
777
778 # find if $symbol exists in System.map $mapfile
779 sym_exists() {
780         local mapfile="$1"
781         local symbol="$2"
782         if [ ! -f $mapfile ]; then
783                 # missing mapfile (not a pld kernel?)
784                 return 1
785         fi
786
787         awk -vc=1 -vsymbol="$symbol" '$2 == "T" && $3 == symbol {c = 0} END {exit c}' $mapfile
788 }
789
790 # find best compressor (or forced one) for initrd
791 find_compressor() {
792         local mode="$1"
793         # the best compressor list
794         local compressors='xz lzma bzip2 gzip'
795
796         # a specified one, take it
797         if ! is_yes "$mode"; then
798                 compressors="$mode"
799         fi
800
801         debug "finding compressor: $compressors (via $mode)"
802         # check for compressor validity
803         local c prog map=/boot/System.map-$kernel
804         for c in $compressors; do
805                 case $c in
806                 xz)
807                         sym=unxz
808                         prog=/usr/bin/xz
809                         ;;
810                 lzma)
811                         sym=unlzma
812                         prog=/usr/bin/xz
813                         ;;
814                 bzip2)
815                         sym=bzip2
816                         prog=/usr/bin/bzip2
817                         ;;
818                 gzip)
819                         sym=gunzip
820                         prog=/bin/gzip
821                         ;;
822                 *)
823                         die "Unknown compressor $c"
824                         ;;
825                 esac
826                 if sym_exists $map $sym && [ -x $prog ]; then
827                         echo $c
828                         return
829                 fi
830         done
831
832         debug "using gzip for compressor (fallback)"
833         echo gzip
834 }
835
836 if [ -r /etc/sysconfig/geninitrd ]; then
837         . /etc/sysconfig/geninitrd
838 fi
839
840 if [ ! -f /proc/mounts ]; then
841         warn "/proc filesystem not mounted, may cause wrong results or failure."
842 fi
843
844 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs scsi
845
846 while [ $# -gt 0 ]; do
847         case $1 in
848         --fstab=*)
849                 fstab=${1#--fstab=}
850                 ;;
851         --fstab)
852                 fstab=$2
853                 shift
854                 ;;
855         --modules-conf=*)
856                 modulefile=${1#--modules-conf=}
857                 ;;
858         --modules-conf)
859                 modulefile=$2
860                 shift
861                 ;;
862         --with-bootsplash)
863                 BOOT_SPLASH=yes
864                 ;;
865         --without-bootsplash)
866                 BOOT_SPLASH=no
867                 ;;
868         --with-fbsplash)
869                 FB_SPLASH=yes
870                 ;;
871         --without-fbsplash)
872                 FB_SPLASH=no
873                 ;;
874         --with-fbcondecor)
875                 FB_CON_DECOR=yes
876                 ;;
877         --without-fbcondecor)
878                 FB_CON_DECOR=no
879                 ;;
880         --with-suspend)
881                 USE_SUSPEND=yes
882                 ;;
883         --without-suspend)
884                 USE_SUSPEND=no
885                 ;;
886         --with-suspend2 | --with-tuxonice)
887                 USE_TUXONICE=yes
888                 ;;
889         --without-suspend2 | --without-tuxonice)
890                 USE_TUXONICE=no
891                 ;;
892         --lvmversion=*)
893                 LVMTOOLSVERSION=${1#--lvmversion=}
894                 ;;
895         --lvmtoolsversion=*)
896                 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
897                 ;;
898         --lvmtoolsversion|--lvmversion)
899                 LVMTOOLSVERSION=$2
900                 shift
901                 ;;
902         --without-udev)
903                 USE_UDEV=no
904                 ;;
905         --with-udev)
906                 USE_UDEV=yes
907                 ;;
908         --without-dmraid)
909                 USE_DMRAID=no
910                 ;;
911         --without-multipath)
912                 USE_MULTIPATH=no
913                 ;;
914         --with-multipath=*)
915                 USE_MULTIPATH=${1#--with-multipath=}
916                 ;;
917         --without-blkid)
918                 USE_BLKID=no
919                 ;;
920         --without-luks)
921                 USE_LUKS=no
922                 ;;
923         --with=*)
924                 BASICMODULES="$BASICMODULES ${1#--with=}"
925                 ;;
926         --with)
927                 BASICMODULES="$BASICMODULES $2"
928                 shift
929                 ;;
930         --version)
931                 echo "$PROGRAM: version $VERSION"
932                 exit 0
933                 ;;
934         -v)
935                 verbose=-v
936                 ;;
937         --compress)
938                 COMPRESS=$2
939                 ;;
940         --compress=*)
941                 COMPRESS="${1#--compress=}"
942                 ;;
943         --nocompress)
944                 COMPRESS=no
945                 ;;
946         --ifneeded)
947                 ifneeded=1
948                 ;;
949         -f)
950                 force=1
951                 ;;
952         --preload=*)
953                 PREMODS="$PREMODS ${1#--preload=}"
954                 ;;
955         --preload)
956                 PREMODS="$PREMODS $2"
957                 shift
958                 ;;
959         --fs=* | --fs)
960                 die "--fs option is obsoleted. Use --initrdfs instead"
961                 ;;
962         --initrdfs=*)
963                 INITRDFS=${1#--initrdfs=}
964                 ;;
965         --initrdfs)
966                 INITRDFS=$2
967                 shift
968                 ;;
969         --image-version)
970                 img_vers=yes
971                 ;;
972         --ide-only-root)
973                 ide_only_root="yes"
974                 ;;
975         *)
976                 if [ -z "$target" ]; then
977                         target="$1"
978                 elif [ -z "$kernel" ]; then
979                         kernel="$1"
980                 else
981                         usage >&2
982                         exit 1
983                 fi
984                 ;;
985         esac
986
987         shift
988 done
989
990 if [ -z "$target" -o -z "$kernel" ]; then
991         usage >&2
992         exit 1
993 fi
994
995 # main()
996 if [ "$(id -u)" != 0 ]; then
997         die "You need to be root to generate initrd"
998 fi
999
1000 if [ -d /usr/lib64 ]; then
1001         _lib=lib64
1002 else
1003         _lib=lib
1004 fi
1005
1006 initrd_dir=/usr/$_lib/initrd
1007 kernel_version=$(echo "$kernel" | awk -F. '{print sprintf("%03d%03d",$1,$2)}')
1008 kernel_version_long=$(echo "$kernel" | awk -F. '{print sprintf("%03d%03d%03d",$1,$2,$3)}')
1009
1010 debug "# $RCSID"
1011 debug "Using _lib: $_lib"
1012 debug "Using initrd_dir: $initrd_dir"
1013
1014 busybox=$(find_tool $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1015
1016 # we setup mods after parsing command line args
1017 geninitrd_setup_mods
1018
1019 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1020         warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1021 fi
1022
1023 if [ -z "$INITRDFS" ]; then
1024         if [ -n "$FS" ]; then
1025                 # FS= can came only via /etc/sysconfig/geninitrd likely?
1026                 die "FS configuration option is obsoleted. Use INITRDFS instead"
1027         fi
1028
1029         # default value
1030         if [ "$kernel_version" -ge "002005" ]; then
1031                 INITRDFS="initramfs"
1032         else
1033                 INITRDFS="rom"
1034         fi
1035 fi
1036
1037 case "$INITRDFS" in
1038   ext2)
1039         [ -x /sbin/mke2fs ] || die "/sbin/mke2fs is missing"
1040         ;;
1041   rom|romfs)
1042         [ -x /sbin/genromfs ] || die "/sbin/genromfs is missing"
1043         ;;
1044   cram|cramfs)
1045         [ -x /sbin/mkcramfs ] || die "/sbin/mkcramfs is missing"
1046         ;;
1047   initramfs)
1048         [ -x /bin/cpio ] || die "/bin/cpio is missing"
1049         [ -x /usr/bin/find ] || die "/usr/bin/find is missing"
1050         ;;
1051   *)
1052         die "Filesystem $INITRDFS on initrd is not supported"
1053         ;;
1054 esac
1055
1056 if [ -L "$target" ]; then
1057         target=$(readlink -f "$target")
1058 fi
1059
1060 if [ -n "$img_vers" ]; then
1061         target="$target-$kernel"
1062 fi
1063
1064 if [ -z "$force" -a -f "$target" ]; then
1065         die "$target already exists."
1066 fi
1067
1068 if [ ! -d "/lib/modules/$kernel" ]; then
1069         die "/lib/modules/$kernel is not a directory."
1070 fi
1071
1072 if [ "$kernel_version" -ge "002005" ]; then
1073         modext=".ko"
1074 fi
1075
1076 cache_modprobe_conf
1077
1078 for n in $PREMODS; do
1079         find_module "$n"
1080 done
1081
1082 if [ "$FBMODULE" ]; then
1083         find_module "$FBMODULE"
1084 fi
1085
1086 # allow forcing loading SCSI and/or IDE modules
1087 # XXX: where ADDSCSI cames from? drop?
1088 if is_yes "$ADDSCSI"; then
1089         find_modules_scsi
1090 fi
1091
1092 # XXX: where ADDIDE cames from? drop?
1093 if is_yes "$ADDIDE"; then
1094         find_modules_ide
1095 fi
1096
1097 if is_yes "$USE_SUSPEND"; then
1098         find_modules_suspend
1099 fi
1100
1101 find_root "$fstab" || exit
1102 debug "Using $rootdev as device for rootfs"
1103
1104 find_modules_for_devpath "$rootdev"
1105
1106 # if USE_MULTIPATH is path to device, scan that too
1107 # this is to bootstrap multipath setup into initrd.
1108 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1109         find_modules_multipath $USE_MULTIPATH
1110 fi
1111
1112 find_module "-$rootFs"
1113
1114 for n in $BASICMODULES; do
1115         find_module "$n"
1116 done
1117
1118 if is_yes "$USE_TUXONICE"; then
1119         find_module "-lzf"
1120 fi
1121
1122 find_modules_fbsplash
1123
1124 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1125         debug "No modules are needed -- not building initrd image."
1126         exit 0
1127 fi
1128
1129 debug "Building initrd..."
1130 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1131 RCFILE="$DESTDIR/linuxrc"
1132 > "$RCFILE"
1133 chmod a+rx "$RCFILE"
1134 ln -s linuxrc $DESTDIR/init
1135
1136 # create dirs that we really need
1137 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,sys}
1138
1139 modules_install "$MODULES"
1140
1141 # mknod'ing the devices instead of copying them works both with and
1142 # without devfs...
1143 mknod "$DESTDIR/dev/console" c 5 1
1144 mknod "$DESTDIR/dev/null" c 1 3
1145 mknod "$DESTDIR/dev/zero" c 1 5
1146 mknod "$DESTDIR/dev/urandom" c 1 9
1147
1148 inst_exec $busybox /bin/initrd-busybox
1149 ln -s initrd-busybox $DESTDIR/bin/sh
1150 # for older busyboxes who had /bin/busybox as EXEPATH
1151 ln -s initrd-busybox $DESTDIR/bin/busybox
1152
1153 add_linuxrc <<EOF
1154 #!/bin/sh
1155 # initrd generated by:
1156 # $RCSID
1157
1158 EOF
1159 mount_proc
1160 add_linuxrc <<-'EOF'
1161         read CMDLINE < /proc/cmdline; export CMDLINE
1162
1163         for arg in $CMDLINE; do
1164                 if [ "${arg}" = "debuginitrd" ]; then
1165                         DEBUGINITRD=yes
1166                 fi
1167                 if [ "${arg##debuginitrd=}" != "${arg}" ]; then
1168                         DEBUGINITRD=${arg##debuginitrd=}
1169                 fi
1170                 if [ "${arg##root=}" != "${arg}" ]; then
1171                         ROOT=${arg##root=}
1172                 fi
1173         done
1174
1175         # make debugshell() invoke subshell if $DEBUGINITRD=sh
1176         if [ "$DEBUGINITRD" = "sh" ]; then
1177                 debugshell() {
1178 EOF
1179 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1180 add_linuxrc <<-'EOF'
1181         echo "debug shell disabled by /etc/sysconfig/system:RUN_SULOGIN_ON_ERR setting"
1182 EOF
1183 else
1184 add_linuxrc <<-'EOF'
1185         sh
1186 EOF
1187 fi
1188 add_linuxrc <<-'EOF'
1189                 }
1190         else
1191                 debugshell() {
1192                         :
1193                 }
1194         fi
1195
1196         if [ "$DEBUGINITRD" ]; then
1197                 set -x
1198         fi
1199 EOF
1200
1201 modules_add_linuxrc $MODULES
1202
1203 # TODO: rewrite for busybox
1204 #if [ -n "$loopDev" ]; then
1205 #       if [ ! -d /initrd ]; then
1206 #               mkdir /initrd
1207 #       fi
1208 #
1209 #       cp -a "$loopDev" "$DESTDIR/dev"
1210 #       cp -a "$rootdev" "$DESTDIR/dev"
1211 #       echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1212 #       echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1213 #       echo "echo Setting up loopback device $rootdev" >> $RCFILE
1214 #       echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1215 #fi
1216
1217 if is_yes "$USE_UDEV"; then
1218         initrd_gen_udev
1219 fi
1220
1221 if is_yes "$USE_TUXONICE"; then
1222         initrd_gen_tuxonice
1223 fi
1224
1225 find_modules_uvesafb
1226 initrd_gen_uvesafb
1227
1228 if is_yes "$have_luks"; then
1229         initrd_gen_luks
1230 fi
1231
1232 if is_yes "$have_dmraid"; then
1233         initrd_gen_dmraid
1234 fi
1235
1236 if is_yes "$have_multipath"; then
1237         initrd_gen_multipath
1238 fi
1239
1240 if is_yes "$USE_BLKID"; then
1241         initrd_gen_blkid
1242 fi
1243
1244 if is_yes "$have_nfs"; then
1245         initrd_gen_nfs
1246 elif is_yes "$have_md"; then
1247         initrd_gen_md
1248         if is_yes "$have_lvm"; then
1249                 initrd_gen_lvm
1250         else
1251                 initrd_gen_setrootdev
1252         fi
1253 elif is_yes "$have_lvm"; then
1254         initrd_gen_lvm
1255 else
1256         initrd_gen_setrootdev
1257 fi
1258
1259 if is_yes "$USE_SUSPEND"; then
1260         initrd_gen_suspend
1261 fi
1262
1263 # additional devs always needed
1264 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1265
1266 if is_yes "$USE_UDEV"; then
1267         initrd_gen_stop_udevd
1268 fi
1269
1270 if [ "$INITRDFS" = "initramfs" ]; then
1271         initrd_gen_initramfs_switchroot
1272 else
1273         umount_all
1274 fi
1275
1276 if is_yes "$FB_SPLASH"; then
1277         initrd_gen_fbsplash
1278 fi
1279
1280 if is_yes "$FB_CON_DECOR"; then
1281         initrd_gen_fbcondecor
1282 fi
1283
1284 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1285
1286 debug "Creating $INITRDFS image $IMAGE"
1287 case "$INITRDFS" in
1288   ext2)
1289         dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1290         mke2fs -q -F -b 1024 -m 0 "$IMAGE" 2>/dev/null 1>&2
1291         tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1292
1293         local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1294         debug "Mounting ext2 image $IMAGE to $tmpmnt"
1295         mount -o loop -t ext2 "$IMAGE" "$tmpmnt"
1296         # We don't need this directory, so let's save space
1297         rm -rf "$tmpmnt"/lost+found
1298
1299         debug "Copy recursively $DESTDIR -> $tmpmnt"
1300         cp -a $DESTDIR/* $tmpmnt
1301         umount "$IMAGE"
1302         rmdir "$tmpmnt"
1303
1304         ;;
1305   rom|romfs)
1306         genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD initrd for kernel $kernel"
1307         ;;
1308   cram|cramfs)
1309         mkcramfs "$DESTDIR" "$IMAGE"
1310         ;;
1311   initramfs)
1312         (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1313         ;;
1314   *)
1315         die "Filesystem $INITRDFS not supported by $PROGRAM"
1316 esac
1317
1318 # TODO: figure out this automatically
1319 CONFIG_BLK_DEV_RAM_SIZE=4096
1320
1321 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1322 debug   "image size: $IMAGESIZE KiB ($DESTDIR)"
1323 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1324         warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1325 fi
1326
1327 if ! is_no "$COMPRESS"; then
1328         tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1329         compressor=$(find_compressor "$COMPRESS")
1330         debug "Compressing $target with $compressor"
1331
1332         # TODO: the image name (specified from kernel.spec) already contains
1333         # extension, which is .gz most of the time.
1334         case "$compressor" in
1335         xz)
1336                 # don't use -9 here since kernel won't understand it
1337                 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp"
1338                 ;;
1339         lzma)
1340                 xz --format=lzma -9 < "$IMAGE" > "$tmp"
1341                 ;;
1342         bzip2)
1343                 bzip2 -9 < "$IMAGE" > "$tmp"
1344                 ;;
1345         gzip)
1346                 gzip -9 < "$IMAGE" > "$tmp"
1347                 ;;
1348         esac
1349         mv -f "$tmp" "$target"
1350 else
1351         cp -a "$IMAGE" "$target"
1352 fi
1353
1354 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1355 if is_yes "$BOOT_SPLASH"; then
1356         initrd_gen_bootsplash "$target"
1357 fi
1358
1359 rm -rf "$DESTDIR" "$IMAGE"
1360
1361 # vim:ts=4:sw=4:noet:fdm=marker
This page took 0.155192 seconds and 4 git commands to generate.