New /linuxrc boot mechanism
authorJohn Bowler <jbowler@nslu2-linux.org>
Mon, 23 May 2005 18:02:35 +0000 (18:02 +0000)
committerJohn Bowler <jbowler@nslu2-linux.org>
Mon, 23 May 2005 18:02:35 +0000 (18:02 +0000)
Use "turnup help" to find out how to do turnup now!

BKrev: 42921abbPAuC7JcmxHiVNgYZgCeE5A

packages/busybox/busybox-1.00/openslug/udhcpscript.patch [new file with mode: 0644]
packages/busybox/busybox_1.00.bb
packages/meta/openslug-image.bb
packages/openslug-init/openslug-init-0.10/leds_rs_green
packages/openslug-init/openslug-init-0.10/sysconfsetup
packages/openslug-init/openslug-init-0.10/turnup
packages/openslug-init/openslug-init_0.10.bb

diff --git a/packages/busybox/busybox-1.00/openslug/udhcpscript.patch b/packages/busybox/busybox-1.00/openslug/udhcpscript.patch
new file mode 100644 (file)
index 0000000..e69de29
index a532168..0ae99d0 100644 (file)
@@ -10,7 +10,7 @@ HOMEPAGE = "http://www.busybox.net"
 LICENSE = "GPL"
 SECTION = "base"
 PRIORITY = "required"
-PR = "r19"
+PR = "r20"
 
 SRC_URI = "http://www.busybox.net/downloads/busybox-${PV}.tar.gz \
            file://add-getkey-applet.patch;patch=1 \
index 5dc3fc4..8e50c1b 100644 (file)
@@ -1,4 +1,4 @@
-PR = "r10"
+PR = "r11"
 
 IMAGE_BASENAME = "openslug"
 
@@ -19,6 +19,7 @@ DEPENDS = "virtual/kernel base-files base-passwd \
 
 # NOTE: file system kernel modules are defined in openslug.conf
 # (OPENSLUG_EXTRA_FILESYSTEMS, included in OPENSLUG_EXTRA_INSTALL)
+# kernel-module-af-packet must be in the image for DHCP to work
 IPKG_INSTALL = "base-files base-passwd \
         busybox dropbear hotplug-ng initscripts netbase \
         update-modules sysvinit tinylogin lrzsz portmap \
@@ -27,6 +28,8 @@ IPKG_INSTALL = "base-files base-passwd \
         ipkg-collateral ipkg ipkg-link diffutils \
        cpio findutils e2fsprogs-mke2fs \
        e2fsprogs-fsck e2fsprogs-e2fsck \
+       kernel-module-af-packet \
+       kernel-module-netconsole \
         ${OPENSLUG_EXTRA_INSTALL}"
 
 inherit image_ipk
index e69de29..5483d67 100644 (file)
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# This script is executed at the start and end of each run-level
+# transition.  It is the first 'stop' script and the last 'start'
+# script.
+#
+# 'stop'  sets the correct colour power LED to flash between the
+#         two colours of the previous and next runlevel.
+# 'start' sets the LED to steady
+#
+# 'red'   is the initial setting on kernel boot
+#
+# 'amber' is used for run levels S (from /linuxrc), 0 (halt),
+#         1 (single user) and 6 (reboot).  halt and reboot do not
+#         terminate therefore the LED remains flashing until the
+#         kernel terminates.
+#
+# 'green' is used for run levels 2-5 - the normal user run levels.
+#
+# colours are 'g' (green), 'r' (red) or 'gr' (amber).
+colour() {
+       case "$1" in
+       S|0|1|6) echo gr;;
+       2|3|4|5) echo g;;
+       N)       echo gr;; # apparently used for S as well
+       *)       echo "led change: $runlevel: runlevel unknown" >&2
+                echo r;;
+       esac
+}
+
+# leds syntax is -A +<init state> /<new state>
+case "$1" in
+start) leds -A +"$(colour "$runlevel")";;
+stop)  leds -A +"$(colour "$previous")" /"$(colour "$runlevel")";;
+*)     echo "led change: $1: command ignored" >&2;;
+esac
+
+exit 0
index 83b8d34..4ed4e10 100644 (file)
 #!/bin/sh
