. /lib/functions.sh
-# combined-image uses 64k blocks
-CI_BLKSZ=65536
-# 'data' partition on NAND contains UBI
+# 'kernel' partition on NAND contains the kernel
+CI_KERNPART="kernel"
+
+# 'ubi' partition on NAND contains UBI
CI_UBIPART="ubi"
+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 "$ubivoldir" ] && continue
if [ "$( cat $ubivoldir/name )" = "$2" ]; then
basename $ubivoldir
+ ubi_mknod "$ubivoldir"
return 0
fi
done
[ ! "$mtdnum" ] && continue
if [ "$mtdnum" = "$cmtdnum" ]; then
ubidev=$( basename $ubidevdir )
+ ubi_mknod "$ubidevdir"
echo $ubidev
return 0
fi
done
}
-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 rootfs )"
- 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/sysupgrade.tgz"
- umount /tmp/new_root
- sync
- rmdir /tmp/new_root
-}
-
-nand_upgrade_ubinized() {
- local upgrade_image="$1"
- local conf_tar="$2"
- local save_config="$3"
- local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
- if [ ! "$mtdnum" ]; then
- echo "cannot find mtd device $CI_UBIPART"
- return 1;
- fi
- local mtddev="/dev/mtd${mtdnum}"
- ubidetach -p "${mtddev}" || true
- sync
- ubiformat "${mtddev}" -y -f "$upgrade_image"
- ubiattach -p "${mtddev}"
- sync
- if [ -f "$conf_tar" -a "$save_config" -eq 1 ]; then
- nand_restore_config "$conf_tar"
- fi
- return 0;
+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 the first 4 bytes (magic) of a given file starting at offset in hex format
-get_magic_long_at() {
- dd if="$2" skip=$1 bs=$CI_BLKSZ 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() {
- local block;
- local magic=$( get_magic_long_at ${2:-0} "$1" )
+identify_magic() {
+ local magic=$1
case "$magic" in
"55424923")
echo "ubi"
esac
}
-nand_upgrade_combined_ubi() {
- local kernel_image="$1"
- local kernel_length=0
- local rootfs_image="$2"
- local rootfs_length=`ls -la $rootfs_image | awk '{ print $5}')`
- local conf_tar="$3"
+
+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 rootfs )"
+ 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/sysupgrade.tgz"
+ 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 root_fs="$( identify "$rootfs_image" )"
local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
- local has_kernel=0
-
- [ -z "$kernel_image" ] || {
- has_kernel=1
- kernel_length=`ls -la $kernel_image | awk '{ print $5}')`
- echo "kernel length $kernel_length"
- }
- [ "$has_kernel" = 0 ] || echo "kernel is inside ubi"
- echo "rootfs type $root_fs, length $rootfs_length"
-
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" )"
- [ -z "$has_env" ] || {
+ [ "$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 kernel )"
local root_ubivol="$( nand_find_volume $ubidev rootfs )"
local data_ubivol="$( nand_find_volume $ubidev rootfs_data )"
fi
# kill volumes
- if [ "$kern_ubivol" ]; then
- ubirmvol /dev/$ubidev -N kernel || true
- fi
- if [ "$root_ubivol" ]; then
- ubirmvol /dev/$ubidev -N rootfs || true
- fi
- if [ "$data_ubivol" ]; then
- ubirmvol /dev/$ubidev -N rootfs_data || true
- fi
+ [ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N kernel || true
+ [ "$root_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs || true
+ [ "$data_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs_data || true
# update kernel
if [ "$has_kernel" = "1" ]; then
# update rootfs
local root_size_param
- if [ "$root_fs" = "ubifs" ]; then
+ if [ "$rootfs_type" = "ubifs" ]; then
root_size_param="-m"
else
root_size_param="-s $rootfs_length"
fi
# create rootfs_data for non-ubifs rootfs
- if [ "$root_fs" != "ubifs" ]; then
+ 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
+}
- if [ "$has_kernel" = "1" ]; then
- local kern_ubivol="$( nand_find_volume $ubidev kernel )"
- ubiupdatevol /dev/$kern_ubivol -s $kernel_length $kernel_image
- fi
+nand_do_upgrade_success() {
+ local conf_tar="/tmp/sysupgrade.tgz"
+
+ sync
+ [ -f "$conf_tar" ] && nand_restore_config "$conf_tar"
+ echo "sysupgrade successful"
+ reboot -f
+}
- local root_ubivol="$( nand_find_volume $ubidev rootfs )"
- ubiupdatevol /dev/$root_ubivol -s $rootfs_length $rootfs_image
- if [ -f "$conf_tar" ]; then
- nand_restore_config "$conf_tar"
+# 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"
+ reboot -f
fi
- echo "sysupgrade successfull"
- return 0
+
+ local mtddev="/dev/mtd${mtdnum}"
+ ubidetach -p "${mtddev}" || true
+ sync
+ ubiformat "${mtddev}" -y -f "${ubi_file}"
+ ubiattach -p "${mtddev}"
+ nand_do_upgrade_success
}
-nand_do_upgrade_stage1() {
- local board_name="$1"
- local tar_file="$2"
- local kernel_file=""
- local kernel_file=""
+# Write the UBIFS image to UBI volume
+nand_upgrade_ubifs() {
+ local rootfs_length=`(cat $1 | wc -c) 2> /dev/null`
- tar xzf $tar_file -C /tmp/
- [ -f "/tmp/sysupgrade-$board_name/CONTROL" ] || {
- echo "failed to find /tmp/sysupgrade-$board_name/CONTROL"
- return 1
- }
+ nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "0" "0"
+
+ local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
+ local root_ubivol="$(nand_find_volume $ubidev rootfs)"
+ ubiupdatevol /dev/$root_ubivol -s $rootfs_length $1
- kernel_file=/tmp/sysupgrade-$board_name/kernel
- [ -f "$kernel_file" ] || {
- echo "$kernel_file is missing"
- return 1
+ nand_do_upgrade_success
+}
+
+nand_upgrade_tar() {
+ local tar_file="$1"
+ local board_name="$(cat /tmp/sysinfo/board_name)"
+ local kernel_mtd="$(find_mtd_index $CI_KERNPART)"
+
+ local kernel_length=`(tar xf $tar_file sysupgrade-$board_name/kernel -O | wc -c) 2> /dev/null`
+ local rootfs_length=`(tar xf $tar_file sysupgrade-$board_name/root -O | wc -c) 2> /dev/null`
+
+ local rootfs_type="$(identify_tar "$tar_file" sysupgrade-$board_name/root)"
+
+ local has_kernel=1
+ local has_env=0
+
+ [ "$kernel_length" != 0 -a -n "$kernel_mtd" ] && {
+ tar xf $tar_file sysupgrade-$board_name/kernel -O | mtd write - $CI_KERNPART
}
+ [ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel=0
- rootfs_file=/tmp/sysupgrade-$board_name/root
- [ -f "$rootfs_file" ] || {
- echo "$rootfs_file is missing"
- return 1
+ 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 kernel)"
+ tar xf $tar_file sysupgrade-$board_name/kernel -O | \
+ ubiupdatevol /dev/$kern_ubivol -s $kernel_length -
}
-
- echo -n /tmp/sysupgrade-$board_name > /tmp/sysupgrade-nand-folder
- cp /sbin/upgraded /tmp/
- return 0
+ local root_ubivol="$(nand_find_volume $ubidev rootfs)"
+ tar xf $tar_file sysupgrade-$board_name/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_stage2() {
- rootfs_file=$1/root
- kernel_file=$1/kernel
- config_file=$1/config
-
- [ -f $config_file ] || config_file=""
+ local file_type=$(identify $1)
- . $1/CONTROL
+ [ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART="rootfs"
- [ "$UBI_KERNEL" = "1" ] || {
- mtd write $kernel_file kernel
- kernel_file=""
- }
- nand_upgrade_combined_ubi "$kernel_file" "$rootfs_file" "$conf_tar" "$UBI_ENV"
- reboot -f
+ case "$file_type" in
+ "ubi") nand_upgrade_ubinized $1;;
+ "ubifs") nand_upgrade_ubifs $1;;
+ *) nand_upgrade_tar $1;;
+ esac
}
-nand_do_upgrade() {
+nand_upgrade_stage2() {
[ $1 = "nand" ] && {
- [ -d "$2" ] && {
+ [ -f "$2" ] && {
touch /tmp/sysupgrade
killall -9 telnetd
}
nand_upgrade_stage1() {
- [ -f /tmp/sysupgrade-nand-folder ] && {
- folder="$(cat /tmp/sysupgrade-nand-folder)"
- [ "$SAVE_CONFIG" = 1 -a -f "$CONF_TAR" ] &&
- cp $CONF_TAR $folder/config
+ [ -f /tmp/sysupgrade-nand-path ] && {
+ path="$(cat /tmp/sysupgrade-nand-path)"
+ [ "$SAVE_CONFIG" != 1 -a -f "$CONF_TAR" ] &&
+ rm $CONF_TAR
- ubus call system nandupgrade "{\"folder\": \"$folder\" }"
+ ubus call system nandupgrade "{\"path\": \"$path\" }"
exit 0
}
}
append sysupgrade_pre_upgrade nand_upgrade_stage1
+
+# 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
+}
+
+# Start NAND upgrade process
+#
+# $(1): file to be used for upgrade
+nand_do_upgrade() {
+ echo -n $1 > /tmp/sysupgrade-nand-path
+ cp /sbin/upgraded /tmp/
+ nand_upgrade_stage1
+}