Initial commit
This commit is contained in:
241
package/base-files/files/lib/upgrade/common.sh
Normal file
241
package/base-files/files/lib/upgrade/common.sh
Normal file
@@ -0,0 +1,241 @@
|
||||
#!/bin/sh
|
||||
|
||||
RAM_ROOT=/tmp/root
|
||||
|
||||
export BACKUP_FILE=sysupgrade.tgz # file extracted by preinit
|
||||
|
||||
[ -x /usr/bin/ldd ] || ldd() { LD_TRACE_LOADED_OBJECTS=1 $*; }
|
||||
libs() { ldd $* 2>/dev/null | sed -r 's/(.* => )?(.*) .*/\2/'; }
|
||||
|
||||
install_file() { # <file> [ <file> ... ]
|
||||
local target dest dir
|
||||
for file in "$@"; do
|
||||
if [ -L "$file" ]; then
|
||||
target="$(readlink -f "$file")"
|
||||
dest="$RAM_ROOT/$file"
|
||||
[ ! -f "$dest" ] && {
|
||||
dir="$(dirname "$dest")"
|
||||
mkdir -p "$dir"
|
||||
ln -s "$target" "$dest"
|
||||
}
|
||||
file="$target"
|
||||
fi
|
||||
dest="$RAM_ROOT/$file"
|
||||
[ -f "$file" -a ! -f "$dest" ] && {
|
||||
dir="$(dirname "$dest")"
|
||||
mkdir -p "$dir"
|
||||
cp "$file" "$dest"
|
||||
}
|
||||
done
|
||||
}
|
||||
|
||||
install_bin() {
|
||||
local src files
|
||||
src=$1
|
||||
files=$1
|
||||
[ -x "$src" ] && files="$src $(libs $src)"
|
||||
install_file $files
|
||||
}
|
||||
|
||||
run_hooks() {
|
||||
local arg="$1"; shift
|
||||
for func in "$@"; do
|
||||
eval "$func $arg"
|
||||
done
|
||||
}
|
||||
|
||||
ask_bool() {
|
||||
local default="$1"; shift;
|
||||
local answer="$default"
|
||||
|
||||
[ "$INTERACTIVE" -eq 1 ] && {
|
||||
case "$default" in
|
||||
0) echo -n "$* (y/N): ";;
|
||||
*) echo -n "$* (Y/n): ";;
|
||||
esac
|
||||
read answer
|
||||
case "$answer" in
|
||||
y*) answer=1;;
|
||||
n*) answer=0;;
|
||||
*) answer="$default";;
|
||||
esac
|
||||
}
|
||||
[ "$answer" -gt 0 ]
|
||||
}
|
||||
|
||||
v() {
|
||||
[ "$VERBOSE" -ge 1 ] && echo "$@"
|
||||
}
|
||||
|
||||
json_string() {
|
||||
local v="$1"
|
||||
v="${v//\\/\\\\}"
|
||||
v="${v//\"/\\\"}"
|
||||
echo "\"$v\""
|
||||
}
|
||||
|
||||
rootfs_type() {
|
||||
/bin/mount | awk '($3 ~ /^\/$/) && ($5 !~ /rootfs/) { print $5 }'
|
||||
}
|
||||
|
||||
get_image() { # <source> [ <command> ]
|
||||
local from="$1"
|
||||
local cmd="$2"
|
||||
|
||||
if [ -z "$cmd" ]; then
|
||||
local magic="$(dd if="$from" bs=2 count=1 2>/dev/null | hexdump -n 2 -e '1/1 "%02x"')"
|
||||
case "$magic" in
|
||||
1f8b) cmd="zcat";;
|
||||
425a) cmd="bzcat";;
|
||||
*) cmd="cat";;
|
||||
esac
|
||||
fi
|
||||
|
||||
cat "$from" 2>/dev/null | $cmd
|
||||
}
|
||||
|
||||
get_magic_word() {
|
||||
(get_image "$@" | dd bs=2 count=1 | hexdump -v -n 2 -e '1/1 "%02x"') 2>/dev/null
|
||||
}
|
||||
|
||||
get_magic_long() {
|
||||
(get_image "$@" | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2>/dev/null
|
||||
}
|
||||
|
||||
export_bootdevice() {
|
||||
local cmdline bootdisk rootpart uuid blockdev uevent line class
|
||||
local MAJOR MINOR DEVNAME DEVTYPE
|
||||
|
||||
if read cmdline < /proc/cmdline; then
|
||||
case "$cmdline" in
|
||||
*block2mtd=*)
|
||||
bootdisk="${cmdline##*block2mtd=}"
|
||||
bootdisk="${bootdisk%%,*}"
|
||||
;;
|
||||
*root=*)
|
||||
rootpart="${cmdline##*root=}"
|
||||
rootpart="${rootpart%% *}"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$bootdisk" in
|
||||
/dev/*)
|
||||
uevent="/sys/class/block/${bootdisk##*/}/uevent"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$rootpart" in
|
||||
PARTUUID=[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]-[a-f0-9][a-f0-9])
|
||||
uuid="${rootpart#PARTUUID=}"
|
||||
uuid="${uuid%-[a-f0-9][a-f0-9]}"
|
||||
for blockdev in $(find /dev -type b); do
|
||||
set -- $(dd if=$blockdev bs=1 skip=440 count=4 2>/dev/null | hexdump -v -e '4/1 "%02x "')
|
||||
if [ "$4$3$2$1" = "$uuid" ]; then
|
||||
uevent="/sys/class/block/${blockdev##*/}/uevent"
|
||||
break
|
||||
fi
|
||||
done
|
||||
;;
|
||||
/dev/*)
|
||||
uevent="/sys/class/block/${rootpart##*/}/../uevent"
|
||||
;;
|
||||
0x[a-f0-9][a-f0-9][a-f0-9] | 0x[a-f0-9][a-f0-9][a-f0-9][a-f0-9] | \
|
||||
[a-f0-9][a-f0-9][a-f0-9] | [a-f0-9][a-f0-9][a-f0-9][a-f0-9])
|
||||
rootpart=0x${rootpart#0x}
|
||||
for class in /sys/class/block/*; do
|
||||
while read line; do
|
||||
export -n "$line"
|
||||
done < "$class/uevent"
|
||||
if [ $((rootpart/256)) = $MAJOR -a $((rootpart%256)) = $MINOR ]; then
|
||||
uevent="$class/../uevent"
|
||||
fi
|
||||
done
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -e "$uevent" ]; then
|
||||
while read line; do
|
||||
export -n "$line"
|
||||
done < "$uevent"
|
||||
export BOOTDEV_MAJOR=$MAJOR
|
||||
export BOOTDEV_MINOR=$MINOR
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
export_partdevice() {
|
||||
local var="$1" offset="$2"
|
||||
local uevent line MAJOR MINOR DEVNAME DEVTYPE
|
||||
|
||||
for uevent in /sys/class/block/*/uevent; do
|
||||
while read line; do
|
||||
export -n "$line"
|
||||
done < "$uevent"
|
||||
if [ $BOOTDEV_MAJOR = $MAJOR -a $(($BOOTDEV_MINOR + $offset)) = $MINOR -a -b "/dev/$DEVNAME" ]; then
|
||||
export "$var=$DEVNAME"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
hex_le32_to_cpu() {
|
||||
[ "$(echo 01 | hexdump -v -n 2 -e '/2 "%x"')" = "3031" ] && {
|
||||
echo "${1:0:2}${1:8:2}${1:6:2}${1:4:2}${1:2:2}"
|
||||
return
|
||||
}
|
||||
echo "$@"
|
||||
}
|
||||
|
||||
get_partitions() { # <device> <filename>
|
||||
local disk="$1"
|
||||
local filename="$2"
|
||||
|
||||
if [ -b "$disk" -o -f "$disk" ]; then
|
||||
v "Reading partition table from $filename..."
|
||||
|
||||
local magic=$(dd if="$disk" bs=2 count=1 skip=255 2>/dev/null)
|
||||
if [ "$magic" != $'\x55\xAA' ]; then
|
||||
v "Invalid partition table on $disk"
|
||||
exit
|
||||
fi
|
||||
|
||||
rm -f "/tmp/partmap.$filename"
|
||||
|
||||
local part
|
||||
for part in 1 2 3 4; do
|
||||
set -- $(hexdump -v -n 12 -s "$((0x1B2 + $part * 16))" -e '3/4 "0x%08X "' "$disk")
|
||||
|
||||
local type="$(( $(hex_le32_to_cpu $1) % 256))"
|
||||
local lba="$(( $(hex_le32_to_cpu $2) ))"
|
||||
local num="$(( $(hex_le32_to_cpu $3) ))"
|
||||
|
||||
[ $type -gt 0 ] || continue
|
||||
|
||||
printf "%2d %5d %7d\n" $part $lba $num >> "/tmp/partmap.$filename"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
indicate_upgrade() {
|
||||
. /etc/diag.sh
|
||||
set_state upgrade
|
||||
}
|
||||
|
||||
# Flash firmware to MTD partition
|
||||
#
|
||||
# $(1): path to image
|
||||
# $(2): (optional) pipe command to extract firmware, e.g. dd bs=n skip=m
|
||||
default_do_upgrade() {
|
||||
sync
|
||||
if [ -n "$UPGRADE_BACKUP" ]; then
|
||||
get_image "$1" "$2" | mtd $MTD_ARGS $MTD_CONFIG_ARGS -j "$UPGRADE_BACKUP" write - "${PART_NAME:-image}"
|
||||
else
|
||||
get_image "$1" "$2" | mtd $MTD_ARGS write - "${PART_NAME:-image}"
|
||||
fi
|
||||
[ $? -ne 0 ] && exit 1
|
||||
}
|
||||
25
package/base-files/files/lib/upgrade/do_stage2
Executable file
25
package/base-files/files/lib/upgrade/do_stage2
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
include /lib/upgrade
|
||||
|
||||
v "Performing system upgrade..."
|
||||
if type 'platform_do_upgrade' >/dev/null 2>/dev/null; then
|
||||
platform_do_upgrade "$IMAGE"
|
||||
else
|
||||
default_do_upgrade "$IMAGE"
|
||||
fi
|
||||
|
||||
if [ -n "$UPGRADE_BACKUP" ] && type 'platform_copy_config' >/dev/null 2>/dev/null; then
|
||||
platform_copy_config
|
||||
fi
|
||||
|
||||
v "Upgrade completed"
|
||||
sleep 1
|
||||
|
||||
v "Rebooting system..."
|
||||
umount -a
|
||||
reboot -f
|
||||
sleep 5
|
||||
echo b 2>/dev/null >/proc/sysrq-trigger
|
||||
65
package/base-files/files/lib/upgrade/fwtool.sh
Normal file
65
package/base-files/files/lib/upgrade/fwtool.sh
Normal file
@@ -0,0 +1,65 @@
|
||||
fwtool_check_signature() {
|
||||
[ $# -gt 1 ] && return 1
|
||||
|
||||
[ ! -x /usr/bin/ucert ] && {
|
||||
if [ "$REQUIRE_IMAGE_SIGNATURE" = 1 ]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
if ! fwtool -q -s /tmp/sysupgrade.ucert "$1"; then
|
||||
echo "Image signature not found"
|
||||
[ "$REQUIRE_IMAGE_SIGNATURE" = 1 -a "$FORCE" != 1 ] && {
|
||||
echo "Use sysupgrade -F to override this check when downgrading or flashing to vendor firmware"
|
||||
}
|
||||
[ "$REQUIRE_IMAGE_SIGNATURE" = 1 ] && return 1
|
||||
return 0
|
||||
fi
|
||||
|
||||
fwtool -q -T -s /dev/null "$1" | \
|
||||
ucert -V -m - -c "/tmp/sysupgrade.ucert" -P /etc/opkg/keys
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
fwtool_check_image() {
|
||||
[ $# -gt 1 ] && return 1
|
||||
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
if ! fwtool -q -i /tmp/sysupgrade.meta "$1"; then
|
||||
echo "Image metadata not found"
|
||||
[ "$REQUIRE_IMAGE_METADATA" = 1 -a "$FORCE" != 1 ] && {
|
||||
echo "Use sysupgrade -F to override this check when downgrading or flashing to vendor firmware"
|
||||
}
|
||||
[ "$REQUIRE_IMAGE_METADATA" = 1 ] && return 1
|
||||
return 0
|
||||
fi
|
||||
|
||||
json_load "$(cat /tmp/sysupgrade.meta)" || {
|
||||
echo "Invalid image metadata"
|
||||
return 1
|
||||
}
|
||||
|
||||
device="$(cat /tmp/sysinfo/board_name)"
|
||||
|
||||
json_select supported_devices || return 1
|
||||
|
||||
json_get_keys dev_keys
|
||||
for k in $dev_keys; do
|
||||
json_get_var dev "$k"
|
||||
[ "$dev" = "$device" ] && return 0
|
||||
done
|
||||
|
||||
echo "Device $device not supported by this image"
|
||||
echo -n "Supported devices:"
|
||||
for k in $dev_keys; do
|
||||
json_get_var dev "$k"
|
||||
echo -n " $dev"
|
||||
done
|
||||
echo
|
||||
|
||||
return 1
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# Essential files that will be always kept
|
||||
/etc/hosts
|
||||
/etc/inittab
|
||||
/etc/group
|
||||
/etc/passwd
|
||||
/etc/profile
|
||||
/etc/shadow
|
||||
/etc/shells
|
||||
/etc/sysctl.conf
|
||||
/etc/rc.local
|
||||
323
package/base-files/files/lib/upgrade/nand.sh
Normal file
323
package/base-files/files/lib/upgrade/nand.sh
Normal file
@@ -0,0 +1,323 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2014 OpenWrt.org
|
||||
#
|
||||
|
||||
. /lib/functions.sh
|
||||
|
||||
# 'kernel' partition on NAND contains the kernel
|
||||
CI_KERNPART="${CI_KERNPART:-kernel}"
|
||||
|
||||
# 'ubi' partition on NAND contains UBI
|
||||
CI_UBIPART="${CI_UBIPART:-ubi}"
|
||||
|
||||
# 'rootfs' partition on NAND contains the rootfs
|
||||
CI_ROOTPART="${CI_ROOTPART:-rootfs}"
|
||||
|
||||
ubi_mknod() {
|
||||
local dir="$1"
|
||||
local dev="/dev/$(basename $dir)"
|
||||
|
||||
[ -e "$dev" ] && return 0
|
||||
|
||||
local devid="$(cat $dir/dev)"
|
||||
local major="${devid%%:*}"
|
||||
local minor="${devid##*:}"
|
||||
mknod "$dev" c $major $minor
|
||||
}
|
||||
|
||||
nand_find_volume() {
|
||||
local ubidevdir ubivoldir
|
||||
ubidevdir="/sys/devices/virtual/ubi/$1"
|
||||
[ ! -d "$ubidevdir" ] && return 1
|
||||
for ubivoldir in $ubidevdir/${1}_*; do
|
||||
[ ! -d "$ubivoldir" ] && continue
|
||||
if [ "$( cat $ubivoldir/name )" = "$2" ]; then
|
||||
basename $ubivoldir
|
||||
ubi_mknod "$ubivoldir"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
nand_find_ubi() {
|
||||
local ubidevdir ubidev mtdnum
|
||||
mtdnum="$( find_mtd_index $1 )"
|
||||
[ ! "$mtdnum" ] && return 1
|
||||
for ubidevdir in /sys/devices/virtual/ubi/ubi*; do
|
||||
[ ! -d "$ubidevdir" ] && continue
|
||||
cmtdnum="$( cat $ubidevdir/mtd_num )"
|
||||
[ ! "$mtdnum" ] && continue
|
||||
if [ "$mtdnum" = "$cmtdnum" ]; then
|
||||
ubidev=$( basename $ubidevdir )
|
||||
ubi_mknod "$ubidevdir"
|
||||
echo $ubidev
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
nand_get_magic_long() {
|
||||
dd if="$1" skip=$2 bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"'
|
||||
}
|
||||
|
||||
get_magic_long_tar() {
|
||||
( tar xf $1 $2 -O | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null
|
||||
}
|
||||
|
||||
identify_magic() {
|
||||
local magic=$1
|
||||
case "$magic" in
|
||||
"55424923")
|
||||
echo "ubi"
|
||||
;;
|
||||
"31181006")
|
||||
echo "ubifs"
|
||||
;;
|
||||
"68737173")
|
||||
echo "squashfs"
|
||||
;;
|
||||
"d00dfeed")
|
||||
echo "fit"
|
||||
;;
|
||||
"4349"*)
|
||||
echo "combined"
|
||||
;;
|
||||
*)
|
||||
echo "unknown $magic"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
identify() {
|
||||
identify_magic $(nand_get_magic_long "$1" "${2:-0}")
|
||||
}
|
||||
|
||||
identify_tar() {
|
||||
identify_magic $(get_magic_long_tar "$1" "$2")
|
||||
}
|
||||
|
||||
nand_restore_config() {
|
||||
sync
|
||||
local ubidev=$( nand_find_ubi $CI_UBIPART )
|
||||
local ubivol="$( nand_find_volume $ubidev rootfs_data )"
|
||||
[ ! "$ubivol" ] &&
|
||||
ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )"
|
||||
mkdir /tmp/new_root
|
||||
if ! mount -t ubifs /dev/$ubivol /tmp/new_root; then
|
||||
echo "mounting ubifs $ubivol failed"
|
||||
rmdir /tmp/new_root
|
||||
return 1
|
||||
fi
|
||||
mv "$1" "/tmp/new_root/$BACKUP_FILE"
|
||||
umount /tmp/new_root
|
||||
sync
|
||||
rmdir /tmp/new_root
|
||||
}
|
||||
|
||||
nand_upgrade_prepare_ubi() {
|
||||
local rootfs_length="$1"
|
||||
local rootfs_type="$2"
|
||||
local has_kernel="${3:-0}"
|
||||
local has_env="${4:-0}"
|
||||
|
||||
local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
|
||||
if [ ! "$mtdnum" ]; then
|
||||
echo "cannot find ubi mtd partition $CI_UBIPART"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
|
||||
if [ ! "$ubidev" ]; then
|
||||
ubiattach -m "$mtdnum"
|
||||
sync
|
||||
ubidev="$( nand_find_ubi "$CI_UBIPART" )"
|
||||
fi
|
||||
|
||||
if [ ! "$ubidev" ]; then
|
||||
ubiformat /dev/mtd$mtdnum -y
|
||||
ubiattach -m "$mtdnum"
|
||||
sync
|
||||
ubidev="$( nand_find_ubi "$CI_UBIPART" )"
|
||||
[ "$has_env" -gt 0 ] && {
|
||||
ubimkvol /dev/$ubidev -n 0 -N ubootenv -s 1MiB
|
||||
ubimkvol /dev/$ubidev -n 1 -N ubootenv2 -s 1MiB
|
||||
}
|
||||
fi
|
||||
|
||||
local kern_ubivol="$( nand_find_volume $ubidev $CI_KERNPART )"
|
||||
local root_ubivol="$( nand_find_volume $ubidev $CI_ROOTPART )"
|
||||
local data_ubivol="$( nand_find_volume $ubidev rootfs_data )"
|
||||
|
||||
# remove ubiblock device of rootfs
|
||||
local root_ubiblk="ubiblock${root_ubivol:3}"
|
||||
if [ "$root_ubivol" -a -e "/dev/$root_ubiblk" ]; then
|
||||
echo "removing $root_ubiblk"
|
||||
if ! ubiblock -r /dev/$root_ubivol; then
|
||||
echo "cannot remove $root_ubiblk"
|
||||
return 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
# kill volumes
|
||||
[ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_KERNPART || true
|
||||
[ "$root_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_ROOTPART || true
|
||||
[ "$data_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs_data || true
|
||||
|
||||
# update kernel
|
||||
if [ "$has_kernel" = "1" ]; then
|
||||
if ! ubimkvol /dev/$ubidev -N $CI_KERNPART -s $kernel_length; then
|
||||
echo "cannot create kernel volume"
|
||||
return 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
# update rootfs
|
||||
local root_size_param
|
||||
if [ "$rootfs_type" = "ubifs" ]; then
|
||||
root_size_param="-m"
|
||||
else
|
||||
root_size_param="-s $rootfs_length"
|
||||
fi
|
||||
if ! ubimkvol /dev/$ubidev -N $CI_ROOTPART $root_size_param; then
|
||||
echo "cannot create rootfs volume"
|
||||
return 1;
|
||||
fi
|
||||
|
||||
# create rootfs_data for non-ubifs rootfs
|
||||
if [ "$rootfs_type" != "ubifs" ]; then
|
||||
if ! ubimkvol /dev/$ubidev -N rootfs_data -m; then
|
||||
echo "cannot initialize rootfs_data volume"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
sync
|
||||
return 0
|
||||
}
|
||||
|
||||
nand_do_upgrade_success() {
|
||||
local conf_tar="/tmp/sysupgrade.tgz"
|
||||
|
||||
sync
|
||||
[ -f "$conf_tar" ] && nand_restore_config "$conf_tar"
|
||||
echo "sysupgrade successful"
|
||||
umount -a
|
||||
reboot -f
|
||||
}
|
||||
|
||||
# Flash the UBI image to MTD partition
|
||||
nand_upgrade_ubinized() {
|
||||
local ubi_file="$1"
|
||||
local mtdnum="$(find_mtd_index "$CI_UBIPART")"
|
||||
|
||||
[ ! "$mtdnum" ] && {
|
||||
CI_UBIPART="rootfs"
|
||||
mtdnum="$(find_mtd_index "$CI_UBIPART")"
|
||||
}
|
||||
|
||||
if [ ! "$mtdnum" ]; then
|
||||
echo "cannot find mtd device $CI_UBIPART"
|
||||
umount -a
|
||||
reboot -f
|
||||
fi
|
||||
|
||||
local mtddev="/dev/mtd${mtdnum}"
|
||||
ubidetach -p "${mtddev}" || true
|
||||
sync
|
||||
ubiformat "${mtddev}" -y -f "${ubi_file}"
|
||||
ubiattach -p "${mtddev}"
|
||||
nand_do_upgrade_success
|
||||
}
|
||||
|
||||
# Write the UBIFS image to UBI volume
|
||||
nand_upgrade_ubifs() {
|
||||
local rootfs_length=`(cat $1 | wc -c) 2> /dev/null`
|
||||
|
||||
nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "0" "0"
|
||||
|
||||
local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
|
||||
local root_ubivol="$(nand_find_volume $ubidev $CI_ROOTPART)"
|
||||
ubiupdatevol /dev/$root_ubivol -s $rootfs_length $1
|
||||
|
||||
nand_do_upgrade_success
|
||||
}
|
||||
|
||||
nand_upgrade_tar() {
|
||||
local tar_file="$1"
|
||||
local kernel_mtd="$(find_mtd_index $CI_KERNPART)"
|
||||
|
||||
local board_dir=$(tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$')
|
||||
board_dir=${board_dir%/}
|
||||
|
||||
local kernel_length=`(tar xf $tar_file ${board_dir}/kernel -O | wc -c) 2> /dev/null`
|
||||
local rootfs_length=`(tar xf $tar_file ${board_dir}/root -O | wc -c) 2> /dev/null`
|
||||
|
||||
local rootfs_type="$(identify_tar "$tar_file" ${board_dir}/root)"
|
||||
|
||||
local has_kernel=1
|
||||
local has_env=0
|
||||
|
||||
[ "$kernel_length" != 0 -a -n "$kernel_mtd" ] && {
|
||||
tar xf $tar_file ${board_dir}/kernel -O | mtd write - $CI_KERNPART
|
||||
}
|
||||
[ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel=0
|
||||
|
||||
nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "$has_kernel" "$has_env"
|
||||
|
||||
local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
|
||||
[ "$has_kernel" = "1" ] && {
|
||||
local kern_ubivol="$(nand_find_volume $ubidev $CI_KERNPART)"
|
||||
tar xf $tar_file ${board_dir}/kernel -O | \
|
||||
ubiupdatevol /dev/$kern_ubivol -s $kernel_length -
|
||||
}
|
||||
|
||||
local root_ubivol="$(nand_find_volume $ubidev $CI_ROOTPART)"
|
||||
tar xf $tar_file ${board_dir}/root -O | \
|
||||
ubiupdatevol /dev/$root_ubivol -s $rootfs_length -
|
||||
|
||||
nand_do_upgrade_success
|
||||
}
|
||||
|
||||
# Recognize type of passed file and start the upgrade process
|
||||
nand_do_upgrade() {
|
||||
local file_type=$(identify $1)
|
||||
|
||||
if type 'platform_nand_pre_upgrade' >/dev/null 2>/dev/null; then
|
||||
platform_nand_pre_upgrade "$1"
|
||||
fi
|
||||
|
||||
[ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART="rootfs"
|
||||
|
||||
case "$file_type" in
|
||||
"ubi") nand_upgrade_ubinized $1;;
|
||||
"ubifs") nand_upgrade_ubifs $1;;
|
||||
*) nand_upgrade_tar $1;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Check if passed file is a valid one for NAND sysupgrade. Currently it accepts
|
||||
# 3 types of files:
|
||||
# 1) UBI - should contain an ubinized image, header is checked for the proper
|
||||
# MAGIC
|
||||
# 2) UBIFS - should contain UBIFS partition that will replace "rootfs" volume,
|
||||
# header is checked for the proper MAGIC
|
||||
# 3) TAR - archive has to include "sysupgrade-BOARD" directory with a non-empty
|
||||
# "CONTROL" file (at this point its content isn't verified)
|
||||
#
|
||||
# You usually want to call this function in platform_check_image.
|
||||
#
|
||||
# $(1): board name, used in case of passing TAR file
|
||||
# $(2): file to be checked
|
||||
nand_do_platform_check() {
|
||||
local board_name="$1"
|
||||
local tar_file="$2"
|
||||
local control_length=`(tar xf $tar_file sysupgrade-$board_name/CONTROL -O | wc -c) 2> /dev/null`
|
||||
local file_type="$(identify $2)"
|
||||
|
||||
[ "$control_length" = 0 -a "$file_type" != "ubi" -a "$file_type" != "ubifs" ] && {
|
||||
echo "Invalid sysupgrade file."
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
137
package/base-files/files/lib/upgrade/stage2
Executable file
137
package/base-files/files/lib/upgrade/stage2
Executable file
@@ -0,0 +1,137 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/system.sh
|
||||
|
||||
export IMAGE="$1"
|
||||
COMMAND="$2"
|
||||
|
||||
export INTERACTIVE=0
|
||||
export VERBOSE=1
|
||||
export CONFFILES=/tmp/sysupgrade.conffiles
|
||||
|
||||
RAMFS_COPY_BIN= # extra programs for temporary ramfs root
|
||||
RAMFS_COPY_DATA= # extra data files
|
||||
|
||||
include /lib/upgrade
|
||||
|
||||
|
||||
supivot() { # <new_root> <old_root>
|
||||
/bin/mount | grep "on $1 type" 2>&- 1>&- || /bin/mount -o bind $1 $1
|
||||
mkdir -p $1$2 $1/proc $1/sys $1/dev $1/tmp $1/overlay && \
|
||||
/bin/mount -o noatime,move /proc $1/proc && \
|
||||
pivot_root $1 $1$2 || {
|
||||
/bin/umount -l $1 $1
|
||||
return 1
|
||||
}
|
||||
|
||||
/bin/mount -o noatime,move $2/sys /sys
|
||||
/bin/mount -o noatime,move $2/dev /dev
|
||||
/bin/mount -o noatime,move $2/tmp /tmp
|
||||
/bin/mount -o noatime,move $2/overlay /overlay 2>&-
|
||||
return 0
|
||||
}
|
||||
|
||||
switch_to_ramfs() {
|
||||
for binary in \
|
||||
/bin/busybox /bin/ash /bin/sh /bin/mount /bin/umount \
|
||||
pivot_root mount_root reboot sync kill sleep \
|
||||
md5sum hexdump cat zcat bzcat dd tar \
|
||||
ls basename find cp mv rm mkdir rmdir mknod touch chmod \
|
||||
'[' printf wc grep awk sed cut \
|
||||
mtd partx losetup mkfs.ext4 \
|
||||
ubiupdatevol ubiattach ubiblock ubiformat \
|
||||
ubidetach ubirsvol ubirmvol ubimkvol \
|
||||
snapshot snapshot_tool \
|
||||
$RAMFS_COPY_BIN
|
||||
do
|
||||
local file="$(which "$binary" 2>/dev/null)"
|
||||
[ -n "$file" ] && install_bin "$file"
|
||||
done
|
||||
install_file /etc/resolv.conf /lib/*.sh /lib/functions/*.sh /lib/upgrade/*.sh /lib/upgrade/do_stage2 /usr/share/libubox/jshn.sh $RAMFS_COPY_DATA
|
||||
|
||||
[ -L "/lib64" ] && ln -s /lib $RAM_ROOT/lib64
|
||||
|
||||
supivot $RAM_ROOT /mnt || {
|
||||
echo "Failed to switch over to ramfs. Please reboot."
|
||||
exit 1
|
||||
}
|
||||
|
||||
/bin/mount -o remount,ro /mnt
|
||||
/bin/umount -l /mnt
|
||||
|
||||
grep /overlay /proc/mounts > /dev/null && {
|
||||
/bin/mount -o noatime,remount,ro /overlay
|
||||
/bin/umount -l /overlay
|
||||
}
|
||||
}
|
||||
|
||||
kill_remaining() { # [ <signal> [ <loop> ] ]
|
||||
local loop_limit=10
|
||||
|
||||
local sig="${1:-TERM}"
|
||||
local loop="${2:-0}"
|
||||
local run=true
|
||||
local stat
|
||||
local proc_ppid=$(cut -d' ' -f4 /proc/$$/stat)
|
||||
|
||||
echo -n "Sending $sig to remaining processes ... "
|
||||
|
||||
while $run; do
|
||||
run=false
|
||||
for stat in /proc/[0-9]*/stat; do
|
||||
[ -f "$stat" ] || continue
|
||||
|
||||
local pid name state ppid rest
|
||||
read pid name state ppid rest < $stat
|
||||
name="${name#(}"; name="${name%)}"
|
||||
|
||||
# Skip PID1, our parent, ourself and our children
|
||||
[ $pid -ne 1 -a $pid -ne $proc_ppid -a $pid -ne $$ -a $ppid -ne $$ ] || continue
|
||||
|
||||
local cmdline
|
||||
read cmdline < /proc/$pid/cmdline
|
||||
|
||||
# Skip kernel threads
|
||||
[ -n "$cmdline" ] || continue
|
||||
|
||||
echo -n "$name "
|
||||
kill -$sig $pid 2>/dev/null
|
||||
|
||||
[ $loop -eq 1 ] && run=true
|
||||
done
|
||||
|
||||
let loop_limit--
|
||||
[ $loop_limit -eq 0 ] && {
|
||||
echo
|
||||
echo "Failed to kill all processes."
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
echo
|
||||
}
|
||||
|
||||
indicate_upgrade
|
||||
|
||||
killall -9 telnetd
|
||||
killall -9 dropbear
|
||||
killall -9 ash
|
||||
|
||||
kill_remaining TERM
|
||||
sleep 3
|
||||
kill_remaining KILL 1
|
||||
|
||||
sleep 1
|
||||
|
||||
|
||||
if [ -n "$IMAGE" ] && type 'platform_pre_upgrade' >/dev/null 2>/dev/null; then
|
||||
platform_pre_upgrade "$IMAGE"
|
||||
fi
|
||||
|
||||
if [ -n "$(rootfs_type)" ]; then
|
||||
echo "Switching to ramdisk..."
|
||||
switch_to_ramfs
|
||||
fi
|
||||
|
||||
# Exec new shell from ramfs
|
||||
exec /bin/busybox ash -c "$COMMAND"
|
||||
Reference in New Issue
Block a user