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