|
|
@@ -1,31 +1,129 @@
|
|
|
. /lib/functions.sh
|
|
|
|
|
|
-fortinet_fwinfo_blocks() {
|
|
|
+fortinet_bswap32() {
|
|
|
+ local val="$(printf %08x $(($1)))"
|
|
|
+
|
|
|
+ # swap and print in hex
|
|
|
+ echo "0x${val:6:2}${val:4:2}${val:2:2}${val:0:2}"
|
|
|
+}
|
|
|
+
|
|
|
+fortinet_by2bl() {
|
|
|
+ local blks="$(($1 / 0x200))"
|
|
|
+ [ $(($1 % 0x200)) -gt 0 ] && blks=$((blks + 1))
|
|
|
+
|
|
|
+ printf "0x%08x" $blks
|
|
|
+}
|
|
|
+
|
|
|
+fortinet_bl2by() {
|
|
|
+ printf "0x%08x" $(($1 * 0x200))
|
|
|
+}
|
|
|
+
|
|
|
+fortinet_build_partmap() {
|
|
|
+ local new="$1" old="$2"
|
|
|
+ local len="${old%%@*}" ofs="${old##*@}"
|
|
|
+
|
|
|
+ case "$new" in
|
|
|
+ @*) ofs="$(fortinet_by2bl ${new##@})" ;; # "@<offset>"
|
|
|
+
|
|
|
+ *@*) len="$(fortinet_by2bl ${new%%@*})" # "<length>@<offset>"
|
|
|
+ ofs="$(fortinet_by2bl ${new##*@})" ;;
|
|
|
+
|
|
|
+ "") ;; # "" (empty)
|
|
|
+
|
|
|
+ *) len="$(fortinet_by2bl ${new%%@*})" ;; # "<length>"
|
|
|
+ esac
|
|
|
+
|
|
|
+ # print N blocks of length/offset in dec
|
|
|
+ echo "${len}@${ofs}"
|
|
|
+}
|
|
|
+
|
|
|
+# Update firmware information in "firmware-info" partition
|
|
|
+#
|
|
|
+# parameters:
|
|
|
+# $1: image index (0/1)
|
|
|
+# $2: new image name (up to 32 characters)
|
|
|
+# $3: length and/or offset for kernel (bytes)
|
|
|
+# $4: length and/or offset for rootfs (bytes)
|
|
|
+#
|
|
|
+# Note: $3 and $4 support multiple formats:
|
|
|
+#
|
|
|
+# - <length>@<offset>: set <length> and <rootfs>
|
|
|
+# - <length> : set <length> and keep the current offset
|
|
|
+# - @<offset> : set <offset> and keep the current length
|
|
|
+# - "" (empty) : keep the current length and offset
|
|
|
+fortinet_update_fwinfo() {
|
|
|
local fwinfo_mtd="$(find_mtd_part firmware-info)"
|
|
|
- local offset="$1"
|
|
|
- local len="$2"
|
|
|
- local blks
|
|
|
+ local index="$1"
|
|
|
+ local name="$2"
|
|
|
+ local offset
|
|
|
+ local old_kr
|
|
|
+ local old new tmp part pos
|
|
|
+ local output
|
|
|
|
|
|
if [ -z "$fwinfo_mtd" ]; then
|
|
|
- echo "WARN: MTD device \"firmware-info\" not found"
|
|
|
+ echo "ERROR: MTD device \"firmware-info\" not found"
|
|
|
return 1
|
|
|
fi
|
|
|
|
|
|
- blks=$((len / 0x200))
|
|
|
- [ $((len % 0x200)) -gt 0 ] && blks=$((blks + 1))
|
|
|
- blks=$(printf "%04x" $blks)
|
|
|
- printf "fwinfo: offset-> 0x%x, blocks-> 0x%s (len: 0x%08x)\n" \
|
|
|
- $offset $blks $len
|
|
|
+ # Image Name
|
|
|
+ case "$index" in
|
|
|
+ 0) offset=0x10 ;;
|
|
|
+ 1) offset=0x30 ;;
|
|
|
+ *) echo "ERROR: invalid image index specified!"; return 1 ;;
|
|
|
+ esac
|
|
|
+
|
|
|
+ printf "Image Index: %d\n" $index
|
|
|
+
|
|
|
+ old="$(dd bs=16 count=2 skip=$((offset / 16)) if=$fwinfo_mtd 2>/dev/null)"
|
|
|
+ printf "Image Name : \"%s\"\n" "$old"
|
|
|
+ if [ -n "$name" ]; then
|
|
|
+ echo -n "$name" | \
|
|
|
+ dd bs=32 count=1 oflag=seek_bytes seek=$((offset)) \
|
|
|
+ conv=sync,notrunc of=$fwinfo_mtd 2>/dev/null
|
|
|
+ printf " --> \"%s\"\n\n" "$name"
|
|
|
+ else
|
|
|
+ printf "\n"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # length/offset values of kernel/rootfs
|
|
|
+ case "$index" in
|
|
|
+ 0) offset=0x180 ;;
|
|
|
+ 1) offset=0x190 ;;
|
|
|
+ esac
|
|
|
+
|
|
|
+ # <kernel offset:4><kernel length:4><rootfs offset:4><rootfs length:4>
|
|
|
+ old_kr="$(hexdump -n 16 -v -s $((offset)) -e '1/4 "%08x"' $fwinfo_mtd)"
|
|
|
+
|
|
|
+ pos=0
|
|
|
+ for part in kernel rootfs; do
|
|
|
+ old="0x${old_kr:$((8 + pos)):8}@0x${old_kr:$((0 + pos)):8}"
|
|
|
+ new="$(fortinet_build_partmap "$3" "$old")"
|
|
|
+ shift
|
|
|
+
|
|
|
+ printf " %s:\n" $part
|
|
|
+ printf " old: 0x%08x@0x%08x\n" \
|
|
|
+ $(fortinet_bl2by ${old%%@*}) $(fortinet_bl2by ${old##*@})
|
|
|
+ printf " new: 0x%08x@0x%08x\n\n" \
|
|
|
+ $(fortinet_bl2by ${new%%@*}) $(fortinet_bl2by ${new##*@})
|
|
|
|
|
|
- printf "\x${blks:2:2}\x${blks:0:2}" | \
|
|
|
- dd bs=2 count=1 seek=$((offset / 2)) conv=notrunc of=${fwinfo_mtd}
|
|
|
+ tmp="$(fortinet_bswap32 ${new%%@*})@$(fortinet_bswap32 ${new##*@})"
|
|
|
+ new="$(echo $tmp | sed 's/0x\([0-9a-f]\{8\}\)@0x\([0-9a-f]\{8\}\)/\2\1/')"
|
|
|
+ output="${output}${new}"
|
|
|
+
|
|
|
+ pos=$((pos + 16))
|
|
|
+ done
|
|
|
+
|
|
|
+ data_2bin "$output" | \
|
|
|
+ dd bs=16 count=1 seek=$((offset / 16)) conv=notrunc \
|
|
|
+ of=$fwinfo_mtd 2>/dev/null
|
|
|
}
|
|
|
|
|
|
fortinet_do_upgrade() {
|
|
|
local board_dir="$(tar tf "$1" | grep -m 1 '^sysupgrade-.*/$')"
|
|
|
local kern_mtd="$(find_mtd_part kernel)"
|
|
|
local root_mtd="$(find_mtd_part rootfs)"
|
|
|
- local kern_len root_len
|
|
|
+ local kern_len kern_ofs root_len root_ofs
|
|
|
+ local imgname
|
|
|
|
|
|
board_dir="${board_dir%/}"
|
|
|
|
|
|
@@ -34,6 +132,14 @@ fortinet_do_upgrade() {
|
|
|
umount -a
|
|
|
reboot -f
|
|
|
fi
|
|
|
+ kern_ofs=$(cat /sys/class/mtd/${kern_mtd//\/dev\/mtdblock/mtd}/offset)
|
|
|
+ root_ofs=$(cat /sys/class/mtd/${root_mtd//\/dev\/mtdblock/mtd}/offset)
|
|
|
+
|
|
|
+ if [ -z "$kern_ofs" ] || [ -z "$root_ofs" ]; then
|
|
|
+ echo "ERROR: failed to get offset of kernel or rootfs"
|
|
|
+ umount -a
|
|
|
+ reboot -f
|
|
|
+ fi
|
|
|
|
|
|
kern_len=$( (tar xOf "$1" "$board_dir/kernel" | wc -c) 2> /dev/null)
|
|
|
root_len=$( (tar xOf "$1" "$board_dir/root" | wc -c) 2> /dev/null)
|
|
|
@@ -44,8 +150,34 @@ fortinet_do_upgrade() {
|
|
|
reboot -f
|
|
|
fi
|
|
|
|
|
|
- fortinet_fwinfo_blocks "0x184" "$kern_len"
|
|
|
- fortinet_fwinfo_blocks "0x18c" "$root_len"
|
|
|
+ # try to load and parse /tmp/sysupgrade.meta for image name
|
|
|
+ if [ -r "/tmp/sysupgrade.meta" ]; then
|
|
|
+ local key value
|
|
|
+
|
|
|
+ sed -e 's/, \{1,2\}\"/\n"/g' \
|
|
|
+ -e 's/{ \{1,2\}/\n/g' \
|
|
|
+ -e 's/ \{1,2\}}/\n/g' < /tmp/sysupgrade.meta \
|
|
|
+ > /tmp/sysupgrade.meta.tmp
|
|
|
+ while read key value; do
|
|
|
+ key="${key//\"/}"
|
|
|
+ value="${value//\"/}"
|
|
|
+
|
|
|
+ [ -z "$value" ] && continue
|
|
|
+ case "$key" in
|
|
|
+ dist:|\
|
|
|
+ version:|\
|
|
|
+ revision:) imgname="${imgname}$value " ;;
|
|
|
+ esac
|
|
|
+ done < /tmp/sysupgrade.meta.tmp
|
|
|
+ else
|
|
|
+ imgname="OpenWrt"
|
|
|
+ fi
|
|
|
+
|
|
|
+ fortinet_update_fwinfo 0 "${imgname%% }" \
|
|
|
+ "${kern_len}@${kern_ofs}" "${root_len}@${root_ofs}" || {
|
|
|
+ umount -a
|
|
|
+ reboot -f
|
|
|
+ }
|
|
|
|
|
|
tar xOf "$1" "$board_dir/kernel" | \
|
|
|
mtd write - "kernel"
|