mirror of
https://github.com/LibreELEC/LibreELEC.tv
synced 2025-09-24 19:46:01 +07:00
383 lines
9.7 KiB
Bash
Executable File
383 lines
9.7 KiB
Bash
Executable File
#!/bin/sh
|
||
|
||
################################################################################
|
||
# This file is part of OpenELEC - http://www.openelec.tv
|
||
# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv)
|
||
# Copyright (C) 2010-2011 Roman Weber (roman@openelec.tv)
|
||
# Copyright (C) 2012 Yann Cézard (eesprit@free.fr)
|
||
#
|
||
# This Program is free software; you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation; either version 2, or (at your option)
|
||
# any later version.
|
||
#
|
||
# This Program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with OpenELEC.tv; see the file COPYING. If not, write to
|
||
# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA.
|
||
# http://www.gnu.org/copyleft/gpl.html
|
||
################################################################################
|
||
|
||
MODULE_DIR=/lib/modules
|
||
UPDATE_DIR=/storage/.update
|
||
|
||
IMAGE_SYSTEM="SYSTEM"
|
||
IMAGE_KERNEL="KERNEL"
|
||
REBOOT="0"
|
||
|
||
NBD_DEVS="0"
|
||
|
||
# mount all needed special filesystems
|
||
/bin/busybox mount -t devtmpfs none /dev
|
||
/bin/busybox mount -t proc none /proc
|
||
/bin/busybox mount -t sysfs none /sys
|
||
|
||
# hide kernel log messages on console
|
||
echo '1 4 1 7' > /proc/sys/kernel/printk
|
||
|
||
# clear screen and hide cursor
|
||
/bin/busybox clear
|
||
echo 0 > /sys/devices/virtual/graphics/fbcon/cursor_blink
|
||
|
||
# parse command line arguments
|
||
for arg in $(cat /proc/cmdline); do
|
||
case $arg in
|
||
debugging)
|
||
DEBUG=yes
|
||
;;
|
||
bootchart)
|
||
BOOTCHART=yes
|
||
;;
|
||
ssh)
|
||
SSH=yes
|
||
;;
|
||
progress)
|
||
PROGRESS=yes
|
||
;;
|
||
fastboot)
|
||
FASTBOOT=yes
|
||
;;
|
||
overlay)
|
||
OVERLAY=yes
|
||
;;
|
||
break=*)
|
||
BREAK="${arg#*=}"
|
||
;;
|
||
iscsi_auto)
|
||
ISCSI_AUTO=yes
|
||
;;
|
||
iscsi_initiator=*)
|
||
ISCSI_INITIATOR="${arg#iscsi_initiator=}"
|
||
;;
|
||
iscsi_target_name=*)
|
||
ISCSI_TARGET_NAME="${arg#iscsi_target_name=}"
|
||
;;
|
||
iscsi_target_ip=*)
|
||
ISCSI_TARGET_IP="${arg#iscsi_target_ip=}"
|
||
;;
|
||
iscsi_target_port=*)
|
||
ISCSI_TARGET_PORT="${arg#iscsi_target_port=}"
|
||
;;
|
||
iscsi_target_group=*)
|
||
ISCSI_TARGET_GROUP="${arg#iscsi_target_group=}"
|
||
;;
|
||
iscsi_username=*)
|
||
ISCSI_USERNAME="${arg#iscsi_username=}"
|
||
;;
|
||
iscsi_password=*)
|
||
ISCSI_PASSWORD="${arg#iscsi_password=}"
|
||
;;
|
||
iscsi_in_username=*)
|
||
ISCSI_IN_USERNAME="${arg#iscsi_in_username=}"
|
||
;;
|
||
iscsi_in_password=*)
|
||
ISCSI_IN_PASSWORD="${arg#iscsi_in_password=}"
|
||
;;
|
||
esac
|
||
done
|
||
|
||
if test "$FASTBOOT" = "yes"; then
|
||
IONICE="/bin/busybox ionice -c 1 -n 0"
|
||
fi
|
||
|
||
if test "$DEBUG" = "yes"; then
|
||
exec 3>&1
|
||
else
|
||
exec 3>/dev/null
|
||
fi
|
||
SILENT_OUT=3
|
||
|
||
progress() {
|
||
if test "$PROGRESS" = "yes"; then
|
||
echo "### $1 ###"
|
||
fi
|
||
}
|
||
|
||
debug_shell() {
|
||
echo "### Starting debugging shell... type exit to quit ###"
|
||
|
||
# show cursor
|
||
echo 0 > /sys/devices/virtual/graphics/fbcon/cursor_blink
|
||
|
||
/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 >&$SILENT_OUT 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_cifs() {
|
||
# Mount CIFS (Samba) share
|
||
CIFS_SHARE="${1%%,*}"
|
||
CIFS_OPTIONS="${1#*,}"
|
||
[ "$CIFS_OPTIONS" = "$1" ] && CIFS_OPTIONS=
|
||
|
||
mount_common "$CIFS_SHARE" "$2" "$3,$CIFS_OPTIONS" "cifs"
|
||
}
|
||
|
||
mount_nbd() {
|
||
# Mount NBD device
|
||
NBD_SERVER="${1%%:*}"
|
||
NBD_PORT="${1#*:}"
|
||
NBD_DEV="/dev/nbd$NBD_DEVS"
|
||
|
||
$IONICE /bin/busybox nbd-client $NBD_SERVER $NBD_PORT $NBD_DEV >&$SILENT_OUT 2>&1 || \
|
||
error "nbd-client" "Could not connect to NBD server $1"
|
||
|
||
mount_common "$NBD_DEV" "$2" "$3" "$4"
|
||
|
||
NBD_DEVS=$(( ${NBD_DEVS} + 1 ))
|
||
}
|
||
|
||
mount_nfs() {
|
||
# Mount NFS export
|
||
NFS_OPTIONS="nolock,retrans=10"
|
||
|
||
mount_common "$1" "$2" "$3,$NFS_OPTIONS" "nfs"
|
||
}
|
||
|
||
mount_part() {
|
||
# Mount a local or network filesystem
|
||
# $1:[TYPE=]target, $2:mountpoint, $3:mount options, [$4:fs type]
|
||
progress "mount filesystem $1 ..."
|
||
|
||
MOUNT_TARGET="${1#*=}"
|
||
case $1 in
|
||
LABEL=*|UUID=*|/*)
|
||
MOUNT_CMD="mount_common"
|
||
MOUNT_TARGET="$1"
|
||
;;
|
||
CIFS=*|SMB=*)
|
||
MOUNT_CMD="mount_cifs"
|
||
;;
|
||
NBD=*)
|
||
MOUNT_CMD="mount_nbd"
|
||
;;
|
||
NFS=*)
|
||
MOUNT_CMD="mount_nfs"
|
||
;;
|
||
*)
|
||
error "mount_part" "Unknown filesystem $1"
|
||
;;
|
||
esac
|
||
$MOUNT_CMD "$MOUNT_TARGET" "$2" "$3" "$4"
|
||
}
|
||
|
||
update() {
|
||
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
|
||
$IONICE /bin/busybox mount -o remount,ro /flash
|
||
$IONICE /bin/busybox sync
|
||
[ "$2" = "$IMAGE_KERNEL" ] && REBOOT="1"
|
||
fi
|
||
}
|
||
|
||
hfsdiskprep() {
|
||
for DEVICE in /dev/sd*; do
|
||
for device in $(/bin/busybox blkid $DEVICE); do
|
||
case $device in
|
||
TYPE=*)
|
||
FS_TYPE=${device#TYPE=}
|
||
;;
|
||
esac
|
||
done
|
||
|
||
if [ "$FS_TYPE" = "\"hfs\"" -o "$FS_TYPE" = "\"hfsplus\"" ]; then
|
||
progress "check filesystem $DEVICE [$FS_TYPE]..."
|
||
/bin/fsck_hfs -r -y $DEVICE >&$SILENT_OUT 2>&1
|
||
fi
|
||
done
|
||
}
|
||
|
||
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
|
||
}
|
||
|
||
do_iscsi_login ()
|
||
{
|
||
if [ -z $ISCSI_AUTO ]; then
|
||
for i in $ISCSI_TARGET_IP; do
|
||
/sbin/iscsistart -i $ISCSI_INITIATOR -t $ISCSI_TARGET_NAME \
|
||
-g $ISCSI_TARGET_GROUP -a $i \
|
||
-p $ISCSI_TARGET_PORT \
|
||
${ISCSI_USERNAME:+-u "$ISCSI_USERNAME"} \
|
||
${ISCSI_PASSWORD:+-w "$ISCSI_PASSWORD"} \
|
||
${ISCSI_IN_USERNAME:+-U "$ISCSI_IN_USERNAME"} \
|
||
${ISCSI_IN_PASSWORD:+-W "$ISCSI_IN_PASSWORD"}
|
||
|
||
done
|
||
else
|
||
echo "Network configuration based on iBFT."
|
||
/sbin/iscsistart -N
|
||
echo "iSCSI auto connect based on iBFT."
|
||
/sbin/iscsistart -b
|
||
fi
|
||
}
|
||
|
||
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"
|
||
|
||
if [ -n "$disk" ]; then
|
||
if [ -n "$OVERLAY" ]; then
|
||
OVERLAY_DIR=`cat /sys/class/net/eth0/address | /bin/busybox tr -d :`
|
||
|
||
mount_part "$disk" "/storage" "rw,noatime"
|
||
mkdir -p /storage/$OVERLAY_DIR
|
||
/bin/busybox umount /storage
|
||
|
||
# split $disk into $target,$options so we can append $OVERLAY_DIR
|
||
options="${disk#*,}"
|
||
target="${disk%%,*}"
|
||
if [ "$options" = "$disk" ]; then
|
||
disk="$target/$OVERLAY_DIR"
|
||
else
|
||
disk="$target/$OVERLAY_DIR,$options"
|
||
fi
|
||
fi
|
||
|
||
mount_part "$disk" "/storage" "rw,noatime"
|
||
fi
|
||
}
|
||
|
||
check_update() {
|
||
progress "Checking for updates"
|
||
|
||
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
|
||
}
|
||
|
||
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
|
||
|
||
if [ -n "$disk" ]; then
|
||
/bin/busybox mount --move /storage /sysroot/storage
|
||
fi
|
||
|
||
[ -f "/sysroot/sbin/init" ] || error "final_check" "Could not find system."
|
||
}
|
||
|
||
if [ -n "$ISCSI_AUTO" -o -n "$ISCSI_TARGET_NAME" ]; then
|
||
do_iscsi_login
|
||
fi
|
||
|
||
# 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
|
||
/bin/busybox mount --move /proc /sysroot/proc
|
||
/bin/busybox mount --move /sys /sysroot/sys
|
||
|
||
# switch to new sysroot and start real init
|
||
exec /bin/busybox switch_root /sysroot /sbin/init
|
||
|
||
error "switch_root" "Error in initramfs. Could not switch to new root"
|