-if [ ! -e /etc/linksysconf ]
+# This script is run once when the system first boots.  Its sole
+# purpose is to create /etc/default/sysconf (the overall system
+# configuration file) and other files derived from this.
+#
+# The script runs immediately after S10checkroot.sh - this is the
+# point at which the rootfs will be mounted rw even if the kernel
+# booted with it ro.
+#
+# rm or mv the file to run this again.  If this is done the
+# following configuration files will be rewritten:
+#
+# /etc/default/sysconf
+# /etc/hostname
+# /etc/defaultdomain
+# /etc/network/interfaces
+# /etc/resolv.conf
+#
+test -r /etc/default/sysconf && exit 0
+#
+# /etc/default/functions contains useful utility functions - it's
+# in a separate file so that it can be loaded by any script
+. /etc/default/functions
+#
+# Utility to deal with absence of DNS configuration
+echodns(){
+       local dns
+       if test $# -gt 0
+       then
+               for dns in "$@"
+               do
+                       echo "nameserver $dns"
+               done
+       fi
+}
+#
+# The SysConf device must exist in /dev at this point for this script
+# to work.
+#
+# It is important not to hard-wire the name of the device because of
+# the posibility of changing the flash partition layout.
+sysdev="$(mtdev SysConf)"
+if test -n "$sysdev" -a -c "$sysdev"
 then
-
-#  Ok this may be a little hack for now
-#  but Make sure the kernel module info is updated
-#  So the driver can actually load the first time
-   /usr/sbin/update-modules
-
-#  Set the default root password so ppl can ssh in
-   sed -i -e 's/root::/root:uf8TRGX9WDuH2:/' /etc/passwd
-
-   dd if=/dev/mtdblock1 of=/etc/linksysconf
-   cat <<EOF > /etc/original-network-settings
-# /etc/network/interfaces -- configuration file for ifup(8), ifdown(8)
-
-# The loopback interface
-auto lo
-iface lo inet loopback
-
-auto eth0
-iface eth0 inet static
-EOF
-
-   # Use the bootproto key to set "static" or "dhcp", then do other stuff based on that.
-   # strings /etc/linksysconf | grep bootproto >> /etc/original-network-settings
-   # sed -i -e 's/bootproto=//' /etc/original-network-settings
-
-   strings /etc/linksysconf | grep ip_addr >> /etc/original-network-settings
-   strings /etc/linksysconf | grep ^netmask >> /etc/original-network-settings
-   strings /etc/linksysconf | grep ^gateway=. >> /etc/original-network-settings
-   strings /etc/linksysconf | grep hw_addr >> /etc/original-network-settings
-   sed -i -e 's/ip_addr=/        address /' /etc/original-network-settings
-   sed -i -e 's/netmask=/        netmask /' /etc/original-network-settings
-   sed -i -e 's/gateway=/        gateway /' /etc/original-network-settings
-   sed -i -e 's/hw_addr=/        hwaddress ether /' /etc/original-network-settings
-
-   mv /etc/network/interfaces /etc/network/interfaces.old
-   cp /etc/original-network-settings /etc/network/interfaces
-
-   echo "Configured /etc/network/interfaces from /etc/linksysconf"
-
-   strings /etc/linksysconf | grep disk_server_name >> /tmp/hostname
-   sed -i -e 's/disk_server_name=//' /tmp/hostname
-
-   if [ -s /tmp/hostname ] ; then
-       mv /etc/hostname /etc/hostname.old
-       mv /tmp/hostname /etc/hostname
-       echo "Configured /etc/hostname from /etc/linksysconf"
-   fi
-
-   strings /etc/linksysconf | grep dns_server1 >> /tmp/resolv.conf
-   sed -i -e 's/dns_server1=/nameserver /' /tmp/resolv.conf
-
-   if [ -s /tmp/resolv.conf ] ; then
-       mv /etc/resolv.conf /etc/resolv.conf.old
-       mv /tmp/resolv.conf /etc/resolv.conf
-       echo "Configured /etc/resolv.conf from /etc/linksysconf"
-   fi
-
+       # Read the defined part of SysConf into /etc/default/sysconf.
+       # SysConf has lines of two forms:
+       #
+       #  [section]
+       #  name=value
+       #
+       # In practice SysConf also contains other stuff, use the command:
+       #
+       #  devio '<</dev/mtd1;cpb'
+       #
+       # to examine the current settings.  The badly formatted stuff
+       # is removed (to be exact, the sed script selects only lines
+       # which match one of the two above).  The lan interface, which
+       # defaults to ixp0, is changed to the correct value for openslug,
+       # eth0
+       devio '<<'"$sysdev"';cpb;fb1,10' | sed -n '/^\[[^][]*\]$/p;
+               s/^lan_interface=ixp0$/lan_interface=eth0/;
+               /^[-a-zA-Z0-9_][-a-zA-Z0-9_]*=/p' >/etc/default/sysconf
+       #
+       # Now take the result and set up the 'standard' files in the
+       # root file system (these couldn't be set up before because
+       # they depend on stuff which RedBoot puts into SysConf from the
+       # ID info on the specific machine - in particular the hardware
+       # address of eth0, which must be the one assigned for *this*
+       # box!)
+       #
+       # HOSTNAME: defaults to LGK<mac> i.e. something derived from
+       # the ethernet hardware.  LinkSys documentation explains how
+       # to determine this.  Set by the user in linksys setup software.
+       # DOMAINNAME: LinkSys puts this in w_d_name.
+       test -n "$(config host)" && config host >/etc/hostname
+       domain="$(config domain)"
+       test -n "$domain" && echo "$domain" >/etc/defaultdomain
+       #
+       # Ethernet information.  This goes into /etc/network/interfaces,
+       # however this is only used for static setup (and this is not
+       # the default).  With dhcp the openslug udhcp script,
+       # /etc/udhcpc.d/50default, loads the values from sysconf.  The
+       # lan_interface config value must exist for the file to be
+       # overwritten here.
+       iface="$(config iface)"
+       if test -n "$iface"
+       then
+               boot="$(config boot)"
+               # Only dhcp and static are supported at present - bootp
+               # support requires installation of appropriate packages
+               # dhcp is the fail-safe
+               case "$boot" in
+               dhcp|static) ;;
+               *)    boot=dhcp;;
+               esac
+               #
+               mac="$(config mac)"
+               ip="$(config ip)"
+               netmask="$(config netmask)"
+               gateway="$(config gateway)"
+               {
+                       echo "# /etc/network/interfaces"
+                       echo "# configuration file for ifup(8), ifdown(8)"
+                       echo "#"
+                       echo "# The loopback interface"
+                       echo "auto lo"
+                       echo "iface lo inet loopback"
+                       echo "#"
+                       echo "# The NSLU2 built-in ethernet"
+                       echo "auto eth0"
+                       echo "# Automatically generated from /etc/default/sysconf"
+                       if test -n "$mac"
+                       then
+                               echo "# The pre-up option must always be supplied, regardless"
+                               echo "# of configuration, to set the hardware correctly."
+                               echo "# Severe network problems may result if this option is"
+                               echo "# removed."
+                               c=
+                       else
+                               echo "# WARNING: improperly configured network interface."
+                               echo "# WARNING: the pre-up line must be corrected or severe"
+                               echo "# WARNING: network problems may result."
+                               c='#'
+                               mac='<WARNING: unknown hardware address>'
+                       fi
+                       echo "iface $iface inet $boot"
+                       echo "${c}      pre-up ifconfig $iface hw ether $mac"
+                       # The following are ignored for DHCP but are harmless
+                       test -n "$ip"      && echo "    address $ip"
+                       test -n "$netmask" && echo "    netmask $netmask"
+                       test -n "$gateway" && echo "    gateway $gateway"
+               } >/etc/network/interfaces
+       fi
+       #
+       # The DNS server information gives up to three nameservers, but this
+       # currently only binds in the first.
+       {
+               test -n "$domain" && echo "search $domain"
+               echodns $(config dns) $(config dns1) $(config dns2)
+       } >/etc/resolv.conf
 fi
 
-# Module loading handled more properly by update-modules and modprobe.conf
+exit 0
index e69de29..b688bc3 100644 (file)
@@ -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.
index 5b38791..ceb04b0 100644 (file)
@@ -2,9 +2,17 @@ DESCRIPTION = "Openslug initial network config via sysconf"
 SECTION = "console/network"
 LICENSE = "GPL"
 DEPENDS = "base-files"
-PR = "r22"
+PR = "r24"
 
 SRC_URI = "file://linuxrc \
+          file://boot/flash \
+          file://boot/disk \
+          file://boot/nfs \
+          file://boot/ram \
+          file://boot/network \
+          file://boot/udhcpc.script \
+          file://functions \
+          file://rmrecovery \
           file://sysconfsetup \
           file://turnup \
           file://modutils.txt \
@@ -13,49 +21,101 @@ SRC_URI = "file://linuxrc \
           file://leds.h \
           file://leds.c \
           file://kern_header.c \
+          file://devio.c \
           file://update-kernel"
 
-inherit autotools update-rc.d
+SBINPROGS = "devio leds"
+USRSBINPROGS = "kern_header"
+CPROGS = "${USRSBINPROGS} ${SBINPROGS}"
+SCRIPTS = "turnup update-kernel"
+BOOTSCRIPTS = "flash disk nfs ram network udhcpc.script"
 
