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