diff options
20 files changed, 1290 insertions, 1162 deletions
diff --git a/packages/slugos-init/files/boot/disk b/packages/slugos-init/files/boot/disk index ede33a3ee6..e8d1f5245b 100755 --- a/packages/slugos-init/files/boot/disk +++ b/packages/slugos-init/files/boot/disk @@ -3,14 +3,14 @@ # 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 # +leds boot system +# if test -n "$1" then device="$1" diff --git a/packages/slugos-init/files/boot/flash b/packages/slugos-init/files/boot/flash index e0bcebc9b8..12729d7b5d 100755 --- a/packages/slugos-init/files/boot/flash +++ b/packages/slugos-init/files/boot/flash @@ -1,14 +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 +# nothing need be done apart from setting the +# system LED status correctly +. /etc/default/functions +leds beep +leds boot system +test -x /sbin/init && 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' +leds boot system panic exec <>/dev/console >&0 2>&0 -exec /sbin/sulogin -exec /bin/sh +test -x /sbin/sulogin && exec /sbin/sulogin +test -x /bin/sh && exec /bin/sh exit 1 diff --git a/packages/slugos-init/files/boot/network b/packages/slugos-init/files/boot/network index 02b226d1f3..599250e744 100755 --- a/packages/slugos-init/files/boot/network +++ b/packages/slugos-init/files/boot/network @@ -11,15 +11,6 @@ # 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 +test -n "$iface" && ifup "$iface" # 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 index 534d8b7cb0..5f1cbbe323 100755 --- a/packages/slugos-init/files/boot/nfs +++ b/packages/slugos-init/files/boot/nfs @@ -3,7 +3,8 @@ # must be given) using options from the rest of # the command line. # -/sbin/leds -A '!gr' +. /etc/default/functions +leds boot system # # Use the standard init path (see /etc/init.d/rcS) export PATH=/sbin:/bin:/usr/sbin:/usr/bin diff --git a/packages/slugos-init/files/boot/ram b/packages/slugos-init/files/boot/ram index 66d46a7089..42ff8329f9 100755 --- a/packages/slugos-init/files/boot/ram +++ b/packages/slugos-init/files/boot/ram @@ -3,14 +3,15 @@ # 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 # +leds beep double +leds boot system +# if test -n "$1" then device="$1" diff --git a/packages/slugos-init/files/conffiles b/packages/slugos-init/files/conffiles index 51a8091b1e..68dd26d897 100644 --- a/packages/slugos-init/files/conffiles +++ b/packages/slugos-init/files/conffiles @@ -25,7 +25,7 @@ preserve etc/.configured preserve etc/TZ diff etc/default/conffiles diff etc/default/devpts -diff etc/default/rcS +preserve etc/default/rcS preserve etc/default/sysconf diff etc/default/usbd preserve etc/defaultdomain diff --git a/packages/slugos-init/files/functions b/packages/slugos-init/files/functions index e90f03aead..d7e5c9905a 100755 --- a/packages/slugos-init/files/functions +++ b/packages/slugos-init/files/functions @@ -1,5 +1,41 @@ +#!/bin/sh # . this file to load the following utility functions # +# hardware +# the 'Hardware' string from cpuinfo +hardware(){ + sed -n 's!^Hardware *: !!p' /proc/cpuinfo +} +# +# machine +# outputs an identifier of the current machine - i.e. the board +# slugos is running on. +machine(){ + case "$(hardware)" in + *Coyote*) echo coyote;; + *IXDPG425*) echo ixdpg425;; + *WRV54G*) echo wrv54g;; + *IXDP425*) echo ixdp425;; + *IXDP465*) echo ixdp465;; + *IXCDP1100*) echo ixcdp1100*;; + *Avila*) echo avila;; + *Loft*) echo loft;; + *NAS?100d*) echo nas100d;; + *NSLU2*) echo nslu2;; + *) echo unknown;; + esac +} +# +# load_functions "source" +# load the functions in '/sbin/source' - relies on /sbin/source being +# a shell script and having support for this function. +load_functions(){ + test -n "$1" -a -x "/sbin/$1" && . "/sbin/$1" || { + echo "$0: /sbin/$1: script not found" >&2 + return 1 + } +} +# # mtdev "name" # return (output) the character device name for flash parition "name" # /proc/mtd has the general form: @@ -27,90 +63,81 @@ mtsize(){ # 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. +# if there are multiple definitions only the last is output # 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! +# below if necessary. This is because 'config' does the defaulting. 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 + test -r "$config_root/etc/default/sysconf" && + sysvalof "$1" "$2" "$config_root/etc/default/sysconf" +} +# +# syssection "section" +# outputs all the values from the given section changed to the format "name value" +# (i.e. the '=' is dropped). +syssection(){ + test -r "$config_root/etc/default/sysconf" && + sed -n '/^\['"$1"'\]$/,/^\[.*\]$/s/^\([^=]*\)=\(.*\)$/\1 \2/p' "$config_root/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. +# NOTE: this function does the defaulting, 'sysval' does not! +# config_root: if set this will override the root where config/sysval +# looks for /etc/default/sysconf 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 + mac="$(test -r /proc/net/maclist && + sed -n '/^[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]$/p' /proc/net/maclist | + sed -n 1p)" + # + case "$1" in + mac) test -n "$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 + elif test -n "$mac" + then + echo "$mac" | sed -n 's/^\(..\):\(..\):\(..\):\(..\):\(..\):\(..\)$/slug\1\2\3\4\5\6/p' + else + # because we want the name to remain constant: + echo "brokenslug" + 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) test -r "$config_root/etc/default/sysconf" -a -n "$mac";; + *) return 1;; + esac } # # checkif "iface" @@ -130,11 +157,13 @@ 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 \ + \( -d "$1/mnt" \) -a \ \( -x "$1/bin/sh" -o -h "$1/bin/sh" \) -a \ + \( -x "$1/usr/sbin/chroot" -o -h "$1/usr/sbin/chroot" -o \ + -x "$1/sbin/chroot" -o -h "$1/sbin/chroot" \) -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" \) + -x "$1/etc/init" -o -h "$1/etc/init" -o \ + -x "$1/bin/init" -o -h "$1/bin/init" \) } # # swivel "new root" "old root" @@ -147,7 +176,7 @@ checkmount(){ # Normally this function never returns! # On return 0,1,2 are connected to /dev/console - this may not # have been true before! -swivel() { +swivel(){ cd "$1" exec <&- >&- 2>&- # This is just-in-case the called mounted /proc and was @@ -169,11 +198,26 @@ swivel() { # 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 "\ + if test -x usr/sbin/chroot -o -h usr/sbin/chroot + then + chroot=usr/sbin/chroot + elif test -x sbin/chroot -o -h sbin/chroot + then + chroot=sbin/chroot + else + chroot=chroot + fi + # + exec "$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' + mount -t sysfs sysfs /mnt + echo -n timer >/mnt/class/leds/ready/trigger + echo -n timer >/mnt/class/leds/status/trigger + echo -n 80 >/mnt/class/leds/ready/frequency + echo -n 80 >/mnt/class/leds/status/frequency + umount /mnt sleep 10 >/.recovery sync;sync;sync exit 1" @@ -245,7 +289,7 @@ ifdown(){ # # mountflash "flash device" "flash root directory" {mount options} # Finds and mounts the flash file system on the given directory -mountflash() { +mountflash(){ local ffsdev ffsdir ffsdev="$1" @@ -272,7 +316,7 @@ mountflash() { # 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() { +umountflash(){ local rootok ffsno ffsdev rootok=1 case "$1" in @@ -324,7 +368,7 @@ umountflash() { } # ffs_umount </proc/mounts || { - echo "$0: umount $ffsdev from all mount points then re-run reflash" >&2 + echo "$0: umount $ffsdev from all mount points then re-run $0" >&2 return 1 } diff --git a/packages/slugos-init/files/initscripts/sysconfsetup b/packages/slugos-init/files/initscripts/sysconfsetup index 4111633a2b..a4f9074d9c 100644 --- a/packages/slugos-init/files/initscripts/sysconfsetup +++ b/packages/slugos-init/files/initscripts/sysconfsetup @@ -7,225 +7,40 @@ # 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: +# rm or mv the file (/etc/default/sysconf) to recreate it, run this +# script with the reload option to overwrite the system files. The +# configuration files described in sysconf_reload (in +# /sbin/sysconf) will be overwritten on reload. # -# /etc/default/sysconf -# /etc/hostname -# /etc/defaultdomain -# /etc/network/interfaces -# /etc/resolv.conf +# start: standard startup, do a complete (auto) restore if necessary +# reinit: always do a complete auto restore +# reload: just reload sysconf (no config files!) # # /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 +load_functions sysconf || exit 1 # -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 slugos, - # 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 +case "$1" in +start) test -s /etc/default/sysconf || { + if sysconf_read 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 slugos 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= + if sysconf_valid + then + sysconf_restore auto + else + sysconf_reload + fi 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>' + sysconf_default + sysconf_reload 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 + };; + +reload) test -s /etc/default/sysconf || sysconf_read || sysconf_default + sysconf_reload;; + +reinit) sysconf_restore auto;; -exit 0 +*) ;; +esac diff --git a/packages/slugos-init/files/initscripts/umountinitrd.sh b/packages/slugos-init/files/initscripts/umountinitrd.sh index da39b425f8..9cb1f7a25d 100644 --- a/packages/slugos-init/files/initscripts/umountinitrd.sh +++ b/packages/slugos-init/files/initscripts/umountinitrd.sh @@ -4,15 +4,21 @@ # 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 -} +. /etc/default/functions +while read device directory remainder +do + case "$directory" in + /mnt) echo "InitRD: unmount initrd on /mnt" >&2 + umount /mnt;; + /initrd)# need the device for a remount + ffspart=Flashdisk + ffsdev="$(mtblockdev $ffspart)" + echo "InitRD: remount $ffdev read-only on /initrd" >&2 + if test -n "$ffsdev" -a -b "$ffsdev" + then + mount -o remount,ro "$ffsdev" /initrd + else + echo "Flashdisk: $ffsdev: flash device not found" >&2 + fi;; + esac +done </proc/mounts diff --git a/packages/slugos-init/files/initscripts/zleds b/packages/slugos-init/files/initscripts/zleds index b6d2f1600b..f5bd703b65 100644 --- a/packages/slugos-init/files/initscripts/zleds +++ b/packages/slugos-init/files/initscripts/zleds @@ -4,76 +4,25 @@ # 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 +# 'stop' indicates the start of a runlevel change +# 'start' at the end of the runlevel change - we are in the new +# runlevel. # -# The 'ready' led is used for the indication of state, except that -# if a 'status' led is used ready+status is set in place of !ready. -# -# For NSLU2: -# -# '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. -# -# state outputs 's' (for 'system') or 'u' (for user) to distinguish -# the required colours. -# -# NOTE: this will change +# state outputs 'system', 'user' etc according the the nature of +# the runlevel it is passed (the *new* runlevel is used). state(){ case "$1" in - S|0|1|6) echo s;; - 2|3|4|5) echo u;; - N) echo s;; + S|N) echo system;; + 0|6) echo shutdown;; + 1) echo singleuser;; + 2|3|4|5) echo user;; *) echo "led change: $runlevel: runlevel unknown" >&2 - echo s;; + echo system;; esac } -# Make the named LED do something -flash(){ - echo timer >/sys/class/leds/"$1"/trigger - echo 200 >/sys/class/leds/"$1"/frequency -} -on(){ - echo none >/sys/class/leds/"$1"/trigger - echo 100 >/sys/class/leds/"$1"/brightness -} -off(){ - echo none >/sys/class/leds/"$1"/trigger - echo 0 >/sys/class/leds/"$1"/brightness -} - -test -d /sys/class/leds/ready && case "$1" in -start) if test -d /sys/class/leds/status - then - case "$(state "$runlevel")" in - s) on status - on ready;; - u) off status - on ready;; - esac - else - on ready - fi;; -stop) if test -d /sys/class/leds/status - then - case "$(state "$previous")$(state "$runlevel")" in - ss) flash status - flash ready;; - su|us) flash status - on ready;; - uu) off status - flash ready;; - esac - else - flash ready - fi;; +case "$1" in +start) leds "$(state "$runlevel")";; +stop) leds boot "$(state "$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 deleted file mode 100644 index 73b46eec0c..0000000000 --- a/packages/slugos-init/files/kern_header.c +++ /dev/null @@ -1,47 +0,0 @@ - -#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 b/packages/slugos-init/files/leds new file mode 100644 index 0000000000..8132a22046 --- /dev/null +++ b/packages/slugos-init/files/leds @@ -0,0 +1,214 @@ +#!/bin/sh +# leds +# +# utilities to manipulate the settings of the system leds +# +# load the utility functions unless this script is being called +# just to load its own functions. +test "$1" != leds && { + . /etc/default/rcS + . /etc/default/functions +} + +# +# led_set led-dir off|on|slow|fast|panic|blink|flash|user|* +# set the given LED (expressed as a directory) to the +# given status. USER_LED may be set to indicate how to +# handle the 'user' setting. +led_user_default(){ + case "$(machine)" in + nslu2) echo -n "cpu-idle";; + *) echo -n "cpu-activity";; + esac +} +# +led_set(){ + local setting + # expect led-dir state + if test -d "$1" + then + setting="$2" + case "$setting" in + user) if test -n "$USER_LED" + then + setting="$USER_LED" + else + setting="$(led_user_default)" + fi;; + esac + + case "$setting" in + off|on) echo -n none + + case "$setting" in + on) echo -n 100;; + off) echo -n 0;; + esac >"$1/brightness";; + + slow|fast|panic|blink|flash) + echo -n timer + + case "$setting" in + flash) echo -n 727;; + blink) echo -n 72;; + slow) echo -n 400;; + fast) echo -n 100;; + panic) echo -n 50;; + esac >"$1/frequency" + + case "$setting" in + flash) echo -n 10;; + blink) echo -n 1000;; + *) echo -n 100;; + esac >"$1/duty_cycle";; + + cpu-idle) echo -n cpu-idle + # these settings work well on NSLU2 + echo -n 80 >"$1/frequency" + echo -n 10 >"$1/duty_cycle";; + + *) echo -n "$setting";; + esac >"$1/trigger" + else + echo "leds: $1: no such directory" >&2 + return 1 + fi +} + +# +# sysled [boot] system|user|singleuser|shutdown [error|panic|*] +# set the system LEDs to indicate the given boot state, the function +# will temporarily mount sysfs is necessary (using /mnt) +# +# the cases for two LEDs (ready+status) +sysled_readystatus(){ + local ready status + # expect dir [boot](system|user) [error|panic] + case "$3" in + error) ready=fast; status=off;; + panic) ready=fast; status=fast;; + *) case "$2" in + bootsystem) ready=slow; status=slow;; + system) ready=on; status=on;; + bootuser) ready=on; status=slow;; + user) ready=user; status=off;; + bootsingleuser) ready=on; status=slow;; + singleuser) ready=user; status=user;; + bootshutdown) ready=on; status=slow;; + shutdown) ready=slow; status=on;; + esac;; + esac + + led_set "$1/ready" "$ready" + led_set "$1/status" "$status" +} +# +# the cases for one LED (just ready) +sysled_ready(){ + local ready + # expect dir [boot](system|user) [error|panic] + case "$3" in + error) ready=fast;; + panic) ready=panic;; + *) case "$2" in + bootsystem) ready=flash;; + system) ready=blink;; + bootuser) ready=slow;; + user) ready=user;; + bootsingleuser) ready=flash;; + singleuser) ready=blink;; + bootshutdown) ready=slow;; + shutdown) ready=blink;; + esac;; + esac + + led_set "$1/ready" "$ready" +} +# +sysled(){ + local mp st boot isst + mp=/sys + st=1 + boot= + + # validate arguments + if test "$1" = boot + then + shift + boot=boot + fi + case "$1" in + system|user|singleuser|shutdown) :;; + *) echo "sysled: unknown option '$1'" >&2 + echo " usage: sysled [boot] system|user|singleuser|shutdown [error|panic|*]" >&2 + return 1;; + esac + + if test ! -d "$mp/class/leds" && mount -t sysfs sysfs /mnt + then + mp=/mnt + fi + # + # check for the 'ready' LED - otherwise do nothing + if test -d "$mp/class/leds/ready" + then + if test -d "$mp/class/leds/status" + then + sysled_readystatus "$mp/class/leds" $boot"$@" + else + sysled_ready "$mp/class/leds" $boot"$@" + fi + fi + # + # clean up + test "$mp" = /mnt && umount /mnt + return "$st" +} + +# +# beep [double] +# emit a beep, or a double beep +# dummy - at present does nothing +beep(){ + return 0 +} + +# +# leds_help +# be helpful +# leds <led> off|on|slow|fast|panic|blink|flash|user|* +# leds [boot] system|user|singleuser|shutdown [error|panic|*] +leds_help(){ + echo "leds: change the setting of the LEDs" >&2 + echo " usage:" >&2 + echo " leds [boot] system|user|singleuser|shutdown [error|panic|*]" >&2 + echo " set leds during system boot to indicate a particular boot" >&2 + echo " state. 'boot' means that the system is transitioning to" >&2 + echo " the new state. 'error' or 'panic' means a (potentially)" >&2 + echo " recoverable error or an unrecoverable error ('panic') has" >&2 + echo " occured." >&2 + echo " <led> off|on|slow|fast|panic|blink|flash|user|*" >&2 + echo " set the named led to the given display, an arbitrary led" >&2 + echo " trigger may be given. 'user' will use the default specified" >&2 + echo " in USER_LED from /etc/default/rcS, if not specified a cpu" >&2 + echo " activity setting appropriate to the machine is selected" >&2 + echo " beep [double]" >&2 + echo " if possible cause the machine to emit a beep" >&2 +} + +# +# the real command, if required +case "$1" in +boot|system|user|singleuser|shutdown) + sysled "$@";; + +beep) beep "$@";; + +"") leds_help;; +help) leds_help;; + +leds) # just load the functions + ;; + +*) led_set /sys/class/leds/"$@" +esac diff --git a/packages/slugos-init/files/leds.c b/packages/slugos-init/files/leds.c deleted file mode 100644 index e2120ae5d6..0000000000 --- a/packages/slugos-init/files/leds.c +++ /dev/null @@ -1,190 +0,0 @@ - #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 deleted file mode 100644 index 0b236dd6c0..0000000000 --- a/packages/slugos-init/files/leds.h +++ /dev/null @@ -1,21 +0,0 @@ - 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/linuxrc b/packages/slugos-init/files/linuxrc deleted file mode 100755 index 7c20a55b65..0000000000 --- a/packages/slugos-init/files/linuxrc +++ /dev/null @@ -1,146 +0,0 @@ -#!/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/reflash b/packages/slugos-init/files/reflash index bcf51fc606..ad1c4c26ad 100644 --- a/packages/slugos-init/files/reflash +++ b/packages/slugos-init/files/reflash @@ -10,6 +10,13 @@ # # /etc/default/functions contains useful utility functions . /etc/default/functions +load_functions sysconf +# +# NSLU2 flash layout is non-standard. +case "$(machine)" in +nslu2) isnslu2=1;; +*) isnslu2=;; +esac # # CHECKING FOR INPUT (ARGUMENTS ETC) # ---------------------------------- @@ -37,31 +44,43 @@ do ffsfile="$1" shift;; -i) shift + test -n "$isnslu2" || { + echo "reflash: -i: only supported on the LinkSys NSLU2" >&2 + echo " use -k and -j to specify the kernel and root file system" >&2 + exit 1 + } 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 + *) if test -n "$isnslu2" + then + echo "reflash: usage: $0 [-k kernel] [-j rootfs] [-i image]" >&2 + else + echo "reflash: usage: $0 [-k kernel] [-j rootfs]" >&2 + fi 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 + test -n "$isnslu2" && + 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 +# Sanity check on the arguments (note that the first case can only fire +# on NSLU2 because of the check for -i above.) if test -n "$imgfile" -a -n "$ffsfile" -a -n "$kfile" then - echo "reflash: -k,-j,-i: specify at most two files" >&2 + echo "reflash: 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 + echo "reflash: specify at least one file to flash" >&2 exit 1 fi # @@ -270,20 +289,8 @@ then 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") || { + # sysconf_save_conffiles <flash-directory> <dest> <list> + sysconf_save_conffiles "$ffsdir" "$saved" "$list" || { echo "reflash: $saved: copy of saved configuration files failed" >&2 rm -rf "$saved" rm "$list" @@ -311,21 +318,22 @@ echo "reflash: about to flash new image" >&2 # 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 +# +# -p causes the progress indicator to be displayed +progress=-p do_kernel() { + local cmd + if test -n "$isnslu2" + then + # NSLU2: write length,0,0,0 header, then fill + cmd="wb L,4; fb 12,0; cpL" + else + # Other: just write the kernel bytes + cmd="cpL" + fi 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 + ' "<= $imgkoffset" "L=$imgksize" "$cmd" ' # fill with 255 fb #t-,255' } @@ -445,135 +453,13 @@ mountflash "$ffsdev" "$ffsdir" && :>"$ffsdir/etc/.configured" || { 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") || { +# sysconf_restore_conffiles <flash-directory> <source-dir> <restore> +restore="/tmp/restore.$$" +sysconf_restore_conffiles "$ffsdir" "$saved" "$restore" <"$list" || { 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 " files selected for restore is in $restore" >&2 echo " You should restore any required configuration from $saved," >&2 echo " then umount $ffsdir and reboot." >&2 exit 1 @@ -581,9 +467,9 @@ done <"$list" 3>/tmp/restore.$$ | (cd "$saved"; exec cpio -p -d -u "$ffsdir") || # # remove the copied files (i.e. the ones which were preserved) ( cd "$saved" - exec rm $(cat /tmp/restore.$$) + exec rm $(cat "$restore") ) -rm /tmp/restore.$$ +rm "$restore" # # clean up, files left in $saved need to be handled by the user files="$(find "$saved" ! -type d -print)" diff --git a/packages/slugos-init/files/sysconf b/packages/slugos-init/files/sysconf new file mode 100644 index 0000000000..1a9cdf0005 --- /dev/null +++ b/packages/slugos-init/files/sysconf @@ -0,0 +1,780 @@ +#!/bin/sh +# sysconf +# +# utility to manipulate system configuration information help +# in a RedBoot SysConf partition +# +# load the utility functions (unless this is being called just +# to load these functions!) +test "$1" != sysconf && . /etc/default/functions + +# +# sysconf_valid +# return true if the SysConf partition exists and seems to be +# potentially valid (it starts with a reasonable length). +sysconf_valid(){ + local sysdev + sysdev="$(mtblockdev SysConf)" + test -n "$sysdev" -a -b "$sysdev" && + devio "<<$sysdev" '!! b.10>s32768<&!' +} + +# +# sysconf_read [prefix] +# read the SysConf partition (if present) writing the result into +# /etc/default/sysconf, if the result is empty it will be removed. +sysconf_read(){ + local sysdev sedcmd mac config_root + config_root="$1" + rm -f /tmp/sysconf.new + sysdev="$(mtblockdev SysConf)" + if sysconf_valid + 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 + # on NSLU2 defaults to ixp0, is changed to the correct value for + # slugos, 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) + sedcmd='/^\[[^][]*\]$/p;' + # only do the ip_addr and lan_interface fixups on NSLU2 + if test "$(machine)" = nslu2 + then + sedcmd="$sedcmd"' + s/^lan_interface=ixp0$/lan_interface=eth0/; + /^ip_addr=192\.168\.1\.77$/,/^bootproto/s/^bootproto=static$/bootproto=dhcp/;' + fi + # always fix up the hardware addr if it is present + mac="$(config mac)" + if test -n "$mac" + then + sedcmd="$sedcmd"' + s/^hw_addr=.*$/hw_addr='"$mac"'/;' + fi + # and only print lines of the correct form + sedcmd="$sedcmd"' + /^[-a-zA-Z0-9_][-a-zA-Z0-9_]*=/p' + + devio "<<$sysdev" cpb fb1,10 | sed -n "$sedcmd" >/tmp/sysconf.new + fi + # + # test the result - sysconf must be non-empty + if test -s /tmp/sysconf.new + then + mv /tmp/sysconf.new "$config_root/etc/default/sysconf" + else + rm -f /tmp/sysconf.new + return 1 + fi +} + +# +# sysconf_default [prefix] +# Provde a default /etc/default/sysconf when there is no SysConf partition, +# or when it is invalid, this function will read from an existing sysconf, +# copying the values into the new one. +# sysconf_line tag config-tag +# write an appropriate line if the config value is non-empty +sysconf_line(){ + config "$2" | { + local value + read value + test -n "$value" && echo "$1"="$value" + } +} +# +sysconf_default(){ + local config_root + config_root="$1" + { echo '[network]' + sysconf_line hw_addr mac + sysconf_line disk_server_name host + sysconf_line w_d_name domain + sysconf_line lan_interface iface + sysconf_line ip_addr ip + sysconf_line netmask netmask + sysconf_line gateway gateway + sysconf_line dns_server1 dns + sysconf_line dns_server2 dns2 + sysconf_line dns_server3 dns3 + sysconf_line bootproto boot + } >/tmp/sysconf.new + mv /tmp/sysconf.new "$config_root/etc/default/sysconf" +} + +# +# sysconf_reload [prefix] +# read the values from /etc/default/sysconf and use these values to set +# up the following system files: +# +# /etc/hostname +# /etc/defaultdomain +# /etc/resolv.conf +# /etc/network/interfaces +# /etc/motd +# +sysconf_reload(){ + local config_root host domain iface boot ip netmask gateway ifname iftype + config_root="$1" + host="$(config host)" + test -n "$host" && echo "$host" >"$config_root/etc/hostname" + domain="$(config domain)" + test -n "$domain" && echo "$domain" >"$config_root/etc/defaultdomain" + # + # The DNS server information gives up to three nameservers, + # but this currently only binds in the first. + { + test -n "$domain" && echo "search $domain" + test -n "$(config dns)" && echo "nameserver $(config dns)" + test -n "$(config dns2)" && echo "nameserver $(config dns2)" + test -n "$(config dns3)" && echo "nameserver $(config dns3)" + } >"$config_root/etc/resolv.conf" + # + # 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 slugos udhcp script, + # /etc/udhcpc.d/50default, loads the values from sysconf. + iface="$(config iface)" + 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 + # + 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 interface used by default during boot" + echo "auto $iface" + echo "# Automatically generated from /etc/default/sysconf" + echo "# address, netmask and gateway are ignored for 'dhcp'" + echo "# but required for 'static'" + echo "iface $iface inet $boot" + # 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" + # + # Now read all the other ARPHRD_ETHER (type=1) interfaces + # and add an entry for each. + for ifname in $(test -d /sys/class/net && ls /sys/class/net) + do + if test -r "/sys/class/net/$ifname/type" -a "$ifname" != "$iface" + then + read iftype <"/sys/class/net/$ifname/type" + case "$iftype" in + 1) echo "#" + echo "# /sys/class/net/$ifname:" + echo "auto $ifname" + echo "iface $ifname inet dhcp";; + esac + fi + done + } >"$config_root/etc/network/interfaces" + # + # Finally rewrite /etc/motd + { echo "Host name: $host" + echo "Domain name: $domain" + echo "Host MAC: $(config 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 preserve' to save the configuration permanently" + echo "Use 'turnup restore' to restore a previously saved configuration" + echo "Use 'turnup disk|nfs -i <device> options to initialise a non-flash root" + echo "Use 'turnup help' for more information" + } >"$config_root/etc/motd" +} + +# +# sysconf_save_conffiles <flash-directory> <dest> <list> +# preserve the configuration files in a directory or in a CPIO archive +# (which is *not* compressed). If <dest> is a directory the files are +# copied, otherwise a CPIO archive is made with that name. <list> is +# the listing file giving the preserved files and the processing option. +sysconf_save_conffiles(){ + local ffsdir dest list file + ffsdir="$1" + saved="$2" + list="$3" + test -n "$ffsdir" -a -r "$ffsdir/etc/default/conffiles" -a -n "$saved" -a -n "$list" || { + echo "sysconf_save_conffiles: invalid arguments: '$*'" >&2 + echo " usage sysconf_save_conffiles <flash-directory> <dest> <list>" >&2 + return 1 + } + # + ( 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" + if test -d "$saved" + then + exec cpio -p -d -m -u "$saved" + else + exec cpio -o -H crc >"$saved" + fi + ) +} + +# +# sysconf_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. +# +# globals: the following must be defined in the calling context! +# saved: the directory containing the unpacked saved files +# ffsdir: the flash directory to which the files are being restored (/) +# +sysconf_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" +} +# +sysconf_verify() { + local command file + + # return 1 here causes the file not to be overwritten, + # control should never get here! + test -n "$sysconf_noninteractive" && { + echo "$0: $*: changed file cannot be handled non-interactively" >&2 + return 1 + } + + file="$1" + echo "$0: $file: configuration file changed." + sysconf_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;; + *) sysconf_verify_help "$file";; + esac + done +} +# the same, but for a link +sysconf_verify_link() { + local command link + + # return 1 here causes the file not to be overwritten, + # control should never get here! + test -n "$sysconf_noninteractive" && { + echo "$0: $*: changed link cannot be handled non-interactively" >&2 + return 1 + } + + link="$1" + echo "reflash: $link: configuration link changed." + sysconf_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;; + *) sysconf_verify_help "$link";; + esac + done +} + +# +# sysconf_restore_conffiles <flash-directory> <source-dir> <restore> +# restore the configuration files from a directory. 'source-dir' +# If <source> is a directory of files from sysconf_save_conffiles. The +# list of files restored is written to the third argument (restore), +# but is not required (/dev/null would be ok). +# +# the list of files to restore is read from stdin, along with the +# processing option for each file (the format is as produced by +# sysconf_save_conffiles in the 'list' output). +sysconf_restore_conffiles(){ + local ffsdir saved restore + # these are the globals used by the above function + ffsdir="$1" + saved="$2" + restore="$3" + test -n "$ffsdir" -a -r "$ffsdir/etc/default/conffiles" -a -d "$saved" -a -n "$restore" || { + echo "restore_conffiles: invalid arguments: '$*'" >&2 + echo " usage sysconf_restore_conffiles <flash-directory> <source-dir> <list>" >&2 + return 1 + } + # + # read the list and process each given file + 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 "sysconf_restore_conffiles: $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 sysconf_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 sysconf_verify "$file" <>/dev/tty >&0 2>&0 + then + echo "$file" + echo "$file" >&3 + fi;; + esac + fi + fi + done 3>"$restore" | (cd "$saved"; exec cpio -p -d -u "$ffsdir") +} + +# +# sysconf_test_restore <flash-directory> <source-dir> +# return true only if the restore does not need to do an interactive +# compare +sysconf_test_restore(){ + local ffsdir saved + # these are the globals used by the above function + ffsdir="$1" + saved="$2" + # this is an error case, but return 0 so that the error is + # detected later + test -n "$ffsdir" -a -r "$ffsdir/etc/default/conffiles" -a -d "$saved" || + return 0 + # + # read the list and check each diff file (this is just a copy of the + # logic above with all the work removed!) + while read op file + do + # handle .configured specially (to preserve the original datestamp) + if test "$op" != diff + then + : # no diff required + elif test "$file" = "etc/.configured" + then + : # special handling + 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 + else + # assume a change regardless + return 1 + fi + else + # only overwrite if necessary + if test -e "$ffsdir/$file" && cmp -s "$saved/$file" "$ffsdir/$file" + then + : # do not overwrite + elif test ! -e "$ffsdir/$file" + then + : # always preserve + else + # a change + return 1 + fi + fi + done + + return 0 +} + +# +# sysconf_save +# save the system configuration to SysConf - SysConf must exist and +# there must be a writeable device for it. +sysconf_save(){ + local sysdev ffspart ffsdev ffsdir saved list size status + ffspart=Flashdisk + ffsdev="$(mtblockdev $ffspart)" + sysdev="$(mtblockdev SysConf)" + status=1 + if test -n "$sysdev" -a -b "$sysdev" -a -n "$ffsdev" -a -b "$ffsdev" + then + # this will succeed silently if the flash device is on / + umountflash "$ffsdev" || exit 1 + # + # Everything is umounted, now remount on a temporary directory. + ffsdir="/tmp/flashdisk.$$" + mkdir "$ffsdir" || { + echo "$0: $ffsdir: failed to create temporary directory" >&2 + exit 1 + } + # + mountflash "$ffsdev" "$ffsdir" -o ro || { + rmdir "$ffsdir" + exit 1 + } + # need temporary files for the cpio output and the listing + saved=/tmp/cpio.$$ + list=/tmp/preserve.$$ + rm -rf "$saved" "$list" + sysconf_save_conffiles "$ffsdir" "$saved" "$list" || { + echo "$0: $saved: archive of saved configuration files failed" >&2 + rm -rf "$saved" + rm "$list" + umount "$ffsdir" && rmdir "$ffsdir" || + echo "$0: $ffsdir: temporary directory cleanup failed" >&2 + return 1 + } + # ignore the error in this case: + umount "$ffsdir" && rmdir "$ffsdir" || + echo "$0: $ffsdir: temporary directory cleanup failed" >&2 + # + # we now have: + # /etc/default/sysconf the basic config + # /tmp/preserve.$$ the list of saved files + # /tmp/cpio.$$ the CPIO archive of those files + # + # make one big file with the sysconf data followed by the + # compressed archive in /tmp/sysconf.$$ + { { cat /etc/default/sysconf + echo '[preserve]' + } | sed -n '1,/^\[preserve\]^/p' + while read op file + do + echo "$op"="$file" + done <"$list" + } >/tmp/sysconf.$$ + size="$(devio "<</tmp/sysconf.$$" 'pr$')" + gzip -9 <"$saved" >>/tmp/sysconf.$$ + # + # more cleanup, then try to write the new sysconf to SysConf + # the format is a 4 byte big-endian length then the text data + # if the data won't fit exit with error code 7 + rm "$saved" "$list" + devio -p "<</tmp/sysconf.$$" ">>$sysdev" ' + $( $4+ # > + !! 7 + $) 0 + wb '"$size"',4 + cp $' + case $? in + 0) echo " done" >&2 + status=0;; + 1) echo " failed" >&2 + echo " SysConf could not be written (no changes made)" >&2;; + 3) echo " failed" >&2 + echo " SysConf partially written, you may want to reset it" >&2;; + 7) echo " failed" >&2 + echo " SysConf is too small: $size bytes required" >&2 + echo " No change made" >&2;; + *) echo " failed" >&2 + echo " Internal error writing SysConf" >&2;; + esac + # + rm -f /tmp/sysconf.$$ + else + echo "sysconf save: SysConf or $ffspart partition not found" >&2 + echo " A RedBoot partition named 'SysConf' must exist in the system" >&2 + echo " flash memory for this command to work, and there must be a" >&2 + echo " block device to access this partition (udev will normally" >&2 + echo " create this automatically. The flash partition contents must" >&2 + echo " also be accessible in a partition called '$ffspart'" >&2 + echo + echo " To create the SysConf partition use the 'fis create' command" >&2 + echo " in the RedBoot boot loader, it is sufficient to make the" >&2 + echo " partition one erase block in size unless you have substantially" >&2 + echo " increased the size of the files listed in /etc/default/conffiles" >&2 + fi + + return $status +} + +# +# sysconf_restore [auto] +# restore previously saved configuration information from SysConf +sysconf_restore_error(){ + local root + root="$1" + shift + # ------------------------------------------------------------------------------- + { echo " WARNING: saved configuration files not restored" + test -n "$1" && echo "$*" + echo + echo "The configuration of this machine has been reinitialised using the values" + echo "from /etc/default/sysconf, however configuration files saved in the SysConf" + echo "partition have not been restored." + echo + echo "You can restore these files by correcting any reported errors then running" + echo + echo " sysconf restore" + echo + echo "from the command line. This will completely reinitialise the configuration" + echo "using the information in the SysConf partition." + } >"$root/etc/motd" + cat "$root/etc/motd" >&2 +} +# +sysconf_restore(){ + local sysdev ffspart ffsdev ffsdir saved restore size status sysconf_noninteractive config_root + + # if set this means 'do no diff' - this avoids the code above which + # would open /dev/tty and therefore allows this stuff to be done from + # an init script + sysconf_noninteractive= + test "$1" = auto && sysconf_noninteractive=1 + + ffspart=Flashdisk + ffsdev="$(mtblockdev $ffspart)" + sysdev="$(mtblockdev SysConf)" + status=1 + if test -n "$sysdev" -a -b "$sysdev" -a -n "$ffsdev" -a -b "$ffsdev" && + sysconf_valid + then + # this will succeed silently if the flash device is on / + umountflash "$ffsdev" || exit 1 + # + # Everything is umounted, now remount on a temporary directory. + ffsdir="/tmp/flashdisk.$$" + config_root="$ffsdir" + mkdir "$ffsdir" || { + echo "$0: $ffsdir: failed to create temporary directory" >&2 + exit 1 + } + # + mountflash "$ffsdev" "$ffsdir" || { + rmdir "$ffsdir" + exit 1 + } + # + # first restore the SysConf section + sysconf_read "$ffsdir" || sysconf_default "$ffsdir" + # + # now use this to regenerate the system files + sysconf_reload "$ffsdir" + # + # now examine the [preserve] section, if it is there restore + # it if possible. + if test -n "$(syssection preserve)" + then + # 'saved' is a directory, 'restore' is a file (which is + # used to detect unrestored files). The directory needs + # to be populated with files. + saved=/tmp/cpio.$$ + restore=/tmp/restore.$$ + rm -rf "$saved" "$restore" + # + mkdir "$saved" || { + sysconf_restore_error "$ffsdir" "$saved: failed to create temporary directory" + return 1 + } + # + # the CPIO archive is gzip compressed after the text part + # of sysconf, gzip will handle the LZ stream termination + # correctly (and break the pipe) so we don't need to know + # the real length of the data + devio "<<$sysdev" '<=b4+.' 'cp $s-' | gunzip | ( + cd "$saved" + exec cpio -i -d -m -u + ) || { + rm -rf "$saved" + sysconf_restore_error "$ffsdir" "$saved: cpio -i failed" + return 1 + } + # either there must be no 'diff' files or it must + # be possible to interact with a real user. + if test -z "$sysconf_noninteractive" || + syssection preserve | sysconf_test_restore "$ffsdir" "$saved" + then + # + # remove the 'init' motd from sysconf_reload + rm "$ffsdir/etc/motd" + # + # now restore from the directory, using the information in + # the preserve section, if this fails in a non-interactive + # setting the system might not reboot + syssection preserve | + sysconf_restore_conffiles "$ffsdir" "$saved" "$restore" || { + # there is a chance of the user cleaning this up +#------------------------------------------------------------------------------ + sysconf_restore_error "$ffsdir" \ +"$0: $saved: restore of saved configuration files failed. + The flash file system is mounted on $ffsdir. + The saved files are in $saved and the list of files selected for + restore is in $restore. + You should restore any required configuration from $saved, then umount + $ffsdir and reboot." + # this prevents cleanup/umount + return 1 + } + # + # remove the copied files (i.e. the ones which were preserved) + ( cd "$saved" + exec rm $(cat "$restore") + ) + rm "$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 +#------------------------------------------------------------------------------ + sysconf_restore_error "$ffsdir" \ +"$0: some saved configuration files have not been handled: + +$files + +These files can be examined in $saved and restored to +$ffsdir if required. The saved files are in a temporary +directory and will not be retained across a reboot - copy then elsewhere if +you are unsure whether they are needed." + return 1 + fi + # + # so this is safe now (no files, links etc) + rm -rf "$saved" + else + rm -rf "$saved" + # non-interactive and some changed diff files + sysconf_restore_error "$ffsdir" \ +"$0: some of the saved configuration files must be +examined before restoration" + # but continue to the umount + fi + fi + # + # ignore the error in this case: + umount "$ffsdir" && rmdir "$ffsdir" || + echo "$0: $ffsdir: temporary directory cleanup failed" >&2 + status=0 + else + echo "sysconf restore: SysConf or $ffspart partition not found" >&2 + echo " You must have used 'sysconf save' to save configuration data" >&2 + echo " into the SysConf partition before using this command. The command" >&2 + echo " will restore the configuration data to the flash root partition" >&2 + echo " named '$ffspart' - this must also be accessible." >&2 + fi + + return $status +} + +# +# sysconf_help +# help text +sysconf_help(){ + # ------------------------------------------------------------------------------- + echo "sysconf: usage: sysconf read|default|reload|save|restore" >&2 + echo " read: the current SysConf partition is read into /etc/default/sysconf" >&2 + echo " default: a default /etc/default/sysconf is created" >&2 + echo " reload: system configuration files are recreated from /etc/default/sysconf" >&2 + echo " save: /etc/default/sysconf and the files listed in /etc/default/conffiles" >&2 + echo " are written to the SysConf partition" >&2 + echo " restore: the configuration information in the SysConf partition saved by" >&2 + echo " 'sysconf save' is restored" >&2 +} + +# +# the real commands +sysconf_command="$1" +test $# -gt 0 && shift +case "$sysconf_command" in +read) sysconf_read "$@";; +default)sysconf_default "$@";; +reload) sysconf_reload "$@";; +save) sysconf_save "$@";; +restore)sysconf_restore "$@";; +valid) sysconf_valid "$@";; + +sysconf)# just load the functions + ;; + +*) # help text + sysconf_help "$@";; +esac diff --git a/packages/slugos-init/files/turnup b/packages/slugos-init/files/turnup index 0029697c50..0d50e4d39a 100644 --- a/packages/slugos-init/files/turnup +++ b/packages/slugos-init/files/turnup @@ -6,14 +6,16 @@ # # configuration -# The following variables control which directories in /var end up on the rootfs -# and which end up in a temporary file system. +# 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 @@ -31,6 +33,7 @@ fstype() { done </proc/mounts echo "$result" } + # # fsoptions arguments # Collapses the mount (-o) options into a single list which is @@ -63,6 +66,7 @@ fsoptions() { echo defaults fi } + # # get_flash <directory> {mount options} # mount the flash device, writeable, on the given directory @@ -80,6 +84,7 @@ get_flash() { umountflash "$ffsdev" && mountflash "$ffsdev" "$ffsdir" "$@" } + # # check_rootfs [-i] <root fs directory> # Make sure the candidate rootfs is empty @@ -107,6 +112,7 @@ check_rootfs() { return 1;; esac } + # # copy_rootfs old new # Make a copy of the given root file system, copying only the @@ -185,8 +191,9 @@ setup_bootdev() { # Populates /var. # Removes the /var tmpfs entry from /etc/fstab. # Creates links from /var into /media/ram for NFS and Memstick. - setup_var() { + local ram_targets directory + test -n "$1" -a -d "$1"/var || { echo "turnup: setup_var($1,$2): expected a directory" >&2 return 1 @@ -205,17 +212,17 @@ setup_var() { } case "$2" in - disk) RAMTARGETS=${INRAM_DISK};; - nfs) RAMTARGETS=${INRAM_NFS};; - memstick) RAMTARGETS=${INRAM_MEMSTICK};; + disk) ram_targets="$INRAM_DISK";; + nfs) ram_targets="$INRAM_NFS";; + memstick) + ram_targets="$INRAM_MEMSTICK";; esac - for d in ${RAMTARGETS}; do - RAMDIR="/media/ram${d}" - REALDIR="${d}" - rm -rf "${1}${REALDIR}" - ln -s "${RAMDIR}" "${1}${REALDIR}" - done + for directory in $ram_targets + do + rm -rf "$1/$directory" + ln -s "/media/ram/$directory" "$1/$directory" + 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 @@ -307,7 +314,6 @@ setup_fstab() { } } - # # boot_rootfs <boot type> <flash file system> <sleep time> <device> [options] # Change the flash partition (not the current root!) to boot off @@ -655,95 +661,6 @@ nfs() { } # -# 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() { @@ -754,6 +671,7 @@ read_one() { test -z "$n" && n="$o" eval "$3='$n'" } + # # init_network # Change the network initialisation @@ -803,7 +721,7 @@ init_network() { } >/etc/default/sysconf # # And reload the result - /etc/init.d/sysconfsetup reload + sysconf reload # # The remove the spurious 'init' motd rm /etc/motd @@ -814,21 +732,14 @@ init_network() { # script which actually does anything!) case "$1" in init) shift - if config valid && test "$1" != -f + if init_network "$@" then - if init_network "$@" - then - echo "turnup init: you must reboot the NSLU2 for the changes to take effect" >&2 - else - exit 1 - fi + echo "turnup init: you must reboot for the changes to take effect" >&2 + echo " You may want to run 'turnup preserve' to save these settings," >&2 + echo " after making any additional configuration changes which you" >&2 + echo " require." >&2 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 + exit 1 fi;; disk) shift disk "$@";; @@ -839,6 +750,12 @@ nfs) shift nfs "$@";; flash) boot_reset flash;; ram) boot_reset ram;; +preserve) + shift + sysconf save "$@";; +restore) + shift + sysconf restore "$@";; *) echo "\ usage: turnup command [options] commands: @@ -848,7 +765,7 @@ usage: turnup command [options] correct errors in network information initialise network information when DHCP is not available change network information - disk [-i] [-s<seconds>] <device> [mount options] + disk [-i] [-s<seconds>] <device>|<uuid> [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 @@ -856,7 +773,7 @@ usage: turnup command [options] 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] + memstick [-i] <device>|<uuid> [mount options] Behaves as disk however options appropriate to a flash memory stick are automatically added nfs [-i] <nfs mount path> [mount options] @@ -875,6 +792,14 @@ usage: turnup command [options] ram Boot (once) into a ramdisk, subsequent boots will be to the flash file system. + preserve + Save the system configuration to the SysConf partition, you + will need to create the SysConf partition from the boot loader + before using this if SysConf does not already exist. This + just runs 'sysconf save'. + restore + Restore a previously saved system configuration. This just + runs 'sysconf restore'. disk formatting: The argument to 'nfs' or 'disk' must be an empty partition of sufficient size to hold the root file system (at least diff --git a/packages/slugos-init/files/update-kernel b/packages/slugos-init/files/update-kernel deleted file mode 100755 index 796d45e953..0000000000 --- a/packages/slugos-init/files/update-kernel +++ /dev/null @@ -1,82 +0,0 @@ -#!/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 - - diff --git a/packages/slugos-init/slugos-init_0.10.bb b/packages/slugos-init/slugos-init_0.10.bb index 268ee1a8b7..8ec69e88f1 100644 --- a/packages/slugos-init/slugos-init_0.10.bb +++ b/packages/slugos-init/slugos-init_0.10.bb @@ -1,12 +1,12 @@ DESCRIPTION = "SlugOS initial network config via sysconf" -SECTION = "console/network" +SECTION = "base" +PRIORITY = "required" LICENSE = "GPL" DEPENDS = "base-files devio" RDEPENDS = "busybox devio" -PR = "r48" +PR = "r49" -SRC_URI = "file://linuxrc \ - file://boot/flash \ +SRC_URI = "file://boot/flash \ file://boot/disk \ file://boot/nfs \ file://boot/ram \ @@ -22,6 +22,8 @@ SRC_URI = "file://linuxrc \ file://initscripts/umountinitrd.sh \ file://functions \ file://conffiles \ + file://sysconf \ + file://leds \ file://turnup \ file://reflash \ file://links.conf \ @@ -30,7 +32,7 @@ SRC_URI = "file://linuxrc \ SBINPROGS = "" USRSBINPROGS = "" CPROGS = "${USRSBINPROGS} ${SBINPROGS}" -SCRIPTS = "turnup reflash" +SCRIPTS = "turnup reflash leds sysconf" BOOTSCRIPTS = "flash disk nfs ram network udhcpc.script" INITSCRIPTS = "syslog.buffer syslog.file syslog.network zleds\ leds_startup rmrecovery sysconfsetup umountinitrd.sh" @@ -78,7 +80,7 @@ do_install() { # Shell scripts for p in ${SCRIPTS} do - install -m 0755 $p ${D}${sbindir}/$p + install -m 0755 $p ${D}${base_sbindir}/$p done # @@ -122,7 +124,7 @@ pkg_postinst_slugos-init() { update-rc.d $opt sysconfsetup start 12 S . update-rc.d $opt syslog.file start 39 S . start 47 0 6 . update-rc.d $opt syslog.network start 44 S . start 39 0 6 . - update-rc.d $opt zleds start 99 S 1 2 3 4 5 . stop 5 0 1 2 3 4 5 6 . + update-rc.d $opt zleds start 99 S 1 2 3 4 5 . start 89 0 6 . stop 5 0 1 2 3 4 5 6 . update-rc.d $opt rmrecovery start 99 1 2 3 4 5 . # bug fix for startup update-rc.d $opt leds_startup start 1 1 2 3 4 5 . |