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