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