# # Debian-initrd -- translate general intentions to exact initrd layout # Copyright (C) 2005 Erik van Konijnenburg # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # This is written in a special purpose language; # see the HTML documentation for syntax definition. # # These templates define the translation from general intentions in the # plan to exact lists of files and script fragments to be included # on the initrd image. Templates are indexed by an action name, and include: # - files to be copied from current system to initrd; # often executables. # - directories to be created # - fragments to be appended to scripts on the image, # these are in a hash from script name to script content. # # Filenames and script fragments are processed by HTML::Template # before being added to the image. # # If you want to implement busybox support, this is the place to do it. # # Obviously, the template names and the attributes used in the template # should match what is provided by the planner. # TEMPLATE SET TEMPLATE prologue BEGIN # # In principle, we don't want device files on the initrd # image: device numbers can change between kernels. # Instead, create device files at boot time based on info # in sysfs. However, /dev/null and /dev/console are needed # to mount sysfs. # FILE "/dev/null" FILE "/dev/console" FILE "/bin/dash" FILE "/bin/cat" FILE "/bin/mkdir" FILE "/bin/mount" FILE "/bin/umount" FILE "/bin/mknod" FILE "/bin/sleep" FILE "/usr/sbin/chroot" FILE "/sbin/pivot_root" DIRECTORY "/mnt" DIRECTORY "/proc" DIRECTORY "/sys" DIRECTORY "/dev" DIRECTORY "/etc" DIRECTORY "/var" SCRIPT "/linuxrc" BEGIN !#!/bin/dash !set -x !export PATH=/sbin:/bin !mount -nt proc proc /proc !root=$(cat proc/sys/kernel/real-root-dev) !echo 256 > proc/sys/kernel/real-root-dev !echo "linuxrc: root is $root" !umount -n /proc !exit 0 END SCRIPT # # We can provide debugging opportunities in the # initramfs image; the question is when and how # to enable this. Consider two types of user: # - a developer, working on the template # - an end user, who has a boot problem with # an image that was generated automatically # after installing a new distribution kernel. # # The developer can simply add debugging code # to the template. # For the end user, adding an option to the kernel # command line is easier to enable debugging # than rebuilding the boot image with special # options or a modified configuration file. # # For this reason, we won't provide a template # parameter to control debugging, instead we # interpret a new kernel command line parameter: # ydebug. # SCRIPT "/sbin/init" BEGIN !#!/bin/dash !# !# Generator version: yaird . !# Kernel version: . !# !INIT_DEBUG= !if [ "$INIT_DEBUG" != "" ] !then ! set -x !fi ! !# !# Utility functions !# !mksymdev () { ! devfile="$1" ! sysfile="$2" ! cb="$3" ! devpair=$(/bin/cat "$sysfile") ! for delay in 1 2 4 8 16 ! do ! if [ "$devpair" = "" ] ! then ! echo "Waiting $delay seconds for $sysfile to show up" ! sleep $delay ! fi ! devpair=$(/bin/cat "$sysfile") ! done ! ! if [ "$devpair" = "" ] ! then ! echo "Device $sysfile seems to be down." ! echo "Debugging opportunity, type ^D to continue." ! /bin/dash ! fi ! ! maj=${devpair%:*} ! min=${devpair#*:} ! /bin/mknod "$devfile" $cb $maj $min !} !mkcdev () { ! mksymdev "$1" "/sys/class/$2/dev" c !} !mkbdev () { ! mksymdev "$1" "/sys/block/$2/dev" b !} ! !switchroot () { ! if [ "$INIT_DEBUG" != "" ] ! then ! echo "Debugging opportunity, ^D to continue." ! /bin/dash ! fi ! ! echo "Switching root ..." ! cd /mnt ! # unmount /dev/twice, may have devfs planted by kernel ! /bin/umount -n /dev ! /bin/umount -n /dev ! /bin/umount -n /var ! /bin/umount -n /etc ! /bin/umount -n /sys ! /bin/umount -n /proc ! /sbin/pivot_root . initrd ! exec initrd/usr/sbin/chroot . $init "$@" < dev/console > dev/console 2>&1 !} ! !# !# Setting up mounts !# !/bin/mount -nt sysfs sysfs /sys !/bin/mount -nt proc proc /proc !/bin/mount -nt tmpfs none /dev !# these help for vgchange !/bin/mount -nt tmpfs tmpfs /etc !/bin/mount -nt tmpfs tmpfs /var !# /dev/tty is needed for eg cryptsetup. !mkcdev /dev/tty tty/tty ! !# !# Command line processing !# init - first proc to start on next root !# root - to be done: how should it relate !# to file system selection? !# ro,rw - mount root read-only or read-write. !# This is like a mount -r; it overrules !# a -o rw. !# noresume, resume - to be done !# ide - options for module ide_core. !# need a way to append these to proper !# module. do a check on module name !# in insmod template? !# ip=, nfsaddrs=, nfsroot= - support NFS boot !# !ro=-r !ip= !nfsroot= !init=/sbin/init !for i in $(cat /proc/cmdline) !do ! case "$i" in ! init=*) ! init=${i#init=} ! ;; ! ro) ! ro=-r ! ;; ! rw) ! ro= ! ;; ! ip=*|nfsaddrs=*) ! ip="$ip $i" ! ;; ! nfsroot=*) ! nfsroot="$i" ! ;; ! ydebug) ! INIT_DEBUG=yes ! esac !done !if [ "$INIT_DEBUG" != "" ] !then ! set -x !fi END SCRIPT END TEMPLATE TEMPLATE insmod BEGIN FILE "" FILE "/sbin/insmod" # optionList may be undef # and already is suitably escaped. SCRIPT "/sbin/init" BEGIN !/sbin/insmod '' END SCRIPT END TEMPLATE TEMPLATE mkbdev BEGIN SCRIPT "/sbin/init" BEGIN !mkbdev '' '' END SCRIPT END TEMPLATE # # We cannot make mapper/control any earlier, # since dm-mod needs to be loaded to be able # to determine devno. # TEMPLATE vgchange BEGIN # Older Debian releases needs this one #FILE "/lib/lvm-200/vgchange" FILE "/sbin/vgchange" SCRIPT "/sbin/init" BEGIN !if [ ! -c /dev/mapper/control ] !then ! /bin/mkdir /dev/mapper ! mkcdev /dev/mapper/control misc/device-mapper !fi !/sbin/vgchange -a y '' END SCRIPT END TEMPLATE # # NOTE: mdadm can operate without knowledge # of device numbers; it will assign an unused # one to the new device. Thus you could have # device name /dev/md/boot that is stable, # regardless of which other raid devices are # operational. However, debian installer # consistently uses device names like /dev/md0, # where the name depends on earlier minors # that happen to have been assigned. # To work around this problem, we forego # the --auto option, and mknod the device # before putting an md under it. Better hope # the major number is not going to change ... # TEMPLATE mdadm BEGIN FILE "/sbin/mdadm" SCRIPT "/sbin/init" BEGIN !mknod b !mdadm --assemble --uuid \ ! END SCRIPT END TEMPLATE # # cryptsetup arguments: # - target # - cipher # - keySize (always there, 0 for NULL crypto) # - hash (hashname or undef) # - src # - verify (yes or undef) # # A loop around 'cryptsetup --verify' can help detect # and correct typo's in the crypt password. # TEMPLATE cryptsetup BEGIN FILE "/sbin/cryptsetup" FILE "/bin/loadkeys" FILE "/bin/gzip" FILE "/etc/console/boottime.kmap.gz" FILE "/sbin/blkid" SCRIPT "/sbin/init" BEGIN !# loadkeys from the kbd package has problems !# uncompressing the keymap on-the-fly when !# run from initramfs, don't know why !if [ -e /etc/console/boottime.kmap.gz ] !then ! gzip -d /etc/console/boottime.kmap.gz !fi !if [ -e /etc/console/boottime.kmap ] !then ! loadkeys /etc/console/boottime.kmap !fi !DOCRYPT=1 !while [ "$DOCRYPT" != "0" ] !do ! /sbin/cryptsetup \ ! -c \ ! -s \ ! \ ! -h '' \ ! \ ! -y \ ! create '' \ ! '' ! DOCRYPT=$? ! while [ "$DOCRYPT" = "0" ] \ ! && [ -x /sbin/blkid ] \ ! && [ -z "`/sbin/blkid '/dev/mapper/'`" ] ! do ! echo 'Unable to identify the filesystem on volume .' ! echo 'Reenter, Ignore, Shell?' ! read a ! case "$a" in ! i|I) ! break ! ;; ! s|S) ! /bin/dash ! ;; ! r|R|*) ! /sbin/cryptsetup remove '' ! DOCRYPT=1 ! ;; ! esac ! done !done END SCRIPT END TEMPLATE # # cryptsetup arguments: # - target # - src # - verify (yes or undef) # # A loop around 'cryptsetup --verify' can help detect # and correct typo's in the crypt password. # TEMPLATE cryptsetup_luks BEGIN FILE "/sbin/cryptsetup" FILE "/bin/loadkeys" FILE "/bin/gzip" FILE "/etc/console/boottime.kmap.gz" FILE "/sbin/blkid" SCRIPT "/sbin/init" BEGIN !# loadkeys from the kbd package has problems !# uncompressing the keymap on-the-fly when !# run from initramfs, don't know why !if [ -e /etc/console/boottime.kmap.gz ] !then ! gzip -d /etc/console/boottime.kmap.gz !fi !if [ -e /etc/console/boottime.kmap ] !then ! loadkeys /etc/console/boottime.kmap !fi !DOCRYPT=1 !while [ "$DOCRYPT" != "0" ] !do ! /sbin/cryptsetup \ ! -y \ ! luksOpen '' \ ! '' ! DOCRYPT=$? ! while [ "$DOCRYPT" = "0" ] \ ! && [ -x /sbin/blkid ] \ ! && [ -z "`/sbin/blkid '/dev/mapper/'`" ] ! do ! echo 'Unable to identify the filesystem on volume .' ! echo 'Reenter, Ignore, Shell?' ! read a ! case "$a" in ! i|I) ! break ! ;; ! s|S) ! /bin/dash ! ;; ! r|R|*) ! /sbin/cryptsetup luksClose '' ! DOCRYPT=1 ! ;; ! esac ! done !done END SCRIPT END TEMPLATE # # NOTE: honouring the kernel cmdline option ro,rw # is very nice, but... If you have an ext3 in a # file loopback-mounted from vfat, it's unlikely # that a remount rw of root will also make the # underlying vfat read-write. Underlying filesystems # should ignore the kernel ro/rw option; we # have an attribute isRoot that's defined iff # this is the real root. # # always -n, since we dont have writable /etc/mtab. # TEMPLATE mount BEGIN SCRIPT "/sbin/init" BEGIN !/bin/mount -n \ ! $ro \ ! -t \ ! \ ! '' \ ! '' END SCRIPT END TEMPLATE TEMPLATE nfsstart BEGIN FILE "/trynfs" SCRIPT "/sbin/init" BEGIN !if [ "$ip" != "" ] !then ! /trynfs $ip $nfsroot /mnt ! switchroot "$@" !fi END SCRIPT END TEMPLATE TEMPLATE postlude BEGIN SCRIPT "/sbin/init" BEGIN !switchroot "$@" END SCRIPT END TEMPLATE END TEMPLATE SET