ixp4xx: add sysupgrade support
[openwrt.git] / target / linux / ixp4xx / base-files / lib / upgrade / platform.sh
1 . /lib/ixp4xx.sh
2
3 RAMFS_COPY_DATA="/lib/ixp4xx.sh"
4
5 # testing
6 RAMFS_COPY_BIN="/usr/bin/less /usr/bin/hexdump"
7
8 CI_BLKSZ=65536
9 CI_LDADR=0x00800000
10
11 platform_find_partitions() {
12         local first dev size erasesize name
13         while read dev size erasesize name; do
14                 name=${name#'"'}; name=${name%'"'}
15                 case "$name" in
16                         vmlinux.bin.l7|kernel|linux|rootfs)
17                                 if [ -z "$first" ]; then
18                                         first="$name"
19                                 else
20                                         echo "$erasesize:$first:$name"
21                                         break
22                                 fi
23                         ;;
24                 esac
25         done < /proc/mtd
26 }
27
28 platform_find_kernelpart() {
29         local part
30         for part in "${1%:*}" "${1#*:}"; do
31                 case "$part" in
32                         vmlinux.bin.l7|kernel|linux)
33                                 echo "$part"
34                                 break
35                         ;;
36                 esac
37         done
38 }
39
40 platform_find_part_size() {
41         local first dev size erasesize name
42         while read dev size erasesize name; do
43                 name=${name#'"'}; name=${name%'"'}
44                 [ "$name" = "$1" ] && {
45                         echo "$size"
46                         break
47                 }
48         done < /proc/mtd
49 }
50
51 platform_do_upgrade_combined() {
52         local partitions=$(platform_find_partitions)
53         local kernelpart=$(platform_find_kernelpart "${partitions#*:}")
54         local erase_size=$((0x${partitions%%:*})); partitions="${partitions#*:}"
55         local kern_part_size=0x$(platform_find_part_size "$kernelpart")
56         local kern_part_blocks=$(($kern_part_size / $CI_BLKSZ))
57         local kern_length=0x$(dd if="$1" bs=2 skip=1 count=4 2>/dev/null)
58         local kern_blocks=$(($kern_length / $CI_BLKSZ))
59         local root_blocks=$((0x$(dd if="$1" bs=2 skip=5 count=4 2>/dev/null) / $CI_BLKSZ))
60
61         v "platform_do_upgrade_combined"
62         v "partitions=$partitions"
63         v "kernelpart=$kernelpart"
64         v "kernel_part_size=$kern_part_size"
65         v "kernel_part_blocks=$kern_part_blocks"
66         v "kern_length=$kern_length"
67         v "erase_size=$erase_size" 
68         v "kern_blocks=$kern_blocks"
69         v "root_blocks=$root_blocks"
70         v "kern_pad_blocks=$(($kern_part_blocks-$kern_blocks))"
71
72         if [ -n "$partitions" ] && [ -n "$kernelpart" ] && \
73            [ ${kern_blocks:-0} -gt 0 ] && \
74            [ ${root_blocks:-0} -gt 0 ] && \
75            [ ${erase_size:-0} -gt 0 ];
76         then
77                 local append=""
78                 [ -f "$CONF_TAR" -a "$SAVE_CONFIG" -eq 1 ] && append="-j $CONF_TAR"
79
80                 # write the kernel
81                 dd if="$1" bs=$CI_BLKSZ skip=1 count=$kern_blocks 2>/dev/null | \
82                         mtd -F$kernelpart:$kern_part_size:$CI_LDADR write - $kernelpart
83                 # write the rootfs
84                 dd if="$1" bs=$CI_BLKSZ skip=$((1+$kern_blocks)) count=$root_blocks 2>/dev/null | \
85                         mtd $append write - rootfs
86         else
87                 echo "invalid image"
88         fi
89 }
90
91 platform_check_image() {
92         local board=$(ixp4xx_board_name)
93         local magic="$(get_magic_word "$1")"
94         local partitions=$(platform_find_partitions)
95         local kernelpart=$(platform_find_kernelpart "${partitions#*:}")
96         local kern_part_size=0x$(platform_find_part_size "$kernelpart")
97         local kern_length=0x$(dd if="$1" bs=2 skip=1 count=4 2>/dev/null)
98
99         [ "$ARGC" -gt 1 ] && return 1
100
101         case "$board" in
102         avila | cambria )
103                 [ "$magic" != "4349" ] && {
104                         echo "Invalid image. Use *-sysupgrade.bin files on this board"
105                         return 1
106                 }
107
108                 kern_length_b=$(printf '%d' $kern_length)
109                 kern_part_size_b=$(printf '%d' $kern_part_size)
110                 if [ $kern_length_b -gt $kern_part_size_b ]; then
111                         echo "Invalid image. Kernel size ($kern_length) exceeds kernel partition ($kern_part_size)"
112                         return 1
113                 fi 
114
115                 local md5_img=$(dd if="$1" bs=2 skip=9 count=16 2>/dev/null)
116                 local md5_chk=$(dd if="$1" bs=$CI_BLKSZ skip=1 2>/dev/null | md5sum -); md5_chk="${md5_chk%% *}"
117                 if [ -n "$md5_img" -a -n "$md5_chk" ] && [ "$md5_img" = "$md5_chk" ]; then
118                         return 0
119                 else
120                         echo "Invalid image. Contents do not match checksum (image:$md5_img calculated:$md5_chk)"
121                         return 1
122                 fi
123
124                 return 0
125                 ;;
126         esac
127
128         echo "Sysupgrade is not yet supported on $board."
129         return 1
130 }
131
132 platform_do_upgrade() {
133         local board=$(ixp4xx_board_name)
134
135         v "board=$board"
136         case "$board" in
137         avila | cambria )
138                 platform_do_upgrade_combined "$ARGV"
139                 ;;
140         *)
141                 default_do_upgrade "$ARGV"
142                 ;;
143         esac
144 }
145
146 disable_watchdog() {
147         v "killing watchdog"
148         killall watchdog
149         ( ps | grep -v 'grep' | grep '/dev/watchdog' ) && {
150                 echo 'Could not disable watchdog'
151                 return 1
152         }
153 }
154
155 # CONFIG_WATCHDOG_NOWAYOUT=y - can't kill watchdog unless kernel cmdline has a mpcore_wdt.nowayout=0
156 #append sysupgrade_pre_upgrade disable_watchdog