summaryrefslogtreecommitdiff
path: root/packages/openslug-init/openslug-init-0.10/turnup
diff options
context:
space:
mode:
authorJohn Bowler <jbowler@nslu2-linux.org>2005-05-23 18:02:35 +0000
committerJohn Bowler <jbowler@nslu2-linux.org>2005-05-23 18:02:35 +0000
commit4b72cfb3f2a471ece09a87321a790c92cfe6966f (patch)
tree49b8bd2df4c5800fa98a5e20f6def71886227a4f /packages/openslug-init/openslug-init-0.10/turnup
parent25282cd2b0ad770927943ef428f7f4eca869cb98 (diff)
New /linuxrc boot mechanism
Use "turnup help" to find out how to do turnup now! BKrev: 42921abbPAuC7JcmxHiVNgYZgCeE5A
Diffstat (limited to 'packages/openslug-init/openslug-init-0.10/turnup')
-rw-r--r--packages/openslug-init/openslug-init-0.10/turnup612
1 files changed, 612 insertions, 0 deletions
diff --git a/packages/openslug-init/openslug-init-0.10/turnup b/packages/openslug-init/openslug-init-0.10/turnup
index e69de29bb2..b688bc3051 100644
--- a/packages/openslug-init/openslug-init-0.10/turnup
+++ b/packages/openslug-init/openslug-init-0.10/turnup
@@ -0,0 +1,612 @@
+#!/bin/sh
+# turnup
+# See the help block at the end for documentation.
+#
+. /etc/default/functions
+
+#
+# force: override certain checks
+force=
+#
+# check_rootfs [-i] <root fs directory>
+# Make sure the candidate rootfs is empty
+check_rootfs() {
+ local fcount
+
+ case "$1" in
+ -i) shift
+ case "$force" in
+ -f) return 0;;
+ esac
+
+ fcount="$(find "$1" ! -type d -print | wc -l)"
+ test "$fcount" -eq 0 && return 0
+
+ echo "turnup: $1: partition contains existing files, specify -f to overwrite" >&2
+ return 1;;
+ *) checkmount "$1" && return 0
+
+ echo "turnup: $1: partition does not seem to be a valid root partition" >&2
+ if test -f "$1"/.recovery
+ then
+ echo " $1/.recovery exists: fix the partition then remove it" >&2
+ fi
+ return 1;;
+ esac
+}
+#
+# copy_rootfs old new
+# Make a copy of the given root file system, copying only the
+# directories needed. The root must be the flash file system
+copy_rootfs() {
+ local old new
+ old="$1"
+ new="$2"
+ test -d "$old" -a -d "$new" || {
+ echo "turnup: rootfs: copy $old $new: not a directory" >&2
+ return 1
+ }
+ #
+ # There are no problem file names in the flash file system, so
+ # it is possible to use -print, not -print0. The following
+ # files and directories are not copied:
+ #
+ # /dev/*
+ # /boot, /boot/*
+ # /linuxrc*
+ # /var/*
+ echo "turnup: copying root file system" >&2
+ ( cd "$1"
+ find . -mount -print |
+ sed '\@^./dev/@d;\@^./boot/@d;\@^./boot$@d;\@^./linuxrc@d;\@^./var/@d' |
+ cpio -p -d -m -u "$2"
+ ) || {
+ echo "turnup: rootfs: cpio $old $new failed" >&2
+ return 1
+ }
+ echo "done" >&2
+}
+
+#
+# setup_dev new device_table
+# Populates the /dev directory, removes the ramfs mount of /dev by
+# removing the links to the devices startup file.
+setup_dev() {
+ test -n "$1" -a -d "$1"/dev -a -r "$2" || {
+ echo "turnup: setup_dev($1,$2): expected a directory and a file" >&2
+ return 1
+ }
+ # at present the device_table is not used because it is incomplete,
+ # /etc/init.d/devices adds extra stuff. So this script copies the
+ # existing /dev. FIXME.
+ echo "turnup: copying dev file system" >&2
+ ( cd /
+ find dev -print0 | cpio -p -0 -d -m -u "$1"
+ ) || {
+ echo "turnup: rootfs: cpio /dev $1 failed" >&2
+ return 1
+ }
+ echo "done" >&2
+ # now remove the startup links which mount the ramfs on /dev
+ rm "$1"/etc/rc?.d/[KS]??devices
+ return 0
+}
+
+#
+# setup_bootdev new device_table
+# As above but actually uses the supplied device table - this is possible if
+# the table is just used for boot because the extra setup is not required.
+setup_bootdev() {
+ test -n "$1" -a -d "$1"/dev -a -r "$2" || {
+ echo "turnup: setup_bootdev($1,$2): expected a directory and a file" >&2
+ return 1
+ }
+ # NOTE: this fails silently with 0 return code(!) when a directory
+ # does not exist yet things are created within it.
+ makedevs -r "$1" -D "$2"
+}
+
+#
+# setup_var new type
+# Populates /var. Should only be called for true disk systems and NFS -
+# it's a waste on USB memory sticks! Removes the /var tmpfs setting
+# for disks, sets it to /var/tmp for NFS.
+setup_var() {
+ test -n "$1" -a -d "$1"/var || {
+ echo "turnup: setup_var($1,$2): expected a directory" >&2
+ return 1
+ }
+ case "$2" in
+ disk|nfs);;
+ *) echo "turnup: setup_var($1,$2): expected 'disk' or 'nfs'" >&2
+ return 1;;
+ esac
+ #
+ # populate /var, there is a shell script to do this, but it uses
+ # absolute path names
+ chroot "$1" /bin/busybox sh /etc/init.d/populate-var.sh || {
+ echo "turnup: /var: could not populate directory" >&2
+ return 1
+ }
+ # and remove the startup links
+ rm "$1"/etc/rc?.d/[KS]??populate-var.sh
+ # remove the /var tmpfs entry from the new /etc/fstab
+ case "$2" in
+ disk) sed -i '\@\s/var\s\s*tmpfs\s@d' "$1"/etc/fstab
+ echo "turnup: tmpfs will no longer be mounted on /var" >&2;;
+ nfs) sed -i '\@\s/var\s\s*tmpfs\s@s@\s/var@&/tmp@' "$1"/etc/fstab
+ echo "turnup: tmpfs /var mount moved to /var/tmp" >&2;;
+ esac
+ #
+ # warn the user - it's not enough to put the /var mount back, it
+ # is necessary to reinsert the populate-var.sh links!
+ echo " If you remount tmpfs on /var it must be populated at boot, use:" >&2
+ echo " update-rc.d populate-var.sh start 37 S ." >&2
+ return 0
+}
+
+#
+# setup_files new
+# At present just puts the rmrecovery links in.
+setup_files() {
+ test -n "$1" -a -d "$1"/etc || {
+ echo "turnup: setup_files($1): expected a directory" >&2
+ return 1
+ }
+ #
+ # add the script to remove .recovery
+ update-rc.d -r "$1" rmrecovery start 99 1 2 3 4 5 .
+ return 0
+}
+
+#
+# setup_syslog new
+# Moves the syslog to a file - appropriate for disk and nfs types, not
+# otherwise.
+setup_syslog() {
+ test -n "$1" -a -d "$1"/etc || {
+ echo "turnup: setup_syslog($1): expected a directory" >&2
+ return 1
+ }
+ #
+ # if the syslog is to the buffer redirect it to a file
+ if egrep -q '^DESTINATION="buffer"' "$1"/etc/syslog.conf
+ then
+ if cp "$1"/etc/syslog.conf "$1"/etc/syslog.conf.sav
+ then
+ # the busybox syslog will fail with ROTATESIZE and ROTATEGENS
+ sed -i 's!DESTINATION="buffer"!DESTINATION="file"!
+ /^ROTATESIZE=/d
+ /^ROTATEGENS=/d' "$1"/etc/syslog.conf
+ echo "turnup: /etc/syslog.conf: changed to file buffering" >&2
+ echo " Old (buffer) version in /etc/syslog.conf.sav" >&2
+ echo " Log messages will be in /var/log/messages" >&2
+ else
+ echo "turnup: /etc/syslog.conf: failed to make a copy" >&2
+ echo " syslog will log to a buffer" >&2
+ fi
+ fi
+ return 0
+}
+
+#
+# setup_rootfs type new device_table
+# Populates the /dev and /var directories, alters the startup to
+# not mount or populate them further. Does the right thing according
+# to the given $type
+setup_rootfs() {
+ local type new table
+ type="$1"
+ new="$2"
+ table="$3"
+
+ test -n "$new" -a -d "$new" -a -f "$table" || {
+ echo "turnup: setup_rootfs($type,$new,$table): expected a directory and a file" >&2
+ return 1
+ }
+
+ case "$type" in
+ flash) return 0;;
+ disk) setup_dev "$new" "$table" &&
+ setup_var "$new" disk &&
+ setup_files "$new" &&
+ setup_syslog "$new";;
+ memstick)
+ setup_bootdev "$new" "$table" &&
+ setup_files "$new";;
+ nfs) setup_dev "$new" "$table" &&
+ setup_var "$new" nfs &&
+ setup_files "$new" &&
+ setup_syslog "$new";;
+ *) echo "turnup: setup_rootfs: $type: unknown rootfs type" >&2
+ return 1;;
+ esac
+ # return code of last setup function
+}
+
+#
+# boot_rootfs <boot type> <flash file system> <sleep time> <device> [options]
+# Change the flash partition (not the current root!) to boot off
+# the new root file system
+boot_rootfs() {
+ local type ffs sleep device opt
+
+ type="$1"
+ ffs="$2"
+ sleep="$3"
+ device="$4"
+
+ # test this first as the test does not depend on the correctness
+ # of the other arguments
+ test -n "$ffs" -a -d "$ffs" || {
+ echo "turnup: boot_rootfs($type, $ffs, $device): expected directory" >&2
+ return 1
+ }
+ test -x "$ffs"/boot/"$type" || {
+ echo "turnup: boot_rootfs($type, $ffs, $device): invalid boot type $type" >&2
+ return 1
+ }
+ shift
+ shift
+
+ case "$type" in
+ disk) test -n "$device" -a -b "$device" || {
+ echo "turnup: boot_rootfs($ffs, $type, $device): expected block device" >&2
+ return 1
+ }
+ shift 2;;
+ nfs) shift 2;;
+ flash) ;;
+ ram) ;;
+ *) echo "turnup: boot_rootfs($type, $ffs, $device): unknown type" >&2
+ return 1;;
+ esac
+
+ #
+ # The /linuxrc records the correct options to mount the device,
+ # since we have already mounted if correctly with these options
+ # we can be sure (maybe) that the boot will work. If not /boot/disk
+ # falls back to flash.
+ #
+ # This modifies the boot process, until this point no harm has been
+ # done to the system, but at this point the boot rootfs will change
+ rm -f "$ffs"/linuxrc.new || {
+ echo "turnup: boot_rootfs: failed to remove $ffs/linuxrc.new" >&2
+ return 1
+ }
+ case "$type" in
+ flash) ln -s "boot/flash" "$ffs"/linuxrc.new || {
+ echo "turnup: boot_rootfs: failed to create $ffs/linuxrc.new" >&2
+ return 1
+ };;
+ ram) { echo '#!/bin/sh'
+ echo 'rm -f /linuxrc.new'
+ echo 'ln -s boot/flash /linuxrc.new'
+ echo 'mv /linuxrc.new /linuxrc'
+ echo 'exec /boot/ram /dev/ram0'
+ echo 'exec /boot/flash'
+ } >"$ffs"/linuxrc.new &&
+ chmod 744 "$ffs"/linuxrc.new || {
+ echo "turnup: boot_rootfs: failed to write $ffs/linuxrc.new" >&2
+ return 1
+ };;
+ *) { echo '#!/bin/sh'
+ test "$sleep" -gt 0 && echo -n "sleep='$sleep' "
+ echo -n "exec '/boot/$type' '$device'"
+ for opt in "$@"
+ do
+ echo -n " '$opt'"
+ done
+ echo
+ echo 'exec /boot/flash'
+ } >"$ffs"/linuxrc.new &&
+ chmod 744 "$ffs"/linuxrc.new || {
+ echo "turnup: boot_rootfs: failed to write $ffs/linuxrc.new" >&2
+ return 1
+ };;
+ esac
+ rm -f "$ffs"/linuxrc.sav || {
+ echo "turnup: boot_rootfs: failed to remove $ffs/linuxrc.sav" >&2
+ return 1
+ }
+ ln "$ffs"/linuxrc "$ffs"/linuxrc.sav || {
+ echo "turnup: boot_rootfs: failed to save /linuxrc.sav" >&2
+ return 1
+ }
+ mv -f "$ffs"/linuxrc.new "$ffs"/linuxrc || {
+ echo "turnup: boot_rootfs: failed to install new /linuxrc" >&2
+ return 1
+ }
+ return 0
+}
+
+#
+# mountflash <flash root directory>
+# Finds and mounts the flash file system
+mountflash() {
+ local ffsdev
+
+ ffsdev="$(mtblockdev Flashdisk)"
+ test -n "$ffsdev" -a -b "$ffsdev" || {
+ echo "turnup disk: unable to find flash file system to copy ($ffsdev)" >&2
+ return 1
+ }
+ mount -t jffs2 "$ffsdev" "$1" || {
+ echo "turnup disk: $ffsdev: unable to mount flash file system on $1" >&2
+ return 1
+ }
+ return 0
+}
+
+#
+# disk [-m] [-i] [-s<time>] <device> {options}
+# Carefully copy the flash file system to the named device.
+disk() {
+ local setup_type sleep init device new ffs
+
+ setup_type=disk
+ sleep=0
+ init=
+ while test $# -gt 0
+ do
+ case "$1" in
+ -f) force="$1"
+ shift;;
+ -m) setup_type=memstick
+ shift;;
+ -i) init="$1"
+ shift;;
+ -s*) sleep="${1#-s}"
+ sleep="${sleep:-10}"
+ shift;;
+ *) break;;
+ esac
+ done
+
+ device="$1"
+ test -n "$device" -a -b "$device" || {
+ echo "turnup disk: $device: block device required" >&2
+ return 1
+ }
+ shift
+
+ # make temporary directories for the mount points
+ new="/tmp/rootfs.$$"
+ ffs="/tmp/flashdisk.$$"
+ mkdir "$new" "$ffs" || {
+ echo "turnup: disk: failed to create temporary directories" >&2
+ return 1
+ }
+
+ # make sure we can get to the flash file system first
+ mountflash "$ffs" || {
+ rmdir "$new" "$ffs"
+ return 1
+ }
+
+ # Now mount the device with the given options, note that specifying
+ # read only is *not* an option, this is important because the boot/disk
+ # script needs a rw file system
+ status=1
+ if mount "$@" "$device" "$new"
+ then
+ if check_rootfs $init "$new" && {
+ test -z "$init" || {
+ copy_rootfs "$ffs" "$new" &&
+ setup_rootfs "$setup_type" "$new" "$ffs"/etc/device_table
+ }
+ }
+ then
+ status=0
+ fi
+
+ # clean up the disk. It is worrying if this umount fails!
+ umount "$new" || {
+ echo "turnup disk: $device: umount failed" >&2
+ echo " you must unmount this device cleanly yourself, then use" >&2
+ echo " the -i option to boot from the device" >&2
+ status=1
+ }
+
+ # if everything went ok boot from this disk
+ if test $status -eq 0
+ then
+ # memsticks boot like disks, so ignore the -m
+ boot_rootfs disk "$ffs" "$sleep" "$device" "$@"
+ fi
+ else
+ echo "turnup disk: $device($*): unable to mount device on $new" >&2
+ fi
+
+ # clean up the flash file system
+ umount "$ffs"
+ rmdir "$new" "$ffs"
+ return $status
+}
+
+#
+# boot_reset <type>
+# Resets the boot type to flash or ram, as appropriate
+boot_reset() {
+ local ffs typ status
+
+ case "$1" in
+ flash|ram)type="$1"
+ shift;;
+ *) echo "turnup: boot_reset($1): invalid type" >&2
+ return 1;;
+ esac
+
+ ffs="/tmp/flashdisk.$$"
+ mkdir "$ffs" || {
+ echo "turnup: $1: failed to create temporary directory" >&2
+ return 1
+ }
+
+ mountflash "$ffs" || {
+ rmdir "$ffs"
+ return 1
+ }
+
+ # now try to set the /linuxrc appropriately
+ boot_rootfs "$type" "$ffs"
+ status=$?
+
+ # clean up
+ umount "$ffs"
+ rmdir "$ffs"
+ return $status
+}
+
+#
+# nfs [-i] <root partition> {options}
+# Copy the flash file system to the given NFS root partition.
+nfs() {
+ local init nfsroot new ffs
+
+ init=
+ while test $# -gt 0
+ do
+ case "$1" in
+ -i) init="$1"
+ shift;;
+ -f) force="$1"
+ shift;;
+ *) break;;
+ esac
+ done
+
+ nfsroot="$1"
+ test -n "$nfsroot" || {
+ echo "turnup nfs: $nfsroot: NFS root file system required" >&2
+ return 1
+ }
+ shift
+
+ # make temporary directories for the mount points
+ new="/tmp/rootfs.$$"
+ ffs="/tmp/flashdisk.$$"
+ mkdir "$new" "$ffs" || {
+ echo "turnup nfs: failed to create temporary directories" >&2
+ return 1
+ }
+
+ # make sure we can get to the flash file system first
+ mountflash "$ffs" || {
+ rmdir "$new" "$ffs"
+ return 1
+ }
+
+ # Now mount the device with the given options, note that specifying
+ # read only is *not* an option, this is important because the boot/disk
+ # script needs a rw file system
+ status=1
+ if mount -t nfs -o nolock,noatime,hard,intr,rsize=1024,wsize=1024,"$@" "$nfsroot" "$new"
+ then
+ if :>"$new"/ttt && test -O "$new"/ttt && rm "$new"/ttt
+ then
+ if check_rootfs $init "$new" && {
+ test -z "$init" || {
+ copy_rootfs "$ffs" "$new" &&
+ setup_rootfs nfs "$new" "$ffs"/etc/device_table
+ }
+ }
+ then
+ status=0
+ fi
+ else
+ echo "turnup nfs: $nfsroot: partition must be mounted no_root_squash" >&2
+ fi
+
+ # clean up the disk. It is worrying if this umount fails!
+ umount "$new" || {
+ echo "turnup nfs: $nfsroot: umount failed" >&2
+ if test $status -eq 0
+ then
+ echo " you must unmount this partition cleanly yourself, then use" >&2
+ echo " the -i option to boot from the NFS root" >&2
+ status=1
+ fi
+ }
+
+ # if everything went ok boot from this disk
+ if test $status -eq 0
+ then
+ # the options used are exactly those which worked before.
+ boot_rootfs nfs "$ffs" 0 "$nfsroot" -t nfs \
+ -o nolock,noatime,hard,intr,rsize=1024,wsize=1024,"$@"
+ fi
+ else
+ echo "turnup disk: $nfsroot($*): unable to mount device on $new" >&2
+ fi
+
+ # clean up the flash file system
+ umount "$ffs"
+ rmdir "$new" "$ffs"
+ return $status
+}
+
+#
+# Basic command switch (this should be the only thing in this
+# script which actually does anything!)
+case "$1" in
+init) shift
+ echo "turnup init: NYI" >&2
+ exit 1;;
+disk) shift
+ disk "$@";;
+memstick)
+ shift
+ disk -m "$@" -o noatime;;
+nfs) shift
+ nfs "$@";;
+flash) boot_reset flash;;
+ram) boot_reset ram;;
+*) echo "\
+usage: turnup command [options]
+ commands:
+ help
+ output this help
+ init
+ initialise network information when DHCP is not available
+ disk [-i] [-s<seconds>] <device> [mount options]
+ With -i make <device> a bootable file system then (with or
+ without -i) arrange for the next reboot to use that device.
+ The device must already be formatted as a file system, with
+ -i it must be completely empty, without it must contain an
+ apparently bootable file system. -s (for example -s5)
+ specifies a delay in seconds to wait at boot time before
+ mounting the device.
+ memstick [-i] <device> [mount options]
+ Behaves as disk however options appropriate to a flash memory
+ stick are automatically added
+ nfs [-i] <nfs mount path> [mount options]
+ <nfs mount path> must be a mountable NFS file system. With
+ -i the partition must be empty and is initialised with a
+ bootable file system. Without -i the partition must already
+ contain a bootable file system. In either case the NFS
+ partition must be available to be mounted without root id
+ sqashing (i.e. root must be root) and it will be selected
+ as the root file system for subsequent reboots.
+ The options are added to the -o list, therefore to give
+ additional flag arguments specify an empty first option.
+ The options may be used to override the defaults just by
+ specifying the new value.
+ flash
+ Revert to booting from the flash disk on next reboot.
+ ram
+ Boot (once) into a ramdisk, subsequent boots will be to
+ the flash file system.
+ disk formatting:
+ The argument to 'nfs' or 'disk' must be an empty partition
+ of sufficient size to hold the root file system (at least
+ 16MByte but more is recommended to allow package installation).
+ An appropriate ext3 partition can be made using the command:
+
+ mke2fs -j <device> # for example: /dev/sda1
+
+ An appropriate NFS partition can be emptied using 'rm', but
+ must be set up (exported) on the NFS server." >&2
+ exit 0;;
+esac
+# Exit with return code from command.