Last active
March 20, 2016 04:12
-
-
Save MilhouseVH/65ffdaeb9f21e87971b0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
################################################################################ | |
# This file is part of OpenELEC - http://www.openelec.tv | |
# Copyright (C) 2009-2014 Stephan Raue ([email protected]) | |
# Copyright (C) 2010-2011 Roman Weber ([email protected]) | |
# Copyright (C) 2012 Yann Cézard ([email protected]) | |
# | |
# OpenELEC 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 of the License, or | |
# (at your option) any later version. | |
# | |
# OpenELEC 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. If not, see <http://www.gnu.org/licenses/>. | |
################################################################################ | |
# create directories | |
/bin/busybox mkdir -p /dev | |
/bin/busybox mkdir -p /proc | |
/bin/busybox mkdir -p /sys | |
/bin/busybox mkdir -p /tmp | |
/bin/busybox mkdir -p /flash | |
/bin/busybox mkdir -p /sysroot | |
/bin/busybox mkdir -p /storage | |
# mount all needed special filesystems | |
/bin/busybox mount -t devtmpfs devtmpfs /dev | |
/bin/busybox mount -t proc proc /proc | |
/bin/busybox mount -t sysfs sysfs /sys | |
# set needed variables | |
MODULE_DIR=/lib/modules | |
UPDATE_ROOT=/storage/.update | |
UPDATE_DIR="$UPDATE_ROOT" | |
UPDATE_KERNEL="KERNEL" | |
UPDATE_SYSTEM="SYSTEM" | |
IMAGE_KERNEL="KERNEL" | |
IMAGE_SYSTEM="SYSTEM" | |
BOOT_STEP="start" | |
MD5_FAILED="0" | |
RUN_FSCK="yes" | |
RUN_FSCK_DISKS="" | |
NBD_DEVS="0" | |
FLASH_FREE_MIN="5" | |
INSTALLED_MEMORY=`cat /proc/meminfo | grep 'MemTotal:' | awk '{print $2}'` | |
SYSTEM_TORAM_LIMIT=1024000 | |
LIVE="no" | |
# Show frame-buffer cursor | |
showcursor() { | |
echo -en "\033[?25h" | |
# show cursor | |
if [ -f /sys/devices/virtual/graphics/fbcon/cursor_blink ] ; then | |
echo 1 > /sys/devices/virtual/graphics/fbcon/cursor_blink | |
fi | |
} | |
# Hide frame-buffer cursor | |
hidecursor() { | |
echo -en "\033[?25l" | |
if [ -f /sys/devices/virtual/graphics/fbcon/cursor_blink ] ; then | |
echo 0 > /sys/devices/virtual/graphics/fbcon/cursor_blink | |
fi | |
} | |
# hide kernel log messages on console | |
echo '1 4 1 7' > /proc/sys/kernel/printk | |
# set ondemand up_threshold | |
if [ -e /sys/devices/system/cpu/cpufreq/ondemand/up_threshold ] ; then | |
echo 50 > /sys/devices/system/cpu/cpufreq/ondemand/up_threshold | |
fi | |
# run platform_init script if exists | |
if [ -f "./platform_init" ]; then | |
./platform_init | |
fi | |
# clear screen and hide cursor | |
clear | |
hidecursor | |
# parse command line arguments | |
for arg in $(cat /proc/cmdline); do | |
case $arg in | |
BOOT_IMAGE=*) | |
IMAGE_KERNEL="${arg#*=}" | |
;; | |
SYSTEM_IMAGE=*) | |
IMAGE_SYSTEM="${arg#*=}" | |
;; | |
boot=*) | |
boot="${arg#*=}" | |
case $boot in | |
ISCSI=*|NBD=*|NFS=*) | |
UPDATE_DISABLED=yes | |
FLASH_NETBOOT=yes | |
;; | |
/dev/*|LABEL=*|UUID=*) | |
RUN_FSCK_DISKS="$RUN_FSCK_DISKS $boot" | |
;; | |
esac | |
;; | |
disk=*) | |
disk="${arg#*=}" | |
case $disk in | |
ISCSI=*|NBD=*|NFS=*) | |
STORAGE_NETBOOT=yes | |
;; | |
/dev/*|LABEL=*|UUID=*) | |
RUN_FSCK_DISKS="$RUN_FSCK_DISKS $disk" | |
;; | |
esac | |
;; | |
wol_mac=*) | |
wol_mac="${arg#*=}" | |
;; | |
wol_wait=*) | |
wol_wait="${arg#*=}" | |
;; | |
textmode) | |
INIT_UNIT="--unit=textmode.target" | |
;; | |
installer) | |
INIT_UNIT="--unit=installer.target" | |
;; | |
debugging) | |
DEBUG=yes | |
;; | |
progress) | |
PROGRESS=yes | |
INIT_ARGS="$INIT_ARGS --show-status=1" | |
;; | |
nofsck) | |
RUN_FSCK=no | |
;; | |
nosplash) | |
SPLASH=no | |
;; | |
noram) | |
SYSTEM_TORAM=no | |
;; | |
live) | |
LIVE=yes | |
;; | |
overlay) | |
OVERLAY=yes | |
;; | |
break=*) | |
BREAK="${arg#*=}" | |
;; | |
esac | |
done | |
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 ###" | |
showcursor | |
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 ***" | |
debug_shell | |
} | |
break_after() { | |
# Start debug shell after boot step $1 | |
case $BREAK in | |
all|*$1*) | |
debug_shell | |
;; | |
esac | |
} | |
# Start a progress meter | |
# $1: spinner, percent, countdown | |
# $2: [all types] message to display | |
# [percent] | |
# $3: name of filename to be progress monitored | |
# $4: terminal size (in bytes) of $3 when progress is complete | |
# [countdown] | |
# $3: number of seconds to start counting down from | |
# $4: completion message, default is nothing | |
StartProgress() { | |
# Use files for inter-process communication. | |
# This file is used to indicate a metter is running/active | |
echo > /tmp/progress.run | |
if [ "$1" = "spinner" ]; then | |
ProgressTask_Spinner "$2" & | |
elif [ "$1" = "percent" ]; then | |
ProgressTask_Percent "$2" $3 $4 & | |
elif [ "$1" = "countdown" ]; then | |
ProgressTask_Countdown "$2" $3 "$4" | |
else | |
echo "Unknown spinner type: $1" | |
return 1 | |
fi | |
return 0 | |
} | |
# Stop a progress meter, displaying optional completion message | |
# $1: optional completion message (appropriate default used if not specified) | |
StopProgress() { | |
# Instruct running progress meter to end, showing specified completion message | |
echo "${1}" > /tmp/progress.stop | |
# Wait for progress meter to stop running | |
while [ -f /tmp/progress.run ]; do | |
usleep 250000 | |
done | |
# Clean up | |
rm -f /tmp/progress.stop | |
return 0 | |
} | |
# Use this task for processes of indeterminate duration | |
ProgressTask_Spinner() { | |
local msg="$1" | |
local spinner="|/-\\|/-\\" | |
local count=0 done | |
echo -n "${msg} " | |
while [ ! -f /tmp/progress.stop ]; do | |
echo -en "\b${spinner:$count:1}" | |
usleep 500000 | |
count=$(((count + 1) % 8)) | |
done | |
done="$(cat /tmp/progress.stop)" | |
echo -e "\b${done:-done}" | |
rm -f /tmp/progress.run | |
exit 0 | |
} | |
# Use this task when transferring a file of known size | |
ProgressTask_Percent() { | |
local msg="$1" filename="$2" fsize=$3 csize done | |
echo -n "${msg} " | |
while [ ! -f /tmp/progress.stop ]; do | |
[ -f ${filename} ] && csize=$(stat -t "${filename}" | awk '{print $2}') || csize=0 | |
echo $csize $fsize | awk '{ printf "\b\b\b\b%3d%%", ($1 * 100 / $2) }' | |
usleep 250000 | |
done | |
done="$(cat /tmp/progress.stop)" | |
echo -e "\b\b\b\b${done:-100%}" | |
rm -f /tmp/progress.run | |
exit 0 | |
} | |
# Use this task to countdown a number of seconds | |
# (needs more work for durations > 99 seconds) | |
ProgressTask_Countdown() { | |
local msg="$1" startfrom=$2 done="$3" | |
echo -n "${msg} " | |
while [ ${startfrom} -gt 0 ]; do | |
echo ${startfrom} | awk '{ printf "\b\b%2d", $1 }' | |
sleep 1 | |
startfrom=$((startfrom - 1)) | |
done | |
echo -e "\b\b${done}" | |
rm -f /tmp/progress.run | |
return 0 | |
} | |
# 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 11 12 13 14 15; do | |
ERR_ENV=1 | |
mount $MOUNT_OPTIONS $1 $2 >&$SILENT_OUT 2>&1 | |
[ "$?" -eq "0" ] && ERR_ENV=0 && break | |
usleep 1000000 | |
done | |
[ "$ERR_ENV" -ne "0" ] && error "mount_common" "Could not mount $1" | |
} | |
get_iscsistart_options() { | |
# Convert kernel commandline ISCSI= options to iscsistart options | |
IFS_SAVE="$IFS" | |
IFS=, | |
for arg in $1; do | |
val="${arg#*=}" | |
case "$arg" in | |
iscsi_initiator=*) | |
option="-i" | |
;; | |
iscsi_target_name=*) | |
option="-t" | |
;; | |
iscsi_target_ip=*) | |
option="-a" | |
;; | |
iscsi_target_port=*) | |
option="-p" | |
;; | |
iscsi_target_group=*) | |
option="-g" | |
;; | |
iscsi_username=*) | |
option="-u" | |
;; | |
iscsi_password=*) | |
option="-w" | |
;; | |
iscsi_in_username=*) | |
option="-U" | |
;; | |
iscsi_in_password=*) | |
option="-W" | |
;; | |
esac | |
echo "$option $val" | |
done | |
IFS="$IFS_SAVE" | |
} | |
mount_iscsi() { | |
# Mount iSCSI target | |
ISCSI_DEV="${1##*,}" | |
ISCSI_OPTIONS="${1%,*}" | |
if [ ! -f "/sbin/iscsistart" ]; then | |
error "iscsistart" "iSCSI support not available" | |
fi | |
if [ "$ISCSI_OPTIONS" = "auto" ]; then | |
progress "Network configuration based on iBFT" | |
/sbin/iscsistart -N >&$SILENT_OUT 2>&1 || \ | |
error "iscsistart" "Unable to configure network" | |
progress "iSCSI auto connect based on iBFT" | |
/sbin/iscsistart -b >&$SILENT_OUT 2>&1 || \ | |
error "iscsistart" "Unable to auto connect" | |
else | |
/sbin/iscsistart $(get_iscsistart_options "$ISCSI_OPTIONS") >&$SILENT_OUT 2>&1 || \ | |
error "iscsistart" "Unable to connect to ISCSI target" | |
fi | |
mount_common "$ISCSI_DEV" "$2" "$3" "$4" | |
} | |
mount_nbd() { | |
# Mount NBD device | |
NBD_SERVER="${1%%:*}" | |
NBD_PORT="${1#*:}" | |
NBD_DEV="/dev/nbd$NBD_DEVS" | |
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_EXPORT="${1%%,*}" | |
NFS_OPTIONS="${1#*,}" | |
[ "$NFS_OPTIONS" = "$1" ] && NFS_OPTIONS= | |
mount_common "$NFS_EXPORT" "$2" "$3,nolock,soft,timeo=3,retrans=2,rsize=32768,wsize=32768,$NFS_OPTIONS" "nfs" | |
} | |
mount_ubifs() { | |
mount_common "$1" "$2" "$3" "ubifs" | |
} | |
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 | |
/dev/ubi*) | |
MOUNT_CMD="mount_ubifs" | |
MOUNT_TARGET="$1" | |
RUN_FSCK="no" | |
;; | |
LABEL=*|UUID=*|/*) | |
MOUNT_CMD="mount_common" | |
MOUNT_TARGET="$1" | |
;; | |
ISCSI=*) | |
MOUNT_CMD="mount_iscsi" | |
;; | |
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_file() { | |
if [ -f "$UPDATE_DIR/$2" -a -f "$3" ]; then | |
mount -o remount,rw /flash | |
StartProgress percent "Updating $1... " "$3" $(stat -t "$UPDATE_DIR/$2" | awk '{print $2}') | |
# use dd here with conv=fsync so that all writes are non-buffered | |
# ensuring accurate progress - take the sync hit during the | |
# transfer, rather than when flushing file buffers after the progress | |
# meter declares the transfer already complete | |
dd if=$UPDATE_DIR/$2 of=$3 bs=1M conv=fsync 2>/dev/null | |
StopProgress | |
# loopback file needs writable /flash all the time | |
if [ "${disk%%=*}" != "FILE" ]; then | |
mount -o remount,ro /flash | |
fi | |
sync | |
fi | |
} | |
update_partition() { | |
local result | |
if [ -f "$UPDATE_DIR/$2" -a -b "$3" ]; then | |
StartProgress spinner "Updating $1... " | |
result="$(dd if="$UPDATE_DIR/$2" of="$3" conv=fsync 2>&1)" | |
StopProgress "done" | |
echo "${result}" | |
fi | |
} | |
update_bootloader() { | |
local result | |
export BOOT_ROOT="/flash" | |
export SYSTEM_ROOT="/sysroot" | |
mount_part "/flash/$IMAGE_SYSTEM" "/sysroot" "ro,loop" | |
if [ -f $SYSTEM_ROOT/usr/share/bootloader/update.sh ]; then | |
StartProgress spinner "Updating Bootloader... " | |
result="$(sh $SYSTEM_ROOT/usr/share/bootloader/update.sh 2>&1)" | |
sync | |
StopProgress "done" | |
[ -n "${result}" ] && echo "${result}" | |
fi | |
umount /sysroot | |
} | |
load_modules() { | |
progress "Loading kernel modules" | |
[ ! -f "/etc/modules" ] && return | |
for module in $(cat /etc/modules); do | |
progress "Loading kernel module $module" | |
insmod "$MODULE_DIR/$module.ko" || \ | |
progress "... Failed to load kernel module $module, skipping" | |
done | |
} | |
load_splash() { | |
if [ ! "$SPLASH" = "no" ]; then | |
progress "Loading bootsplash" | |
SPLASHIMAGE="/splash/splash-full.png" | |
# load uvesafb module if needed | |
if [ -f "$MODULE_DIR/uvesafb.ko" -a ! -e /dev/fb0 ]; then | |
progress "Loading kernel module uvesafb.ko" | |
insmod "$MODULE_DIR/uvesafb.ko" || \ | |
progress "... Failed to load kernel module uvesafb, skipping" | |
# set framebuffer to a default resolution (1024x768-32) | |
if [ ! "$SWITCH_FRAMEBUFFER" = "no" ]; then | |
fbset -g 1024 768 1024 768 32 | |
SPLASHIMAGE="/splash/splash-1024.png" | |
fi | |
fi | |
if [ -e /dev/fb0 ]; then | |
# load splash | |
if [ -f /flash/oemsplash.png ]; then | |
SPLASHIMAGE="/flash/oemsplash.png" | |
elif [ -f /splash/splash.conf ]; then | |
. /splash/splash.conf | |
fi | |
ply-image $SPLASHIMAGE > /dev/null 2>&1 | |
fi | |
fi | |
} | |
do_reboot() { | |
echo "System reboots now..." | |
# syncing filesystem | |
sync | |
# unmount filesystems | |
if /bin/busybox mountpoint -q /flash ; then | |
/bin/busybox umount /flash | |
fi | |
if /bin/busybox mountpoint -q /storage ; then | |
/bin/busybox umount /storage | |
fi | |
usleep 2000000 | |
/bin/busybox reboot | |
} | |
force_fsck() { | |
echo "Filesystem corruption has been detected!" | |
echo "To prevent an automatic repair attempt continuing," | |
echo "press any key or power off your system within the next 120 seconds" | |
echo "" | |
read -t120 -n1 | |
# The exit status is 0 if input is available | |
# The exit status is greater than 128 if the timeout is exceeded | |
if [ "$?" -ne "0" -o "$?" -gt "128" ] ; then | |
echo "Repairing filesystem..." | |
echo "" | |
/sbin/fsck -T -M -y $RUN_FSCK_DISKS | |
FSCK_RET="$?" | |
if [ "$(( $FSCK_RET & 8 ))" = 8 ] ; then | |
# fubar | |
echo "Forced fsck failed. Your system is broken beyond repair" | |
echo "Please re-install OpenELEC" | |
echo "" | |
echo "Press enter to shutdown now" | |
echo "" | |
read fubar | |
poweroff | |
fi | |
do_reboot | |
else | |
echo "Shutting down..." | |
sleep 5 | |
sync | |
poweroff | |
fi | |
} | |
check_disks() { | |
if [ "$RUN_FSCK" = "yes" -a -n "$RUN_FSCK_DISKS" ]; then | |
progress "Checking disk(s): $RUN_FSCK_DISKS" | |
/sbin/fsck -T -M -p -a $RUN_FSCK_DISKS > /dev/null 2>&1 | |
FSCK_RET="$?" | |
# FSCK_RET is the bit-wise OR of the exit codes for each filesystem that is checked. | |
if [ "$(( $FSCK_RET & 4 ))" = 4 ] ; then | |
# errors left | |
force_fsck | |
elif [ "$(( $FSCK_RET & 2 ))" = 2 ] ; then | |
# reboot needed | |
echo "Filesystem repaired, reboot needed..." | |
do_reboot | |
elif [ "$(( $FSCK_RET & 1 ))" = 1 ] ; then | |
# filesystem errors corrected | |
progress "Filesystem errors corrected , continuing..." | |
elif [ "$(( $FSCK_RET & 0 ))" = 0 ] ; then | |
# no errors found | |
progress "No filesystem errors found, continuing..." | |
fi | |
fi | |
} | |
wakeonlan() { | |
if [ "$STORAGE_NETBOOT" = "yes" ]; then | |
wol_ip=${disk%:*} | |
wol_ip=${wol_ip#*=} | |
elif [ "$FLASH_NETBOOT" = "yes" ]; then | |
wol_ip=${boot%:*} | |
wol_ip=${wol_ip#*=} | |
else | |
return 0 | |
fi | |
if [ -n "$wol_ip" -a -n "$wol_mac" -a -n "$wol_wait" ]; then | |
progress "Sending Magic Packet (WOL) if needed" | |
if ! ping -q -c 2 "$wol_ip" &>/dev/null; then | |
ether-wake "$wol_mac" | |
StartProgress countdown "WOL magic packet sent to $wol_ip, waiting $wol_wait seconds... " $wol_wait "done" | |
fi | |
fi | |
} | |
mount_flash() { | |
progress "Mounting flash" | |
wakeonlan | |
mount_part "$boot" "/flash" "ro,noatime" | |
} | |
mount_storage() { | |
progress "Mounting storage" | |
if [ "$LIVE" = "yes" ]; then | |
# mount tmpfs and exit early. disk=xx is not allowed in live mode | |
mount -t tmpfs none /storage | |
return | |
fi | |
wakeonlan | |
if [ -n "$disk" ]; then | |
if [ -n "$OVERLAY" ]; then | |
OVERLAY_DIR=`cat /sys/class/net/eth0/address | tr -d :` | |
mount_part "$disk" "/storage" "rw,noatime" | |
mkdir -p /storage/$OVERLAY_DIR | |
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" | |
else | |
# /storage should always be writable | |
mount -t tmpfs none /storage | |
fi | |
} | |
do_cleanup() { | |
StartProgress spinner "Cleaning up... " | |
if [ -d $UPDATE_ROOT/.tmp/mnt ]; then | |
if mountpoint -q $UPDATE_ROOT/.tmp/mnt ; then | |
# busybox umount deletes loop device automatically | |
umount $UPDATE_ROOT/.tmp/mnt | |
fi | |
[ -n $LOOP ] && losetup -d $LOOP &>/dev/null | |
fi | |
[ -f "$UPDATE_TAR" ] && rm -f "$UPDATE_TAR" &>/dev/null | |
[ -f "$UPDATE_IMG_GZ" ] && rm -f "$UPDATE_IMG_GZ" &>/dev/null | |
[ -f "$UPDATE_IMG" ] && rm -f "$UPDATE_IMG" &>/dev/null | |
rm -rf $UPDATE_ROOT/.tmp &>/dev/null | |
rm -rf $UPDATE_ROOT/[0-9a-zA-Z]* &>/dev/null | |
sync | |
StopProgress "done" | |
} | |
check_update() { | |
progress "Checking for updates" | |
UPDATE_TAR=`ls -1 "$UPDATE_DIR"/*.tar 2>/dev/null | head -n 1` | |
UPDATE_IMG_GZ=`ls -1 "$UPDATE_DIR"/*.img.gz 2>/dev/null | head -n 1` | |
UPDATE_IMG=`ls -1 "$UPDATE_DIR"/*.img 2>/dev/null | head -n 1` | |
if ! [ -f "$UPDATE_DIR/$UPDATE_KERNEL" -a -f "$UPDATE_DIR/$UPDATE_SYSTEM" ] && | |
! [ -f "$UPDATE_TAR" -o -f "$UPDATE_IMG_GZ" -o -f "$UPDATE_IMG" ]; then | |
return 0 | |
fi | |
if [ "$UPDATE_DISABLED" = "yes" ] ; then | |
echo "Updating is not supported on netboot" | |
do_cleanup | |
StartProgress countdown "Normal startup in 10s... " 10 "NOW" | |
return 0 | |
fi | |
# remove temporary folder if exist from previous run | |
rm -fr "$UPDATE_DIR/.tmp" &>/dev/null | |
if [ -f "$UPDATE_TAR" ] ; then | |
echo "Found new .tar archive" | |
StartProgress spinner "Extracting tar... " | |
mkdir -p $UPDATE_DIR/.tmp &>/dev/null | |
tar -xf "$UPDATE_TAR" -C $UPDATE_DIR/.tmp &>/dev/null | |
mv $UPDATE_DIR/.tmp/*/target/* $UPDATE_DIR &>/dev/null | |
sync | |
StopProgress "done" | |
elif [ -f "$UPDATE_IMG_GZ" -o -f "$UPDATE_IMG" ] ; then | |
mkdir -p $UPDATE_DIR/.tmp/mnt &>/dev/null | |
IMG_FILE="$UPDATE_DIR/.tmp/update.img" | |
GZRESULT="0" | |
if [ -f "$UPDATE_IMG_GZ" ]; then | |
echo "Found new compressed image file" | |
StartProgress spinner "Decompressing image file... " | |
gunzip -d -c "$UPDATE_IMG_GZ" 1>$IMG_FILE 2>/tmp/gzresult.txt || GZRESULT="1" | |
sync | |
[ "${GZRESULT}" -eq "0" ] && StopProgress "OK" || StopProgress "FAILED" | |
if [ "${GZRESULT}" -eq "1" ]; then | |
echo "Failed to decompress image file!" | |
echo "gunzip result: '$(cat /tmp/gzresult.txt)'" | |
do_cleanup | |
StartProgress countdown "Normal startup in 30s... " 30 "NOW" | |
return 0 | |
fi | |
else | |
echo "Found new image file" | |
mv "$UPDATE_IMG" $IMG_FILE | |
fi | |
LOOP=$(losetup -f) | |
LOOP_NUM=$(echo $LOOP | sed 's|/dev/loop||') | |
mknod $LOOP b 7 $LOOP_NUM | |
losetup $LOOP $IMG_FILE | |
# check for MBR partititon | |
OFFSET=$(fdisk -u -l $LOOP 2>/dev/null | awk '/^[ ]*Device/{part=1; next}; part{if ($2 == "*") {print $3} else {print $2} ; exit}') | |
if [ -z "$OFFSET" ]; then | |
# check for GPT partititon | |
OFFSET=$(fdisk -u -l $LOOP 2>/dev/null | awk '/^Number/{part=1; next}; part{print $2; exit}') | |
if [ -z "$OFFSET" ]; then | |
echo "Could not find a valid system partition in image file!" | |
do_cleanup | |
StartProgress countdown "Normal startup in 10s... " 10 "NOW" | |
return 0 | |
fi | |
fi | |
SECTOR_SIZE=$(cat /sys/devices/virtual/block/loop${LOOP_NUM}/queue/hw_sector_size) | |
losetup -d $LOOP | |
sync | |
OFFSET=$(($OFFSET * $SECTOR_SIZE)) | |
# use losetup because busybox mount does not support the -o offset option | |
echo "Mounting system partition..." | |
losetup -o $OFFSET $LOOP $IMG_FILE | |
mount -o ro,loop $LOOP $UPDATE_DIR/.tmp/mnt | |
# don't make temporary files but instead copy | |
# directly from mountpoint to /flash | |
UPDATE_DIR=$UPDATE_ROOT/.tmp/mnt | |
UPDATE_KERNEL=$(basename $IMAGE_KERNEL) | |
fi | |
sync | |
if [ ! -f "$UPDATE_DIR/$UPDATE_KERNEL" -o ! -f "$UPDATE_DIR/$UPDATE_SYSTEM" ] ; then | |
echo "Missing ${UPDATE_KERNEL} or ${UPDATE_SYSTEM}!" | |
do_cleanup | |
StartProgress countdown "Normal startup in 10s... " 10 "NOW" | |
return 0 | |
fi | |
# check md5 sums if .nocheck doesn't exist | |
if [ ! -f "$UPDATE_DIR/.nocheck" ]; then | |
if [ -f "$UPDATE_DIR/${UPDATE_KERNEL}.md5" -a -f "$UPDATE_DIR/${UPDATE_SYSTEM}.md5" ] ; then | |
# *.md5 size-check | |
if [ ! -s "$UPDATE_DIR/${UPDATE_KERNEL}.md5" -o ! -s "$UPDATE_DIR/${UPDATE_SYSTEM}.md5" ] ; then | |
echo "Zero-sized .md5 file!" | |
MD5_FAILED="1" | |
else | |
sed "s#target/KERNEL#$UPDATE_DIR/$UPDATE_KERNEL#g" "$UPDATE_DIR/${UPDATE_KERNEL}.md5" >"$UPDATE_ROOT/${UPDATE_KERNEL}.check.md5" | |
sed "s#target#$UPDATE_DIR#g" "$UPDATE_DIR/${UPDATE_SYSTEM}.md5" >"$UPDATE_ROOT/${UPDATE_SYSTEM}.check.md5" | |
StartProgress spinner "Checking ${UPDATE_KERNEL}.md5... " | |
if md5sum -sc "$UPDATE_ROOT/${UPDATE_KERNEL}.check.md5"; then | |
StopProgress "OK" | |
else | |
StopProgress "FAILED" | |
MD5_FAILED="1" | |
fi | |
StartProgress spinner "Checking ${UPDATE_SYSTEM}.md5... " | |
if md5sum -sc "$UPDATE_ROOT/${UPDATE_SYSTEM}.check.md5"; then | |
StopProgress "OK" | |
else | |
StopProgress "FAILED" | |
MD5_FAILED="1" | |
fi | |
fi | |
else | |
echo "Missing ${UPDATE_KERNEL}.md5 or ${UPDATE_SYSTEM}.md5!" | |
MD5_FAILED="1" | |
fi | |
if [ "$MD5_FAILED" -eq "1" ]; then | |
echo "md5 check failed!" | |
do_cleanup | |
StartProgress countdown "Normal startup in 30s... " 30 "NOW" | |
return 0 | |
fi | |
fi | |
# get sizes | |
FLASH_FREE=$(df /flash/ | awk '/[0-9]%/{print $4}') | |
FLASH_FREE=$(( $FLASH_FREE * 1024 )) | |
# Disregard kernel size if it's a a block device, which is the case on Amlogic/WeTek devices | |
if [ ! -b $IMAGE_KERNEL ]; then | |
OLD_KERNEL=$(stat -t "/flash/$IMAGE_KERNEL" | awk '{print $2}') | |
else | |
OLD_KERNEL="0" | |
fi | |
OLD_SYSTEM=$(stat -t "/flash/$IMAGE_SYSTEM" | awk '{print $2}') | |
NEW_KERNEL=$(stat -t "$UPDATE_DIR/$UPDATE_KERNEL" | awk '{print $2}') | |
NEW_SYSTEM=$(stat -t "$UPDATE_DIR/$UPDATE_SYSTEM" | awk '{print $2}') | |
# old KERNEL+SYSTEM+free space - new KERNEL+SYSTEM must be higher then 5MB | |
# at least 5MB free after update | |
TMP_SIZE=$(($OLD_KERNEL+$OLD_SYSTEM+$FLASH_FREE-$NEW_KERNEL-$NEW_SYSTEM)) | |
FLASH_FREE_MIN=$(($FLASH_FREE_MIN*1024*1024)) | |
if [ $TMP_SIZE -ge $FLASH_FREE_MIN ]; then | |
echo "Checking size: OK" | |
else | |
echo "Checking size: FAILED" | |
echo "" | |
echo "Your System (FAT) partition is too small for this update," | |
echo "and there is not enough space for the update to be installed!" | |
echo "" | |
echo "You must re-install your system using the disk image of a" | |
echo "current release, or you must re-size your existing partitions" | |
echo "so that the System (FAT) partition is at least 512MB in size." | |
echo "" | |
do_cleanup | |
StartProgress countdown "Normal startup in 60s... " 60 "NOW" | |
return 0 | |
fi | |
# all ok, update | |
if [ -b $IMAGE_KERNEL ]; then | |
update_partition "Kernel" "$UPDATE_KERNEL" "$IMAGE_KERNEL" | |
else | |
update_file "Kernel" "$UPDATE_KERNEL" "/flash/$IMAGE_KERNEL" | |
fi | |
update_file "System" "$UPDATE_SYSTEM" "/flash/$IMAGE_SYSTEM" | |
update_bootloader | |
do_cleanup | |
do_reboot | |
} | |
prepare_sysroot() { | |
progress "Preparing system" | |
if [ "$SYSTEM_TORAM" = "no" -o "$INSTALLED_MEMORY" -lt "$SYSTEM_TORAM_LIMIT" ]; then | |
mount_part "/flash/$IMAGE_SYSTEM" "/sysroot" "ro,loop" | |
else | |
cp /flash/$IMAGE_SYSTEM /dev/$IMAGE_SYSTEM | |
mount_part "/dev/$IMAGE_SYSTEM" "/sysroot" "ro,loop" | |
fi | |
mount --move /flash /sysroot/flash | |
mount --move /storage /sysroot/storage | |
if [ ! -d "/sysroot/lib/modules/$(uname -r)/" -a -f "/sysroot/usr/lib/systemd/systemd" ]; then | |
echo "" | |
echo "NEVER TOUCH boot= in extlinux.conf / cmdline.txt!" | |
echo "If you don't know what you are doing," | |
echo "your installation is now broken." | |
echo "" | |
StartProgress countdown "Normal startup in 60s... " 60 "NOW" | |
fi | |
[ -f "/sysroot/usr/lib/systemd/systemd" ] || error "final_check" "Could not find systemd!" | |
} | |
if [ "${boot%%=*}" = "FILE" ]; then | |
error "check arguments" "boot argument can't be FILE type..." | |
fi | |
# main boot sequence | |
for BOOT_STEP in \ | |
load_modules \ | |
check_disks \ | |
mount_flash \ | |
load_splash \ | |
mount_storage \ | |
check_update \ | |
prepare_sysroot; do | |
$BOOT_STEP | |
[ -n "$DEBUG" ] && break_after $BOOT_STEP | |
done | |
BOOT_STEP=final | |
# log if booting from usb / removable storage | |
STORAGE=$(cat /proc/mounts | grep " /sysroot/storage " | awk '{print $1}' | awk -F '/' '{print $3}') | |
FLASH=$(cat /proc/mounts | grep " /sysroot/flash " | awk '{print $1}' | awk -F '/' '{print $3}') | |
for i in $STORAGE $FLASH ; do | |
if [ -n "$i" ] ; then | |
removable="/sys/class/block/*/$i/../removable" | |
if [ -e $removable ] ; then | |
if [ "$(cat $removable 2>/dev/null)" = "1" ] ; then | |
echo "### BIG FAT WARNING" > /dev/kmsg | |
echo "### $i is removable. suspend/resume may not work" > /dev/kmsg | |
fi | |
fi | |
fi | |
done | |
# 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 | |
/bin/busybox rm -fr /tmp | |
# tell OE settings addon to disable updates | |
if [ "$UPDATE_DISABLED" = "yes" ] ; then | |
echo "" > /sysroot/dev/.update_disabled | |
fi | |
# swap can not be used over nfs.(see scripts/mount-swap) | |
if [ "$STORAGE_NETBOOT" = "yes" ] ; then | |
echo "" > /sysroot/dev/.storage_netboot | |
fi | |
if [ -f /sysroot/storage/.please_resize_me ] ; then | |
INIT_UNIT="--unit=fs-resize.target" | |
fi | |
BACKUP_FILE=`ls -1 /sysroot/storage/.restore/??????????????.tar 2>/dev/null | head -n 1` | |
if [ -f "$BACKUP_FILE" ] ; then | |
INIT_UNIT="--unit=backup-restore.target" | |
fi | |
if [ -f /sysroot/storage/.cache/reset_oe -o -f /sysroot/storage/.cache/reset_xbmc ] ; then | |
INIT_UNIT="--unit=factory-reset.target" | |
fi | |
# switch to new sysroot and start real init | |
exec /bin/busybox switch_root /sysroot /usr/lib/systemd/systemd $INIT_ARGS $INIT_UNIT | |
error "switch_root" "Error in initramfs. Could not switch to new root" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment