#!/bin/sh # # OpenIPC.org | v.20220722 # set -e echo_c() { [ -z "$HASERLVER" ] && t="\e[1;$1m$2\e[0m" || t="$2" echo -e "$t" } die() { echo_c 31 "$1 Aborting." reboot_system } check_soc() { [ "$skip_soc" -eq 1 ] && echo "Skip SoC validation" && return 0 [ "$1" = "$soc" ] && echo "SoC OK" && return 0 die "Wrong SoC!" } compare_versions() { [ "$skip_ver" -eq 1 ] && echo "Skip version checking" && return 1 [ "$1" = "$2" ] && echo_c 32 "Same version, nothing to update" && return 0 echo_c 32 "New version, going to update" && return 1 } do_update_kernel() { x=$1 [ -z "$x" ] && x="/tmp/uImage.$soc" echo_c 33 "\nKernel" echo "Update kernel from $x" [ ! -f "$x" ] && die "File $x not found" check_soc "$(od -j 32 -N 32 -S 1 -A n "$x" | cut -d- -f3)" compare_versions "$kernel_version" "$(get_kernel_version "$x")" && return 0 flashcp -v "$x" "$kernel_device" echo_c 32 "Kernel updated to $(get_kernel_version "$kernel_device")" unset x } do_update_rootfs() { x=$1 [ -z "$x" ] && x="/tmp/rootfs.squashfs.$soc" echo_c 33 "\nRootFS" echo "Update rootfs from $x" [ ! -f "$x" ] && die "File ${x} not found" y=/tmp/rootfs if mkdir -p "$y" && loop=$(losetup -f) && losetup "$loop" "$x" && mount "$loop" "$y"; then check_soc "$(head -1 ${y}/etc/hostname | cut -d- -f2)" compare_versions "$system_version" "$(get_system_version "$y")" && return 0 umount "$y" && rm -rf "$y" && losetup -d "$loop" else die "Unable to mount $y!" fi unset y flashcp -v "$x" "$(get_device "rootfs")" echo_c 32 "RootFS updated to $(get_system_version "")" unset x } do_wipe_overlay() { echo_c 33 "\nOverlayFS" echo "Erase overlay partition" flash_eraseall -j "$(get_device "rootfs_data")" } download_firmware() { echo_c 33 "\nFirmware" osr=$(get_system_build) if [[ "${osr}" == "lite" ]] || [[ "${osr}" == "" ]]; then build="-" else build="-${osr}-" fi [ -z "$url" ] && url="https://github.com/OpenIPC/firmware/releases/download/latest/openipc.${soc}${build}br.tgz" echo "Download from $url" [ -z "$HASERLVER" ] && progress="-#" || progress="-s" [ "$(curl -o /dev/null -s -w '%{http_code}\n' "$url")" = "000" ] && die "Check your network!" curl --connect-timeout 30 -s -m 60 -L "$url" ${progress} -o - | gzip -d | tar xf - -C /tmp && echo_c 32 "Received and unpacked" || die "Cannot retrieve $url" if [ "$skip_md5" -eq 0 ]; then (cd /tmp && md5sum -s -c *.md5sum) || die "Wrong checksum!" fi } free_resources() { # echo_c 97 "\nStop services, unload modules" # killall majestic crond klogd ntpd rngd syslogd >/dev/null 2>&1 || true # "load_$vendor" -r >/dev/null 2>&1 || true # echo_c 97 "\nStop services, sync and fresh memory" for proc in majestic crond klogd ntpd rngd syslogd do echo -n "Killing $proc " while [ -n "$(pidof $proc)" ] do killall $proc >/dev/null 2>&1 || true sleep 0.1 echo -n "." done echo ". OK" done sync; echo 3 > /proc/sys/vm/drop_caches } create_lock() { [ -f /tmp/sysupgrade.lock ] && echo -e "\e[1;31m\nAnother sysupgrade process is already running!\e[0m\n" && exit 1 touch /tmp/sysupgrade.lock } get_device() { echo -n "/dev/$(grep "\"$1\"" /proc/mtd | cut -d: -f1)" } get_kernel_version() { echo -n "0x$(xxd -l 4 -s 8 -p "$1" | xargs)" } get_system_info() { vendor=$(ipcinfo --vendor) soc=$(fw_printenv -n soc) || die "SoC is not defined in U-Boot environment" kernel_device=$(get_device "kernel") kernel_version=$(get_kernel_version "$kernel_device") system_version=$(get_system_version "") } get_system_version() { grep "GITHUB_VERSION" "$1/etc/os-release" | head -1 | cut -d= -f2 | sed 's/"//g' } get_system_build() { grep "BUILD_OPTION" "/etc/os-release" | head -1 | cut -d= -f2 } print_sysinfo() { get_system_info echo_c 33 "OpenIPC System Updater" echo_c 96 "\nVendor\t$vendor\nSoC\t$soc\nKernel\t$kernel_version\nRootFS\t$system_version" } print_usage() { echo " Usage: $0 [options] -k update kernel from online repository -r update rootfs from online repository --url=[URL] custom URL to update from (.tgz format) --kernel=[FILE] update kernel from file (uImage format) --rootfs=[FILE] update rootfs from file (squashfs format) --force_md5 do not validate MD5 hash --force_soc do not validate processor --force_ver do not validate release version --force_all do not validate anything -n, --wipe_overlay wipe overlay partition -x, --no_reboot do not reboot after updating -h, --help display this help and exit " } reboot_system() { [ "$skip_reboot" -eq 1 ] && echo_c 31 "\nReboot needed!" && exit 1 echo_c 97 "\nUnconditional reboot" reboot -d 1 -f } clear_overlay=0 remote_update=0 skip_md5=0 skip_soc=0 skip_ver=0 skip_reboot=0 update_kernel=0 update_rootfs=0 for i in "$@"; do case $i in --force_all) skip_md5=1 skip_soc=1 skip_ver=1 shift ;; --force_md5) skip_md5=1 shift ;; --force_soc) skip_soc=1 shift ;; --force_ver) skip_ver=1 shift ;; -h|--help) print_sysinfo print_usage exit 0 ;; -k ) update_kernel=1 remote_update=1 shift ;; --kernel=*) update_kernel=1 kernel_file="${i#*=}" shift ;; -n|--wipe_overlay) clear_overlay=1 shift ;; -r) update_rootfs=1 remote_update=1 shift ;; --rootfs=*) update_rootfs=1 rootfs_file="${i#*=}" shift ;; --url=*) url="${i#*=}" shift ;; -x|--no_reboot) skip_reboot=1 shift ;; *) print_sysinfo echo_c 97 "\nUnknown option: $1" print_usage exit 1 ;; esac done print_sysinfo [ "$update_kernel" -eq 0 ] && \ [ "$update_rootfs" -eq 0 ] && \ [ "$clear_overlay" -eq 0 ] && \ echo_c 97 "\nTry '$(basename "$0") --help' for options." && \ exit 0 create_lock free_resources [ "$remote_update" -eq 1 ] && download_firmware [ "$update_kernel" -eq 1 ] && do_update_kernel "$kernel_file" [ "$update_rootfs" -eq 1 ] && do_update_rootfs "$rootfs_file" [ "$clear_overlay" -eq 1 ] && do_wipe_overlay reboot_system