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