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