Skip to content

Instantly share code, notes, and snippets.

@MilhouseVH
Last active March 20, 2016 04:12
Show Gist options
  • Save MilhouseVH/65ffdaeb9f21e87971b0 to your computer and use it in GitHub Desktop.
Save MilhouseVH/65ffdaeb9f21e87971b0 to your computer and use it in GitHub Desktop.
#!/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