diff options
author | Rod Whitby <rod@whitby.id.au> | 2006-01-07 08:58:44 +0000 |
---|---|---|
committer | OpenEmbedded Project <openembedded-devel@lists.openembedded.org> | 2006-01-07 08:58:44 +0000 |
commit | 8fb6b2d3d410ad2badf0c99ed7a66b698aafaa17 (patch) | |
tree | 8a700d795bdf33061b8bccc353fe0aaffa044036 /packages/slugos-init/files | |
parent | 0b67482ddc4fe571d16fa094627abb447b9a8edb (diff) |
slugos: Major rename of common SlugOS files and directories from openslug to slugos.
Diffstat (limited to 'packages/slugos-init/files')
30 files changed, 2982 insertions, 0 deletions
diff --git a/packages/slugos-init/files/.mtn2git_empty b/packages/slugos-init/files/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/slugos-init/files/.mtn2git_empty diff --git a/packages/slugos-init/files/README b/packages/slugos-init/files/README new file mode 100644 index 0000000000..264d4d8f85 --- /dev/null +++ b/packages/slugos-init/files/README @@ -0,0 +1,49 @@ +OpenSlug-1.x Family Release README + +Warning: OpenSlug is not for the faint of heart! In fact, OpenSlug has a +specific target audience. + +Some background first. According to the NSLU2 - Linux developers, there are 4 +specific types ("camps") of NSLU2 - Linux users: + + Camp #1: Users who want full Linksys compatibility (including for future + Linksys firmware releases). They can load firmware images via + the Linksys web interface and telnet in - to load Optware - + Unslung packages with ipkg, but have no idea what RedBoot is or + does. + + Camp #2: "Camp #1 Plus users." They can telnet into RedBoot (ability + to "self-rescue" a non-working NSLU2), and are comfortable + using Linux. + + Camp #3: Power users! Firmware flashing via any interface is a walk + in the park. They aren't just *users*, but are developers or + administrators of computers and/or computer software. + However, they have no JTAG or custom bootloaders. + + Camp #4: Bleeding edge users. They create and use custom bootloaders, + certainly having no need or desire for Linksys compatibility, + modifying and/or changing the hardware as well. + +With those camps in mind, OpenSlug is targetted toward Camp #3 and Camp #4 +users. If you're not in Camps 3 & 4, then you should be looking to use the +Unslung firmware. If you are a Camp #2 user, and still want to use OpenSlug, +you need to practice gaining RedBoot access, and be able to recover from bad +flashes, "drive not formatted" conditions, and other common mistakes/problems +which are documented in the NSLU2-Linux Wiki at http://www.nslu2-linux.org. +Once you are comfortable doing those things, then you may consider using +OpenSlug. + +If you're still reading - and still intent on using OpenSlug, click through +the Intel license, download the latest OpenSlug binary and flash it to your +NSLU2! (Without any HD attached while flashing!!!) Your next stop should be +the OpenSlug Turnip page at: + + http://www.nslu2-linux.org/wiki/OpenSlug/OpenSlugTurnUp + +Please add your name and information to the OpenSlug database at the yahoo +NSLU2-Linux group at: + + http://groups.yahoo.com/group/nslu2-linux/ + +Happy OpenSlugging!
\ No newline at end of file diff --git a/packages/slugos-init/files/boot/.mtn2git_empty b/packages/slugos-init/files/boot/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/slugos-init/files/boot/.mtn2git_empty diff --git a/packages/slugos-init/files/boot/disk b/packages/slugos-init/files/boot/disk new file mode 100644 index 0000000000..ede33a3ee6 --- /dev/null +++ b/packages/slugos-init/files/boot/disk @@ -0,0 +1,49 @@ +#!/bin/sh +# boot from the hard disk partition "$1" (which +# must be given) using options from the rest of +# the command line. +# +/sbin/leds -A '!gr' +# +# Use the standard init path (see /etc/init.d/rcS) +export PATH=/sbin:/bin:/usr/sbin:/usr/bin +# +# Load the helper functions +. /etc/default/functions +# +if test -n "$1" +then + device="$1" + shift + echo "boot: rootfs: mount $* $device" + # + # wait if required + test "$sleep" -gt 0 && sleep "$sleep" + # + # Mount read-write because before exec'ing init + # this script creates the '.recovery' link to + # detect failed boot. No file type is given to + if mount "$@" "$device" /mnt + then + # checkmount checks for sh, init and no + # .recovery plus either mnt or initrd + if checkmount /mnt && :>/mnt/.recovery + then + # sync to ensure .recovery is written + sync + # pivot to /initrd if available, else /mnt + cd / + if test -d /mnt/initrd + then + swivel mnt initrd + else + swivel mnt mnt + fi + # swivel failed + fi + # Failure: unmount the partition + umount /mnt + fi +fi +# fallback - use the flash boot +exec /boot/flash diff --git a/packages/slugos-init/files/boot/flash b/packages/slugos-init/files/boot/flash new file mode 100644 index 0000000000..e0bcebc9b8 --- /dev/null +++ b/packages/slugos-init/files/boot/flash @@ -0,0 +1,14 @@ +#!/bin/sh +# boot from the current (flash) root partition +# nothing need be done, make the power led flash +# amber to indicate runlevel S +/sbin/leds -A '!gr' +exec /sbin/init +# fallback if /sbin/init has been deleted (bad!) +# flashing amber/red - failed early boot +# disk lights flashing: failed in flash boot! +/sbin/leds +A '!g12' +exec <>/dev/console >&0 2>&0 +exec /sbin/sulogin +exec /bin/sh +exit 1 diff --git a/packages/slugos-init/files/boot/network b/packages/slugos-init/files/boot/network new file mode 100644 index 0000000000..02b226d1f3 --- /dev/null +++ b/packages/slugos-init/files/boot/network @@ -0,0 +1,25 @@ +#!/bin/sh +# bring up the network before boot, used to allow +# netconsole logging and NFS boot. This runs out +# of flash, but that's ok because the script doesn't +# leave any process running. +# +# NOTE: /etc/default/functions defines ifup as a shell +# function! +. /etc/default/functions +# +# Now all the information for booting should be in the configuration +# file. Config the loopback and network interfaces. +ifconfig lo 127.0.0.1 up +mac="$(config mac)" +iface="$(config iface)" +if test -n "$mac" -a -n "$iface" -a "$mac" != "00:00:00:00:00:00" -a "$mac" != "FF:FF:FF:FF:FF:FF" +then + if ifconfig "$iface" hw ether "$mac" && + ifup "$iface" + then + exit 0 + fi +fi +# exit code is true only if the interface config has succeeded +exit 1 diff --git a/packages/slugos-init/files/boot/nfs b/packages/slugos-init/files/boot/nfs new file mode 100644 index 0000000000..534d8b7cb0 --- /dev/null +++ b/packages/slugos-init/files/boot/nfs @@ -0,0 +1,17 @@ +#!/bin/sh +# boot from the nfs partition "$1" (which +# must be given) using options from the rest of +# the command line. +# +/sbin/leds -A '!gr' +# +# Use the standard init path (see /etc/init.d/rcS) +export PATH=/sbin:/bin:/usr/sbin:/usr/bin +if /boot/network +then + # network is up and running, the NFS mount will + # now succeed (possibly), use /boot/disk + exec /boot/disk "$@" +fi +# fallback - use the flash boot +exec /boot/flash diff --git a/packages/slugos-init/files/boot/ram b/packages/slugos-init/files/boot/ram new file mode 100644 index 0000000000..66d46a7089 --- /dev/null +++ b/packages/slugos-init/files/boot/ram @@ -0,0 +1,47 @@ +#!/bin/sh +# boot from the hard disk partition "$1" (which +# must be given) using options from the rest of +# the command line. +# +/sbin/leds -A '!gr' +# +# Use the standard init path (see /etc/init.d/rcS) +export PATH=/sbin:/bin:/usr/sbin:/usr/bin +# +# Load the helper functions +. /etc/default/functions +# +if test -n "$1" +then + device="$1" + shift + echo "boot: rootfs: mount $* $device" + # + # prepare the device. This uses tmpfs to avoid dependency + # on non-built-in file systems and because tmpfs can expand + # to bigger than the 10MByte ram0 partition used before. + # The 'device' is currently unused. + if mount -t tmpfs "$@" tmpfs /mnt + then + cd / + # filter out boot (with zimage), linuxrc and anything + # below /var, keep dev or the boot will fail (note that + # nothing is mounted this early in the bootstrap). + find . -mount -print | + sed '\@^./boot/@d;\@^./boot$@d;\@^./linuxrc@d;\@^./var/@d' | + cpio -p -d -m -u /mnt + # checkmount checks for sh, init and no .recovery plus + # either mnt or initrd, mnt must exist! + if checkmount /mnt + then + # pivot to /mnt + cd / + swivel mnt mnt + # swivel failed + fi + # Failure: unmount the partition. + umount /mnt + fi +fi +# fallback - use the flash boot +exec /boot/flash diff --git a/packages/slugos-init/files/boot/udhcpc.script b/packages/slugos-init/files/boot/udhcpc.script new file mode 100644 index 0000000000..3f437e3143 --- /dev/null +++ b/packages/slugos-init/files/boot/udhcpc.script @@ -0,0 +1,17 @@ +#!/bin/sh +# executed by udhcpc to do the real work of configuring an interface +# writes the result (if any) to file descriptor 9 +case "$1" in +deconfig) # ignored + :;; +renew|bound) # this gives the real information + test -n "$ip" && { + echo "ip='$ip'" + echo "subnet='$subnet'" + echo "broadcast='$broadcast'" + echo "router='$router'" + } >&9;; +leasefail) # ignore - probably no dhcp server + :;; +*) echo "udhcpc: $*: command not recognised" >&2;; +esac diff --git a/packages/slugos-init/files/conffiles b/packages/slugos-init/files/conffiles new file mode 100644 index 0000000000..51a8091b1e --- /dev/null +++ b/packages/slugos-init/files/conffiles @@ -0,0 +1,50 @@ +# conffiles +# Known SlugOS configuration files. These files are preserved on +# a flash upgrade. Other configuration files, found from: +# +# /usr/lib/ipkg/*.conffiles +# /etc/*.conf +# +# are preserved too with an operation of 'diff' if they have been +# changed since /etc/.configured was created. +# +# Lines starting with # are comments, other lines have +# two fields: +# +# operation file +# +# The file must *NOT* have a leading / +# +# operation may be: +# ignore Do not preserve this file +# preserve Preserve this file unconditionally +# diff Compare file with the new version, ask if different +# +preserve linuxrc +preserve etc/.configured +preserve etc/TZ +diff etc/default/conffiles +diff etc/default/devpts +diff etc/default/rcS +preserve etc/default/sysconf +diff etc/default/usbd +preserve etc/defaultdomain +preserve etc/dropbear/dropbear_dss_host_key +preserve etc/dropbear/dropbear_rsa_host_key +preserve etc/fstab +preserve etc/group +preserve etc/gshadow +preserve etc/hostname +preserve etc/hosts +preserve etc/localtime +ignore etc/modules +ignore etc/modules.conf +preserve etc/motd +preserve etc/network/interfaces +preserve etc/ntp.drift +preserve etc/passwd +preserve etc/profile +preserve etc/resolv.conf +preserve etc/shadow +preserve etc/syslog.conf +preserve etc/timezone diff --git a/packages/slugos-init/files/functions b/packages/slugos-init/files/functions new file mode 100644 index 0000000000..e90f03aead --- /dev/null +++ b/packages/slugos-init/files/functions @@ -0,0 +1,332 @@ +# . this file to load the following utility functions +# +# mtdev "name" +# return (output) the character device name for flash parition "name" +# /proc/mtd has the general form: +# dev: size erasesize name +# mtd5: 00020000 00020000 "FIS directory" +# use this rather than hard-wiring the device because the partition +# table can change - looking in /proc/mtd is more reliable. +mtdev(){ + sed -n 's!^\(mtd[0-9][0-9]*\):[^"]*"'"$1"'"$!/dev/\1!p' /proc/mtd +} +# +# mtblockdev "name" +# as mtdev but output the name of the block (not character) device +mtblockdev(){ + sed -n 's!^mtd\([0-9][0-9]*\):[^"]*"'"$1"'"$!/dev/mtdblock\1!p' /proc/mtd +} +# +# mtsize "name" +# the size of the partition as a hexadecimal value (with 0x at the front) +mtsize(){ + sed -n 's!^mtd[0-9][0-9]*: \([^ ]*\)[^"]*"'"$1"'"$!0x\1!p' /proc/mtd +} +# +# sysvalmatch "section" "name" 'pattern' "configuration file" +# sysvalof "section" "name" "configuration file" +# sysval "section" "name" +# outputs the value of the SysConf variable 'name' from section 'section', +# this is a bit gross, when it gets a match it copies the value to the +# hold space, if no match it jumps over the copy, at the end ($) it copies +# the hold space to the pattern space and prints the result, thus it only +# ever prints the last match +# BUG FIX: busybox sed doesn't initialise the hold space and crashes if it +# is used before initialisation, so temporarily this script does it's own +# tail by hand. +# NOTE: these functions should only be used internally, add entries to 'config' +# below if necessary. This is because 'config' does the defaulting and in the +# recovering case (zero or absent SysConf) /etc/default/sysconf only contains +# the hw_addr entry! +sysvalmatch(){ + # sed -n '/^\['"$1"'\]$/,/^\[.*\]$/s/^'"$2"'=\('"$3"'\)$/\1/;tH;bE;:H;h;:E;$g;$p' "$4" + sed -n '/^\['"$1"'\]$/,/^\[.*\]$/s/^'"$2"'=\('"$3"'\)$/\1/p' "$4" | sed -n '$p' +} +sysvalof(){ + sysvalmatch "$1" "$2" '.*' "$3" +} +sysval(){ + sysvalof "$1" "$2" /etc/default/sysconf +} +# +# config "value" +# convenience callers for specific values to avoid mis-typing in scripts +# NOTE: this function does the defaulting, 'sysval' does not! Validity +# of the sysconf file is determined by the presence of the all important +# hw_addr. +config(){ + local mac + mac= + test -r /etc/default/sysconf && + mac="$(sysvalmatch network hw_addr '[0-9A-Za-z][0-9A-Za-z]:[0-9A-Za-z][0-9A-Za-z]:[0-9A-Za-z][0-9A-Za-z]:[0-9A-Za-z][0-9A-Za-z]:[0-9A-Za-z][0-9A-Za-z]:[0-9A-Za-z][0-9A-Za-z]' /etc/default/sysconf)" + if test -n "$mac" + then + case "$1" in + mac) echo "$mac";; + host) if test -n "$(sysval network disk_server_name)" + then + sysval network disk_server_name + elif test -n "$(sysval network default_server_name)" + then + sysval network default_server_name + else + echo "$mac" | sed -n 's/^..:..:..:\(..\):\(..\):\(..\)$/LKG\1\2\3/p' + fi;; + domain) sysval network w_d_name;; + iface) if test -n "$(sysval network lan_interface)" + then + sysval network lan_interface + else + echo eth0 + fi;; + ip) if test -n "$(sysval network ip_addr)" + then + sysval network ip_addr + else + echo 192.168.1.77 + fi;; + netmask)sysval network netmask;; + gateway)sysval network gateway;; + dns) sysval network dns_server1;; + dns2) sysval network dns_server2;; + dns3) sysval network dns_server3;; + boot) if test -n "$(sysval network bootproto)" + then + sysval network bootproto + else + echo dhcp + fi;; + valid) return 0;; + *) return 1;; + esac + else + # These are the defaults for an invalid mac address, use the compiled + # in hardware address. + case "$1" in + mac) echo "00:02:B3:02:02:01";; + host) echo "brokenslug";; + iface) echo eth0;; + ip) echo 192.168.1.77;; + boot) echo dhcp;; + *) return 1;; + esac + fi +} +# +# checkif "iface" +# Validate an interface name by making sure that it exists +# in /proc/net/dev (and is not lo). The listing outputs the +# interface followed by a :, the check function looks for +# something of the form '$1[a-zA-Z0-9]*:' and outputs the +# part preceding the ':' +checkif(){ + sed -n '/^[ ]*lo:/d;s/^[ ]*\('"$1"'[a-zA-Z0-9]*\):.*$/\1/p;tE;d;:E;q' /proc/net/dev +} +# +# checkmount "mountpoint" +# tests an already mounted mountpoint to see whether to attempt to +# boot with this as root. Returns success if it appears ok. +checkmount(){ + # basic test for init (the kernel will try to load this) + # but require a shell in bin/sh and no .recovery too + test \( ! -f "$1/.recovery" \) -a \ + \( -d "$1/initrd" -o -d "$1/mnt" \) -a \ + \( -x "$1/bin/sh" -o -h "$1/bin/sh" \) -a \ + \( -x "$1/sbin/init" -o -h "$1/sbin/init" -o \ + -x "$1/etc/init" -o -h "$1/etc/init" -o \ + -x "$1/bin/init" -o -h "$1/bin/init" \) +} +# +# swivel "new root" "old root" +# NOTE: the arguments must be paths relative to /, bad things +# will happen if the arguments themselves start with / +# Pivot to a new root. This does all the fancy pivot_root stuff +# including closing streams and does a umount /proc - it doesn't +# matter if this fails (failure codes are ignored), but if /proc +# was mounted it must be restored by the caller on return. +# Normally this function never returns! +# On return 0,1,2 are connected to /dev/console - this may not +# have been true before! +swivel() { + cd "$1" + exec <&- >&- 2>&- + # This is just-in-case the called mounted /proc and was + # unable to close it because of the streams + umount /proc 2>/dev/null + if pivot_root . "$2" + then + # everything must move out of the old root, this process + # is $2/bin/sh so it must die, IO is redirected + # just in case - typically it will be to a device so it + # won't hold the old root open. + # the exec here is the first point at which the old root + # is unused - before the exec regardless of the close of + # 0,1,2 above ash still has *this* shell script open! + # (it's on fd 10). + # init closes all file descriptors, there's no point + # supplying it with fds. + # NOTE: this used to use $2/usr/sbin/chroot, however on + # linux / is already . when the command is executed + # therefore it is essential to use the local (new root) + # chroot to ensure it gets the correct shared libraries. + exec usr/sbin/chroot . bin/sh -c "\ + test -x sbin/init && exec sbin/init + test -x etc/init && exec etc/init + test -x bin/init && exec bin/init + leds -A +gr1 '!g1' + sleep 10 >/.recovery + sync;sync;sync + exit 1" + fi + # + # recovery - must restore the old root + cd "$2" + sbin/pivot_root . "$1" + # cd is back to $1 - either pivot_root doesn't change it and the + # chroot above was not executed, or pivot_root does change it and + # has just changed it back! + exec <>/dev/console >&0 2>&0 +} +# +# ifup "interface" +# bring that interface up with the configured ip and other +# information +ifup(){ + local ip hostname router subnet iface HOSTNAME NETMASK BROADCAST + + iface="$1" + ip="$(config ip)" + hostname="$(config host)" + router="$(config gateway)" + broadcast= + + if test -n "$ip" + then + # only if an ip was specified + subnet="$(config netmask)" + else + ip=192.168.1.77 + fi + + # First try udhcpc - note that the /boot/udhcpc.script + # simply records the values returned and the udhcpc + # is not left running so this will only work for + # the lease length time! + ifconfig "$iface" up + if test "$(config boot)" != static + then + test -n "$hostname" && HOSTNAME="-H $hostname" + # The script writes the required shell variable assignments + # to file descriptor 9 + eval $(udhcpc -i "$iface" -n -q -r "$ip" $HOSTNAME -s /boot/udhcpc.script 9>&1 >/dev/null) + fi + + test -n "$broadcast" && BROADCAST="broadcast $broadcast" + test -n "$subnet" && NETMASK="netmask $subnet" + + if ifconfig "$iface" "$ip" $NETMASK $BROADCAST + then + for route in $router + do + route add default gw "$route" dev "$iface" + done + return 0 + else + ifconfig "$iface" down + return 1 + fi +} +# +# ifdown "interface" +# take the interface down +ifdown(){ + ifconfig "$1" down +} +# +# mountflash "flash device" "flash root directory" {mount options} +# Finds and mounts the flash file system on the given directory +mountflash() { + local ffsdev ffsdir + + ffsdev="$1" + test -n "$ffsdev" -a -b "$ffsdev" || { + echo "$0: unable to find flash file system to copy ($ffsdev)" >&2 + return 1 + } + shift + + ffsdir="$1" + test -n "$ffsdir" -a -d "$ffsdir" || { + echo "$0: mountflash $ffsdir: not a directory (internal error)" >&2 + return 1 + } + shift + + mount -t jffs2 "$@" "$ffsdev" "$ffsdir" || { + echo "$0: $ffsdev: unable to mount flash file system on $ffsdir" >&2 + return 1 + } + return 0 +} +# +# umountflash [-r] "flash device" +# unmount any instance of the given flash device, if -r is specified a mount on +# root is an error, otherwise a mount on root is ignored (and remains). +umountflash() { + local rootok ffsno ffsdev + rootok=1 + case "$1" in + -r) rootok= + shift;; + esac + # + # The argument is ffsdev + ffsdev="$1" + ffsno="$(devio "<<$ffsdev" prd)" + test -n "$ffsno" -a "$ffsno" -ge 0 || { + echo "$0: $ffsdev: device number $ffsno is not valid, cannot continue." >&2 + return 1 + } + # + # Make sure that Flashdisk isn't mounted on / + if test -z "$rootok" -a "$(devio "<</etc/init.d/sysconfsetup" prd)" -eq "$ffsno" + then + echo "$0: $ffsdev is mounted on /, use turnup ram" >&2 + return 1 + fi + # + # The function is currently always used interactively, so output + echo "$0: umounting any existing mount of $ffsdev" >&2 + # + # check each mount point, do this last first because otherwise nested + # mounts of ffsdev cannot be umounted. + ffs_umount() { + local device mp type options stuff + + read device mp type options stuff + test -z "$device" && return 0 + + # handle following entries first + ffs_umount || return 1 + + # handle this entry, since this is currently only used for unmounting + # the flash root partition we know a file which must exist... + case "$mp/$type" in + //jffs2);; # skip / + */jffs2)test "$(devio "<<$mp/etc/init.d/sysconfsetup" prd 2>/dev/null)" -ne "$ffsno" || + umount "$mp" || { + echo "$0: $mp: unable to umount $ffsdev" >&2 + return 1 + };; + esac + + return 0 + } + # + ffs_umount </proc/mounts || { + echo "$0: umount $ffsdev from all mount points then re-run reflash" >&2 + return 1 + } + + return 0 +} diff --git a/packages/slugos-init/files/initscripts/.mtn2git_empty b/packages/slugos-init/files/initscripts/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/slugos-init/files/initscripts/.mtn2git_empty diff --git a/packages/slugos-init/files/initscripts/leds_startup b/packages/slugos-init/files/initscripts/leds_startup new file mode 100644 index 0000000000..945d75bd02 --- /dev/null +++ b/packages/slugos-init/files/initscripts/leds_startup @@ -0,0 +1,11 @@ +#!/bin/sh +# Bug fix: during the initial boot sysvinit sets PREVLEVEL to +# nothing in rcS and to 'N' in the transition from rcS to the +# user state. This script runs on that transition and, if +# the PREVLEVEL is 'N', sets 'previous' (as in /etc/init.d/rc) +# to 'S' +if test "$PREVLEVEL" = N +then + previous=S exec /etc/init.d/zleds stop +fi +exit 0 diff --git a/packages/slugos-init/files/initscripts/rmrecovery b/packages/slugos-init/files/initscripts/rmrecovery new file mode 100644 index 0000000000..eec822b154 --- /dev/null +++ b/packages/slugos-init/files/initscripts/rmrecovery @@ -0,0 +1,4 @@ +#!/bin/sh +# Run to remove /.recovery if the boot seems to have succeeded +test -e /.recovery && rm -f /.recovery +exit 0 diff --git a/packages/slugos-init/files/initscripts/sysconfsetup b/packages/slugos-init/files/initscripts/sysconfsetup new file mode 100644 index 0000000000..31ff38d7ee --- /dev/null +++ b/packages/slugos-init/files/initscripts/sysconfsetup @@ -0,0 +1,231 @@ +#!/bin/sh +# 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 +# +# /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 +# +config valid && test "$1" != reload && exit 0 +# +# 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. +# +# The block device is used here because at present udev does not +# show the character devices +sysdev= +config valid || sysdev="$(mtblockdev SysConf)" +if test -n "$sysdev" -a -b "$sysdev" +then + # 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. The bootproto, which LinkSys sets to static in manufacturing, + # is reset to dhcp if the IP is still the original (192.168.1.77) + devio "<<$sysdev" cpb fb1,10 | sed -n '/^\[[^][]*\]$/p; + s/^lan_interface=ixp0$/lan_interface=eth0/; + /^ip_addr=192\.168\.1\.77$/,/^bootproto/s/^bootproto=static$/bootproto=dhcp/; + /^[-a-zA-Z0-9_][-a-zA-Z0-9_]*=/p' >/etc/default/sysconf + # + # The SysConf must have a hardware id, if it doesn't it has + # probably been erased or never set in the first place and the + # hardware id is retrieved from the RedBoot partition. This is + # the only thing which cannot be defaulted. +fi +# +# Error recovery: no SysConf or invalid SysConf. Make a new one from the +# RedBoot hardware ID information. +# NOTE: this block of code overwrites the shell script arguments. +config valid || { + reddev="$(mtblockdev RedBoot)" + initmac= + if test -n "$reddev" -a -b "$reddev" + then + # The hardware id starts 80 bytes before the end of the + # block, the block ends (or should end) with the signature + # <4 bytes> sErCoMm <bytes> sErCoMm. Note that devio 'pf' + # empties the stack. + set -- $(devio "<<$reddev" ' + <= $80- + .= @ + pf %02X + A= 5 + $( 1 + A= @,A1- + pf :%02X + $) A + pn + <=f4+;cp7;pn + <=$7-;cp7;pn') + if test $# -eq 3 -a "$2" = sErCoMm -a "$3" = sErCoMm + then + initmac="$1" + fi + fi + # + # APEX: may need extra code to set initmac here. + # + if test -n "$initmac" + then + # + # Generate a complete /etc/default/sysconf based on just + # one number ;-) + { echo '[network]' + echo "hw_addr=$initmac" + } >/etc/default/sysconf + # + # See /etc/default/functions (the config function) for + # the derivation of the rest of the information. + fi +} +# +# The config function will now return the correct values - even if sysconf +# is still missing. 'config valid' says if valid configuration information +# is available. +# +# 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 $iface" + echo "# Automatically generated from /etc/default/sysconf" + if config valid + 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 +# +# Invalid config must be handled, do this by hacking /etc/motd. +if config valid +then + echo "Host name: $(config host)" + echo "Host ID: $mac" + echo "Network boot method: $boot" + case "$boot" in + static) echo "Host IP address: $ip";; + esac + echo "Use 'turnup init' to reset the configuration" + echo "Use 'turnup disk|nfs -i <device> options to initialise a non-flash root" + echo "Use 'turnup help' for more information" +else + echo "+=====================================================================+" + echo "| +-----------------------+ |" + echo "| | INITIALISATION FAILED | |" + echo "| +-----------------------+ |" + echo "| |" + echo "| This machine has been booted with a temporary ethernet id |" + echo "| The initialisation failed because the machine id was not available |" + echo "| within the flash memory of the NSLU2. You must run: |" + echo "| |" + echo "| turnup init |" + echo "| |" + echo "| To correct this problem. Severe network problems may occur if this |" + echo "| is not done. |" + echo "+=====================================================================+" +fi >/etc/motd + +exit 0 diff --git a/packages/slugos-init/files/initscripts/syslog.buffer b/packages/slugos-init/files/initscripts/syslog.buffer new file mode 100644 index 0000000000..9285c02946 --- /dev/null +++ b/packages/slugos-init/files/initscripts/syslog.buffer @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Invoke the syslog startup if the configuration +# uses (only) 'buffer' as the DESTINATION +DESTINATION= +test -f /etc/syslog.conf && . /etc/syslog.conf +doit= + +for d in $DESTINATION +do + case "$d" in + buffer) doit=1;; + file) exit 0;; + remote) exit 0;; + *) echo "/etc/syslog.conf: $d: unknown destination" >&2 + exit 1;; + esac +done + +test -n "$doit" -a -x /etc/init.d/syslog && + exec /etc/init.d/syslog "$@" + +exit 0 diff --git a/packages/slugos-init/files/initscripts/syslog.file b/packages/slugos-init/files/initscripts/syslog.file new file mode 100644 index 0000000000..80ee5f0174 --- /dev/null +++ b/packages/slugos-init/files/initscripts/syslog.file @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Invoke the syslog startup if the configuration +# uses 'file' (and, optionally, buffer) as the DESTINATION +DESTINATION= +test -f /etc/syslog.conf && . /etc/syslog.conf +doit= + +for d in $DESTINATION +do + case "$d" in + buffer) :;; + file) doit=1;; + remote) exit 0;; + *) echo "/etc/syslog.conf: $d: unknown destination" >&2 + exit 1;; + esac +done + +test -n "$doit" -a -x /etc/init.d/syslog && + exec /etc/init.d/syslog "$@" + +exit 0 diff --git a/packages/slugos-init/files/initscripts/syslog.network b/packages/slugos-init/files/initscripts/syslog.network new file mode 100644 index 0000000000..3d7f4ab8e6 --- /dev/null +++ b/packages/slugos-init/files/initscripts/syslog.network @@ -0,0 +1,28 @@ +#!/bin/sh +# +# Invoke the syslog startup if the configuration +# uses 'remote', or doesn't use 'buffer' or 'file' +DESTINATION= +test -f /etc/syslog.conf && . /etc/syslog.conf +doit= +doneit= + +for d in $DESTINATION +do + case "$d" in + buffer) doneit=1;; + file) doneit=1;; + remote) doit=1;; + *) doit=1 + echo "/etc/syslog.conf: $d: unknown destination" >&2 + exit 1;; + esac +done + +# One of doneit or doit is set unless the DESTINATION value +# is empty (which is probably an error), let syslog handle +# the error. +test \( -n "$doit" -o -z "$doneit" \) -a -x /etc/init.d/syslog && + exec /etc/init.d/syslog "$@" + +exit 0 diff --git a/packages/slugos-init/files/initscripts/umountinitrd.sh b/packages/slugos-init/files/initscripts/umountinitrd.sh new file mode 100644 index 0000000000..da39b425f8 --- /dev/null +++ b/packages/slugos-init/files/initscripts/umountinitrd.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# +# umount /mnt, which is where the initrd ends up mounted +# if the directory /initrd is not present, if this fails +# then the /initrd is mounted and we want to remount that +# ro - this works round the shutdown -r hang problem +umount /mnt 2>/dev/null || { + # need the device for a remount + . /etc/default/functions + ffspart=Flashdisk + ffsdev="$(mtblockdev $ffspart)" + if test -n "$ffsdev" -a -b "$ffsdev" + then + mount -o remount,ro "$ffsdev" /initrd + else + echo "Flashdisk: $ffsdev: flash device not found" >&2 + fi +} diff --git a/packages/slugos-init/files/initscripts/zleds b/packages/slugos-init/files/initscripts/zleds new file mode 100644 index 0000000000..c4e2b37219 --- /dev/null +++ b/packages/slugos-init/files/initscripts/zleds @@ -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 r;; + *) echo "led change: $runlevel: runlevel unknown" >&2 + echo r;; + esac +} + +# leds syntax is -A +<init state> /<new state> +case "$1" in +start) leds -gr +"$(colour "$runlevel")";; +stop) leds -gr +"$(colour "$previous")" /"$(colour "$runlevel")";; +*) echo "led change: $1: command ignored" >&2;; +esac + +exit 0 diff --git a/packages/slugos-init/files/kern_header.c b/packages/slugos-init/files/kern_header.c new file mode 100644 index 0000000000..73b46eec0c --- /dev/null +++ b/packages/slugos-init/files/kern_header.c @@ -0,0 +1,47 @@ + +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> + + +int main(int argc, char **argv) +{ + struct stat sbuf; + char *devtype; + FILE *headerfile; + unsigned int header[4]; + + + if (argc != 3) { + fprintf(stderr, "usage: %s NSLU2_kernel_file_name prepend_header_filename\nThis program builds a 16 byte header which can be prepended to a NSLU2 Kernel for reflashing\n", argv[0]); + exit (1); + } + + if (stat(argv[1], &sbuf) < 0) { + fprintf(stderr, "%s: stat: %s\n", argv[1], strerror(errno)); + exit (1); + } + + /* printf ("File %s is %d bytes long\n", argv[1], sbuf.st_size); */ + if ((headerfile=fopen(argv[2],"wb"))==NULL) + { + fprintf(stderr,"Error opening file\n"); + exit (1); + } + + if ((sbuf.st_size + 16) > 0x100000) { + fprintf(stderr,"Error Kernel + Header is > 1 MB\n"); + exit (1); + } + + header[0] = (unsigned int)sbuf.st_size + 16; + header[1] = 0; + header[2] = 0; + header[3] = 0; + if (!fwrite(&header, sizeof(unsigned int), 4, headerfile)) + fprintf(stderr,"Error write to headerfile: %s\n", strerror(errno)); + + fclose(headerfile); +} + diff --git a/packages/slugos-init/files/leds.c b/packages/slugos-init/files/leds.c new file mode 100644 index 0000000000..e2120ae5d6 --- /dev/null +++ b/packages/slugos-init/files/leds.c @@ -0,0 +1,190 @@ + #include <stdio.h> + #include <stdlib.h> + #include <math.h> + #include <errno.h> + #include <string.h> + #include <endian.h> + #include <unistd.h> + #include <fcntl.h> + #include <sys/ioctl.h> + #include "leds.h" + + static int leds; + static int reset; + static int verbose = 0; + enum { + off=0, on=1, blink, unknown, transition=unknown + }; + + + void init_leds(void) + { + int i; + if ((leds = open("/dev/leds", O_RDWR)) < 0) { + int e1 = errno; + if (e1 != ENOENT) { + + fprintf(stderr,"Error: Could not open LEDS device file '/dev/leds' : %s\n", + strerror(e1)); + if(e1 == EACCES) + fprintf(stderr,"Run as root\n"); + exit(1); + } + } + + if (verbose) + printf("leds: initialized.\n"); + } + + void led_ioctl( int cmd, int num ) + { + int i, st; + + if (ioctl(leds, cmd, num) < 0) { + int e1 = errno; + fprintf(stderr, "leds: ioctl(%d,%d): failed to set leds: %s\n", + cmd, num, strerror(e1)); + exit(1); + } + } + + void led_set( int led, int state ) + { + switch (state) { + case off: if (!reset) led_ioctl(N2_LM_OFF, led); break; + case on: led_ioctl(N2_LM_ON, led); break; + case blink: /* Ensure any previous timer gets deleted first and that + * the LED is in a well known state. + */ + if (!reset) led_ioctl(N2_LM_OFF, led); + led_ioctl(N2_LM_BLINK, led); break; + } + } + + int led( int ch ) { + switch (ch) { + case 'r': return LED_RS_RED; + case 'g': return LED_RS_GRN; + case '1': return LED_DISK1; + case '2': return LED_DISK2; + case 'A': reset = 1; return LED_ALL; + default: fprintf(stderr, "leds: %c: unknown LED (use r,g,0,1 or A)\n", ch); + exit(1); + } + } + + int main( int argc, char **argv ) + { + /* Default: switch green on, red off (-A +g). */ + if (argc == 1) { + verbose = 1; + init_leds(); + led_ioctl(N2_LM_ALL_OFF, 0); + led_ioctl(N2_LM_ON, LED_RS_GRN); + } else { + int i, alt=0, state[PHYS_LEDS]; + for(i=0; i<PHYS_LEDS; ++i) + state[i] = unknown; + reset = 0; + + while (--argc > 0) { + char *arg = *++argv; + int st; + if (strcmp(arg, "-v") == 0) { + ++verbose; + continue; + } + + switch (*arg) { + case '+': st = on; break; + case '-': st = off; break; + case '!': st = blink; break; + case '/': st = transition; break; + default: fprintf(stderr, "leds: %c: unknown option\n", *arg); + exit(1); + } + + if (st != transition) { + while (*++arg) { + i = led(*arg); + if (i == LED_ALL) + for (i=0; i<PHYS_LEDS; ++i) state[i] = st; + else + state[i] = st; + } + } else { + int done, newstate[PHYS_LEDS]; + for(i=0; i<PHYS_LEDS; ++i) + newstate[i] = off; + while (*++arg) { + i = led(*arg); + if (i == LED_ALL) + for (i=0; i<PHYS_LEDS; ++i) newstate[i] = on; + else + newstate[i] = on; + } + + /* Merge the newstate back in. This sets 'alt' if going + * from an old state of just red to a new of just green + * or vice versa (and this is the only way of getting + * 'alt') + */ + /* Blink anything which changes from off to on or from + * on to off (this ignores anything already blinking). + */ + for (done=i=0; i<PHYS_LEDS; ++i) { + if (state[i] == !newstate[i]) { + done = 1; + state[i] = blink; + } + } + + /* Is anything (new) blinking? If it is then deal + * with the red/green case - blinking red,green is + * amber, is that what we want? This could be + * improved by a better kernel interface - it would + * be nice just to specify on/off times and a start + * time for each LED. + */ + if (done) { + if (state[LED_RS_RED] == blink && state[LED_RS_GRN] == blink && + newstate[LED_RS_RED] == !newstate[LED_RS_GRN]) { + /* Kernel bug: must switch off r and g first. */ + alt = 1; + } + } else { + for (i=0; i<PHYS_LEDS; ++i) { + if (newstate[i] == on) { + state[i] = blink; + } + } + } + } + } + + /* Go through the list making the required settings. 'alt' is + * special. 'reset' means A was given and all the settings are + * known. + */ + init_leds(); + if (reset) + led_ioctl(N2_LM_ALL_OFF, 0); + if (alt) { + /* Turn the leds off first to get to a known state. */ + led_set(LED_RS_GRN, off); + led_set(LED_RS_RED, off); + led_ioctl(N2_LM_ALT, LED_RS_RED); + } else { + /* KERNEL BUG: setting the green timer zaps the red behaviour + * to toggle the green, therefore if red blink is set before + * green blink no blink will happen! + */ + led_set(LED_RS_GRN, state[LED_RS_GRN]); + led_set(LED_RS_RED, state[LED_RS_RED]); + } + led_set(LED_DISK1, state[LED_DISK1]); + led_set(LED_DISK2, state[LED_DISK2]); + } + + return 0; + } diff --git a/packages/slugos-init/files/leds.h b/packages/slugos-init/files/leds.h new file mode 100644 index 0000000000..0b236dd6c0 --- /dev/null +++ b/packages/slugos-init/files/leds.h @@ -0,0 +1,21 @@ + void init_leds(void); + void led_on(int); + void led_off( int ); + void led_toggle(int num); + + // ioctls -- 'M" is used for sound cards...we don't got one so it seems safe + #define N2_LM_OFF _IOW('M',32,long) + #define N2_LM_ON _IOW('M',33,long) + #define N2_LM_BLINK _IOW('M',34,long) + #define N2_LM_ALT _IOW('M',35,long) + #define N2_LM_ALL_ON _IO('M',36) + #define N2_LM_ALL_OFF _IO('M',37) + + // The LED names for switches + #define LED_RS_RED 0 + #define LED_RS_GRN 1 + #define LED_DISK1 2 + #define LED_DISK2 3 + #define LED_ALL 4 + + #define PHYS_LEDS 4 diff --git a/packages/slugos-init/files/links.conf b/packages/slugos-init/files/links.conf new file mode 100644 index 0000000000..fdd1f3ce23 --- /dev/null +++ b/packages/slugos-init/files/links.conf @@ -0,0 +1,6 @@ +# This file does not exist. Please do not ask the debian maintainer about it. +# You may use it to do strange and wonderful things, at your risk. + +# The new RTC class does not create the /dev/rtc symlink, and udev rules don't get run for built-in modules. +# So it looks like we have to do this here for the moment, until someone comes up with a better idea ... +L rtc rtc0 diff --git a/packages/slugos-init/files/linuxrc b/packages/slugos-init/files/linuxrc new file mode 100644 index 0000000000..7c20a55b65 --- /dev/null +++ b/packages/slugos-init/files/linuxrc @@ -0,0 +1,146 @@ +#!/bin/sh + +# **** DO NOT EVEN THINK OF EDITING OR REMOVING THIS FILE **** +# **** UNLESS YOU REALLY KNOW *EXACTLY* WHAT YOU ARE DOING. **** + + +# Determine the desired rootfs based on user flag files. + +if [ -f /.ramdisk ] ; then + /bin/echo "Preferred root device is /dev/ram0 (maintenence)" + mounted=/mnt + prefroot=maintenence +elif [ -f /.sda1root ] ; then + /bin/echo "Preferred root device is /dev/sda1 (disk 1)" + mounted=/mnt + prefroot=sda1 +elif [ -f /.sda2root ] ; then + /bin/echo "Preferred root device is /dev/sda2 (disk 1)" + mounted=/mnt + prefroot=sda2 +elif [ -f /.sdb1root ] ; then + /bin/echo "Preferred root device is /dev/sdb1 (disk 2)" + mounted=/mnt + prefroot=sdb1 +elif [ -f /.sdb2root ] ; then + /bin/echo "Preferred root device is /dev/sdb2 (disk 2)" + mounted=/mnt + prefroot=sdb2 +elif [ -f /.nfsroot ] ; then + /bin/echo "Preferred root device is NFS" + mounted=/mnt + prefroot=nfsroot +else + /bin/echo "Preferred root device is jffs2" + mounted= + prefroot=jffs2 +fi + + +# Perform prepatory tasks, and determine whether the desired rootfs is viable. + +/bin/mount -t proc proc /proc + +if [ $prefroot = "sda1" -o $prefroot = "sda2" -o $prefroot = "sdb1" -o $prefroot = "sdb2" ] ; then + /bin/echo "Sleeping 10sec while waiting for disk..." + sleep 10 + /bin/mount -rt ext3 /dev/$prefroot /mnt + if [ -L /mnt/sbin/init -o -x /mnt/sbin/init -o \ + -L /mnt/bin/init -o -x /mnt/bin/init ] ; then + /bin/echo "Root filesystem will be mounted from /dev/$prefroot ..." + else + /bin/umount /mnt + /bin/echo "Can't find valid rootfs on /dev/$prefroot, using jffs2 ..." + mounted= + prefroot=jffs2 + fi +fi + +if [ $prefroot = "maintenence" ] ; then + /bin/dd if=/dev/zero of=/dev/ram0 bs=1k count=12k 2>/dev/null + /usr/bin/mke2fs -m 0 /dev/ram0 12288 + /bin/mount -t ext2 /dev/ram0 /mnt + ( /usr/bin/find . -print0 -mount | /usr/bin/cpio -p -0 -d -m -u /mnt ) + /bin/rm -f /mnt/linuxrc + /bin/cp /mnt/home/httpd/html/Management/upgrade.cgi /mnt/home/httpd/html/Management/upgrade-real.cgi + /bin/echo "#!/bin/sh" > /mnt/home/httpd/html/Management/upgrade.cgi + /bin/echo >> /mnt/home/httpd/html/Management/upgrade.cgi + /bin/echo "/bin/mount -t ramfs none /upload -o size=8196 2>/dev/null" \ + >> /mnt/home/httpd/html/Management/upgrade.cgi + /bin/echo "/bin/dd if=/dev/zero of=/upload/free-ram bs=1k count=8k 2>/dev/null" \ + >> /mnt/home/httpd/html/Management/upgrade.cgi + /bin/echo "/bin/umount /upload 2>/dev/null" \ + >> /mnt/home/httpd/html/Management/upgrade.cgi + /bin/echo "exec /home/httpd/html/Management/upgrade-real.cgi" \ + >> /mnt/home/httpd/html/Management/upgrade.cgi + /bin/echo "Root filesystem will be mounted from /dev/ram0 (a copy of /dev/mtdblock4) ..." +fi + +if [ $prefroot = "nfsroot" ] ; then + + sysconflen=`/bin/dd if=/dev/mtd1 bs=4 count=1 2>/dev/null | /usr/bin/hexdump -n 6 -e '"%02d"'` + ipaddr=`/bin/dd if=/dev/mtd1 bs=1 count=$sysconflen skip=4 2>/dev/null | grep ip_addr | sed -e s/ip_addr=//` + netmask=`/bin/dd if=/dev/mtd1 bs=1 count=$sysconflen skip=4 2>/dev/null | grep netmask | sed -e s/netmask=//` + gateway=`/bin/dd if=/dev/mtd1 bs=1 count=$sysconflen skip=4 2>/dev/null | grep gateway | sed -e s/gateway=//` + + /sbin/insmod ixp400 + /sbin/insmod ixp425_eth + /sbin/ifconfig ixp0 up $ipaddr netmask $netmask + /sbin/route add default gw $gateway + + /sbin/ifconfig lo up 127.0.0.1 + + # The nfsrootloc and nfsrootopts vars can be overridden here. + . /.nfsroot + + /bin/mount $nfsrootopts $nfsrootloc /mnt + + if [ -L /mnt/sbin/init -o -x /mnt/sbin/init -o \ + -L /mnt/bin/init -o -x /mnt/bin/init ] ; then + /bin/echo "Root filesystem will be mounted from an NFS root ..." + mounted=/mnt + else + /bin/umount /mnt + /bin/echo "Can't find valid NFS rootfs, using jffs2 ..." + mounted= + prefroot=jffs2 + fi +fi + +if [ $prefroot = "jffs2" ] ; then + /bin/echo "Root filesystem will be mounted from /dev/mtdblock4 ..." + mounted= +fi + + +/bin/umount /proc + +# Pivot to the desired rootfs and run the initial executable. + +if [ -n "$mounted" ] ; then + + cd $mounted + + if [ -x ./sbin/init -o -L ./sbin/init ] ; then + runboot=/sbin/init + elif [ -x ./bin/init -o -L ./bin/init ] ; then + runboot=/bin/init + else + runboot=/bin/sh + fi + + /sbin/pivot_root . initrd + + exec /usr/sbin/chroot . $runboot < /dev/console 1> /dev/console 2> /dev/console + +else + + exec /sbin/init + +fi + +/bin/echo "Can't chroot to $prefroot, using jffs2 ..." +exec /sbin/init + +# Last-resort fall-back - this should never be reached. +/bin/sh diff --git a/packages/slugos-init/files/modprobe.conf b/packages/slugos-init/files/modprobe.conf new file mode 100644 index 0000000000..08482e8c6d --- /dev/null +++ b/packages/slugos-init/files/modprobe.conf @@ -0,0 +1,3 @@ +# Add an alias for eth0 to MODULE to cause the S40networking +# init script to load the MODULE driver on the first boot +alias eth0 MODULE diff --git a/packages/slugos-init/files/modutils.txt b/packages/slugos-init/files/modutils.txt new file mode 100644 index 0000000000..a73b480efe --- /dev/null +++ b/packages/slugos-init/files/modutils.txt @@ -0,0 +1 @@ +# Adding modules to be automatically loaded via update-modules diff --git a/packages/slugos-init/files/reflash b/packages/slugos-init/files/reflash new file mode 100644 index 0000000000..bcf51fc606 --- /dev/null +++ b/packages/slugos-init/files/reflash @@ -0,0 +1,620 @@ +#!/bin/sh +# reflash +# ensure the flash disk is not mounted +# save configuration files +# update the kernel +# update the flashdisk +# restore the saved configuration files +# the set of configuration files is described by +# /etc/default/conffiles. +# +# /etc/default/functions contains useful utility functions +. /etc/default/functions +# +# CHECKING FOR INPUT (ARGUMENTS ETC) +# ---------------------------------- +# +# find the kernel and the new flash file system, an image file can +# be used to specify both images. +ffsfile= +kfile= +imgfile= +while test $# -gt 0 +do + case "$1" in + -k) shift + test $# -gt 0 || { + echo "reflash: -k: give the file containing the kernel image" >&2 + exit 1 + } + kfile="$1" + shift;; + -[jr]) shift + test $# -gt 0 || { + echo "reflash: -j: give the file containing the root jffs2 image" >&2 + exit 1 + } + ffsfile="$1" + shift;; + -i) shift + test $# -gt 0 || { + echo "reflash: -i: give the file containing the complete flash image" >&2 + exit 1 + } + imgfile="$1" + shift;; + *) echo "reflash: usage: $0 [-k kernel] [-j rootfs] [-i image]" >&2 + echo " -k file: the new compressed kernel image ('zImage')" >&2 + echo " -j file: the new root file system (jffs2)" >&2 + echo " -i file: a complete flash image (gives both kernel and jffs2)" >&2 + echo " The current jffs2 will be umounted if mounted." >&2 + exit 1;; + esac +done +# +# Sanity check on the arguments +if test -n "$imgfile" -a -n "$ffsfile" -a -n "$kfile" +then + echo "reflash: -k,-j,-i: specify at most two files" >&2 + echo " -i has both a kernel and rootfs, the kernel from -k and" >&2 + echo " the rootfs from -j override the one in the image (if given)" >&2 + exit 1 +elif test -z "$imgfile" -a -z "$ffsfile" -a -z "$kfile" +then + echo "reflash: -k,-j,-i: specify at least one file to flash" >&2 + exit 1 +fi +# +# Perform basic checks on the input (must exist, size must be ok). +if test -n "$imgfile" +then + if test -r "$imgfile" + then + # read the partition table and from this find the offset + # and size of Kernel and Flashdisk partitions. The following + # devio command just dumps the partition table in a format + # similar to /proc/mtd (but it outputs decimal values!) + #NOTE: this uses a here document because this allows the while + # loop to set the variables, a pipe would put the while in + # a sub-shell and the variable settings would be lost. This + # works in ash, no guarantees about other shells! + while read size base name + do + case "$name" in + Kernel) imgksize="$size" + imgkoffset="$base";; + Flashdisk) + imgffssize="$size" + imgffsoffset="$base";; + esac + done <<EOI +$(devio "<<$imgfile" ' + <= $ 0x20000 - + L= 0x1000 + $( 1 + # 0xff byte in name[0] ends the partition table + $? @ 255 = + # output size base name + <= f15+ + .= b 0xfffffff & + <= f4+ + .= b + pf "%lu %lu " + <= f28- + cp 16 + pn + <= f240+ + L= L256- + $) L255>') +EOI + # check the result + test "$imgksize" -gt 0 -a "$imgkoffset" -ge 0 || { + echo "reflash: $imgfile: failed to find Kernel partition in image" >&2 + exit 1 + } + # the kernel is after a 16 byte header which holds the + # values length,0,0,0 Get the true size. + ktmp="$(devio "<<$imgfile" "L=$imgksize" "O=$imgkoffset" ' + $( OL+$>! + <= O + A= b + $( AL>! + pr A + $) 0 + $) 0')" + test "$ktmp" -gt 0 || { + echo "reflash: $imgfile($imgkoffset,$imgksize): invalid kernel offset/size" >&2 + exit 1 + } + # update the size and offset to these values (the offset is 16+ because + # of the header). + imgksize="$ktmp" + imgkoffset="$(devio "O=$imgkoffset" 'pr O16+')" + # just test the size for the rootfs + test "$imgffssize" -gt 0 -a "$imgffsoffset" -ge 0 || { + echo "reflash: $imgfile: failed to find Flashdisk" >&2 + exit 1 + } + else + echo "reflash: $imgfile: image file not found" >&2 + exit 1 + fi +fi +if test -n "$kfile" +then + if test ! -r "$kfile" + then + echo "reflash: $kfile: kernel file not found" >&2 + exit 1 + fi + # the file values override anything from the image. + imgksize="$(devio "<<$kfile" 'pr$')" + imgkoffset=0 +else + kfile="$imgfile" +fi +if test -n "$ffsfile" +then + if test ! -r "$ffsfile" + then + echo "reflash: $ffsfile: root file system image file not found" >&2 + exit 1 + fi + # values override those from the image + imgffssize="$(devio "<<$ffsfile" 'pr$')" + imgffsoffset=0 +else + ffsfile="$imgfile" +fi +# +# INPUTS OK, CHECKING THE ENVIRONMENT +# ----------------------------------- +# basic setup. This could be parameterised to use different partitions! +kpart=Kernel +ffspart=Flashdisk +# +kdev= +ksize=0 +if test -n "$kfile" +then + # we have a new kernel + kdev="$(mtblockdev $kpart)" + test -n "$kdev" -a -b "$kdev" || { + echo "reflash: $kpart($kdev): cannot find $kpart mtd partition." >&2 + echo " check /proc/mtd, either the partition does not exist or there is no" >&2 + echo " corresponding block device." >&2 + exit 1 + } + ksize="$(devio "<<$kdev" 'pr$')" + # + # check the input file size + test -n "$imgksize" -a "$imgksize" -gt 0 -a "$imgksize" -le "$ksize" || { + echo "reflash: $kfile: bad Kernel size ($s, max $ksize)" >&2 + exit 1 + } +fi +# +ffsdev= +ffssize=0 +if test -n "$ffsfile" +then + ffsdev="$(mtblockdev $ffspart)" + test -n "$ffsdev" -a -b "$ffsdev" || { + echo "reflash: $ffspart($ffsdev): cannot find $ffspart mtd partition." >&2 + echo " check /proc/mtd, either the partition does not exist or there is no" >&2 + echo " corresponding block device." >&2 + exit 1 + } + ffssize="$(devio "<<$ffsdev" 'pr$')" + # + # check the input file size + test -n "$imgffssize" -a "$imgffssize" -gt 0 -a "$imgffssize" -le "$ffssize" || { + echo "reflash: $ffsfile: bad Flashdisk size ($s, max $ffssize)" >&2 + exit 1 + } +fi + +# +# INPUTS OK, ENVIRONMENT OK, UMOUNT ANY EXISTING MOUNT OF THE FLASHDISK +# --------------------------------------------------------------------- +# This is only required if the device is going to be used +if test -n "$ffsdev" +then + # -r causes this to fail if the flash device is mounted on / + umountflash -r "$ffsdev" || exit 1 + # + # Everything is umounted, now remount on a temporary directory. + ffsdir="/tmp/flashdisk.$$" + mkdir "$ffsdir" || { + echo "reflash: $ffsdir: failed to create temporary directory" >&2 + exit 1 + } + # + mountflash "$ffsdev" "$ffsdir" -o ro || { + rmdir "$ffsdir" + exit 1 + } + # + # this is a utility function to make the cleanup easier + errorexit() { + umount "$ffsdir" && rmdir "$ffsdir" || + echo "reflash: $ffsdir: temporary directory cleanup failed" >&2 + exit 1 + } + # + test -r "$ffsdir/etc/default/conffiles" || { + echo "reflash: [/initrd]/etc/default/conffiles: file not found" >&2 + errorexit + } +else + errorexit() { + exit 1 + } +fi +# +# PRESERVE EXISTING CONFIGURATION +# ------------------------------- +# Only required if the flash partition will be written +if test -n "$ffsdev" +then + echo "reflash: preserving existing configuration file" >&2 + # + # This step produces /tmp/preserve.$$ and /tmp/cpio.$$, the former is + # a list of the preserved configuration files together with the processing + # option, the latter is a directory tree of the preserved files (a directory + # tree makes the restore step easier.) + saved=/tmp/cpio.$$ + list=/tmp/preserve.$$ + mkdir "$saved" || { + echo "reflash: $saved: could not create save directory" >&2 + errorexit + } + # + ( cd "$ffsdir" + find etc/*.conf $(sed 's!^/!!' usr/lib/ipkg/info/*.conffiles) ! -type d -newer etc/.configured -print | + sed 's/^/diff /' + exec sed 's/#.*$//;/^[ ]*$/d' etc/default/conffiles + ) | sed 's!^/*!!' | awk '{ op=$1; $1=""; file[$0]=op } + END{ for (f in file) if (file[f] != "ignore") print file[f] f }' | + while read op file + do + if test -e "$ffsdir/$file" + then + echo "$op $file" >&3 + echo "$file" + fi + done 3>"$list" | (cd "$ffsdir"; exec cpio -p -d -m -u "$saved") || { + echo "reflash: $saved: copy of saved configuration files failed" >&2 + rm -rf "$saved" + rm "$list" + errorexit + } + # + # If this umount fails do not try to continue... + umount "$ffsdir" || { + echo "reflash: $ffsdir: temporary mount point umount failed" >&2 + echo " No changes have been made." >&2 + rm -rf "$saved" + rm "$list" + exit 1 + } +fi +# +# FLASH THE NEW IMAGES +# -------------------- +echo "reflash: about to flash new image" >&2 +# +# There are four possibilities here - kernel only, flashdisk only, then +# kernel&flashdisk in either one or two different files. The code used +# to attempt to do everything in one step, but this complicates it, +# so two steps are used (as required). A failure between the two +# steps is a problem, but then so is a failure in a partial write. +# Write the flashdisk first because this is larger (most likely to +# fail). +# Temporarily check for devio progress indicator capability this way... +if devio -p '' 2>/dev/null +then + progress=-p +else + progress= +fi +do_kernel() { + devio $progress "$@" "<<$kfile" ">>$kdev" ' + # kernel is at imgkoffset[imgksize] + ' "<= $imgkoffset" "L=$imgksize" ' + # kernel write length,0,0,0 header, then fill + wb L,4 + fb 12,0 + cp L + # fill with 255 + fb #t-,255' +} +# +do_ffs() { + devio $progress "$@" "<<$ffsfile" ">>$ffsdev" ' + # rootfs is at imgffsoffset[imgffssize] + ' "<= $imgffsoffset" "cp $imgffssize" ' + # fill with 255 + fb #t-,255' +} +# +# check_status $? type file(offset,size) device +# check the devio status code (given in $1) +check_status() { + case "$1" in + 0) echo " done" >&2;; + 1) echo " failed" >&2 + echo "reflash: $3: flash $2 failed, no changes have been made to $4" >&2 + if test "$2" = rootfs + then + rm -rf "$saved" + rm "$list" + exit 1 + else + echo "reflash: $2: continuing with rootfs changes" >&2 + echo " NOTE: the old kernel is still in $4!" >&2 + fi;; + 3) echo " failed" >&2 + echo "reflash: $3: WARNING: partial flash of $2 to $4 the system is unbootable" >&2 + echo " Reflash from RedBoot or correct the problem here." >&2 + if test "$2" = rootfs + then + exit 3 + else + echo "reflash: $2: continuing with rootfs changes" >&2 + echo " NOTE: the kernel in $4 must be reflashed!" >&2 + fi;; + *) echo " failed" >&2 + echo "reflash($1): $3: internal error flashing $2 to $4" >&2 + exit $1;; + esac +} +# +if test -n "$ffsdev" +then + echo -n "reflash: writing rootfs to $ffsdev " >&2 + do_ffs + check_status $? rootfs "$ffsfile($imgffsoffset,$imgffssize)" "$ffsdev" +fi +# +if test -n "$kdev" +then + echo -n "reflash: writing kernel to $kdev " >&2 + do_kernel + check_status $? kernel "$kfile($imgkoffset,$imgksize)" "$kdev" +fi +# +# verify - this just produces a warning +if test -n "$ffsdev" +then + echo -n "reflash: verifying new flash image " >&2 + if do_ffs -v + then + echo " done" >&2 + else + echo " failed" >&2 + echo "reflash: WARNING: rootfs flash image verification failed" >&2 + echo " The system is probably unbootable." >&2 + echo " System configuration files will be restored but this may fail" >&2 + echo " Starting a shell for user recovery (exit to continue)" >&2 + PS1='badflash$ ' sh -i <>/dev/tty >&0 2>&0 + fi +fi +# +if test -n "$kdev" +then + echo -n "reflash: verifying new kernel image " >&2 + if do_kernel -v + then + echo " done" >&2 + else + echo " failed" >&2 + echo "reflash: WARNING: kernel flash image verification failed" >&2 + echo " The system is probably unbootable." >&2 + echo " System configuration files will be restored in the rootfs." >&2 + fi +fi +# +# RESTORE THE OLD CONFIGURATION +# ----------------------------- +# If not write the rootfs none of the following is required - exit now. +test -n "$ffsdev" || exit 0 +# +echo "reflash: restoring saved configuration files" >&2 +# +# the file /etc/.configured is the datestamp file used to ensure that +# changed configuration files can be recognised. It is created by +# /etc/rcS.d/S99finish on first boot (if it does not exist). We need +# a timestamp earlier than any files we create so touch it here, this +# also acts as a test on the mounted file system +mountflash "$ffsdev" "$ffsdir" && :>"$ffsdir/etc/.configured" || { + rmdir "$ffsdir" + echo "reflash: mount of new flash root file system failed" >&2 + if test -d "$ffsdir/etc" + then + echo " The file system does not seem to be writeable." >&2 + echo " The mounted file system is in $ffsdir" >&2 + fi + echo " WARNING: the kernel and root file system have been reflashed," >&2 + echo " HOWEVER the new root file system seems to be unuseable." >&2 + echo " Saved configuration files are in $saved" >&2 + echo " The list of saved configuration files is in $list" >&2 + echo " You should determine the reason for the failed mount, mount the new" >&2 + echo " file system and restore the configuration from $saved - it's just a" >&2 + echo " matter of copying the saved files where required." >&2 + exit 1 +} +# +# verify file +# this is called with the name of a 'diff' file which is, indeed, +# different and with all the std streams connected to the tty. It +# returns a status code to say whether (0) or not (1) to copy the +# file over. +# +verify_help() { + echo "Please specify how to handle this file or link, the options are as follows," + echo "two character abbreviations may be used:" + echo + echo " keep: retain the old file, overwrite the new flash image file" + echo " upgrade: retain the new file, the old (saved) file is not used" + echo " diff: display the differences between the old and the new using diff -u" + echo " shell: temporarily start an interactive shell (sh -i), exit to continue" + echo " skip: ignore this file for the moment. The file is left in the directory" + echo " $saved and many be handled after this script has completed" +} +# +verify() { + local command file + + file="$1" + echo "reflash: $file: configuration file changed." + verify_help "$file" + while : + do + echo -n "option: " + read command + case "$command" in + ke*) return 0;; + up*) rm "$saved/$file" + return 1;; + di*) echo "DIFF OLD($saved) NEW($ffsdir)" + diff -u "$saved/$file" "$ffsdir/$file";; + sh*) PS1="$file: " sh -i;; + sk*) return 1;; + *) verify_help "$file";; + esac + done +} +# the same, but for a link +verify_link() { + local command link + + link="$1" + echo "reflash: $link: configuration link changed." + verify_help "$link" + while : + do + echo -n "option: " + read command + case "$command" in + ke*) return 0;; + up*) rm "$saved/$link" + return 1;; + di*) echo "DIFF:" + echo "OLD($saved): $link -> $(readlink "$saved/$link")" + echo "NEW($ffsdir): $link -> $(readlink "$ffsdir/$link")";; + sh*) PS1="$link: " sh -i;; + sk*) return 1;; + *) verify_help "$link";; + esac + done +} +# +while read op file +do + # handle .configured specially (to preserve the original datestamp) + if test "$file" = "etc/.configured" + then + # this should definately not fail because of the test above! + if cp -a "$saved/$file" "$ffsdir/$file" + then + echo "$file" >&3 + else + echo "reflash: $file: timestamp copy failed (ignored)" >&2 + fi + elif test -h "$saved/file" -o -h "$ffsdir/$file" + then + # new or old symbolic link + if test -h "$saved/$file" -a -h "$ffsdir/$file" && + test "$(readlink "$saved/$file")" = "$(readlink "$ffsdir/$file")" + then + # no change + echo "$file" >&3 + else + # assume a change regardless + case "$op" in + preserve) + echo "$file" + echo "$file" >&3;; + diff) # need user input + if verify_link "$file" <>/dev/tty >&0 2>&0 + then + echo "$file" + echo "$file" >&3 + fi;; + esac + fi + else + # only overwrite if necessary + if test -e "$ffsdir/$file" && cmp -s "$saved/$file" "$ffsdir/$file" + then + # do not overwrite + echo "$file" >&3 + elif test ! -e "$ffsdir/$file" + then + # always preserve + echo "$file" + echo "$file" >&3 + else + case "$op" in + preserve) + echo "$file" + echo "$file" >&3;; + diff) # the files are different, get user input + if verify "$file" <>/dev/tty >&0 2>&0 + then + echo "$file" + echo "$file" >&3 + fi;; + esac + fi + fi +done <"$list" 3>/tmp/restore.$$ | (cd "$saved"; exec cpio -p -d -u "$ffsdir") || { + echo "reflash: $saved: restore of saved configuration files failed" >&2 + echo " The new flash file system is mounted on $ffsdir" >&2 + echo " The saved files are in $saved and the list in $list, the list of" >&2 + echo " files selected for restore is in /tmp/restore.$$" >&2 + echo " You should restore any required configuration from $saved," >&2 + echo " then umount $ffsdir and reboot." >&2 + exit 1 +} +# +# remove the copied files (i.e. the ones which were preserved) +( cd "$saved" + exec rm $(cat /tmp/restore.$$) +) +rm /tmp/restore.$$ +# +# clean up, files left in $saved need to be handled by the user +files="$(find "$saved" ! -type d -print)" +if test -n "$files" +then + echo "reflash: the following saved configuration files remain:" >&2 + echo "$files" >&2 + echo "The full list of preserved files is in $list. To alter the" >&2 + echo "new root file system use the command:" >&2 + echo "" >&2 + echo " mount -t jffs2 $ffsdev /mnt" >&2 + echo "" >&2 + echo "The saved files are in the temporary directory, they will not" >&2 + echo "be retained across a system boot. Copy them elsewhere if you" >&2 + echo "are unsure whether they are needed" >&2 +else + rm -rf "$saved" + rm "$list" +fi +# +# now the final umount +if umount "$ffsdir" +then + rmdir "$ffsdir" + echo "reflash: system upgrade complete. Reboot to continue." >&2 + exit 0 +else + echo "reflash: $ffsdir: temporary mount point umount failed" >&2 + echo " ALL changes have been made successfully, however the umount of" >&2 + echo " the new root file system has failed. You should determine the" >&2 + echo " cause of the failure, umount $ffsdir, then reboot the system (this" >&2 + echo " will use the upgraded kernel and root file system)" >&2 + exit 1 +fi diff --git a/packages/slugos-init/files/turnup b/packages/slugos-init/files/turnup new file mode 100644 index 0000000000..0029697c50 --- /dev/null +++ b/packages/slugos-init/files/turnup @@ -0,0 +1,890 @@ +#!/bin/sh +# turnup +# See the help block at the end for documentation. +# +. /etc/default/functions + +# +# configuration +# The following variables control which directories in /var end up on the rootfs +# and which end up in a temporary file system. +INRAM_MEMSTICK="/var/cache /var/lock /var/log /var/run /var/tmp /var/lib/ipkg" +INRAM_NFS="/var/cache /var/lock /var/run /var/tmp" +INRAM_DISK="" +# +# force: override certain checks +force= +# +# fstype new +# The type of the file system mounted on "new" Outputs the last +# piece of information found, which should be the one for the +# currently visible mount! +fstype() { + local cwd dev mp type options pass freq result + cwd="$(cd "$1"; /bin/pwd)" + result= + while read dev mp type options pass freq + do + case "$mp" in + "$cwd") result="$type";; + esac + done </proc/mounts + echo "$result" +} +# +# fsoptions arguments +# Collapses the mount (-o) options into a single list which is +# printed on stdout. Accepts an arbitrary list of options and +# just joins them together. +fsoptions() { + local options + options= + while test $# -gt 1 + do + case "$1" in + -t) shift;; + -o) if test -n "$2" + then + if test -n "$options" + then + options="$options,$2" + else + options="$2" + fi + fi + shift;; + esac + shift + done + if test -n "$options" + then + echo "$options" + else + echo defaults + fi +} +# +# get_flash <directory> {mount options} +# mount the flash device, writeable, on the given directory +get_flash() { + local ffsdir ffsdev + + ffsdir="$1" + shift + test -n "$ffsdir" -a -d "$ffsdir" || { + echo "$0: $ffsdir: internal error, flash mount point not a directory" >&2 + return 1 + } + + ffsdev="$(mtblockdev Flashdisk)" + umountflash "$ffsdev" && + mountflash "$ffsdev" "$ffsdir" "$@" +} +# +# 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 +# In flash file systems /dev is in ramfs, in disk systems /dev +# can be populated permanently. This is done by creating a +# single entry '.noram' in /dev - the devices init script will +# then populate the directory without overmounting it. The +# devices in the passed in device table are also created, but +# note that this is insufficient, /etc/init.d/devices must +# also run. +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 + } + echo "turnup: initialising dev file system" >&2 + # init tries to open the following devices: + # /dev/console + # /dev/tty0 + # /dev/null + # syslog, and maybe other things, only work if fd 1 is valid, therefore + # we must create these devices here... + makedevs --root="$1" --devtable="$2" + :>"$1"/dev/.noram + 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. +# Removes the /var tmpfs entry from /etc/fstab. +# Creates links from /var into /media/ram for NFS and Memstick. + +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|memstick);; + *) echo "turnup: setup_var($1,$2): expected 'disk', 'nfs' or 'memstick'" >&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-volatile.sh || { + echo "turnup: /var: could not populate directory" >&2 + return 1 + } + + case "$2" in + disk) RAMTARGETS=${INRAM_DISK};; + nfs) RAMTARGETS=${INRAM_NFS};; + memstick) RAMTARGETS=${INRAM_MEMSTICK};; + esac + + for d in ${RAMTARGETS}; do + RAMDIR="/media/ram${d}" + REALDIR="${d}" + rm -rf "${1}${REALDIR}" + ln -s "${RAMDIR}" "${1}${REALDIR}" + done + # the startup link is left for the moment, this seems safer + #rm "$1"/etc/rc?.d/[KS]??populate-var.sh + # remove the /var tmpfs entry from the new /etc/fstab + sed -i '\@[ ]/var[ ][ ]*tmpfs[ ]@d' "$1"/etc/fstab + echo "turnup: tmpfs will no longer be mounted on /var" >&2 + # + # Previous versions of turnup removed populate-var.sh from the + # startup links, this one doesn't, so /var can be made back into + # a tmpfs just by a change to /etc/fstab. + 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" "$type" && + setup_syslog "$new";; + memstick) + setup_bootdev "$new" "$table" && + setup_var "$new" "$type" ;; + nfs) setup_dev "$new" "$table" && + setup_var "$new" "$type" && + setup_syslog "$new";; + *) echo "turnup: setup_rootfs: $type: unknown rootfs type" >&2 + return 1;; + esac + # return code of last setup function +} + +# +# setup_fstab new fsdev fstype fsoptions +# Alters the /etc/fstab entry for / to refer to the correct device and +# have the correct type and options. Essential for checkroot to remount +# / with the correct options. +# bad, since sed won't fail even if it changes nothing. +setup_fstab() { + sed -i '\@^[^ ]*[ ][ ]*/[ ]@s@^.*$@'"$2 / $3 $4 1 1"'@' "$1"/etc/fstab + egrep -q "^$2 / $3 $4 1 1\$" "$1"/etc/fstab || { + echo "turnup: /etc/fstab: root(/) entry not changed" >&2 + echo " you probably need to check the options in /etc/fstab" >&2 + echo " to ensure that the root partition is mounted correctly" >&2 + return 1 + } +} + + +# +# 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 +} + +# +# 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 fst fso + + 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 + get_flash "$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 + fst= + fso="$(fsoptions "$@")" + if mount "$@" "$device" "$new" + then + fst="$(fstype "$new")" + umount "$new" || + echo "turnup disk: $device($new): umount does not seem to work" >&2 + fi + + if test -n "$fst" && mount -t "$fst" -o "$fso" "$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 + setup_fstab "$new" "$device" "$fst" "$fso" + status=0 + fi + + # clean up the disk. It is worrying if this umount fails! + umount "$new" || test "$force" = "-f" || { + echo "turnup disk: $device: umount failed" >&2 + echo " you must unmount this device cleanly yourself, then use" >&2 + if test -z "$init" + then + echo " turnup with the -f option to boot from the device" >&2 + else + echo " turnup without the -i option to boot from the device" >&2 + fi + 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" -t "$fst" -o "$fso" + fi + else + echo "turnup disk: $device($*): unable to mount device on $new" >&2 + # If it worked first time + if test -n "$fst" + then + echo " options used: -t $fst -o $fso [error in this script]" >&2 + fi + 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 + } + + get_flash "$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 + get_flash "$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 + fst= + # These settings for for NFS, something better will probably have to + # be done to support other network file systems. + nfsopt="nolock,noatime,hard,intr,rsize=1024,wsize=1024" + fso="$(fsoptions -o "$nfsopt" "$@")" + if mount -o "$nfsopt" "$@" "$nfsroot" "$new" + then + fst="$(fstype "$new")" + umount "$new" || + echo "turnup nfs: $nfsroot($new): umount does not seem to work" >&2 + fi + + if test -n "$fst" && mount -t "$fst" -o "$fso" "$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 + setup_fstab "$new" "$nfsroot" "$fst" "$fso" + status=0 + fi + else + echo "turnup nfs: $nfsroot: partition must be exported no_root_squash" >&2 + fi + + # clean up the disk. It is worrying if this umount fails! + umount "$new" || test "$force" = "-f" || { + echo "turnup nfs: $nfsroot: umount failed" >&2 + if test $status -eq 0 + then + echo " you must unmount this partition cleanly yourself, then use" >&2 + if test -z "$init" + then + echo " turnup with the -f option to boot from the NFS root" >&2 + else + echo " turnup without the -i option to boot from the NFS root" >&2 + fi + 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 "$fso" + fi + else + echo "turnup nfs: $nfsroot($*): unable to mount device on $new" >&2 + # If it worked first time + if test -n "$fst" + then + echo " options obtained: -t $fst -o $fso" >&2 + fi + fi + + # clean up the flash file system + umount "$ffs" + rmdir "$new" "$ffs" + return $status +} + +# +# fix_hw_addr +# Called when the configuration is invalid to reset /etc/default/sysconf +fix_hw_addr() { + # first look on the flash disk (ideally this stuff would only + # be called from flash, but there is no way of guaranteeing that). + local ffsdev ffs mac name force + + case "$1" in + -f) force="$1";; + esac + + ffsdev="$(mtblockdev Flashdisk)" + test -n "$ffsdev" -a -b "$ffsdev" || { + echo "turnup init: the flash file system device is missing" >&2 + echo " The device (typically /dev/mtdblock4) must exist and" >&2 + echo " it must identify a flash partition called 'Flashdisk'" >&2 + echo " It may be that the /dev directory has not been initialised." >&2 + echo " This script cannot correct this problem." >&2 + return 1 + } + + test -x /etc/init.d/sysconfsetup || { + echo "turnup init: /etc/init.d/sysconfsetup: script not executable" >&2 + echo " or script not present. turnup init requires this script to" >&2 + echo " exist to correct the initialisation" >&2 + return 1 + } + + # use devio to find out if this *is* the flash disk. + ffs= + if test "$(devio "<<$ffsdev" prd)" -ne "$(devio '<</etc/init.d/sysconfsetup' prd)" + then + # this isn't the flash device + ffs="/tmp/flashdisk.$$" + # make sure we can get to the flash file system first + get_flash "$ffs" || { + rmdir "$ffs" + return 1 + } + + # copy if available + if test -r "$ffs/etc/default/sysconf" + then + cp "$ffs/etc/default/sysconf" + force= + fi + + umount "$ffs" + rmdir "$ffs" + fi + + # if the config is still not valid generate sysconf from the slug + # label. + config valid && test -z "$force" || { + mac= + until test -n "$mac" + do + echo "turnup init: please find the 'MAC Address' of your NSLU2" >&2 + echo " The required number is on a label on the bottom of the NSLU2" >&2 + echo " It will be something like 'LKG1A2B3C'" >&2 + echo -n "Enter the mac address: " >/dev/tty + read name </dev/tty + case "$name" in + [Ll][Kk][Gg][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]) + mac="$(echo "$name" | + sed -n 's/^...\(..\)\(..\)\(..\)$/00:0F:66:\1:\2:\3/p')";; + [0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]:[0-9A-Fa-f][0-9A-Fa-f]) + mac="$name" + name= + ;; + "") return 1;; + *) echo "$name: not recognised as a LinkSys mac address" >&2 + echo " Enter the LinkSys value or a full Ethernet MAC addrress" >&2 + mac=;; + esac + + # Now generate the correct sysconf + { echo '[network]' + echo "hw_addr=$mac" + test -n "$name" && echo "default_server_name=$name" + } >/etc/default/sysconf + done + } + + # the configuration should be valid now + /etc/init.d/sysconfsetup reload +} + +# +# read_one 'prompt' 'group' 'name' +# read a single value +read_one() { + local n o + o="$(sysval "$2" "$3")" + echo -n "$1 [$o]: " >/dev/tty + read n </dev/tty + test -z "$n" && n="$o" + eval "$3='$n'" +} +# +# init_network +# Change the network initialisation +init_network() { + # fix the root password + echo "Please enter a new password for 'root'." >/dev/tty + echo "The password must be non-empty for ssh login to succeed!" >/dev/tty + passwd + # now the network configuration + read_one "Host name" network disk_server_name + read_one "Domain name" network w_d_name + read_one "Boot protocol (dhcp|static)" network bootproto + case "$bootproto" in + static) read_one "IP address" network ip_addr + read_one "IP netmask" network netmask + read_one "IP gateway" network gateway + read_one "First DNS server" network dns_server1 + read_one "Second DNS server" network dns_server2 + read_one "Third DNS server" network dns_server3 + echo "$ip_addr $disk_server_name" >> /etc/hosts + ;; + dhcp) sed -i -e "s/localhost\$/localhost $disk_server_name/" /etc/hosts + ;; + *) bootproto=dhcp;; + esac + # + # The other stuff which cannot be changed + hw_addr="$(config mac)" + lan_interface="$(config iface)" + # + # Write this out to a new sysconf + { echo "[network]" + echo "hw_addr=$hw_addr" + echo "lan_interface=$lan_interface" + test -n "$disk_server_name" && echo "disk_server_name=$disk_server_name" + test -n "$w_d_name" && echo "w_d_name=$w_d_name" + echo "bootproto=$bootproto" + case "$bootproto" in + static) echo "ip_addr=$ip_addr" + test -n "$netmask" && echo "netmask=$netmask" + test -n "$gateway" && echo "gateway=$gateway" + test -n "$dns_server1" && echo "dns_server1=$dns_server1" + test -n "$dns_server2" && echo "dns_server2=$dns_server2" + test -n "$dns_server3" && echo "dns_server3=$dns_server3" + ;; + esac + } >/etc/default/sysconf + # + # And reload the result + /etc/init.d/sysconfsetup reload + # + # The remove the spurious 'init' motd + rm /etc/motd +} + +# +# Basic command switch (this should be the only thing in this +# script which actually does anything!) +case "$1" in +init) shift + if config valid && test "$1" != -f + then + if init_network "$@" + then + echo "turnup init: you must reboot the NSLU2 for the changes to take effect" >&2 + else + exit 1 + fi + else + if fix_hw_addr "$@" + then + echo "turnup init: you must reboot the NSLU2 for the changes to take effect" >&2 + else + exit 1 + fi + fi;; +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 + correct errors in network information + initialise network information when DHCP is not available + change network information + 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. + A default set of -o options are provided, additional options + may be given on the command line (multiple -o options will + be combined into a single -o). + 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. diff --git a/packages/slugos-init/files/update-kernel b/packages/slugos-init/files/update-kernel new file mode 100644 index 0000000000..796d45e953 --- /dev/null +++ b/packages/slugos-init/files/update-kernel @@ -0,0 +1,82 @@ +#!/bin/sh + +if [ ! -f /boot/zImage ] ; then + echo "Cannot find kernel to flash in /boot/zImage" + exit 1 +fi + +/bin/rm -f /boot/zImage-partition + +if [ -f /boot/zImage-partition ] ; then + echo "Unable to remove kernel partition file" + exit 1 +fi + +echo "Creating kernel partition header" +/usr/sbin/kern_header /boot/zImage /boot/zImage-partition + +if [ ! -f /boot/zImage-partition ] ; then + echo "Unable to create kernel partition header" + exit 1 +fi + +echo "Creating kernel partition file" +/bin/cat /boot/zImage >> /boot/zImage-partition + +/bin/rm -f /boot/zImage-partition.old + +if [ -f /boot/zImage-partition.old ] ; then + echo "Unable to remove old kernel partition file" + exit 1 +fi + +echo "Saving old kernel partition" +cat /dev/mtdblock2 > /boot/zImage-partition.old + +if [ ! -f /boot/zImage-partition.old ] ; then + echo "Unable to create old kernel partition file" + exit 1 +fi + +/bin/ls -l /boot/zImage /boot/zImage-partition /boot/zImage-partition.old + +echo "Flashing new kernel partition" +cat /boot/zImage-partition > /dev/mtdblock2 + +/bin/rm -f /boot/zImage-partition.verify + +if [ -f /boot/zImage-partition.verify ] ; then + echo "Unable to remove kernel partition verify file" + exit 1 +fi + +echo "Verifing new kernel partition" +/bin/dd if=/dev/mtd2 of=/boot/zImage-partition.verify bs=1 \ + count=`/bin/dd if=/dev/mtd2 bs=4 count=1 2>/dev/null | \ + /usr/bin/hexdump -n 6 -e '"%02d"'` 2>/dev/null + +if [ ! -f /boot/zImage-partition.verify ] ; then + echo "Unable to create kernel partition verify file" + exit 1 +fi + +if cmp /boot/zImage-partition /boot/zImage-partition.verify ; then + echo "Verification successful" + /bin/rm -f /boot/zImage-partition.verify + /bin/rm -f /boot/zImage-partition + /bin/rm -f /boot/zImage-partition.old + exit 0 +fi + +echo "VERIFICATION FAILED - DANGER DANGER DANGER" + +echo "You must now manually reflash the new kernel," +echo "or reflash the old kernel back again." +echo "The kernel partition is /dev/mtdblock2" +echo "The old kernel partition is in /boot/zImage-partition.old" +echo "The present partition contents are in /boot/zImage-partition.verify" +echo "The new kernel partition is in /boot/zImage-partition" + +exit 1 + + |