-INITSCRIPT_NAME = "sysconfsetup"
-INITSCRIPT_PARAMS = "defaults 39"
+# This jsut makes things easier...
+S="${WORKDIR}"
 
 do_compile() {
-       ${CC} -o ${S}/../kern_header ${S}/../kern_header.c
-       ${CC} -o ${S}/../leds ${S}/../leds.c
+       set -ex
+       for p in ${CPROGS}
+       do
+               ${CC} ${CFLAGS} -o $p $p.c
+       done
+       set +ex
 }
 
 do_install() {
-        install -d ${D}/${sysconfdir} \
-                   ${D}/${sysconfdir}/init.d \
-                  ${D}/${sysconfdir}/modutils \
-                   ${D}/${sysconfdir}/rcS.d \
-                  ${D}/${sbindir} 
+       set -ex
+
+       # Directories
+        install -d ${D}${sysconfdir} \
+                   ${D}${sysconfdir}/default \
+                   ${D}${sysconfdir}/init.d \
+                  ${D}${sysconfdir}/modutils \
+                  ${D}${sbindir} \
+                  ${D}${base_sbindir} \
+                  ${D}/initrd \
+                  ${D}/boot
                  
-       install -m 0755 ${D}/../linuxrc ${D}/linuxrc
-
-       install -d ${D}/initrd
-
-       install -m 0755 ${D}/../kern_header ${D}${sbindir}/kern_header
-       install -m 0755 ${D}/../update-kernel ${D}${sbindir}/update-kernel
-       install -m 0755 ${D}/../turnup ${D}${sbindir}/turnup
-       install -m 0755 ${D}/../leds ${D}${sbindir}/leds
-       install -m 0755 ${D}/../sysconfsetup ${D}${sysconfdir}/init.d/
-       install -m 0755 ${D}/../leds_rs_green ${D}${sysconfdir}/init.d/
-       install -m 0644 ${D}/../modutils.txt ${D}${sysconfdir}/modutils/
-       install -m 0644 ${D}/../modprobe.conf ${D}${sysconfdir}/
-       rm -f ${D}${sysconfdir}/rcS.d/S39sysconfsetup
-       ln -s ../init.d/sysconfsetup ${D}${sysconfdir}/rcS.d/S39sysconfsetup
-       # Put this into the user run levels, after the rmnologin (which is
-       # the thing that allows a user log in!)
-       for l in 2 3 4 5
+       # linuxrc
+       rm -f ${D}/linuxrc
+       ln -s boot/flash ${D}/linuxrc
+
+       # C programs
+       for p in ${USRSBINPROGS}
+       do
+               install -m 0755 $p ${D}${sbindir}/$p
+       done
+       for p in ${SBINPROGS}
        do
-               install -d ${D}/${sysconfdir}/rc$l.d
-               rm -f ${D}${sysconfdir}/rc$l.d/S99zleds_rs_green
-               ln -s ../init.d/leds_rs_green ${D}${sysconfdir}/rc$l.d/S99zleds_rs_green
+               install -m 0755 $p ${D}${base_sbindir}/$p
        done
+
+       # Shell scripts
+       for p in ${SCRIPTS}
+       do
+               install -m 0755 $p ${D}${sbindir}/$p
+       done
+
+       #
+       # Init scripts
+       install -m 0644 functions ${D}${sysconfdir}/default
+       install -m 0755 rmrecovery ${D}${sysconfdir}/init.d/
+       install -m 0755 sysconfsetup ${D}${sysconfdir}/init.d/
+       install -m 0755 leds_rs_green ${D}${sysconfdir}/init.d/zleds_rs
+
+       #
+       # Boot scripts
+       for p in ${BOOTSCRIPTS}
+       do
+               install -m 0755 boot/$p ${D}/boot
+       done
+
+       # Configuration files
+       #XXinstall -m 0644 modutils.txt ${D}${sysconfdir}/modutils/
+       install -m 0644 modprobe.conf ${D}${sysconfdir}/
+
+       set +ex
+}
+
+# If the package is installed on an NSLU2 $D will be empty, in that
+# case it is normal to run 'start' and 'stop', but because the conf
+# files installed don't actually start or stop anything this is
+# unnecessary, so the package postfoo handling is simplified here.
+pkg_postinst_openslug-init() {
+       opt=
+       test -n "$D" && opt="-r $D"
+       update-rc.d $opt sysconfsetup start 11 S .
+       update-rc.d $opt zleds_rs start 99 S 1 2 3 4 5 . stop 05 0 1 2 3 4 5 6 .
+}
+
+pkg_postrm_openslug-init() {
+       opt=
+       test -n "$D" && opt="-r $D"
+       update-rc.d $opt sysconfsetup remove
+       update-rc.d $opt zleds_rs remove
 }
 
+PACKAGES = "${PN}"
 FILES_${PN} = "/"
 
-CONFFILES_${PN} = "${sysconfdir}/modutils/modutils.txt ${sysconfdir}/modprobe.conf"
+#CONFFILES_${PN} = "${sysconfdir}/modutils/modutils.txt ${sysconfdir}/modprobe.conf"
+CONFFILES_${PN} = "${sysconfdir}/modprobe.conf"