openwrtv4/package/system/procd/files/nand.sh

304 lines
6.7 KiB
Bash
Raw Normal View History

#!/bin/sh
# Copyright (C) 2014 OpenWrt.org
#
. /lib/functions.sh
# combined-image uses 64k blocks
CI_BLKSZ=65536
# 'data' partition on NAND contains UBI
CI_UBIPART="ubi"
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
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 )
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;
}
# 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"'
}
identify() {
local block;
local magic=$( get_magic_long_at ${2:-0} "$1" )
case "$magic" in
"55424923")
echo "ubi"
;;
"31181006")
echo "ubifs"
;;
"68737173")
echo "squashfs"
;;
"d00dfeed")
echo "fit"
;;
"4349"*)
echo "combined"
;;
*)
echo "unknown $magic"
;;
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"
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" ] || {
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 )"
# 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
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
# update kernel
if [ "$has_kernel" = "1" ]; then
if ! ubimkvol /dev/$ubidev -N kernel -s $kernel_length; then
echo "cannot create kernel volume"
return 1;
fi
fi
# update rootfs
local root_size_param
if [ "$root_fs" = "ubifs" ]; then
root_size_param="-m"
else
root_size_param="-s $rootfs_length"
fi
if ! ubimkvol /dev/$ubidev -N rootfs $root_size_param; then
echo "cannot create rootfs volume"
return 1;
fi
# create rootfs_data for non-ubifs rootfs
if [ "$root_fs" != "ubifs" ]; then
if ! ubimkvol /dev/$ubidev -N rootfs_data -m; then
echo "cannot initialize rootfs_data volume"
return 1
fi
fi
sync
if [ "$has_kernel" = "1" ]; then
local kern_ubivol="$( nand_find_volume $ubidev kernel )"
ubiupdatevol /dev/$kern_ubivol -s $kernel_length $kernel_image
fi
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"
fi
echo "sysupgrade successfull"
return 0
}
nand_do_upgrade_stage1() {
local board_name="$1"
local tar_file="$2"
local kernel_file=""
local kernel_file=""
tar xzf $tar_file -C /tmp/
[ -f "/tmp/sysupgrade-$board_name/CONTROL" ] || {
echo "failed to find /tmp/sysupgrade-$board_name/CONTROL"
return 1
}
kernel_file=/tmp/sysupgrade-$board_name/kernel
[ -f "$kernel_file" ] || {
echo "$kernel_file is missing"
return 1
}
rootfs_file=/tmp/sysupgrade-$board_name/root
[ -f "$rootfs_file" ] || {
echo "$rootfs_file is missing"
return 1
}
echo -n /tmp/sysupgrade-$board_name > /tmp/sysupgrade-nand-folder
cp /sbin/upgraded /tmp/
return 0
}
nand_do_upgrade_stage2() {
rootfs_file=$1/root
kernel_file=$1/kernel
config_file=$1/config
[ -f $config_file ] || config_file=""
. $1/CONTROL
[ "$UBI_KERNEL" = "1" ] || {
mtd write $kernel_file kernel
kernel_file=""
}
nand_upgrade_combined_ubi "$kernel_file" "$rootfs_file" "$conf_tar" "$UBI_ENV"
reboot -f
}
nand_do_upgrade() {
[ $1 = "nand" ] && {
[ -d "$2" ] && {
touch /tmp/sysupgrade
killall -9 telnetd
killall -9 dropbear
killall -9 ash
kill_remaining TERM
sleep 3
kill_remaining KILL
sleep 1
if [ -n "$(rootfs_type)" ]; then
v "Switching to ramdisk..."
run_ramfs ". /lib/functions.sh; include /lib/upgrade; nand_do_upgrade_stage2 $2"
else
nand_do_upgrade_stage2 $2
fi
return 0
}
echo "Nand upgrade failed"
exit 1
}
}
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
ubus call system nandupgrade "{\"folder\": \"$folder\" }"
exit 0
}
}
append sysupgrade_pre_upgrade nand_upgrade_stage1