]> git.pld-linux.org Git - projects/geninitrd.git/blob - geninitrd
Use kernel ready compression settings for xz.
[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                 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='xz 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                 xz)
806                         sym=unxz
807                         prog=/usr/bin/xz
808                         ;;
809                 lzma)
810                         sym=unlzma
811                         prog=/usr/bin/xz
812                         ;;
813                 bzip2)
814                         sym=bzip2
815                         prog=/usr/bin/bzip2
816                         ;;
817                 gzip)
818                         sym=gunzip
819                         prog=/bin/gzip
820                         ;;
821                 *)
822                         die "Unknown compressor $c"
823                         ;;
824                 esac
825                 if sym_exists $map $sym && [ -x $prog ]; then
826                         echo $c
827                         return
828                 fi
829         done
830
831         debug "using gzip for compressor (fallback)"
832         echo gzip
833 }
834
835 if [ -r /etc/sysconfig/geninitrd ]; then
836         . /etc/sysconfig/geninitrd
837 fi
838
839 if [ ! -f /proc/mounts ]; then
840         warn "/proc filesystem not mounted, may cause wrong results or failure."
841 fi
842
843 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs scsi
844
845 while [ $# -gt 0 ]; do
846         case $1 in
847         --fstab=*)
848                 fstab=${1#--fstab=}
849                 ;;
850         --fstab)
851                 fstab=$2
852                 shift
853                 ;;
854         --modules-conf=*)
855                 modulefile=${1#--modules-conf=}
856                 ;;
857         --modules-conf)
858                 modulefile=$2
859                 shift
860                 ;;
861         --with-bootsplash)
862                 BOOT_SPLASH=yes
863                 ;;
864         --without-bootsplash)
865                 BOOT_SPLASH=no
866                 ;;
867         --with-fbsplash)
868                 FB_SPLASH=yes
869                 ;;
870         --without-fbsplash)
871                 FB_SPLASH=no
872                 ;;
873         --with-fbcondecor)
874                 FB_CON_DECOR=yes
875                 ;;
876         --without-fbcondecor)
877                 FB_CON_DECOR=no
878                 ;;
879         --with-suspend)
880                 USE_SUSPEND=yes
881                 ;;
882         --without-suspend)
883                 USE_SUSPEND=no
884                 ;;
885         --with-suspend2 | --with-tuxonice)
886                 USE_TUXONICE=yes
887                 ;;
888         --without-suspend2 | --without-tuxonice)
889                 USE_TUXONICE=no
890                 ;;
891         --lvmversion=*)
892                 LVMTOOLSVERSION=${1#--lvmversion=}
893                 ;;
894         --lvmtoolsversion=*)
895                 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
896                 ;;
897         --lvmtoolsversion|--lvmversion)
898                 LVMTOOLSVERSION=$2
899                 shift
900                 ;;
901         --without-udev)
902                 USE_UDEV=no
903                 ;;
904         --with-udev)
905                 USE_UDEV=yes
906                 ;;
907         --without-dmraid)
908                 USE_DMRAID=no
909                 ;;
910         --without-multipath)
911                 USE_MULTIPATH=no
912                 ;;
913         --with-multipath=*)
914                 USE_MULTIPATH=${1#--with-multipath=}
915                 ;;
916         --without-blkid)
917                 USE_BLKID=no
918                 ;;
919         --without-luks)
920                 USE_LUKS=no
921                 ;;
922         --with=*)
923                 BASICMODULES="$BASICMODULES ${1#--with=}"
924                 ;;
925         --with)
926                 BASICMODULES="$BASICMODULES $2"
927                 shift
928                 ;;
929         --version)
930                 echo "$PROGRAM: version $VERSION"
931                 exit 0
932                 ;;
933         -v)
934                 verbose=-v
935                 ;;
936         --compress)
937                 COMPRESS=$2
938                 ;;
939         --compress=*)
940                 COMPRESS="${1#--compress=}"
941                 ;;
942         --nocompress)
943                 COMPRESS=no
944                 ;;
945         --ifneeded)
946                 ifneeded=1
947                 ;;
948         -f)
949                 force=1
950                 ;;
951         --preload=*)
952                 PREMODS="$PREMODS ${1#--preload=}"
953                 ;;
954         --preload)
955                 PREMODS="$PREMODS $2"
956                 shift
957                 ;;
958         --fs=* | --fs)
959                 die "--fs option is obsoleted. Use --initrdfs instead"
960                 ;;
961         --initrdfs=*)
962                 INITRDFS=${1#--initrdfs=}
963                 ;;
964         --initrdfs)
965                 INITRDFS=$2
966                 shift
967                 ;;
968         --image-version)
969                 img_vers=yes
970                 ;;
971         --ide-only-root)
972                 ide_only_root="yes"
973                 ;;
974         *)
975                 if [ -z "$target" ]; then
976                         target="$1"
977                 elif [ -z "$kernel" ]; then
978                         kernel="$1"
979                 else
980                         usage >&2
981                         exit 1
982                 fi
983                 ;;
984         esac
985
986         shift
987 done
988
989 if [ -z "$target" -o -z "$kernel" ]; then
990         usage >&2
991         exit 1
992 fi
993
994 # main()
995 if [ "$(id -u)" != 0 ]; then
996         die "You need to be root to generate initrd"
997 fi
998
999 if [ -d /usr/lib64 ]; then
1000         _lib=lib64
1001 else
1002         _lib=lib
1003 fi
1004
1005 initrd_dir=/usr/$_lib/initrd
1006 kernel_version=$(echo "$kernel" | awk -F. '{print sprintf("%03d%03d",$1,$2)}')
1007 kernel_version_long=$(echo "$kernel" | awk -F. '{print sprintf("%03d%03d%03d",$1,$2,$3)}')
1008
1009 debug "# $RCSID"
1010 debug "Using _lib: $_lib"
1011 debug "Using initrd_dir: $initrd_dir"
1012
1013 busybox=$(find_tool $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1014
1015 # we setup mods after parsing command line args
1016 geninitrd_setup_mods
1017
1018 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1019         warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1020 fi
1021
1022 if [ -z "$INITRDFS" ]; then
1023         if [ -n "$FS" ]; then
1024                 # FS= can came only via /etc/sysconfig/geninitrd likely?
1025                 die "FS configuration option is obsoleted. Use INITRDFS instead"
1026         fi
1027
1028         # default value
1029         if [ "$kernel_version" -ge "002005" ]; then
1030                 INITRDFS="initramfs"
1031         else
1032                 INITRDFS="rom"
1033         fi
1034 fi
1035
1036 case "$INITRDFS" in
1037   ext2)
1038         [ -x /sbin/mke2fs ] || die "/sbin/mke2fs is missing"
1039         ;;
1040   rom|romfs)
1041         [ -x /sbin/genromfs ] || die "/sbin/genromfs is missing"
1042         ;;
1043   cram|cramfs)
1044         [ -x /sbin/mkcramfs ] || die "/sbin/mkcramfs is missing"
1045         ;;
1046   initramfs)
1047         [ -x /bin/cpio ] || die "/bin/cpio is missing"
1048         [ -x /usr/bin/find ] || die "/usr/bin/find is missing"
1049         ;;
1050   *)
1051         die "Filesystem $INITRDFS on initrd is not supported"
1052         ;;
1053 esac
1054
1055 if [ -L "$target" ]; then
1056         target=$(readlink -f "$target")
1057 fi
1058
1059 if [ -n "$img_vers" ]; then
1060         target="$target-$kernel"
1061 fi
1062
1063 if [ -z "$force" -a -f "$target" ]; then
1064         die "$target already exists."
1065 fi
1066
1067 if [ ! -d "/lib/modules/$kernel" ]; then
1068         die "/lib/modules/$kernel is not a directory."
1069 fi
1070
1071 if [ "$kernel_version" -ge "002005" ]; then
1072         modext=".ko"
1073 fi
1074
1075 cache_modprobe_conf
1076
1077 for n in $PREMODS; do
1078         find_module "$n"
1079 done
1080
1081 if [ "$FBMODULE" ]; then
1082         find_module "$FBMODULE"
1083 fi
1084
1085 # allow forcing loading SCSI and/or IDE modules
1086 # XXX: where ADDSCSI cames from? drop?
1087 if is_yes "$ADDSCSI"; then
1088         find_modules_scsi
1089 fi
1090
1091 # XXX: where ADDIDE cames from? drop?
1092 if is_yes "$ADDIDE"; then
1093         find_modules_ide
1094 fi
1095
1096 if is_yes "$USE_SUSPEND"; then
1097         find_modules_suspend
1098 fi
1099
1100 find_root "$fstab" || exit
1101 debug "Using $rootdev as device for rootfs"
1102
1103 find_modules_for_devpath "$rootdev"
1104
1105 # if USE_MULTIPATH is path to device, scan that too
1106 # this is to bootstrap multipath setup into initrd.
1107 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1108         find_modules_multipath $USE_MULTIPATH
1109 fi
1110
1111 find_module "-$rootFs"
1112
1113 for n in $BASICMODULES; do
1114         find_module "$n"
1115 done
1116
1117 if is_yes "$USE_TUXONICE"; then
1118         find_module "-lzf"
1119 fi
1120
1121 find_modules_fbsplash
1122
1123 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1124         debug "No modules are needed -- not building initrd image."
1125         exit 0
1126 fi
1127
1128 debug "Building initrd..."
1129 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1130 RCFILE="$DESTDIR/linuxrc"
1131 > "$RCFILE"
1132 chmod a+rx "$RCFILE"
1133 ln -s linuxrc $DESTDIR/init
1134
1135 # create dirs that we really need
1136 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,sys}
1137
1138 modules_install "$MODULES"
1139
1140 # mknod'ing the devices instead of copying them works both with and
1141 # without devfs...
1142 mknod "$DESTDIR/dev/console" c 5 1
1143 mknod "$DESTDIR/dev/null" c 1 3
1144 mknod "$DESTDIR/dev/zero" c 1 5
1145 mknod "$DESTDIR/dev/urandom" c 1 9
1146
1147 inst_exec $busybox /bin/initrd-busybox
1148 ln -s initrd-busybox $DESTDIR/bin/sh
1149 # for older busyboxes who had /bin/busybox as EXEPATH
1150 ln -s initrd-busybox $DESTDIR/bin/busybox
1151
1152 add_linuxrc <<EOF
1153 #!/bin/sh
1154 # initrd generated by:
1155 # $RCSID
1156
1157 EOF
1158 mount_proc
1159 add_linuxrc <<-'EOF'
1160         read CMDLINE < /proc/cmdline; export CMDLINE
1161
1162         for arg in $CMDLINE; do
1163                 if [ "${arg}" = "debuginitrd" ]; then
1164                         DEBUGINITRD=yes
1165                 fi
1166                 if [ "${arg##debuginitrd=}" != "${arg}" ]; then
1167                         DEBUGINITRD=${arg##debuginitrd=}
1168                 fi
1169                 if [ "${arg##root=}" != "${arg}" ]; then
1170                         ROOT=${arg##root=}
1171                 fi
1172         done
1173
1174         # make debugshell() invoke subshell if $DEBUGINITRD=sh
1175         if [ "$DEBUGINITRD" = "sh" ]; then
1176                 debugshell() {
1177 EOF
1178 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1179 add_linuxrc <<-'EOF'
1180         echo "debug shell disabled by /etc/sysconfig/system:RUN_SULOGIN_ON_ERR setting"
1181 EOF
1182 else
1183 add_linuxrc <<-'EOF'
1184         sh
1185 EOF
1186 fi
1187 add_linuxrc <<-'EOF'
1188                 }
1189         else
1190                 debugshell() {
1191                         :
1192                 }
1193         fi
1194
1195         if [ "$DEBUGINITRD" ]; then
1196                 set -x
1197         fi
1198 EOF
1199
1200 modules_add_linuxrc $MODULES
1201
1202 # TODO: rewrite for busybox
1203 #if [ -n "$loopDev" ]; then
1204 #       if [ ! -d /initrd ]; then
1205 #               mkdir /initrd
1206 #       fi
1207 #
1208 #       cp -a "$loopDev" "$DESTDIR/dev"
1209 #       cp -a "$rootdev" "$DESTDIR/dev"
1210 #       echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1211 #       echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1212 #       echo "echo Setting up loopback device $rootdev" >> $RCFILE
1213 #       echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1214 #fi
1215
1216 if is_yes "$USE_UDEV"; then
1217         initrd_gen_udev
1218 fi
1219
1220 if is_yes "$USE_TUXONICE"; then
1221         initrd_gen_tuxonice
1222 fi
1223
1224 find_modules_uvesafb
1225 initrd_gen_uvesafb
1226
1227 if is_yes "$have_luks"; then
1228         initrd_gen_luks
1229 fi
1230
1231 if is_yes "$have_dmraid"; then
1232         initrd_gen_dmraid
1233 fi
1234
1235 if is_yes "$have_multipath"; then
1236         initrd_gen_multipath
1237 fi
1238
1239 if is_yes "$USE_BLKID"; then
1240         initrd_gen_blkid
1241 fi
1242
1243 if is_yes "$have_nfs"; then
1244         initrd_gen_nfs
1245 elif is_yes "$have_md"; then
1246         initrd_gen_md
1247         if is_yes "$have_lvm"; then
1248                 initrd_gen_lvm
1249         else
1250                 initrd_gen_setrootdev
1251         fi
1252 elif is_yes "$have_lvm"; then
1253         initrd_gen_lvm
1254 else
1255         initrd_gen_setrootdev
1256 fi
1257
1258 if is_yes "$USE_SUSPEND"; then
1259         initrd_gen_suspend
1260 fi
1261
1262 # additional devs always needed
1263 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1264
1265 if is_yes "$USE_UDEV"; then
1266         initrd_gen_stop_udevd
1267 fi
1268
1269 if [ "$INITRDFS" = "initramfs" ]; then
1270         initrd_gen_initramfs_switchroot
1271 else
1272         umount_all
1273 fi
1274
1275 if is_yes "$FB_SPLASH"; then
1276         initrd_gen_fbsplash
1277 fi
1278
1279 if is_yes "$FB_CON_DECOR"; then
1280         initrd_gen_fbcondecor
1281 fi
1282
1283 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1284
1285 debug "Creating $INITRDFS image $IMAGE"
1286 case "$INITRDFS" in
1287   ext2)
1288         dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1289         mke2fs -q -F -b 1024 -m 0 "$IMAGE" 2>/dev/null 1>&2
1290         tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1291
1292         local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1293         debug "Mounting ext2 image $IMAGE to $tmpmnt"
1294         mount -o loop -t ext2 "$IMAGE" "$tmpmnt"
1295         # We don't need this directory, so let's save space
1296         rm -rf "$tmpmnt"/lost+found
1297
1298         debug "Copy recursively $DESTDIR -> $tmpmnt"
1299         cp -a $DESTDIR/* $tmpmnt
1300         umount "$IMAGE"
1301         rmdir "$tmpmnt"
1302
1303         ;;
1304   rom|romfs)
1305         genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD initrd for kernel $kernel"
1306         ;;
1307   cram|cramfs)
1308         mkcramfs "$DESTDIR" "$IMAGE"
1309         ;;
1310   initramfs)
1311         (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1312         ;;
1313   *)
1314         die "Filesystem $INITRDFS not supported by $PROGRAM"
1315 esac
1316
1317 # TODO: figure out this automatically
1318 CONFIG_BLK_DEV_RAM_SIZE=4096
1319
1320 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1321 debug   "image size: $IMAGESIZE KiB ($DESTDIR)"
1322 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1323         warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1324 fi
1325
1326 if ! is_no "$COMPRESS"; then
1327         tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1328         compressor=$(find_compressor "$COMPRESS")
1329         debug "Compressing $target with $compressor"
1330
1331         # TODO: the image name (specified from kernel.spec) already contains
1332         # extension, which is .gz most of the time.
1333         case "$compressor" in
1334         xz)
1335                 # don't use -9 here since kernel won't understand it
1336                 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp"
1337                 ;;
1338         lzma)
1339                 xz --format=lzma -9 < "$IMAGE" > "$tmp"
1340                 ;;
1341         bzip2)
1342                 bzip2 -9 < "$IMAGE" > "$tmp"
1343                 ;;
1344         gzip)
1345                 gzip -9 < "$IMAGE" > "$tmp"
1346                 ;;
1347         esac
1348         mv -f "$tmp" "$target"
1349 else
1350         cp -a "$IMAGE" "$target"
1351 fi
1352
1353 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1354 if is_yes "$BOOT_SPLASH"; then
1355         initrd_gen_bootsplash "$target"
1356 fi
1357
1358 rm -rf "$DESTDIR" "$IMAGE"
1359
1360 # vim:ts=4:sw=4:noet:fdm=marker
This page took 0.147376 seconds and 4 git commands to generate.