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