]> git.pld-linux.org Git - projects/geninitrd.git/blob - geninitrd
0a422ee4c9820f1517773ed0d09d71f1de6f3eaa
[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 VERSION='devel'
11 PROGRAM=${0##*/}
12
13 . /etc/rc.d/init.d/functions
14 . /lib/geninitrd/functions
15 . /etc/sysconfig/system
16
17 # list of geninitrd modules which need setup routine after commandline args parsing
18 GENINITRD_MODS=""
19 COMPRESS=yes
20 LILO_MICROCODE=yes
21 STRIP=/usr/bin/strip
22 target=""
23 kernel=""
24 force=""
25 verbose=""
26 MODULES_TO_INSTALL=""
27 MODULES_TO_LOAD=""
28 img_vers=""
29 fstab=/etc/fstab
30 modext=.o
31 rootdev_nr=0
32 # device node for rootfs from fstab
33 rootdev=""
34
35 # internal variables
36 # is /dev on tmpfs
37 dev_mounted=no
38 # is /proc mounted
39 proc_mounted=no
40 # is /sys mounted
41 sys_mounted=no
42 # is /tmp mounted on tmpfs
43 tmp_mounted=no
44
45 # are /dev nodes already created from /proc/devices info?
46 proc_partitions=no
47
48 usage() {
49         echo "Usage: $PROGRAM [--version] [-v] [-f] [--ifneeded] [--preload <module>]"
50         echo "       [--with=<module>] [--image-version] [--fstab=<fstab>] [--nocompress]"
51         echo "       [--compress=yes|zstd|xz|lzma|bzip2|gzip|lzo|lz4]"
52         echo "       [--nostrip ] [--strip PATH/strip] [--strip=PATH/strip]"
53         echo "       [--initrdfs=rom|initramfs|ext2|cram] [--modules-conf=<modules.conf>]"
54         echo "       [--with-bootsplash] [--without-bootsplash]"
55         echo "       [--with-fbsplash] [--without-fbsplash]"
56         echo "       [--with-fbcondecor] [--without-fbcondecor]"
57         echo "       [--lvmtoolsversion=1|2] [--with-udev] [--without-udev]"
58         echo "       [--with-suspend] [--without-suspend]"
59         echo "       [--with-tuxonice] [--without-tuxonice]"
60         echo "       [--without-dmraid]"
61         echo "       [--with-multipath=DEVPATH] [--without-multipath]"
62         echo "       [--without-blkid] [--without-luks]"
63         echo "       <initrd-image> <kernel-version>"
64         echo ""
65         echo "Example:"
66
67         local kdir kver dir=${target:-/boot}
68         for kdir in /lib/modules/*; do
69                 [ -d $kdir ] || continue
70                 kver=${kdir##*/}
71                 echo "  $0 -f --initrdfs=initramfs $dir/initrd-$kver.gz $kver $verbose"
72         done | sort -V
73 }
74
75 msg() {
76         echo "$PROGRAM: $*"
77 }
78
79 warn() {
80         msg "WARNING: $*" >&2
81 }
82
83 verbose() {
84         [ -n "$verbose" ] && msg "$*" >&3
85 }
86
87 debug() {
88         [ x"$verbose" = x"-v -v" ] && msg "$*" >&3
89 }
90
91 # add initrd code to print to kmsg
92 # @param string message
93 # @param int loglevel. defaults to "6" (info)
94 # Log levels can be:
95 # Name          String  Meaning
96 # KERN_EMERG    "0"     Emergency messages, system is about to crash or is unstable
97 # KERN_ALERT    "1"     Something bad happened and action must be taken immediately
98 # KERN_CRIT     "2"     A critical condition occurred like a serious hardware/software failure
99 # KERN_ERR      "3"     An error condition, often used by drivers to indicate difficulties with the hardware
100 # KERN_WARNING  "4"     A warning, meaning nothing serious by itself but might indicate problems
101 # KERN_NOTICE   "5"     Nothing serious, but notably nevertheless. Often used to report security events.
102 # KERN_INFO     "6"     Informational message e.g. startup information at driver initialization
103 # KERN_DEBUG    "7"     Debug messages
104 # KERN_CONT     "c"     "continued" line of log printout (only done after a line that had no enclosing \n)
105 kmsg() {
106         local msg="$1" level=${2:-6}
107         echo "echo '<$level>$msg' > /dev/kmsg" | add_linuxrc
108 }
109
110 # aborts program abnormally
111 die() {
112         local rc=${2:-1}
113         msg "ERROR: $1" >&2
114         exit $rc
115 }
116
117 # find program from specified paths
118 find_tool() {
119         local x p b n
120         local paths="$initrd_dirs /bin /sbin /usr/bin /usr/sbin"
121         for x in "$@"; do
122                 debug "find_tool: checking $x"
123                 if [ -x "$x" ]; then
124                         echo $x
125                         verbose "find_tool: found $x"
126                         return 0
127                 fi
128                 n="$x"
129                 for p in $paths; do
130                         b=$(basename $x)
131                         debug "find_tool: checking $p/$b"
132                         if [ -x "$p/$b" ]; then
133                                 echo $p/$b
134                                 verbose "find_tool: found $p/$b"
135                                 return 0
136                         fi
137                         n="$n $p/$b"
138                 done
139         done
140         debug "find_tool: did not find any of: $n"
141         return 1
142 }
143
144 # loads geninitrd modules
145 geninitrd_load_mods() {
146         local mod
147         for mod in "$@"; do
148                 if [ ! -f /lib/geninitrd/mod-$mod.sh ]; then
149                         die "$mod geninitrd module can't be loaded"
150                 fi
151                 . /lib/geninitrd/mod-$mod.sh
152
153                 GENINITRD_MODS="$GENINITRD_MODS $mod"
154         done
155 }
156
157 # setup geninitrd modules
158 geninitrd_setup_mods() {
159         local mod
160
161         for mod in $GENINITRD_MODS; do
162                 debug "# $mod"
163
164                 # some mods want init
165                 if type setup_mod_$mod > /dev/null; then
166                         eval setup_mod_$mod
167                 fi
168         done
169 }
170
171 # append text to /linuxrc
172 # takes STDIN as input
173 add_linuxrc() {
174         cat >> "$RCFILE"
175 }
176
177 # generate code to mount /dev on tmpfs and create initial nodes
178 # can be called multiple times. /dev is cleaned up (umounted) automatically at
179 # the end of script.
180 mount_dev() {
181         # we already generated tmpfs code; return
182         if is_yes "$dev_mounted"; then
183                 return
184         fi
185
186         dev_mounted=yes
187
188         busybox_applet mount mknod mkdir
189         add_linuxrc <<-EOF
190                 : 'Creating /dev'
191                 if ! mount -t devtmpfs -o mode=0755,nosuid devtmpfs /dev > /dev/null 2>&1; then
192                         mount -o mode=0755,nosuid -t tmpfs tmpfs /dev
193                         mknod -m 600 /dev/console c 5 1
194                         mknod -m 666 /dev/null c 1 3
195                         mknod -m 666 /dev/zero c 1 5
196                         mknod -m 666 /dev/random c 1 8
197                         mknod -m 600 /dev/snapshot c 10 231
198                         mknod -m 666 /dev/urandom c 1 9
199                         mknod -m 666 /dev/ptmx c 5 2
200                         mknod -m 644 /dev/kmsg c 1 11
201                 fi
202                 mkdir /dev/pts
203                 mkdir /dev/shm
204         EOF
205 }
206
207 # load font
208 load_font() {
209         local font
210         [ ! -r /etc/sysconfig/console ] && return
211         . /etc/sysconfig/console
212         if [ -n "$CONSOLEFONT" ]; then
213                 font=$(ls -1 /lib/kbd/consolefonts/${CONSOLEFONT}*.gz 2> /dev/null)
214                 if [ -n "$font" ]; then
215                         verbose "Loading font $font"
216                         busybox_applet loadfont
217                         inst_d "/lib/kbd/consolefonts"
218                         cp -a "$font" "$DESTDIR/lib/kbd/consolefonts/"
219                         gunzip ${DESTDIR}/lib/kbd/consolefonts/${CONSOLEFONT}*.gz
220                         font=${font%.gz}
221                         echo "loadfont < $font" | add_linuxrc
222                 fi
223         fi
224 }
225
226 # generate code to mount /proc on initrd
227 # can be called multiple times
228 mount_proc() {
229         if is_yes "$proc_mounted"; then
230                 return
231         fi
232
233         proc_mounted=yes
234     if [ "$INITRDFS" = "initramfs" ]; then
235                 # /proc is mounted with initramfs 2.6.22.14 kernel
236                 # XXX: remove when it is clear why proc was already mounted
237                 echo "[ -f /proc/cmdline ] || mount -t proc none /proc" | add_linuxrc
238         else
239                 echo "mount -t proc none /proc" | add_linuxrc
240         fi
241 }
242
243 # generate code to mount /sys on initrd
244 # can be called multiple times
245 mount_sys() {
246         if is_yes "$sys_mounted"; then
247                 return
248         fi
249
250         sys_mounted=yes
251         echo "mount -t sysfs none /sys" | add_linuxrc
252 }
253
254 # generate code to mount /tmp on initrd
255 # can be called multiple times
256 mount_tmp() {
257     if [ "$INITRDFS" = "initramfs" ]; then
258                 # initramfs is read-write filesystem, no need for tmpfs
259                 return
260         fi
261
262         if is_yes "$tmp_mounted"; then
263                 return
264         fi
265
266         tmp_mounted=yes
267         echo "mount -t tmpfs none /tmp" | add_linuxrc
268 }
269
270 # generate code to mount /run on initrd
271 # can be called multiple times
272 mount_run() {
273         if is_yes "$run_mounted"; then
274                 return
275         fi
276
277         run_mounted=yes
278         echo "mount -t tmpfs run /run -o mode=0755,noexec,nosuid,nodev" | add_linuxrc
279 }
280
281 # unmount all mountpoints mounted by geninitrd
282 # try to move pseudo filesystems to newroot if possible
283 umount_all() {
284
285         add_linuxrc <<-'EOF'
286         : Last shell before umounting all and giving control over to real init.
287         debugshell
288         EOF
289
290         if is_yes "$run_mounted"; then
291                 add_linuxrc <<-EOF
292                 mount -n --move /run /newroot/run
293                 EOF
294                 run_mounted=no
295         fi
296         if is_yes "$dev_mounted"; then
297                 add_linuxrc <<-EOF
298                 mount --bind /dev /newroot/dev
299                 umount /dev
300                 EOF
301                 dev_mounted=no
302         fi
303         if is_yes "$sys_mounted"; then
304                 add_linuxrc <<-EOF
305                 mount --bind /sys /newroot/sys
306                 umount /sys
307                 EOF
308                 sys_mounted=no
309         fi
310         if is_yes "$proc_mounted"; then
311                 add_linuxrc <<-EOF
312                 mount --bind /proc /newroot/proc
313                 umount /proc
314                 EOF
315                 proc_mounted=no
316         fi
317         if is_yes "$tmp_mounted"; then
318                 echo 'umount /tmp' | add_linuxrc
319                 tmp_mounted=no
320         fi
321 }
322
323 # Checks if busybox has support for APPLET(s)
324 # Exits from geninitrd if the support is not present.
325 #
326 # NB! XXX do not output to STDOUT, it will appear in initrd images in some cases!
327 busybox_applet() {
328         local err=0 applet
329
330         if [ -z "$busybox_functions" ]; then
331                 local tmp=$($busybox 2>&1)
332
333                 # BusyBox v1.1.3 says applet not found if it's not called 'busybox'.
334                 if [[ "$tmp" = *applet\ not\ found* ]]; then
335                         local t=$(mktemp -d)
336                         ln -s $busybox $t/busybox
337                         local tmp=$($t/busybox 2>&1)
338                         rm -rf $t
339                 fi
340
341                 busybox_functions=$(echo "$tmp" | \
342                         sed -ne '/Currently defined functions:/,$p' | \
343                         xargs | sed -e 's,.*Currently defined functions: ,,'
344                 )
345         fi
346         for applet in $*; do
347                 local have
348                 # try cache
349                 eval have='$'busybox_have_$applet
350                 if [ -z "$have" ]; then
351                         have=$(echo "$busybox_functions" | grep -Ec "( |^)$applet(,|$)")
352                         if [ "$have" = 0 ]; then
353                                 warn "This setup requires busybox-initrd compiled with applet '$applet' support"
354                                 err=1
355                         fi
356                         eval busybox_have_$applet=$have
357                 fi
358         done
359         if [ $err = 1 ]; then
360                 die "Aborted"
361         fi
362 }
363
364 # Extract the .config file from a kernel image
365 # uses extract-ikconfig from kernel sources (scripts/extract-ikconfig)
366 ikconfig() {
367         local kofile=$(modinfo -k $kernel -n configs 2> /dev/null)
368         if [ -n "$kofile" ]; then
369                 /lib/geninitrd/extract-ikconfig $kofile
370                 return
371         fi
372
373         # see if config available as separate file
374         if [ -f /boot/config-$kernel ]; then
375            cat /boot/config-$kernel
376            return
377         fi
378
379         # finally try vmlinuz itself
380         /lib/geninitrd/extract-ikconfig /boot/vmlinuz-$kernel
381 }
382
383 # @param    $module
384 basename_module() {
385         local module=$1
386
387         module=${module##*/}
388         module=${module%$modext*}
389         echo $module
390 }
391
392 # Finds module dependencies
393 #
394 # @param        $module
395 #
396 # Outputs full path to module and it's dependencies
397 find_depmod() {
398         local module="$1"
399         local skiperrors=0
400
401         # if module is prefixed with dash, we should ignore errors if the module
402         # can't be found.
403         if [ ${module#-} != $module ]; then
404                 skiperrors=1
405                 module=${module#-}
406         fi
407
408         # This works when user has module-init-tools installed even on 2.4 kernels
409         local modprobe
410         modprobe=$(modprobe --set-version $kernel --show-depends $module --ignore-install 2>&1)
411
412         if [ $? != 0 ]; then
413                 if [ $skiperrors = 1 ]; then
414                         return 0
415                 fi
416                 echo >&2 "$modprobe"
417
418                 if ! is_no "$EXIT_IF_MISSING"; then
419                         die "$module: module not found for $kernel kernel"
420                 fi
421
422                 warn "$module: module not found for $kernel kernel"
423                 warn "If $module isn't compiled in kernel then this initrd may not start your system."
424         fi
425
426         local smodule
427
428         echo "$modprobe" | \
429         while read insmod modpath options; do
430                 if [ "$insmod" = "insmod" ]; then
431
432                         # XXX: find a away to autodetect
433                         smodule=$(basename_module $modpath)
434                         case "$smodule" in
435                                 btrfs)
436                                         warn "mounting multidevice btrfs volume requires rootfsflags=device=/dev/...,device=/dev/... kernel option"
437                                         find_depmod "-libcrc32c"
438                                         ;;
439                                 ext4)
440                                         find_depmod "-libcrc32c"
441                                         ;;
442                                 crc-t10dif)
443                                         find_depmod "-crct10dif-pclmul"
444                                         find_depmod "-crct10dif"
445                                         ;;
446                                 libcrc32c)
447                                         find_depmod "-crc32c-intel"
448                                         find_depmod "-crc32c"
449                                         ;;
450                                 virtio_blk|virtio_scsi)
451                                         find_depmod "-virtio_pci"
452                                         find_depmod "-virtio_mmio"
453                                         ;;
454                         esac
455
456                         echo $modpath
457                 fi
458         done
459         return 0
460 }
461
462 find_firmware() {
463         local module="$1"
464
465         # no firmware support in 2.4 kernels
466         if [ "$kernel_version_long" -lt "002005048" ]; then
467                 return
468         fi
469         echo -n $(NEW_MODINFO=1 modinfo -k $kernel -F firmware $module 2>/dev/null | xargs)
470 }
471
472 # @param        $module
473 find_module() {
474         local mod depmod module=$1
475
476         depmod=$(find_depmod $module) || exit 1
477         for mod in $depmod; do
478                 mod=${mod#/lib/modules/$kernel/}
479
480                 # add each module only once
481                 local m have=0
482                 for m in $MODULES_TO_INSTALL; do
483                         [ $m = $mod ] && have=1
484                 done
485                 if [ $have = 0 ]; then
486                         MODULES_TO_INSTALL="$MODULES_TO_INSTALL $mod"
487                         if ! is_yes "$USE_MODPROBE"; then
488                                 MODULES_TO_LOAD="$MODULES_TO_LOAD $mod"
489                         fi
490                 fi
491         done
492         if is_yes "$USE_MODPROBE" && [ -n "$mod" ]; then
493                 MODULES_TO_LOAD="$MODULES_TO_LOAD $mod"
494         fi
495 }
496
497 # install a file to temporary mount image.
498 # it will operate recursively (copying directories)
499 # and will symlink destinations if source is symlink.
500 inst() {
501         if [ $# -lt 2 ]; then
502                 die 'Usage: inst <file> [<file>] <destination>'
503         fi
504
505         local src i=0 c=$(($# - 1))
506         while [ $i -lt $c ]; do
507                 src="$src $1"
508                 i=$((i + 1))
509                 shift
510         done
511         local dest=$1
512         set -- $src
513         local parentDir=$(dirname $DESTDIR$dest)
514         if [ ! -d "$parentDir" ]; then
515                 verbose "+ mkdir -p DESTDIR${parentDir#$DESTDIR}"
516                 mkdir -p $parentDir
517         fi
518         verbose "+ cp $* DESTDIR$dest"
519         cp -HRp "$@" "$DESTDIR$dest"
520 }
521
522 inst_d() {
523         if [ $# = 0 ]; then
524                 die 'Usage: inst_d <destination> <destination>'
525         fi
526         local dir
527         for dir in "$@"; do
528                 install -d "$DESTDIR$dir"
529         done
530 }
531
532 # install executable and it's shared libraries
533 inst_exec() {
534         if [ $# -lt 2 ]; then
535                 die "Invalid params ($@), Usage: inst_exec <file>[, <file>] <destination>"
536         fi
537         local src i=0 c=$(($# - 1))
538         while [ $i -lt $c ]; do
539                 src="$src $1"
540                 i=$((i + 1))
541                 shift
542         done
543         local dest=$1
544         set -- $src
545
546         inst "$@" $dest
547
548         local obj lib libs libs_additional libdir
549         for obj in "$@"; do
550                 case "$obj" in
551                         /lib/ld-linux.so.2 | /lib64/ld-linux-x86-64.so.2 | /libx32/ld-linux-x32.so.2)
552                         continue
553                         ;;
554                     /lib/libpthread.so* | /lib64/libpthread.so* | /libx32/libpthread.so*)
555                                 libs_additional="${obj%/libpthread*}/libgcc_s.so.1"
556                         ;;
557                 esac
558
559
560                 libs=$(ldd "$obj" 2> /dev/null | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
561                 for lib in $libs $libs_additional; do
562                         libdir=$(cd $(dirname "$lib"); pwd)
563                         if [ ! -f "$DESTDIR/$lib" ]; then
564                                 inst_d $libdir
565                                 inst_exec $lib $libdir
566                         fi
567                 done
568         done
569
570         # hack for uclibc linked binaries requiring this fixed path
571         # XXX: shouldn't rpath be used here instead so th
572         for _lib in $(get_libdir LIBDIR); do
573                 if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
574                         lib=$DESTDIR/$_lib/libc.so.0
575                         lib=$(ldd "$lib" 2> /dev/null | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
576                         libdir=$(cd $(dirname "$lib"); pwd)
577                         if [ ! -e $DESTDIR$libdir ]; then
578                                 libdir=$(dirname "$libdir")
579                                 inst_d $libdir
580                                 verbose "+ ln -s /$_lib $DESTDIR$libdir"
581                                 ln -s /$_lib $DESTDIR$libdir
582                                 break
583                         fi
584                 fi
585         done
586 }
587
588 files_exist() {
589         local start_point="$1" pattern="$2"
590         shift
591         test -n "$(find "$start_point" -mindepth 1 -maxdepth 1 -name "$pattern" -print -quit)"
592 }
593
594 # output modules.conf / modprobe.conf
595 modprobe_conf() {
596         echo "$modprobe_conf_cache"
597 }
598
599 # return options for MODULE
600 # @param $1 module name
601 modprobe_options() {
602         local module=$1
603         local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
604         echo ${options# }
605 }
606
607 #
608 # defaults to modprobe -c if not told otherwise, this means include statements
609 # work from there.
610 cache_modprobe_conf() {
611         if [ "$kernel_version" -lt "002005" ]; then
612                 modulefile=/etc/modules.conf
613                 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
614                         modulefile=/etc/conf.modules
615                 fi
616         fi
617
618         if [ -n "$modulefile" ]; then
619                 debug "Using $modulefile for modules config"
620                 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
621
622         else
623                 debug "Using modprobe -c to get modules config"
624                 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
625         fi
626 }
627
628 # find modules for $devpath
629 find_modules_for_devpath() {
630         local devpath="$1"
631         if [ -z "$devpath" ]; then
632                 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
633         fi
634
635         if [[ "$devpath" = /dev/dm-* ]]; then
636                 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
637                 devpath=$(dm_node "$devpath")
638         fi
639
640         if [ -L "$devpath" ] && ! is_lvm "$devpath" && ! is_luks "$devpath"; then
641                 # sanitize things like:
642                 # /dev/block/104:2 -> /dev/cciss/c0d0p2
643                 devpath=$(readlink -f "$devpath")
644         fi
645
646         verbose "Finding modules for device path $devpath"
647
648         if is_luks "$devpath"; then
649                 find_modules_luks "$devpath"
650                 return
651         fi
652
653         if is_nfs "$devpath"; then
654                 find_modules_nfs "$devpath"
655                 return
656         fi
657
658         if is_md "$devpath"; then
659                 find_modules_md "$devpath"
660                 return
661         fi
662
663         if is_multipath "$devpath"; then
664                 if find_modules_multipath "$devpath"; then
665                         return
666                 fi
667
668                 # fallback
669         fi
670
671         if is_dmraid "$devpath"; then
672                 if find_modules_dmraid "$devpath"; then
673                         return
674                 fi
675                 # fallback
676         fi
677
678         if is_scsi "$devpath"; then
679                 find_modules_scsi "$devpath"
680                 return
681         fi
682
683         if is_ide "$devpath"; then
684                 find_modules_ide "$devpath"
685                 return
686         fi
687
688         if [[ "$devpath" == /dev/nvme* ]]; then
689                 find_module "nvme"
690                 return
691         fi
692
693         if [[ "$devpath" == /dev/bcache* ]]; then
694                 find_modules_bcache "$devpath"
695                 return
696         fi
697
698         if [[ "$devpath" == /dev/rd/* ]]; then
699                 find_module "DAC960"
700                 rootdev_add=/dev/rd/
701                 return
702         fi
703
704         if [[ "$devpath" == /dev/ida/* ]]; then
705                 find_module "cpqarray"
706                 rootdev_add=/dev/ida/
707                 return
708         fi
709
710         if [[ "$devpath" == /dev/cciss/* ]]; then
711                 rootdev_add=/dev/cciss/
712
713                 # load hpsa for future kernels, cciss for backwards compat
714                 if [ "$kernel_version_long" -ge "003000000" ]; then
715                         find_module "hpsa" "-cciss"
716                         find_modules_scsi "$devpath"
717                 else
718                         find_module "cciss"
719                 fi
720
721                 return
722         fi
723
724         if [[ "$devpath" == /dev/ataraid/* ]]; then
725                 find_modules_ide
726                 find_module "ataraid"
727                 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
728                 if [ -n "$ataraidmodules" ]; then
729                         # FIXME: think about modules compiled in kernel
730                         die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
731                 fi
732                 for n in $ataraidmodules; do
733                         find_module "$n"
734                 done
735                 rootdev_add=/dev/ataraid/
736                 return
737         fi
738
739         # check to see if we need to set up a loopback filesystem
740         if [[ "$devpath" == /dev/loop*  ]]; then
741                 die "Sorry, root on loop device isn't supported."
742                 # TODO: rewrite for bsp and make nfs ready
743                 if [ ! -x /sbin/losetup ]; then
744                         die "losetup is missing"
745                 fi
746                 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
747                 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
748                         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"
749                 fi
750
751                 line="`awk '/'$key'/ { print $0; }' $fstab`"
752                 loopDev="$(echo $line | awk '{print $3}')"
753                 loopFs="$(echo $line | awk '{print $4}')"
754                 loopFile="$(echo $line | awk '{print $5}')"
755
756                 BASICMODULES="$BASICMODULES -loop"
757                 find_module "-$loopFs"
758                 BASICMODULES="$BASICMODULES -${loopFs}"
759                 return
760         fi
761
762         if is_lvm "$devpath"; then
763                 find_modules_lvm "$devpath"
764                 return
765         fi
766 }
767
768 firmware_install_module() {
769         local module="$1"
770         local firmware_files="$2"
771
772         verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
773         # firmware not yet installed
774         if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
775                 inst_d /lib/firmware
776 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
777 #!/bin/sh -e
778 # handle only firmware add requests
779 if [ "$SUBSYSTEM" != "firmware" ]; then
780         exit 0
781 fi
782 if [ "$ACTION" != "add" ]; then
783         exit 0
784 fi
785 echo 1 > /sys$DEVPATH/loading
786 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
787 echo 0 > /sys$DEVPATH/loading
788 exit 0
789 EOF
790                 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
791
792                 # setup firmware loader agent
793                 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
794         fi
795
796         for firmware in $firmware_files; do
797                 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
798                         FIRMWAREDIR=${firmware%/*}
799                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
800                         inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
801                 elif [ -f "/lib/firmware/$firmware" ]; then
802                         FIRMWAREDIR=${firmware%/*}
803                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
804                         inst /lib/firmware/$firmware /lib/firmware/$firmware
805                 else
806                         warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
807                 fi
808         done
809
810         mount_sys
811 }
812
813 modules_install() {
814         local modules="$1"
815         local mod
816
817         for mod in $modules; do
818                 MODULEDIR=${mod%/*}
819                 inst_d "/lib/modules/$kernel/$MODULEDIR"
820                 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
821                 case $mod in
822                         *.gz)
823                                 gunzip "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress gz"
824                                 mod=${mod%.gz}
825                                 ;;
826                         *.xz)
827                                 xz -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress xz"
828                                 mod=${mod%.xz}
829                                 ;;
830                         *.bz2)
831                                 bzip2 -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress bz2"
832                                 mod=${mod%.bz2}
833                                 ;;
834                 esac
835                 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
836                         $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod}"
837                 fi
838         done
839 }
840
841 modules_add_linuxrc() {
842         local mod modpath
843
844         for mod in "$@"; do
845                 # module path without optional compression
846                 modpath=${mod%.gz}
847                 modpath=${modpath%.xz}
848                 modpath=${modpath%.bz2}
849
850                 # name of the module
851                 local module=${modpath##*/}; module=${module%$modext}
852                 local options
853                 if ! is_yes "$USE_MODPROBE"; then
854                         options=$(modprobe_options "$module")
855                 fi
856                 local genericname=$(echo $module | tr - _)
857                 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
858                 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
859
860                 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
861                         options="scan=sync $options"
862                 fi
863
864                 if [ x"$verbose" = x"-v" ]; then
865                         s=""
866                         if [ "$options" ]; then
867                                 s="$s with options [$options]"
868                         fi
869                         if [ "$usleep" ]; then
870                                 s="$s and $usleep usleep"
871                         fi
872                         verbose "Loading module [$module]$s"
873                 fi
874
875                 if [ -n "$firmware" ]; then
876                         firmware_install_module "$module" "$firmware"
877                 else
878                         for file in $(find_firmware "$module"); do
879                                 firmware_install_module "$module" "$file"
880                         done
881                 fi
882
883                 if is_yes "$USE_MODPROBE"; then
884                         echo "/sbin/modprobe $module $options" | add_linuxrc
885                 else
886                         echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
887                 fi
888                 if [ -n "$usleep" ]; then
889                         echo "usleep $usleep" | add_linuxrc
890                 fi
891                 if [ "$module" = "scsi_wait_scan" ]; then
892                         if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
893                                 echo "rmmod scsi_wait_scan" | add_linuxrc
894                         fi
895                 fi
896
897         done
898 }
899
900 # Generates /dev nodes based on /proc/partitions information.
901 # Needs /proc mounted.
902 # Can be called multiple times.
903 initrd_gen_devices() {
904         if is_yes "$proc_partitions"; then
905                 return
906         fi
907         proc_partitions=yes
908
909         mount_dev
910         add_linuxrc <<-'EOF'
911                 : 'Making device nodes'
912                 cat /proc/partitions | (
913                         # ignore first two lines: header, empty line
914                         read b; read b
915
916                         while read major minor blocks dev rest; do
917                                 node=/dev/$dev
918                                 mkdir -p ${node%/*}
919                                 [ -e $node ] || mknod -m 660 $node b $major $minor
920                         done
921                 )
922         EOF
923 }
924
925
926 initrd_gen_setrootdev() {
927         verbose "Adding rootfs finding based on kernel cmdline root= option support."
928         busybox_applet ls
929         debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
930         add_linuxrc <<-'EOF'
931                 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
932                         rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
933                         # fallback to ls, try two different formats
934                         # http://lists.pld-linux.org/mailman/pipermail/pld-devel-en/2014-May/023915.html
935                         if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
936                                 # busybox up to 1.22
937                                 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
938                         fi
939                         if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
940                                 # busybox 1.22 and upwards
941                                 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $5 + $6; }}')"
942                         fi
943                         if [ "${rootnr:-0}" -gt 0 ]; then
944                                 echo "$rootnr" > /proc/sys/kernel/real-root-dev
945                         fi
946                 fi
947         EOF
948 }
949
950 initrd_gen_initramfs_switchroot() {
951         inst_d /newroot
952         if [ "$rootdev" = "/dev/nfs" ]; then
953                 echo "rootfs on NFS root=/dev/nfs"
954         else
955                 [ -e $rootdev ] && [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
956         fi
957
958         # parse 'root=xxx' kernel commandline
959         # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
960
961         # from lilo-23.2/readme/README:
962         # root=<device> changes the root device. This overrides settings that may
963         # have been made in the boot image and on the LILO command line. <device> is
964         # either the hexadecimal device number or the full path name of the device,
965         # e.g. /dev/hda3 [*]
966         #
967         #  *  The device names are hard-coded in the kernel. Therefore, only the
968         #         "standard" names are supported and some less common devices may not be
969         #         recognized. In those cases, only numbers can be used.
970         busybox_applet cat
971         add_linuxrc <<-'EOF'
972                 device=
973                 eval "$(busybox awk -v root="$ROOT" '
974                         function h2d(str, hstr, res, num, n, digit, i) {        # http://9fans.net/archive/2006/09/261
975                                 hstr = "0123456789abdcef"; res = 0;
976                                 n = split(tolower(str), digit, "");
977
978                                 for (i = 1; i <= n; i++) {
979                                         num = index(hstr, digit[i]) - 1;
980                                         res = res + (num * 16 ^ (n - i));
981                                 }
982                                 return res;
983                         }
984                         BEGIN {
985                                 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
986                                 num_pattern = "[0-9a-fA-F]" num_pattern_short;
987                                 dev_pattern = "[hms][a-z][a-z]([0-9])+";
988                                 partition = ""; min = -1; maj = -1;
989
990                                 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") {  # see if we have /dev/hdX or hdX, we can just take partition name
991                                         partition = root; sub("^/dev/", "", partition);
992                                 } else {        # unify values first
993                                         if (root ~ "^" num_pattern_short "$")  {        # change "303" => "0x0303"
994                                                 root = "0x0" root
995                                         } else if (root ~ "^" num_pattern "$")  {       # change "0303" => "0x0303"
996                                                 root = "0x" root
997                                         }
998                                         maj = h2d(substr(root, 3, 2));
999                                         min = h2d(substr(root, 5, 2));
1000                                 }
1001                         }
1002                         partition && $4 == partition { maj = $1; min = $2; }
1003                         $1 == maj && $2 == min { partition = $4; }
1004                         END {
1005                                 if (maj >= 0 && min >= 0) {     printf("maj=%s; min=%s;\n", maj, min);  }
1006                                 if (partition) {                printf("device=/dev/%s;\n", partition); }
1007                         }' /proc/partitions)"
1008
1009                 if [ -z "$device" ]; then
1010                         if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
1011                                 cat /proc/partitions
1012                         fi
1013                         device=$ROOT
1014                 fi
1015
1016                 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
1017                         mknod -m 660 $device b $maj $min
1018                 fi
1019
1020                 # XXX hack, fallback to rootdev from geninitrd time
1021                 if [ ! -e "$device" ]; then
1022         EOF
1023         add_linuxrc <<-EOF
1024                         device="$rootdev"
1025         EOF
1026         add_linuxrc <<-'EOF'
1027                         echo "DEVICE set to $device based on fstab entry from initrd gen time"
1028                 fi
1029
1030                 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
1031                 if [ ! -e "$device" ]; then
1032                         rrd=$(cat /proc/sys/kernel/real-root-dev)
1033                         major=$(($rrd / 256))
1034                         minor=$(($rrd % 256))
1035
1036                         while read pmajor pminor blocks dev rest; do
1037                                 # skip header and empty line
1038                                 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
1039
1040                                 if [ $pmajor = $major -a $pminor = $minor ]; then
1041                                         device=/dev/$dev
1042                                         echo "DEVICE set to $device based on real-root-dev"
1043                                 fi
1044                         done < /proc/partitions
1045                 fi
1046
1047                 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
1048
1049                 mount -t $ROOTFS -r $device $ROOTFLAGS /newroot || echo "Mount of rootfs failed."
1050                 init=$INIT
1051                 if [ -z "$init" -o ! -x "/newroot$init" ]; then
1052                         init=/sbin/init
1053                 fi
1054         EOF
1055
1056         busybox_applet dmesg
1057         busybox_applet tail
1058         add_linuxrc <<-'EOF'
1059                 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
1060                         echo "Last 20 lines of dmesg:"
1061                         dmesg | tail -n 20
1062                 fi
1063
1064         EOF
1065
1066         kmsg "geninitrd/$VERSION switching root"
1067
1068         umount_all
1069         busybox_applet switch_root usleep
1070         add_linuxrc <<-'EOF'
1071                 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
1072
1073                 # switch root to empty dir will make kernel panic, so sleep 10s before it
1074                 # switch_root needs to be pid 1, so there's no other way to recover from here
1075                 # if /dev is missing, switch root will likely fail, give debug shell before that
1076                 if [ ! -d /newroot/dev ]; then
1077                         echo "/dev is missing, switch_root will likely fail"
1078                         echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
1079                         debugshell
1080                         [ "$DEBUGINITRD" ] || usleep 10000000
1081                 fi
1082
1083                 # systemd[1]: /usr appears to be on its own filesytem and is not
1084                 # already mounted. This is not a supported setup. Some things will
1085                 # probably break (sometimes even silently) in mysterious ways. Consult
1086                 # http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
1087                 # for more information.
1088                 if chroot /newroot findmnt -s -n /usr > /dev/null 2> /dev/null; then
1089                         echo trying to mount /usr
1090                         chroot /newroot mount -n /usr
1091                 fi
1092
1093                 exec switch_root /newroot $init ${1:+"$@"}
1094
1095                 # FIXME: this code is never executed, as "exec" does not return!
1096
1097                 echo "Error! initramfs should not reach this place."
1098                 echo "It probably means you've got old version of busybox, with broken"
1099                 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1100
1101                 exec chroot /newroot $init ${1:+"$@"}
1102
1103                 echo "Failed to chroot!"
1104                 debugshell
1105         EOF
1106         # we need /init being real file, not symlink, otherwise the initramfs will
1107         # not be ran by pid 1 which is required for switch_root
1108         mv $DESTDIR/linuxrc $DESTDIR/init
1109         ln -s init $DESTDIR/linuxrc
1110 }
1111
1112 # find if $symbol exists in System.map $mapfile
1113 sym_exists() {
1114         local mapfile="$1"
1115         local symbol="$2"
1116         if [ ! -f $mapfile ]; then
1117                 # missing mapfile (not a pld kernel?)
1118                 return 1
1119         fi
1120
1121         awk -vc=1 -vsymbol="$symbol" '(tolower($2) == "t" || tolower($2) == "d") && $3 == symbol {c = 0} END {exit c}' $mapfile
1122 }
1123
1124 # find best compressor (or forced one) for initrd
1125 find_compressor() {
1126         local mode="$1"
1127         local compressors='zstd xz lzma bzip2 gzip lzo lz4'
1128
1129         # a specified one, take it
1130         if ! is_yes "$mode"; then
1131                 compressors="$mode"
1132         fi
1133
1134         verbose "finding compressor: $compressors (via $mode)"
1135         # check for compressor validity
1136         local c prog map=/boot/System.map-$kernel
1137         for c in $compressors; do
1138                 case $c in
1139                 xz)
1140                         sym=unxz
1141                         prog=/usr/bin/xz
1142                         ;;
1143                 lzma)
1144                         sym=unlzma
1145                         prog=/usr/bin/xz
1146                         ;;
1147                 bzip2)
1148                         sym=bzip2
1149                         prog=/usr/bin/bzip2
1150                         ;;
1151                 gzip)
1152                         sym=gunzip
1153                         prog=/bin/gzip
1154                         ;;
1155                 lzo)
1156                         sym=unlzo
1157                         prog=/usr/bin/lzop
1158                         ;;
1159                 zstd)
1160                         sym=unzstd
1161                         prog=/usr/bin/zstd
1162                         ;;
1163                 lz4)
1164                         sym=unlz4
1165                         prog=/usr/bin/lz4
1166                         ;;
1167                 none|no)
1168                         # any existing sym will work
1169                         sym=initrd_load
1170                         prog=/bin/cat
1171                         ;;
1172                 *)
1173                         die "Unknown compressor $c"
1174                         ;;
1175                 esac
1176                 if sym_exists $map $sym && [ -x $prog ]; then
1177                         echo $c
1178                         return
1179                 fi
1180         done
1181
1182         verbose "using gzip for compressor (fallback)"
1183         echo gzip
1184 }
1185
1186 # compresses kernel image image
1187 # in function so we could retry with other compressor on failure
1188 compress_image() {
1189         local compressor="$1" IMAGE="$2" target="$3" tmp
1190         tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1191
1192         case "$compressor" in
1193         xz)
1194                 # don't use -9 here since kernel won't understand it
1195                 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1196                 ;;
1197         lzma)
1198                 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1199                 ;;
1200         bzip2)
1201                 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1202                 ;;
1203         gzip)
1204                 gzip -9 < "$IMAGE" > "$tmp" || return $?
1205                 ;;
1206         lzo)
1207                 lzop -9 < "$IMAGE" > "$tmp" || return $?
1208                 ;;
1209         zstd)
1210                 zstd -9 < "$IMAGE" > "$tmp" || return $?
1211                 ;;
1212         lz4)
1213                 lz4 -9 -l < "$IMAGE" > "$tmp" || return $?
1214                 ;;
1215         none|no)
1216                 cat < "$IMAGE" > "$tmp" || return $?
1217                 ;;
1218         esac
1219
1220         mv -f "$tmp" "$target"
1221 }
1222
1223 # prepend file to image
1224 prepend_file_to_image() {
1225         local file="$1" target="$2" tmp
1226         tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1227
1228         cat "$file" "$target" > "$tmp" || return $?
1229
1230         mv -f "$tmp" "$target"
1231 }
1232
1233 if [ -r /etc/sysconfig/geninitrd ]; then
1234         . /etc/sysconfig/geninitrd
1235 fi
1236
1237 if [ ! -f /proc/mounts ]; then
1238         warn "/proc filesystem not mounted, may cause wrong results or failure."
1239 fi
1240
1241 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev swsusp tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1242
1243 while [ $# -gt 0 ]; do
1244         case $1 in
1245         --fstab=*)
1246                 fstab=${1#--fstab=}
1247                 ;;
1248         --fstab)
1249                 fstab=$2
1250                 shift
1251                 ;;
1252         --modules-conf=*)
1253                 modulefile=${1#--modules-conf=}
1254                 ;;
1255         --modules-conf)
1256                 modulefile=$2
1257                 shift
1258                 ;;
1259         --with-bootsplash)
1260                 BOOT_SPLASH=yes
1261                 ;;
1262         --without-bootsplash)
1263                 BOOT_SPLASH=no
1264                 ;;
1265         --with-fbsplash)
1266                 FB_SPLASH=yes
1267                 ;;
1268         --without-fbsplash)
1269                 FB_SPLASH=no
1270                 ;;
1271         --with-fbcondecor)
1272                 FB_CON_DECOR=yes
1273                 ;;
1274         --without-fbcondecor)
1275                 FB_CON_DECOR=no
1276                 ;;
1277         --with-modprobe)
1278                 USE_MODPROBE=yes
1279                 ;;
1280         --without-modprobe)
1281                 USE_MODPROBE=no
1282                 ;;
1283         --without-swsusp)
1284                 USE_SWSUSP=no
1285                 ;;
1286         --with-suspend)
1287                 USE_SUSPEND=yes
1288                 ;;
1289         --without-suspend)
1290                 USE_SUSPEND=no
1291                 ;;
1292         --with-suspend2 | --with-tuxonice)
1293                 USE_TUXONICE=yes
1294                 ;;
1295         --without-suspend2 | --without-tuxonice)
1296                 USE_TUXONICE=no
1297                 ;;
1298         --lvmversion=*)
1299                 LVMTOOLSVERSION=${1#--lvmversion=}
1300                 ;;
1301         --lvmtoolsversion=*)
1302                 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1303                 ;;
1304         --lvmtoolsversion|--lvmversion)
1305                 LVMTOOLSVERSION=$2
1306                 shift
1307                 ;;
1308         --without-udev)
1309                 USE_UDEV=no
1310                 ;;
1311         --with-udev)
1312                 USE_UDEV=yes
1313                 ;;
1314         --without-dmraid)
1315                 USE_DMRAID=no
1316                 ;;
1317         --without-multipath)
1318                 USE_MULTIPATH=no
1319                 ;;
1320         --with-multipath=*)
1321                 USE_MULTIPATH=${1#--with-multipath=}
1322                 ;;
1323         --without-blkid)
1324                 USE_BLKID=no
1325                 ;;
1326         --without-luks)
1327                 USE_LUKS=no
1328                 ;;
1329         --with=*)
1330                 BASICMODULES="$BASICMODULES ${1#--with=}"
1331                 ;;
1332         --with)
1333                 BASICMODULES="$BASICMODULES $2"
1334                 shift
1335                 ;;
1336         --version)
1337                 echo "$PROGRAM: version $VERSION"
1338                 exit 0
1339                 ;;
1340         -v)
1341                 if [ x"$verbose" = x"-v" ]; then
1342                         verbose="-v -v"
1343                 else
1344                         verbose="-v"
1345                 fi
1346                 exec 3>&1
1347                 ;;
1348         --compress)
1349                 COMPRESS=$2
1350                 ;;
1351         --compress=*)
1352                 COMPRESS="${1#--compress=}"
1353                 ;;
1354         --nocompress)
1355                 COMPRESS=no
1356                 ;;
1357         --nostrip)
1358                 STRIP=
1359                 ;;
1360         --strip=*)
1361                 STRIP="${1#--strip=}"
1362                 ;;
1363         --strip)
1364                 STRIP=$2
1365                 shift
1366                 ;;
1367         --ifneeded)
1368                 ifneeded=1
1369                 ;;
1370         -f)
1371                 force=1
1372                 ;;
1373         --preload=*)
1374                 PREMODS="$PREMODS ${1#--preload=}"
1375                 ;;
1376         --preload)
1377                 PREMODS="$PREMODS $2"
1378                 shift
1379                 ;;
1380         --fs=* | --fs)
1381                 die "--fs option is obsoleted. Use --initrdfs instead"
1382                 ;;
1383         --initrdfs=*)
1384                 INITRDFS=${1#--initrdfs=}
1385                 ;;
1386         --initrdfs)
1387                 INITRDFS=$2
1388                 shift
1389                 ;;
1390         --image-version)
1391                 img_vers=yes
1392                 ;;
1393         --ide-only-root)
1394                 ide_only_root="yes"
1395                 ;;
1396         *)
1397                 if [ -z "$target" ]; then
1398                         target="$1"
1399                 elif [ -z "$kernel" ]; then
1400                         kernel="$1"
1401                 else
1402                         usage
1403                         exit 1
1404                 fi
1405                 ;;
1406         esac
1407
1408         shift
1409 done
1410
1411 if [ -z "$target" -o -z "$kernel" ]; then
1412         usage
1413         exit 1
1414 fi
1415
1416 # main()
1417 if [ "$(id -u)" != 0 ]; then
1418         die "You need to be root to generate initrd"
1419 fi
1420
1421 for dir in libx32 lib64 lib; do
1422         initrd_dir=/usr/$dir/initrd
1423         if [ -d "$initrd_dir" ]; then
1424                 initrd_dirs="$initrd_dirs $initrd_dir"
1425         fi
1426 done
1427
1428 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1429 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1430
1431 verbose "# geninitrd $VERSION"
1432 debug "Using initrd_dir: $initrd_dir"
1433
1434 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1435
1436 # we setup mods after parsing command line args
1437 geninitrd_setup_mods
1438
1439 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1440         warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1441 fi
1442
1443 if [ -z "$INITRDFS" ]; then
1444         if [ -n "$FS" ]; then
1445                 # FS= can came only via /etc/sysconfig/geninitrd likely?
1446                 die "FS configuration option is obsoleted. Use INITRDFS instead"
1447         fi
1448
1449         # default value
1450         if [ "$kernel_version" -ge "002005" ]; then
1451                 INITRDFS="initramfs"
1452         else
1453                 INITRDFS="rom"
1454         fi
1455 fi
1456
1457 check_initrd_fs() {
1458         local s sfound sym p prog map=/boot/System.map-$kernel
1459         case "$INITRDFS" in
1460                 ext2)
1461                         # TODO: symbols to check in case of ext2 used via ext3/4 subsystem
1462                         sym=init_ext2_fs
1463                         prog=/sbin/mke2fs
1464                         ;;
1465                 rom|romfs)
1466                         sym=init_romfs_fs
1467                         prog=/sbin/genromfs
1468                         ;;
1469                 cram|cramfs)
1470                         sym=init_cramfs_fs
1471                         prog=/sbin/mkcramfs
1472                         ;;
1473                 initramfs)
1474                         sym=__initramfs_start
1475                         prog="/bin/cpio /usr/bin/find"
1476                         ;;
1477                 *)
1478                         die "Filesystem $INITRDFS on initrd is not supported by geninitrd"
1479                         ;;
1480         esac
1481
1482         # only one is needed (for cases like ext2 via ext2 or via ext3 or via ext4 subsysytem)
1483         sfound=0
1484         for s in $sym; do
1485                 sym_exists $map $s && sfound=1
1486                 break
1487         done
1488         if [ "$sfound" -eq "0" ]; then
1489                 die "Filesystem $INITRDFS on initrd is not supported by kernel"
1490         fi
1491
1492         for p in $prog; do
1493                 [ ! -x "$p" ] && die "$prog is missing"
1494         done
1495 }
1496 check_initrd_fs
1497
1498 if [ -L "$target" ]; then
1499         target=$(readlink -f "$target")
1500 fi
1501
1502 if [ -n "$img_vers" ]; then
1503         target="$target-$kernel"
1504 fi
1505
1506 if [ -z "$force" -a -f "$target" ]; then
1507         die "$target already exists."
1508 fi
1509
1510 if [ ! -d "/lib/modules/$kernel" ]; then
1511         die "/lib/modules/$kernel is not a directory."
1512 fi
1513
1514 if [ "$kernel_version" -ge "002005" ]; then
1515         modext=".ko"
1516 fi
1517
1518 cache_modprobe_conf
1519
1520 for n in $PREMODS; do
1521         find_module "$n"
1522 done
1523
1524 if [ "$FBMODULE" ]; then
1525         find_module "$FBMODULE"
1526 fi
1527
1528 # autodetect USB keyboards
1529 find_modules_usbkbd
1530
1531 # allow forcing loading SCSI and/or IDE modules
1532 # XXX: where ADDSCSI cames from? drop?
1533 if is_yes "$ADDSCSI"; then
1534         find_modules_scsi
1535 fi
1536
1537 # autodetect SATA modules
1538 find_modules_sata
1539
1540 # XXX: where ADDIDE cames from? drop?
1541 if is_yes "$ADDIDE"; then
1542         find_modules_ide
1543 fi
1544
1545 if is_yes "$USE_SUSPEND"; then
1546         find_modules_suspend
1547 fi
1548
1549 if is_yes "$USE_SWSUSP"; then
1550         find_modules_swsusp
1551 fi
1552
1553 find_root "$fstab" || exit
1554 verbose "Using $rootdev as device for rootfs"
1555
1556 find_modules_for_devpath "$rootdev"
1557
1558 # if USE_MULTIPATH is path to device, scan that too
1559 # this is to bootstrap multipath setup into initrd.
1560 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1561         find_modules_multipath $USE_MULTIPATH
1562 fi
1563
1564 find_module "-$rootFs"
1565
1566 for n in $BASICMODULES; do
1567         find_module "$n"
1568 done
1569
1570 if is_yes "$USE_TUXONICE"; then
1571         find_module "-lzf"
1572 fi
1573
1574 find_modules_uvesafb
1575 find_modules_fbsplash
1576
1577 if [ -n "$ifneeded" -a -z "$MODULES_TO_LOAD" ]; then
1578         verbose "No modules are needed -- not building initrd image."
1579         exit 0
1580 fi
1581
1582 verbose "Building initrd..."
1583 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1584 RCFILE="$DESTDIR/linuxrc"
1585 > "$RCFILE"
1586 chmod a+rx "$RCFILE"
1587 ln -s linuxrc $DESTDIR/init
1588
1589 # create dirs that we really need
1590 inst_d /{lib,bin,sbin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys,tmp}
1591
1592 modules_install "$MODULES_TO_INSTALL"
1593
1594 if is_yes "$USE_MODPROBE"; then
1595         inst /lib/modules/$kernel/modules.{builtin,order} /lib/modules/$kernel
1596         depmod -b "$DESTDIR" $kernel
1597 fi
1598
1599 # mknod'ing the devices instead of copying them works both with and
1600 # without devfs...
1601 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1602 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1603 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1604 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1605 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1606 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1607
1608 inst_exec $busybox /bin/busybox
1609 ln -s busybox $DESTDIR/bin/sh
1610 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1611 ln -s busybox $DESTDIR/bin/initrd-busybox
1612
1613 add_linuxrc <<EOF
1614 #!/bin/sh
1615 # initrd generated by geninitrd/$VERSION
1616 # on $(LC_ALL=C date)
1617
1618 EOF
1619 load_font
1620 mount_proc
1621
1622 kmsg "geninitrd/$VERSION starting"
1623
1624 inst_d /lib/geninitrd/
1625 inst /lib/geninitrd/functions.initrd /lib/geninitrd/functions.initrd
1626
1627 add_linuxrc <<-EOF
1628         . /lib/geninitrd/functions.initrd
1629         # builtin defaults from geninitrd
1630         ROOT=$rootdev
1631         ROOTFS=$rootFs
1632 EOF
1633 add_linuxrc <<-'EOF'
1634         read CMDLINE < /proc/cmdline
1635
1636         for arg in $CMDLINE; do
1637                 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1638                         DEBUGINITRD=yes
1639                 fi
1640                 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1641                         DEBUGINITRD=${arg##debug*rd=}
1642                 fi
1643                 if [ "${arg##root=}" != "${arg}" ]; then
1644                         ROOT=${arg##root=}
1645                 fi
1646                 if [ "${arg##rootfs=}" != "${arg}" ]; then
1647                         ROOTFS=${arg##rootfs=}
1648                 fi
1649                 if [ "${arg##rootflags=}" != "${arg}" ]; then
1650                         ROOTFLAGS=${arg##rootflags=}
1651                 fi
1652                 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1653                         ROOTFSFLAGS=${arg##rootfsflags=}
1654                 fi
1655                 if [ "${arg##init=}" != "${arg}" ]; then
1656                         INIT=${arg##init=}
1657                 fi
1658         done
1659
1660         # handling of invalid, rootfsflags, option
1661         if [ -n "$ROOTFSFLAGS" ]; then
1662                 if [ -n "$ROOTFLAGS" ]; then
1663                         ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1664                 else
1665                         ROOTFLAGS="$ROOTFSFLAGS"
1666                 fi
1667         fi
1668
1669         if [ "$DEBUGINITRD" = "sh" ]; then
1670                 # export some vars to subshell for debug to work
1671                 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
1672                 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1673                 export rootnr attrs majmin major minor device
1674
1675                 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1676                 debugshell() {
1677 EOF
1678 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1679 add_linuxrc <<-'EOF'
1680         echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1681 EOF
1682 else
1683 add_linuxrc <<-'EOF'
1684         sh
1685 EOF
1686 fi
1687 add_linuxrc <<-'EOF'
1688                 }
1689         else
1690                 debugshell() {
1691                         :
1692                 }
1693         fi
1694
1695         if [ "$DEBUGINITRD" ]; then
1696                 set -x
1697         fi
1698 EOF
1699
1700 # mount early
1701 mount_tmp
1702 mount_run
1703
1704 if is_yes "$USE_MODPROBE"; then
1705         if files_exist /lib/modprobe.d '*.conf'; then
1706                 inst_d /lib/modprobe.d
1707                 inst /lib/modprobe.d/*.conf /lib/modprobe.d
1708         fi
1709         if files_exist /etc/modprobe.d '*.conf'; then
1710                 inst_d /etc/modprobe.d
1711                 inst /etc/modprobe.d/*.conf /etc/modprobe.d
1712         fi
1713         if files_exist /etc/modprobe.d/$kernel '*.conf'; then
1714                 inst_d /etc/modprobe.d/$kernel
1715                 inst /etc/modprobe.d/$kernel/*.conf /etc/modprobe.d/$kernel
1716         fi
1717         inst_exec /sbin/modprobe /sbin
1718 fi
1719
1720 modules_add_linuxrc $MODULES_TO_LOAD
1721
1722 # TODO: rewrite for busybox
1723 #if [ -n "$loopDev" ]; then
1724 #       if [ ! -d /initrd ]; then
1725 #               mkdir /initrd
1726 #       fi
1727 #
1728 #       cp -a "$loopDev" "$DESTDIR/dev"
1729 #       cp -a "$rootdev" "$DESTDIR/dev"
1730 #       echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1731 #       echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1732 #       echo "echo Setting up loopback device $rootdev" >> $RCFILE
1733 #       echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1734 #fi
1735
1736 if is_yes "$USE_UDEV"; then
1737         initrd_gen_udev
1738 else
1739         initrd_gen_mdev
1740 fi
1741
1742 initrd_gen_uvesafb
1743 initrd_gen_luks
1744 initrd_gen_dmraid
1745 initrd_gen_multipath
1746 initrd_gen_blkid
1747
1748 if is_yes "$have_nfs"; then
1749         initrd_gen_nfs
1750 else
1751         initrd_gen_md
1752         initrd_gen_lvm
1753         initrd_gen_bcache
1754         initrd_gen_blkid
1755         initrd_gen_luks
1756         initrd_gen_setrootdev
1757 fi
1758
1759 # additional devs always needed
1760 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1761
1762 initrd_gen_stop_udevd
1763 initrd_gen_stop_mdev
1764 initrd_gen_stop_uvesafb
1765
1766 # resume after killing local processes
1767 initrd_gen_tuxonice
1768 initrd_gen_suspend
1769 initrd_gen_swsusp
1770
1771 # clean up env
1772 add_linuxrc <<-'EOF'
1773 if [ ! "$DEBUGINITRD" ]; then
1774         ifs=$IFS
1775         IFS="
1776         "
1777         for i in $(export -p); do
1778                 i=${i#declare -x } # ksh/bash
1779                 i=${i#export } # busybox
1780
1781                 case "$i" in
1782                 *=*)
1783                         : ;;
1784                 *)
1785                         continue ;;
1786                 esac
1787
1788                 i=${i%%=*}
1789
1790                 [ -z "$i" ] && continue
1791
1792                 case "$i" in
1793                         ROOT|PATH|HOME|TERM)
1794                                 :
1795                                 ;;
1796                         *)
1797                                 unset $i
1798                                 ;;
1799                 esac
1800         done
1801         IFS=$ifs
1802 fi
1803 EOF
1804
1805 if [ "$INITRDFS" = "initramfs" ]; then
1806         initrd_gen_initramfs_switchroot
1807 else
1808         umount_all
1809 fi
1810
1811 initrd_gen_fbsplash
1812 initrd_gen_fbcondecor
1813
1814 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1815
1816 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1817
1818 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1819 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1820
1821 verbose "Creating $INITRDFS image $IMAGE"
1822 case "$INITRDFS" in
1823   ext2)
1824         dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1825         # NOTE: ext2 label is max 16 chars
1826         mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1827         tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1828
1829         local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1830         debug "Mounting ext2 image $IMAGE to $tmpmnt"
1831         mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1832         # We don't need this directory, so let's save space
1833         rm -rf "$tmpmnt"/lost+found
1834
1835         debug "Copy recursively $DESTDIR -> $tmpmnt"
1836         cp -a $DESTDIR/* $tmpmnt
1837         umount "$IMAGE"
1838         rmdir "$tmpmnt"
1839
1840         ;;
1841   rom|romfs)
1842         genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1843         ;;
1844   cram|cramfs)
1845         mkcramfs "$DESTDIR" "$IMAGE"
1846         ;;
1847   initramfs)
1848         (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1849         ;;
1850   *)
1851         die "Filesystem $INITRDFS not supported by $PROGRAM"
1852 esac
1853
1854 if [ "$INITRDFS" != "initramfs" ]; then
1855         CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1856         if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1857                 CONFIG_BLK_DEV_RAM_SIZE=4096
1858                 warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1859         fi
1860
1861         if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1862                 warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1863         fi
1864 fi
1865
1866 if ! is_no "$COMPRESS"; then
1867         compressor=$(find_compressor "$COMPRESS")
1868         verbose "Compressing $target with $compressor"
1869
1870         # TODO: the image name (specified from kernel.spec) already contains
1871         # extension, which is .gz most of the time.
1872         compress_image "$compressor" "$IMAGE" "$target" || {
1873                 if [ $compressor != gzip ]; then
1874                         warn "Could not compress with $compressor, retrying with gzip"
1875                         compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1876                 else
1877                         die "Could not compress image with $compressor"
1878                 fi
1879         }
1880 else
1881         cp -a "$IMAGE" "$target"
1882 fi
1883
1884 # microcode support for lilo
1885 if ! is_no "$LILO_MICROCODE"; then
1886         if [ -x /sbin/lilo -a -f "/boot/intel-ucode.img" ]; then
1887                 verbose "Prepending $target with microcode image /boot/intel-ucode.img for LILO"
1888                 prepend_file_to_image "/boot/intel-ucode.img" "$target"
1889         fi
1890 fi
1891
1892 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1893 initrd_gen_bootsplash "$target"
1894
1895 rm -rf "$DESTDIR" "$IMAGE"
1896
1897 # vim:ts=4:sw=4:noet:fdm=marker
This page took 0.196004 seconds and 2 git commands to generate.