ar71xx: fix sysupgrade for jjPlus JWAP003
[openwrt.git] / target / linux / ar71xx / base-files / lib / upgrade / dir825.sh
1 #!/bin/sh
2 #
3 # Copyright (C) 2012 OpenWrt.org
4 #
5
6 . /lib/functions.sh
7 . /lib/ar71xx.sh
8
9 get_mtd_part_size() {
10         local part_name=$1
11         local first dev size erasesize name
12         while read dev size erasesize name; do
13                 name=${name#'"'}; name=${name%'"'}
14                 if [ "$name" = "$part_name" ]; then
15                         echo $((0x$size))
16                         break
17                 fi
18         done < /proc/mtd
19 }
20
21 get_magic_at() {
22         local mtddev=$1
23         local pos=$2
24         dd bs=1 count=2 skip=$pos if=$mtddev 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"'
25 }
26
27 dir825b_is_caldata_valid() {
28         local mtddev=$1
29         local magic
30
31         magic=$(get_magic_at $mtddev 4096)
32         [ "$magic" != "a55a" ] && return 0
33
34         magic=$(get_magic_at $mtddev 20480)
35         [ "$magic" != "a55a" ] && return 0
36
37         return 1
38 }
39
40 dir825b_copy_caldata() {
41         local cal_src=$1
42         local cal_dst=$2
43         local mtd_src
44         local mtd_dst
45         local md5_src
46         local md5_dst
47
48         mtd_src=$(find_mtd_part $cal_src)
49         [ -z "$mtd_src" ] && {
50                 echo "no $cal_src partition found"
51                 return 1
52         }
53
54         mtd_dst=$(find_mtd_part $cal_dst)
55         [ -z "$mtd_dst" ] && {
56                 echo "no $cal_dst partition found"
57                 return 1
58         }
59
60         dir825b_is_caldata_valid "$mtd_src" && {
61                 echo "no valid calibration data found in $cal_src"
62                 return 1
63         }
64
65         dir825b_is_caldata_valid "$mtd_dst" && {
66                 echo "Copying calibration data from $cal_src to $cal_dst..."
67                 dd if="$mtd_src" 2>/dev/null | mtd -q -q write - "$cal_dst"
68         }
69
70         md5_src=$(md5sum "$mtd_src") && md5_src="${md5_src%% *}"
71         md5_dst=$(md5sum "$mtd_dst") && md5_dst="${md5_dst%% *}"
72
73         [ "$md5_src" != "$md5_dst" ] && {
74                 echo "calibration data mismatch $cal_src:$md5_src $cal_dst:$md5_dst"
75                 return 1
76         }
77
78         return 0
79 }
80
81 dir825b_do_upgrade_combined() {
82         local fw_part=$1
83         local fw_file=$2
84         local fw_mtd=$(find_mtd_part $fw_part)
85         local fw_length=0x$(dd if="$fw_file" bs=2 skip=1 count=4 2>/dev/null)
86         local fw_blocks=$(($fw_length / 65536))
87
88         if [ -n "$fw_mtd" ] &&  [ ${fw_blocks:-0} -gt 0 ]; then
89                 local append=""
90                 [ -f "$CONF_TAR" -a "$SAVE_CONFIG" -eq 1 ] && append="-j $CONF_TAR"
91
92                 sync
93                 dd if="$fw_file" bs=64k skip=1 count=$fw_blocks 2>/dev/null | \
94                         mtd $append write - "$fw_part"
95         fi
96 }
97
98 dir825b_check_image() {
99         local magic="$(get_magic_long "$1")"
100         local fw_mtd=$(find_mtd_part "firmware_orig")
101
102         case "$magic" in
103         "27051956")
104                 ;;
105         "43493030")
106                 local md5_img=$(dd if="$1" bs=2 skip=9 count=16 2>/dev/null)
107                 local md5_chk=$(dd if="$1" bs=64k skip=1 2>/dev/null | md5sum -); md5_chk="${md5_chk%% *}"
108                 local fw_len=$(dd if="$1" bs=2 skip=1 count=4 2>/dev/null)
109                 local fw_part_len=$(get_mtd_part_size "firmware")
110
111                 if [ -z "$fw_mtd" ]; then
112                         ask_bool 0 "Do you have a backup of the caldata partition?" || {
113                                 echo "Warning, please make sure that you have a backup of the caldata partition."
114                                 echo "Once you have that, use 'sysupgrade -i' for upgrading to the 'fat' firmware."
115                                 return 1
116                         }
117                 fi
118
119                 if [ -z "$md5_img" -o -z "$md5_chk" ]; then
120                         echo "Unable to get image checksums. Maybe you are using a streamed image?"
121                         return 1
122                 fi
123
124                 if [ "$md5_img" != "$md5_chk" ]; then
125                         echo "Invalid image. Contents do not match checksum (image:$md5_img calculated:$md5_chk)"
126                         return 1
127                 fi
128
129                 fw_len=$((0x$fw_len))
130                 fw_part_len=${fw_part_len:-0}
131
132                 if [ $fw_part_len -lt $fw_len ]; then
133                         echo "The upgrade image is too big (size:$fw_len available:$fw_part_len)"
134                         return 1
135                 fi
136                 ;;
137         *)
138                 echo "Unsupported image format."
139                 return 1
140                 ;;
141         esac
142
143         return 0
144 }
145
146 platform_do_upgrade_dir825b() {
147         local magic="$(get_magic_long "$1")"
148         local fw_mtd=$(find_mtd_part "firmware_orig")
149
150         case "$magic" in
151         "27051956")
152                 if [ -n "$fw_mtd" ]; then
153                         # restore calibration data before downgrading to
154                         # the normal image
155                         dir825b_copy_caldata "caldata" "caldata_orig" || {
156                                 echo "unable to restore calibration data"
157                                 exit 1
158                         }
159                         PART_NAME="firmware_orig"
160                 else
161                         PART_NAME="firmware"
162                 fi
163                 default_do_upgrade "$ARGV"
164                 ;;
165         "43493030")
166                 if [ -z "$fw_mtd" ]; then
167                         # backup calibration data before upgrading to the
168                         # fat image
169                         dir825b_copy_caldata "caldata" "caldata_copy" || {
170                                 echo "unable to backup calibration data"
171                                 exit 1
172                         }
173                 fi
174                 dir825b_do_upgrade_combined "firmware" "$ARGV"
175                 ;;
176         esac
177 }