openwrt/package/base-files/files/lib/upgrade/nand.sh
Christian Lamparter 7783f31359 base-files: nand: use CI_KERNPART whenever the kernel volume is needed
The sender domain has a DMARC Reject/Quarantine policy which disallows
sending mailing list messages using the original "From" header.

To mitigate this problem, the original message has been wrapped
automatically by the mailing list software.
This patch is in continuation of: commit 93aa860405
"procd: nand: make it possible to configure kernel and ubi partition"

The $CI_KERNPART variable should be used in place
of the fixed "kernel" partition name. This allows
targets to specifiy alternate names for the kernel
partition.

Cc: Chris Blake <chrisrblake93@gmail.com>
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
2017-05-31 09:55:01 +02:00

337 lines
8.2 KiB
Bash

#!/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}"
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 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 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 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
[ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N $CI_KERNPART || 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
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 rootfs $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 rootfs)"
ubiupdatevol /dev/$root_ubivol -s $rootfs_length $1
nand_do_upgrade_success
}
nand_board_name() {
if type 'platform_nand_board_name' >/dev/null 2>/dev/null; then
platform_nand_board_name
return
fi
cat /tmp/sysinfo/board_name
}
nand_upgrade_tar() {
local tar_file="$1"
local board_name="$(nand_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
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 sysupgrade-$board_name/kernel -O | \
ubiupdatevol /dev/$kern_ubivol -s $kernel_length -
}
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() {
if [ -n "$IS_PRE_UPGRADE" ]; then
# Previously, nand_do_upgrade was called from the platform_pre_upgrade
# hook; this piece of code handles scripts that haven't been
# updated. All scripts should gradually move to call nand_do_upgrade
# from platform_do_upgrade instead.
export do_upgrade=nand_do_upgrade
return
fi
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
}