ar71xx: fix sysupgrade for jjPlus JWAP003
[openwrt.git] / target / linux / ar71xx / base-files / lib / upgrade / allnet.sh
1 # The U-Boot loader of the some Allnet devices requires image sizes and
2 # checksums to be provided in the U-Boot environment.
3 # In case the check fails during boot, a failsafe-system is started to provide
4 # a minimal web-interface for flashing a new firmware.
5
6 # make sure we got uboot-envtools and fw_env.config copied over to the ramfs
7 platform_add_ramfs_ubootenv() {
8         [ -e /usr/sbin/fw_printenv ] && install_bin /usr/sbin/fw_printenv /usr/sbin/fw_setenv
9         [ -e /etc/fw_env.config ] && install_file /etc/fw_env.config
10 }
11 append sysupgrade_pre_upgrade platform_add_ramfs_ubootenv
12
13 # determine size of the main firmware partition
14 platform_get_firmware_size() {
15         local dev size erasesize name
16         while read dev size erasesize name; do
17                 name=${name#'"'}; name=${name%'"'}
18                 case "$name" in
19                         firmware)
20                                 printf "%d" "0x$size"
21                                 break
22                         ;;
23                 esac
24         done < /proc/mtd
25 }
26
27 # get the first 4 bytes (magic) of a given file starting at offset in hex format
28 get_magic_long_at() {
29         dd if="$1" skip=$(( $CI_BLKSZ / 4 * $2 )) bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"'
30 }
31
32 get_filesize() {
33         wc -c "$1" | while read image_size _n ; do echo $image_size ; break; done
34 }
35
36 # scan through the update image pages until matching a magic
37 platform_get_offset() {
38         offsetcount=0
39         magiclong="x"
40         if [ -n "$3" ]; then
41                 offsetcount=$3
42         fi
43         while magiclong=$( get_magic_long_at "$1" "$offsetcount" ) && [ -n "$magiclong" ]; do
44                 case "$magiclong" in
45                         "2705"*)
46                                 # U-Boot image magic
47                                 if [ "$2" = "uImage" ]; then
48                                         echo $offsetcount
49                                         return
50                                 fi
51                         ;;
52                         "68737173"|"73717368")
53                                 # SquashFS
54                                 if [ "$2" = "rootfs" ]; then
55                                         echo $offsetcount
56                                         return
57                                 fi
58                         ;;
59                         "deadc0de"|"19852003")
60                                 # JFFS2 empty page
61                                 if [ "$2" = "rootfs-data" ]; then
62                                         echo $offsetcount
63                                         return
64                                 fi
65                         ;;
66                 esac
67                 offsetcount=$(( $offsetcount + 1 ))
68         done
69 }
70
71 platform_check_image_allnet() {
72         local fw_printenv=/usr/sbin/fw_printenv
73         [ ! -n "$fw_printenv" -o ! -x "$fw_printenv" ] && {
74                 echo "Please install uboot-envtools!"
75                 return 1
76         }
77
78         [ ! -r "/etc/fw_env.config" ] && {
79                 echo "/etc/fw_env.config is missing"
80                 return 1
81         }
82
83         local image_size=$( get_filesize "$1" )
84         local firmware_size=$( platform_get_firmware_size )
85         [ $image_size -ge $firmware_size ] &&
86         {
87                 echo "upgrade image is too big (${image_size}b > ${firmware_size}b)"
88         }
89
90         local vmlinux_blockoffset=$( platform_get_offset "$1" uImage )
91         [ -z $vmlinux_blockoffset ] && {
92                 echo "vmlinux-uImage not found"
93                 return 1
94         }
95
96         local rootfs_blockoffset=$( platform_get_offset "$1" rootfs "$vmlinux_blockoffset" )
97         [ -z $rootfs_blockoffset ] && {
98                 echo "missing rootfs"
99                 return 1
100         }
101
102         local data_blockoffset=$( platform_get_offset "$1" rootfs-data "$rootfs_blockoffset" )
103         [ -z $data_blockoffset ] && {
104                 echo "rootfs doesn't have JFFS2 end marker"
105                 return 1
106         }
107
108         return 0
109 }
110
111 platform_do_upgrade_allnet() {
112         local firmware_base_addr=$( printf "%d" "$1" )
113         local vmlinux_blockoffset=$( platform_get_offset "$2" uImage )
114         if [ ! -n "$vmlinux_blockoffset" ]; then
115                 echo "can't determine uImage offset"
116                 return 1
117         fi
118         local rootfs_blockoffset=$( platform_get_offset "$2" rootfs $(( $vmlinux_blockoffset + 1 )) )
119         local vmlinux_offset=$(( $vmlinux_blockoffset * $CI_BLKSZ ))
120         local vmlinux_addr=$(( $firmware_base_addr + $vmlinux_offset ))
121         local vmlinux_hexaddr=0x$( printf "%08x" "$vmlinux_addr" )
122         if [ ! -n "$rootfs_blockoffset" ]; then
123                 echo "can't determine rootfs offset"
124                 return 1
125         fi
126         local rootfs_offset=$(( $rootfs_blockoffset * $CI_BLKSZ ))
127         local rootfs_addr=$(( $firmware_base_addr + $rootfs_offset ))
128         local rootfs_hexaddr=0x$( printf "%08x" "$rootfs_addr" )
129         local vmlinux_blockcount=$(( $rootfs_blockoffset - $vmlinux_blockoffset ))
130         local vmlinux_size=$(( $rootfs_offset - $vmlinux_offset ))
131         local vmlinux_hexsize=0x$( printf "%08x" "$vmlinux_size" )
132         local data_blockoffset=$( platform_get_offset "$2" rootfs-data $(( $rootfs_blockoffset + 1 )) )
133         if [ ! -n "$data_blockoffset" ]; then
134                 echo "can't determine rootfs size"
135                 return 1
136         fi
137         local data_offset=$(( $data_blockoffset * $CI_BLKSZ ))
138         local rootfs_blockcount=$(( $data_blockoffset - $rootfs_blockoffset ))
139         local rootfs_size=$(( $data_offset - $rootfs_offset ))
140         local rootfs_hexsize=0x$( printf "%08x" "$rootfs_size" )
141
142         local rootfs_md5=$( dd if="$2" bs=$CI_BLKSZ skip=$rootfs_blockoffset count=$rootfs_blockcount 2>/dev/null | md5sum -); rootfs_md5="${rootfs_md5%% *}"
143         local vmlinux_md5=$( dd if="$2" bs=$CI_BLKSZ skip=$vmlinux_blockoffset count=$vmlinux_blockcount 2>/dev/null | md5sum -); vmlinux_md5="${vmlinux_md5%% *}"
144         # this needs a recent version of uboot-envtools!
145         cat >/tmp/fw_env_upgrade <<EOF
146 vmlinux_start_addr $vmlinux_hexaddr
147 vmlinux_size $vmlinux_hexsize
148 vmlinux_checksum $vmlinux_md5
149 rootfs_start_addr $rootfs_hexaddr
150 rootfs_size $rootfs_hexsize
151 rootfs_checksum $rootfs_md5
152 bootcmd bootm $vmlinux_hexaddr
153 EOF
154         fw_setenv -s /tmp/fw_env_upgrade || {
155                 echo "failed to update U-Boot environment"
156                 return 1
157         }
158         shift
159         default_do_upgrade "$@"
160 }