busybox-initramfs: reorganize init script in preparation for boot type handlers

Changes to kernel commandline parameters:

Remove legacy parameters, to be added back later if desired.
Add a new parameter: break=<all|step,step,...> which will cause a debugging
shell to be started after each or the specified boot steps.

Functions:

mount_part, mount_disk, mount_nbd: reorganize to use mount type handlers, which
will support specifying kernel parameters like boot=TYPE=target and
disk=TYPE=target. This initial commit only has mount_default, which supports
LABEL=label and UUID=uuid, as well as block devices /dev/* and image files.

error: show more meaningful error messages, containing the boot step and action
which caused the error.
If not debugging, halt the system. This prevents the error from causing more
damage further on in the boot sequence. If debugging, start a debugging shell.

update: make sure the file to update already exists at the destination, to
prevent clobbering a rootfs mounted on /flash, which can be the case when
mounting a mtd or NBD device.

load_modules: enable loading of kernel modules in early boot, e.g. xhci-hcd
to enable mount of USB3 devices on boot.

Add a simple boot step sequencer, which allows for starting a debugging shell
after each step.

Signed-off-by: Alain Kalker <a.c.kalker@gmail.com>
This commit is contained in:
Alain Kalker 2012-03-19 17:22:23 +01:00
parent 2e66a869ad
commit a3f3a62767

View File

@ -21,17 +21,13 @@
# http://www.gnu.org/copyleft/gpl.html
################################################################################
MODULE_DIR=/lib/modules
UPDATE_DIR=/storage/.update
IMAGE_SYSTEM="SYSTEM"
IMAGE_KERNEL="KERNEL"
REBOOT="0"
# defaults for booting from an nbd root
NBD_ROOT_SERVER="192.168.1.1"
NBD_ROOT_PORT="2000"
NFS_OVERLAY="192.168.1.1:/var/lib/overlay"
# mount all needed special filesystems
/bin/busybox mount -t devtmpfs none /dev
/bin/busybox mount -t proc none /proc
@ -62,22 +58,8 @@ NFS_OVERLAY="192.168.1.1:/var/lib/overlay"
fastboot)
FASTBOOT=yes
;;
netboot)
NETBOOT=yes
;;
nbdroot=*)
nbdroot="${arg#nbdroot=}"
NBD_ROOT_SERVER=$( echo "${nbdroot}" | /bin/busybox sed 's/:.*//')
NBD_ROOT_PORT=$( echo "${nbdroot}" | /bin/busybox sed 's/.*://')
;;
nbdserver=*)
NBD_ROOT_SERVER="${arg#nbdserver=}"
;;
nbdport=*)
NBD_ROOT_PORT="${arg#nbdport=}"
;;
nfsoverlay=*)
NFS_OVERLAY="${arg#nfsoverlay=}"
break=*)
BREAK="${arg#*=}"
;;
esac
done
@ -92,10 +74,6 @@ NFS_OVERLAY="192.168.1.1:/var/lib/overlay"
fi
}
error() {
echo "Error Code: $1 that means: $2"
}
debug_shell() {
echo "### Starting debugging shell... type exit to quit ###"
@ -105,29 +83,66 @@ NFS_OVERLAY="192.168.1.1:/var/lib/overlay"
/bin/busybox sh </dev/tty1 >/dev/tty1 2>&1
}
error() {
# Display fatal error message
# $1:action which caused error, $2:message
echo "*** Error in $BOOT_STEP: $1: $2 ***"
if [ -z "$DEBUG" ]; then
/bin/busybox halt
else
debug_shell
fi
}
break_after() {
# Start debug shell after boot step $1
case $BREAK in
all|*$1*)
debug_shell
;;
esac
}
# Mount handlers
# All handlers take the following parameters:
# $1:target, $2:mountpoint, $3:mount options, [$4:fs type]
mount_common() {
# Common mount handler, handles block devices and filesystem images
MOUNT_OPTIONS="-o $3"
[ -n "$4" ] && MOUNT_OPTIONS="-t $4 $MOUNT_OPTIONS"
for i in 1 2 3 4 5 6 7 8 9 10; do
ERR_ENV=1
$IONICE /bin/busybox mount $MOUNT_OPTIONS $1 $2 > /dev/null 2>&1
[ "$?" -eq "0" ] && ERR_ENV=0 && break
/bin/busybox usleep 1000000
done
[ "$ERR_ENV" -ne "0" ] && error "mount_common" "Could not mount $1"
}
mount_part() {
# progress "check filesystem $1 ..."
# /sbin/fsck -M -T -a $1 > /dev/null 2>&1
# Mount a local or network filesystem
# $1:[TYPE=]target, $2:mountpoint, $3:mount options, [$4:fs type]
MOUNT_TARGET="${1#*=}"
for i in 1 2 3 4 5 6 7 8 9 10; do
ERR_ENV=1
MOUNT_OPTIONS="-o $3 $1 $2"
if [ -n "$4" ]; then
MOUNT_OPTIONS="-t $4 $MOUNT_OPTIONS"
fi
progress "mount filesystem $1 ..."
$IONICE /bin/busybox mount $MOUNT_OPTIONS > /dev/null 2>&1
[ "$?" -eq "0" ] && ERR_ENV=0 && break
/bin/busybox usleep 1000000
done
[ "$ERR_ENV" -ne "0" ] && error "INIT_4" "Could not mount $1" && debug_shell
progress "mount filesystem $1 ..."
case $1 in
LABEL=*|UUID=*|/*)
MOUNT_CMD="mount_common"
MOUNT_TARGET="$1"
;;
*)
error "mount_part" "Unknown filesystem $1"
;;
esac
$MOUNT_CMD "$MOUNT_TARGET" "$2" "$3" "$4"
}
update() {
if [ -f "$UPDATE_DIR/$2" ]; then
if [ -f "$UPDATE_DIR/$2" -a -f "$3" ]; then
echo "updating $1..."
$IONICE /bin/busybox mount -o remount,rw /flash
$IONICE /bin/busybox mv $UPDATE_DIR/$2 $3
@ -154,83 +169,73 @@ NFS_OVERLAY="192.168.1.1:/var/lib/overlay"
done
}
mount_nbd() {
retry_nr=0
retry_delay=20
OVERLAY_DIR=`cat /sys/class/net/eth0/address | /bin/busybox tr -d :`
while [ ${retry_nr} -lt ${retry_delay} ] && [ ! -e /sysroot/sbin/init ]; do
[ ${retry_nr} -gt 0 ] && \
$IONICE /bin/busybox nbd-client $NBD_ROOT_SERVER $NBD_ROOT_PORT /dev/nbd0 && \
mount_part "/dev/nbd0" "/sysroot" "ro" "squashfs"
retry_nr=$(( ${retry_nr} + 1 ))
[ ! -e /sysroot/sbin/init ] && /bin/busybox usleep 1000000
[ ${retry_nr} -gt 0 ]
load_modules() {
progress "Loading kernel modules"
[ ! -f "/etc/modules" ] && return
for module in $(cat /etc/modules); do
progress "Loading kernel module $module"
/bin/busybox insmod "$MODULE_DIR/$module" || \
error "load_modules" "Failed to load kernel module $module"
done
if [ ! -e /sysroot/sbin/init ]; then
error "INIT_2" "Could not mount NBD root from $NBD_ROOT_SERVER port $NBD_ROOT_PORT"
debug_shell
fi
mount_part "$NFS_OVERLAY" "/sysroot/storage" "rw,nolock,retrans=10" "nfs"
if [ ! -d /sysroot/storage/$OVERLAY_DIR ]; then
mkdir /sysroot/storage/$OVERLAY_DIR
fi
/bin/busybox umount /sysroot/storage
mount_part "$NFS_OVERLAY/$OVERLAY_DIR" "/sysroot/storage" "rw,nolock" "nfs"
}
mount_disk() {
# deal with hfs partitions
check_disks() {
progress "Checking disks"
if [ -x /sbin/fsck_hfs ]; then
# deal with hfs partitions
hfsdiskprep
fi
}
mount_disks() {
progress "Mounting disks"
mount_part "$boot" "/flash" "ro,noatime"
mount_part "$disk" "/storage" "rw,noatime"
}
if [ -n "$disk" ]; then
mount_part "$disk" "/storage" "rw,noatime"
if [ -f "/flash/MACH_KERNEL" ]; then
IMAGE_KERNEL="MACH_KERNEL"
fi
update "Kernel" "$IMAGE_KERNEL" "/flash/$IMAGE_KERNEL"
update "System" "$IMAGE_SYSTEM" "/flash/$IMAGE_SYSTEM"
if test "$REBOOT" -eq "1"; then
echo "System reboots now..." && \
/bin/busybox reboot
fi
check_update() {
progress "Checking for updates"
if [ -f "/flash/MACH_KERNEL" ]; then
IMAGE_KERNEL="MACH_KERNEL"
fi
if [ -f "/flash/$IMAGE_SYSTEM" ]; then
mount_part "/flash/$IMAGE_SYSTEM" "/sysroot" "ro,loop"
[ "$ERR_ENV" -ne "0" ] && debug_shell
else
error "INIT_2" "Could not find system."
debug_shell
fi
update "Kernel" "$IMAGE_KERNEL" "/flash/$IMAGE_KERNEL"
update "System" "$IMAGE_SYSTEM" "/flash/$IMAGE_SYSTEM"
# move /flash and /storage to /sysroot
/bin/busybox mount --move /flash /sysroot/flash
if [ -n "$disk" ]; then
/bin/busybox mount --move /storage /sysroot/storage
if test "$REBOOT" -eq "1"; then
echo "System reboots now..." && \
/bin/busybox reboot
fi
}
if [ -z "$NETBOOT" ]; then
mount_disk
else
mount_nbd
fi
prepare_sysroot() {
progress "Preparing system"
if [ -f "/flash/$IMAGE_SYSTEM" ]; then
# /flash is filesystem with system image file
mount_part "/flash/$IMAGE_SYSTEM" "/sysroot" "ro,loop"
/bin/busybox mount --move /flash /sysroot/flash
else
# /flash is actual root filesystem
/bin/busybox mount --move /flash /sysroot
fi
/bin/busybox mount --move /storage /sysroot/storage
[ -f "/sysroot/sbin/init" ] || error "final_check" "Could not find system."
}
# main boot sequence
for BOOT_STEP in \
load_modules \
check_disks \
mount_disks \
check_update \
prepare_sysroot; do
$BOOT_STEP
[ -n "$DEBUG" ] && break_after $BOOT_STEP
done
BOOT_STEP=final
# move some special filesystems
/bin/busybox mount --move /dev /sysroot/dev
@ -240,5 +245,4 @@ NFS_OVERLAY="192.168.1.1:/var/lib/overlay"
# switch to new sysroot and start real init
exec /bin/busybox switch_root /sysroot /sbin/init
error "INIT_3" "Error in initramfs. Could not switch to new root"
debug_shell
error "switch_root" "Error in initramfs. Could not switch to new root"