]> git.pld-linux.org Git - projects/geninitrd.git/blob - geninitrd
- one more
[projects/geninitrd.git] / geninitrd
1 #!/bin/sh
2
3 # geninitrd
4 #
5 #       by Jacek Konieczny <jajcus@pld.org.pl>
6 #
7 # based on mkinitrd from RedHat
8 #
9 RCSID='$Id: geninitrd,v 2.10 2001/12/15 14:33:09 blues Exp $'
10 PATH=/sbin:$PATH
11 export PATH
12
13 VERSION="`echo "$RCSID"|awk '{print $3}'`"
14
15 . /etc/rc.d/init.d/functions
16
17 COMPRESS="yes"
18 FS="rom"
19 USEBSP="yes"
20 USERAIDSTART="no"
21 PRESCSIMODS="scsi_mod unknown sd_mod"
22 PREIDEMODS="ide-mod ide-probe ide-probe-mod ide-disk"
23 target=""
24 kernel=""
25 force=""
26 verbose=""
27 MODULES=""
28 img_vers=""
29 modulefile=/etc/modules.conf
30 raidtab=/etc/raidtab
31 fstab="/etc/fstab"
32
33 usage () {
34         echo "usage: `basename $0` [--version] [-v] [-f] [--ifneeded] [--preload <module>]" 1>&2
35         echo "       [--with=<module>] [--image-version] [--fstab=<fstab>] [--nocompress]" 1>&2 
36         echo "       [--fs=rom|ext2|cram] [--no-bsp] [--modules-conf=<modules.conf>]" 1>&2
37         echo "       <initrd-image> <kernel-version>" 1>&2
38         echo "       (ex: `basename $0` /boot/initrd-2.2.5-15.img 2.2.5-15)" 1>&2
39         exit 1
40 }
41
42
43 my_find() {
44         for name in `ls`
45         do
46                 if [ -d $name ]; then
47                         if [ "$name" != "build" ]; then
48                                 (cd $name;my_find $1/$name $2)
49                         fi
50                 else
51                         if [ -f $name -a "$name" = "$2" ]; then
52                                 echo $1/$name
53                         fi
54                 fi
55         done
56 }
57
58 my_dirname() {
59         echo $1|awk -F/ '{print substr($0, 0, length($0) - length($NF));}'
60 }
61
62 findmodule() {
63         skiperrors=""
64         modName=$1
65         if [ "$(echo $modName | awk '{print(substr($0,1,1));}')" = "-" ]; then
66                 skiperrors=1
67                 modName="$(echo $modName | awk '{print(substr($0,2));}')"
68         fi
69
70         if [ "$modName" = "pluto" ]; then
71                 findmodule fc4
72                 findmodule soc
73         fi
74         if [ "$modName" = "fcal" ]; then
75                 findmodule fc4
76                 findmodule socal
77         fi
78
79         fmPath="`(cd /lib/modules/$kernel; my_find . "$modName.o")`"
80
81         if [ ! -f "/lib/modules/$kernel/$fmPath" ]; then
82                 if [ -n "$skiperrors" ]; then
83                         return
84                 fi
85
86                 # ignore the absence of the scsi modules
87                 for n in $PRESCSIMODS; do
88                         if [ "$n" = "$modName" ]; then
89                                 return;
90                         fi
91                 done;
92
93                 # ignore the absence of the ide modules
94                 for n in $PREIDEMODS; do
95                         if [ "$n" = "$modName" ]; then
96                                 return;
97                         fi
98                 done;
99     
100                 echo "No module $modName found for kernel $kernel" 1>&2
101                 exit 1
102         fi
103
104         # only need to add each module once
105         tmpFmPath="`echo "$fmPath"|awk -F/ '{for(i=1;i<NF;i++) { printf("%s\\\\/",$i); } { print $NF; }}'`"
106         if is_yes "`echo "$MODULES" | awk '/"'$tmpFmPath'"/ { print "yes"; }' `" ; then : ; else
107                 MODULES="$MODULES $fmPath"
108         fi
109 }
110
111 inst() {
112         if [ "$#" != "2" ];then
113                 echo "usage: inst <file> <destination>"
114                 return
115         fi 
116         [ -n "$verbose" ] && echo "$1 -> $2"
117         cp "$1" "$2"
118 }
119
120 get_label_ext2 () {
121         /sbin/e2label $1 2> /dev/null
122 }
123
124 get_uuid_ext2 () {
125         /sbin/tune2fs -l $1 2> /dev/null | awk  -F: '/UUID:/ {gsub(" ",""); print $2}'
126 }
127
128 get_label_xfs () {
129         /usr/sbin/xfs_db -x -p xfs_admin -c label -r "$1"|awk -F= '{sub("^\"","", $2); sub("\"$", "", $2); print $2}'
130         
131 }
132
133 get_uuid_xfs () {
134         /usr/sbin/xfs_db -x -p xfs_admin -c uuid -r "$1"|awk -F= '{print $2}'
135 }
136
137 find_root() { 
138         eval `awk '/^[\t ]*#/ {next} {if ( $2 == "/" ) {print "rootdev=\"" $1 "\"\nrootFs=\"" $3 "\""}}' $fstab`
139         case $rootdev in
140         LABEL=*)
141                 case $rootFs in
142                 ext2) 
143                         if [ ! -x /sbin/e2label ] ; then
144                                 echo "/sbin/e2label is missing" 1>&2
145                                 exit 1
146                         fi
147                         get_label="get_label_ext2"
148                         ;;
149                 xfs)
150                         if [ ! -x /usr/sbin/xfs_db ] ; then
151                                 echo "/usr/sbin/xfs_db is missing" 1>&2
152                                 exit 1
153                         fi
154                         get_label="get_label_xfs"
155                         ;;
156                 *)
157                         echo "LABEL on $rootFs in not supported by geninitrd" 1>&2
158                         exit 1
159                         ;;
160                 esac
161                 if [ ! -r /proc/partitions ] ; then
162                         echo '/proc/partitions is not readable'; 1>&2
163                         exit 1
164                 fi
165                 label=${rootdev#"LABEL="}
166                 for dev in `awk 'BEGIN {getline;getline} {print "/dev/" $4}' /proc/partitions` ; do
167                         if [ -r $dev ] && [ "$label" = "`$get_label $dev`" ] ; then
168                                 if [ -n "$verbose" ] ; then
169                                         echo "Using $dev as device for rootfs"
170                                 fi
171                             rootdev=$dev
172                             rootdev_found=1
173                             break
174                         fi
175                 done
176                 if [ "$rootdev_found" != 1 ] ; then
177                     echo "geninitrd can't find real device for LABEL=$label" 1>&2
178                     exit 1
179                 fi
180                 ;;
181         UUID=*)
182                 case $rootFs in
183                 ext2) 
184                         if [ ! -x /sbin/tune2fs ] ; then
185                                 echo "/sbin/tune2fs is missing" 1>&2
186                                 exit 1
187                         fi
188                         get_uuid="get_uuid_ext2"
189                         ;;
190                 xfs)
191                         if [ ! -x /usr/sbin/xfs_db ] ; then
192                                 echo "/usr/sbin/xfs_db is missing" 1>&2
193                                 exit 1
194                         fi
195                         get_label="get_uuid_xfs"
196                         ;;
197                 *)
198                         echo "UUID on $rootFs in not supported by geninitrd" 1>&2
199                         exit 1
200                         ;;
201                 esac
202                 if [ ! -r /proc/partitions ] ; then
203                         echo '/proc/partitions is not readable'; 1>&2
204                         exit 1
205                 fi
206                 uuid=${rootdev#"UUID="}
207                 for dev in `awk 'BEGIN {getline;getline} {print "/dev/" $4}' /proc/partitions` ; do
208                         if [ -r $dev ] && [ "$uuid" = "`$get_uuid $dev`" ] ; then
209                                 if [ -n "$verbose" ] ; then
210                                         echo "Using $dev as device for rootfs"
211                                 fi
212                             rootdev=$dev
213                             rootdev_found=1
214                             break
215                         fi
216                 done
217                 if [ "$rootdev_found" != 1 ] ; then
218                     echo "geninitrd can't find real device for UUID=$uuid" 1>&2
219                     exit 1
220                 fi
221                 ;;
222         esac
223
224 }
225
226 if [ -r /etc/sysconfig/geninitrd ] ; then
227         . /etc/sysconfig/geninitrd
228 fi
229
230 if is_yes $USEBSP ; then
231         [ ! -x /sbin/bsp ] && USEBSP="no"
232 fi
233 if [ "`uname -m`" = "ia64" ]; then
234         IMAGESIZE=3000
235 else
236         IMAGESIZE=1500
237 fi
238 while [ $# -gt 0 ]; do
239         case $1 in
240         --no-bsp)
241                 USEBSP="no"
242                 ;;
243         --fstab*)
244                 if is_yes "`echo $1 | awk '/=/ { print "yes"; }'`" ; then
245                         fstab="`echo $1 | awk -F= '{print $2;}'`"
246                 else
247                         fstab="$2"
248                         shift
249                 fi                  
250                 ;;
251         --modules-conf=*)
252                 modulefile="`echo $1 | awk -F= '{print $2;}'`"
253                 ;;
254         --modules-conf)
255                 modulefile="$2"
256                 shift
257                 ;;
258         --raidtab=*)
259                 raidtab="`echo $1 | awk -F= '{print $2;}'`"
260                 ;;
261         --raidtab)
262                 raidtab="$2"
263                 shift
264                 ;;
265         --with*)
266                 if is_yes "`echo $1 | awk '/=/ { print "yes"; }'`" ; then
267                         modname="`echo $1 | awk -F= '{print $2;}'`"
268                 else
269                         modname="$2"
270                         shift
271                 fi                  
272
273                 BASICMODULES="$BASICMODULES $modname"
274                 ;;
275         --version)
276                 echo "geninitrd: version $VERSION"
277                 exit 0
278                 ;;
279         -v)
280                 verbose=-v
281                 ;;
282         --nocompress)
283                 COMPRESS="no"
284                 ;;
285         --ifneeded)
286                 ifneeded=1
287                 ;;
288         -f)
289                 force=1
290                 ;;
291         --preload*)
292                 if is_yes "`echo $1 | awk '/=/ { print "yes"; }'`" ; then
293                         modname="`echo $1 | awk -F= '{print $2;}'`"
294                 else
295                         modname="$2"
296                         shift
297                 fi                  
298                 PREMODS="$PREMODS $modname"
299                 ;;
300         --fs=*)
301                 FS="`echo $1 | awk -F= '{print $2;}'`"
302                 ;;
303         --fs)
304                 FS="$2"
305                 shift
306                 ;;
307         --image-version)
308                 img_vers=yes
309                 ;;
310         --use-raidstart)
311                 USERAIDSTART=yes
312                 ;;
313         *)
314                 if [ -z "$target" ]; then
315                         target="$1"
316                 elif [ -z "$kernel" ]; then
317                         kernel="$1"
318                 else
319                         usage
320                 fi
321                 ;;
322         esac
323
324         shift
325 done
326
327 if [ -z "$target" -o -z "$kernel" ]; then
328         usage
329 fi
330
331 case "$FS" in
332         ext2)
333                 if [ ! -x /sbin/mke2fs ]; then
334                         echo "/sbin/mke2fs is missing" 1>&2
335                         exit 1
336                 fi
337                 ;;
338         rom)
339                 if [ ! -x /sbin/genromfs ]; then
340                         echo "/sbin/genromfs is missing" 1>&2
341                         exit 1
342                 fi
343                 ;;
344         cram)
345                 if [ ! -x /sbin/mkcramfs ]; then
346                         echo "/sbin/mkcramfs is missing" 1>&2
347                         exit 1
348                 fi
349                  ;;
350         *)
351                 echo "Filesystem $FS on initrd is not supported" 1>&2
352                 exit 1
353                 ;;
354 esac
355
356 if [ -n "$img_vers" ]; then
357         target="$target-$kernel"
358 fi
359
360 if [ -z "$force" -a -f "$target" ]; then
361         echo "$target already exists." 1>&2
362         exit 1
363 fi
364
365 if [ ! -d "/lib/modules/$kernel" ]; then
366         echo "/lib/modules/$kernel is not a directory." 1>&2
367         exit 1
368 fi
369
370 for n in $PREMODS; do
371         findmodule "$n"
372 done
373
374 find_root
375
376 if is_yes "`echo "$rootdev" | awk '/^\/dev\/md/ { print "yes"; }'`"; then
377         eval `awk -v rootdev=$rootdev 'BEGIN {
378         addide="no"; 
379         addscsi="no";
380         found="no";
381
382
383
384         gsub("\t"," "); 
385         gsub("  +", " "); 
386         gsub("^ ",""); 
387         if (/^[\t ]*#/) 
388                 next; 
389         if (/^raiddev/) { 
390                 if ($2 == rootdev) {
391                         found="yes";
392                 } else {
393                         if (found == "yes") {
394                                 exit 0;
395                         };
396                 }; 
397         }; 
398         if (found == "yes") {
399                 if ($1 == "device") {
400                         if ($2 ~ /\/dev\/(sd|scsi)/) {
401                                 addscsi="yes";
402                         };
403                         if ($2 ~ /\/dev\/(hd|ide)/) {
404                                 addide="yes";
405                         };
406                 };
407                 if ($1 == "raid-level") {
408                         raidlevel=$2;
409                 }
410         };
411 }
412
413 END {
414         print "raidfound=" found "\nADDSCSI=" addscsi "\nADDIDE=" addide "\nraidlevel=" raidlevel "\n";
415 }' $raidtab `
416     if is_yes "$raidfound" ; then
417             case "$raidlevel" in
418             [0145])
419                         findmodule "raid$raidlevel"
420                         ;;
421                 linear)
422                         findmodule "linear"
423                         ;;
424             *)
425                         echo "raid level $number (in $raidtab) not recognized" 1>&2
426                         ;;
427             esac
428     fi
429
430 else
431         USERAIDSTART="no"
432 fi
433
434 if is_yes "$ADDSCSI" || is_yes "$(echo "$rootdev" | awk '/^\/dev\/(sd|scsi)/ { print "yes"; }')" ; then
435
436     for n in $PRESCSIMODS; do
437         if [ "$n" = "unknown" ] ; then
438                 if [ ! -f "$modulefile" ]; then
439                         modulefile=/etc/conf.modules
440                 fi
441                 if [ -f "$modulefile" ]; then
442                         scsimodules="`awk '/scsi_hostadapter/ && ! /^[\t ]*#/ { print $3; }' $modulefile| LC_ALL=C sort -u`"
443                         for n in $scsimodules; do
444                 # for now allow scsi modules to come from anywhere.  There are some
445                 # RAID controllers with drivers in block/
446                                 findmodule "$n"
447                         done
448                 fi
449         else
450                 findmodule "$n"
451         fi
452     done
453
454 fi
455
456 if is_yes "$ADDIDE" || is_yes "`echo "$rootdev" | awk '/^\/dev\/(hd|ide)/ { print "yes"; }'`" ; then
457         for n in $PREIDEMODS; do
458                 findmodule "$n"
459         done
460 fi
461
462 if is_yes "`echo "$rootdev" | awk '/\/dev\/rd\// { print "yes"; }'`" ; then
463         findmodule "DAC960"
464 fi
465
466 if is_yes "`echo "$rootdev" | awk '/\/dev\/ida\// { print "yes"; }'`" ; then
467         findmodule "cpqarray"
468 fi
469
470 if is_yes "`echo "$rootdev" | awk '/\/dev\/cciss\// { print "yes"; }'`" ; then
471         findmodule "cciss"
472 fi
473
474 # check to see if we need to set up a loopback filesystem
475 if is_yes "`echo "$rootdev" | awk -F/ '{print($3);}' | awk '/loop/ { print "yes"; }'`" ; then
476         if [ ! -x /sbin/losetup ]; then
477                 echo "losetup is missing"
478                 exit 1
479         fi
480         key="^# $(echo $rootdev | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
481         if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`" ; then
482                 echo "The root filesystem is on a $rootdev, but there is no magic entry in $fstab" 1>&2
483                 echo "for this device. Consult the geninitrd man page for more information" 1>&2
484                 exit 1
485         fi
486
487         line="`awk '/'$key'/ { print $0; }' $fstab`"
488         loopDev="$(echo $line | awk '{print $3}')"
489         loopFs="$(echo $line | awk '{print $4}')"
490         loopFile="$(echo $line | awk '{print $5}')"
491
492         BASICMODULES="$BASICMODULES -loop"
493         findmodule "-$loopFs"
494         BASICMODULES="$BASICMODULES -${loopFs}"
495         # don't have any clue, how is this supposed to work,
496         # anyway no bsp
497         USEBSP="no"
498 else # Check for other filesystems
499         findmodule "-$rootFs"
500 fi
501
502 for n in $BASICMODULES; do 
503         findmodule "$n"
504 done
505
506 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
507         if [ -n "$verbose" ]; then
508                 echo "No modules are needed -- not building initrd image."
509         fi
510         exit 0
511 fi
512
513 if [ -n "$verbose" ]; then
514         echo "Using modules: $MODULES"
515 fi
516
517 MNTIMAGE="`mktemp -d /tmp/initrd.XXXXXX`"
518 IMAGE="`mktemp -u /tmp/initrd.img-XXXXXX`"
519 MNTPOINT="`mktemp -d /tmp/initrd.mnt-XXXXXX`"
520 RCFILE="$MNTIMAGE/linuxrc"
521
522 if [ -f "$MNTIMAGE" ]; then
523         echo "$MNTIMAGE already exists.  Remove it and try again" 1>&2
524         exit 1
525 fi
526
527 if [ -f "$IMAGE" ]; then
528         echo "$IMAGE already exists. Remove it and try again" 1>&2
529         exit 1
530 fi
531
532 if [ "$FS" = "ext2" ] ; then
533         dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
534
535         # We have to "echo y |" so that it doesn't complain about $IMAGE not
536         # being a block device
537         echo y | mke2fs -F "$IMAGE" "$IMAGESIZE" >/dev/null 2>/dev/null
538
539         mkdir -p "$MNTPOINT"
540         mount -o loop -t ext2 "$IMAGE" "$MNTPOINT"
541 else
542         mkdir -p "$MNTPOINT"
543 fi
544
545
546 mkdir -p "$MNTIMAGE"/{lib,bin,etc,dev,loopfs}
547
548
549 # We don't need this directory, so let's save space
550 rm -rf "$MNTPOINT"/lost+found
551
552 for MODULE in $MODULES; do
553         MODULEDIR="`my_dirname "$MODULE"`"
554         mkdir -p "$MNTIMAGE/lib/modules/$kernel/$MODULEDIR"
555         cp $verbose -a "/lib/modules/$kernel/$MODULE" "$MNTIMAGE/lib/modules/$kernel/$MODULE"
556 done
557
558 # mknod'ing the devices instead of copying them works both with and
559 # without devfs...
560 mknod "$MNTIMAGE/dev/console" c 5 1
561
562 if is_yes "$USEBSP" ; then
563         s="$MNTIMAGE/etc/startup"
564         inst /sbin/bsp "$RCFILE"
565         echo "# autogenerated startup" > "$s"
566         echo "" >> "$s"
567     
568         for MODULE in $MODULES; do
569                 module="`echo $MODULE | awk -F/ '{ $0=$NF } /.o$/ { $0=substr($0,1,length($0)-2); } { print $0; }'`"
570                 options="`awk '{ if($1 == "options" && $2 == "'${module}'") { for(i=3;i<=NF;i++) printf("%s ",$i); }}' "$modulefile"`"
571     
572                 if [ -n "$verbose" ]; then
573                         /bin/echo -n "Loading module $module "
574                         if [ -n "$options" ] ; then
575                                 echo "with options $options."
576                         else
577                                 echo "without options."
578                         fi
579                 fi
580                 echo "insmod /lib/modules/$kernel/$MODULE $options" >> "$s"
581         done
582 else
583         inst /bin/trash "$MNTIMAGE/bin/sh"
584         inst /sbin/insmod.static "$MNTIMAGE/bin/insmod"
585     
586         mknod "$MNTIMAGE/dev/null" c 1 3
587         mknod "$MNTIMAGE/dev/ram" b 1 1
588         mknod "$MNTIMAGE/dev/systty" c 4 0
589         for i in 1 2 3 4; do
590                 mknod "$MNTIMAGE/dev/tty$i" c 4 1
591         done
592         mknod "$MNTIMAGE/dev/zero" c 1 5
593     
594         echo "#!/bin/sh" > "$RCFILE"
595         echo "" >> "$RCFILE"
596     
597         for MODULE in $MODULES; do
598                 module="`echo $MODULE | awk -F/ '{ $0=$NF } /.o$/ { $0=substr($0,1,length($0)-2); } { print $0; }'`"
599                 if [ -f "$modulefile" ] ; then
600                         options="`awk '{ if($1 == "options" && $2 == "'${module}'") { for(i=3;i<=NF;i++) printf("%s ",$i); }}' "$modulefile"`"
601                 else
602                         options=
603                 fi
604
605                 if [ -n "$verbose" ]; then
606                         echo "Loading module $module with options $options"
607                 fi
608                 echo "Add module $module to initrd."
609                 echo "echo \"Loading $module module\"" >> "$RCFILE"
610                 echo "insmod -k /lib/modules/$kernel/$MODULE $options" >> "$RCFILE"
611         done
612
613
614         if [ -n "$loopDev" ]; then
615                 if [ ! -d /initrd ]; then
616                         mkdir /initrd
617                 fi
618     
619                 cp -a "$loopDev" "$MNTIMAGE/dev"
620                 cp -a "$rootdev" "$MNTIMAGE/dev"
621                 echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
622                 echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
623                 echo "echo Setting up loopback device $rootdev" >> $RCFILE
624                 echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
625         fi
626 fi
627
628 if is_yes "$USERAIDSTART" ; then 
629         if [ -x /sbin/raidstart.static ] ; then
630                 [ -n "$verbose" ] && echo "Add raidstart to initrd"
631                 mkdir -p "$MNTIMAGE/etc" || true
632                 inst /sbin/raidstart.static "$MNTIMAGE/bin/raidstart"
633                 inst "$raidtab" "$MNTIMAGE/etc/raidtab"
634                 echo "echo \"Starting RAID\"" >> "$RCFILE"
635                 echo "/bin/raidstart $rootdev" >> "$RCFILE"
636         else
637                 echo "/sbin/raidstart.static is missing" 1>&2
638                 exit 1
639         fi
640 fi
641
642 chmod +x "$RCFILE"
643
644 (cd "$MNTIMAGE"; tar cf - .) | (cd "$MNTPOINT"; tar xf -)
645
646 case "$FS" in
647         ext2)
648                 umount "$IMAGE"
649                 ;;
650         rom)
651                 genromfs -f "$IMAGE" -d "$MNTPOINT" -V "PLD initrd for kernel $kernel"
652                 ;;
653         cram)
654                 mkcramfs "$MNTPOINT" "$IMAGE"
655                 ;;
656         *)
657                 echo "Filesystem $FS not supported by $0";
658 esac            
659
660 if is_yes "$COMPRESS" ; then
661         gzip -9 < "$IMAGE" > "$target"
662 else
663         cp -a "$IMAGE" "$target"
664 fi
665 rm -rf "$MNTIMAGE" "$MNTPOINT" "$IMAGE"
This page took 0.188006 seconds and 3 git commands to generate.