target_util: improve/rework u-boot-upgrade script
[oweals/u-boot_mod.git] / target_util / u-boot-upgrade
1 #!/bin/sh
2
3 #==================================================
4 #      Name: u-boot-upgrade
5 #   Purpose: Update U-Boot partition using mtd tool
6 #
7 #    Author: Piotr Dymacz <piotr@dymacz.pl>
8 # Copyright: Copyright (C) 2014 Piotr Dymacz
9 #   Created: 2014-11-19
10 #==================================================
11
12       MTD_DEVICE="mtd0"
13    NEW_UBOOT_DIR="/etc/u-boot_mod"
14  NEW_UBOOT_FNAME=""
15   MTD_BACKUP_MD5=""
16 MTD_BACKUP_FNAME="mtd0_backup.bin"
17
18 echo_info() {
19         echo -e "[\e[96minfo\e[0m] $1"
20 }
21
22 echo_err() {
23         echo -e "[\e[31merro\e[0m] $1"
24 }
25
26 echo_ok() {
27         echo -e "[\e[92m ok \e[0m] $1"
28 }
29
30 echo_warn() {
31         echo -e "[\e[93mwarn\e[0m] $1"
32 }
33
34 wait_for_yesno() {
35         local question="$1"
36
37         echo ""
38         read -p "-----> $question (type 'yes' or 'no')? " answer
39
40         while true; do
41                 case "$answer" in
42                 "yes")
43                         echo ""
44                         return 0
45                         ;;
46                 "no")
47                         echo ""
48                         return 1
49                         ;;
50                 *)
51                         read -p "Please, type 'yes' or 'no': " answer
52                         ;;
53                 esac
54         done
55 }
56
57 show_disclaimer() {
58         echo ""
59         echo "======================================================="
60         echo -ne "\e[93m"
61         echo "DISCLAIMER: you are using this script at your own risk!"
62         echo -ne "\e[0m"
63         echo ""
64         echo "The author of U-Boot modification and this script takes"
65         echo "no responsibility for any of the results of using them."
66         echo ""
67         echo -ne "\e[31m"
68         echo "     Updating U-Boot is a very dangerous operation"
69         echo "   and may damage your device! You have been warned!"
70         echo -ne "\e[0m"
71         echo "======================================================="
72
73         wait_for_yesno "Do you want to continue" || return 1
74 }
75
76 find_new_uboot_file() {
77         local filesqty=""
78         local new_ubot_md5=""
79
80         [ -d "$NEW_UBOOT_DIR" ] || {
81                 echo_err "Directory '$NEW_UBOOT_DIR' does not exist"
82                 return 1
83         }
84
85         cd "$NEW_UBOOT_DIR" >/dev/null 2>&1 || {
86                 echo_err "Could not change directory to '$NEW_UBOOT_DIR'"
87                 return 1
88         }
89
90         filesqty="$(find . -maxdepth 1 -name "*.bin" | wc -l)"
91
92         [ "$filesqty" -eq "0" ] && {
93                 echo_err "Could not find any binary file in '$NEW_UBOOT_DIR'"
94                 return 1
95         }
96
97         [ "$filesqty" -gt "1" ] && {
98                 echo_err "Found more than one binary file in '$NEW_UBOOT_DIR'"
99                 return 1
100         }
101
102         NEW_UBOOT_FNAME="$(basename "$(find . -maxdepth 1 -name "*.bin")")"
103         new_ubot_md5="$(basename "$NEW_UBOOT_FNAME" .bin).md5"
104
105         [ -e "$new_ubot_md5" ] || {
106                 [ -e "md5sums" ] && \
107                 grep -q "$NEW_UBOOT_FNAME" "md5sums" && \
108                 grep "$NEW_UBOOT_FNAME" "md5sums" > "$new_ubot_md5" && \
109                 echo_info "Checksum file successfully created from 'md5sums'"
110         }
111
112         [ -e "$new_ubot_md5" ] || {
113                 echo_err "Checksum file '$new_ubot_md5' does not exist"
114                 return 1
115         }
116
117         echo_ok "Found U-Boot image file: '$NEW_UBOOT_FNAME'"
118
119         wait_for_yesno "Do you want to use this file" || return 1
120
121         md5sum -cs "$new_ubot_md5" >/dev/null 2>&1 || {
122                 echo_err "MD5 checksum of new U-Boot image file is wrong"
123                 return 1
124         }
125
126         echo_ok "MD5 checksum of new U-Boot image file is correct"
127 }
128
129 backup_mtd_zero() {
130         [ -c "/dev/$MTD_DEVICE" ] || {
131                 echo_err "Device /dev/$MTD_DEVICE does not exist"
132                 return 1
133         }
134
135         cd /tmp >/dev/null 2>&1 || {
136                 echo_err "Could not change directory to '/tmp'"
137                 return 1
138         }
139
140         [ -e "$MTD_BACKUP_FNAME" ] && rm -f "$MTD_BACKUP_FNAME" >/dev/null 2>&1
141
142         dd if=/dev/"$MTD_DEVICE" of="$MTD_BACKUP_FNAME" >/dev/null 2>&1 || {
143                 echo_err "Could not backup '/dev/$MTD_DEVICE'"
144                 return 1
145         }
146
147         MTD_BACKUP_MD5="$(md5sum "$MTD_BACKUP_FNAME" | awk '{print $1}')"
148         [ -n "$MTD_BACKUP_MD5" ] || {
149                 echo_err "Could not calculate MD5 of backup file"
150                 return 1
151         }
152
153         echo_ok "Backup of /dev/$MTD_DEVICE successfully created"
154
155         wait_for_yesno "Do you want to store backup (recommended) in '$NEW_UBOOT_DIR/backup/'" || return 0
156
157         mkdir -p "$NEW_UBOOT_DIR/backup" >/dev/null 2>&1 || {
158                 echo_err "Could not create '$NEW_UBOOT_DIR/backup'"
159                 return 1
160         }
161
162         cp -f "$MTD_BACKUP_FNAME" "$NEW_UBOOT_DIR/backup/$MTD_BACKUP_FNAME" >/dev/null 2>&1 || {
163                 echo_err "Could not copy backup file '$MTD_BACKUP_FNAME' to '$NEW_UBOOT_DIR/backup/'"
164                 return 1
165         }
166
167         echo_ok "Backup of '/dev/$MTD_DEVICE' successfully copied to '$NEW_UBOOT_DIR/backup/'"
168 }
169
170 check_rw_status() {
171         local mtdrw="kmod-mtd-rw"
172         local rwfalg="0x400"
173         local flags=""
174
175         [ -e "/sys/class/mtd/$MTD_DEVICE/flags" ] || return 0
176
177         flags="$(cat /sys/class/mtd/$MTD_DEVICE/flags)"
178         [ "$((flags & rwfalg))" -gt "0" ] && {
179                 echo_info "Partition '/dev/$MTD_DEVICE' is writable"
180                 return 0
181         }
182
183         echo_warn "Partition '/dev/$MTD_DEVICE' is not writable"
184
185         opkg list-installed | grep -q "$mtdrw" || {
186                 wait_for_yesno "Do you want to install '$mtdrw' and unclock '/dev/$MTD_DEVICE'" || return 1
187
188                 echo_info "Updating packages..."
189
190                 opkg update > /dev/null 2>&1 || {
191                         echo_err "Could not update packages, check your Internet connection"
192                         return 1
193                 }
194
195                 echo_ok "Packages successfully updated, installing '$mtdrw'..."
196
197                 opkg install "$mtdrw" > /dev/null 2>&1 || {
198                         echo_err "Could not install '$mtdrw' package"
199                         return 1
200                 }
201
202                 echo_ok "Package '$mtdrw' successfully installed"
203         }
204
205         echo_info "Unlocking '/dev/$MTD_DEVICE' partition..."
206
207         insmod mtd-rw i_want_a_brick=1 >/dev/null 2>&1 || {
208                 echo_err "Could not load 'mtd-rw' kernel module"
209                 return 1
210         }
211
212         flags="$(cat /sys/class/mtd/$MTD_DEVICE/flags)"
213         [ "$((flags & rwfalg))" -gt "0" ] || {
214                 echo_err "Could not unlock '/dev/$MTD_DEVICE' partition"
215                 return 1
216         }
217
218         echo_ok "Partition '/dev/$MTD_DEVICE' successfully unlocked"
219 }
220
221 combine_images() {
222         local new_size=""
223         local old_size=""
224
225         new_size="$(wc -c "$NEW_UBOOT_DIR/$NEW_UBOOT_FNAME" | awk '{print $1}')"
226         old_size="$(wc -c "/tmp/$MTD_BACKUP_FNAME" | awk '{print $1}')"
227
228         [ -n "$old_size" ] || [ -n "$new_size" ] || {
229                 echo_err "Could not get size of new U-Boot image and/or backup file"
230                 return 1
231         }
232
233         # Allow to use only images not bigger than mtd0 size
234         [ "$new_size" -gt "$old_size" ] && {
235                 echo_err "New U-Boot image size ('$new_size' bytes) is bigger than '$MTD_DEVICE' partition size ('$old_size' bytes)"
236                 return 1
237         }
238
239         dd if="$NEW_UBOOT_DIR/$NEW_UBOOT_FNAME" of="/tmp/$MTD_BACKUP_FNAME" conv=notrunc >/dev/null 2>&1 || {
240                 echo_err "Could not combine new U-Boot image with backup file"
241                 return 1
242         }
243
244         echo_ok "New U-Boot image successfully combined with backup file"
245 }
246
247 write_new_image() {
248         local newmd5=""
249
250         echo_info "New U-Boot image is ready to be written into FLASH"
251
252         wait_for_yesno "Do you want to continue" || return 1
253
254         # Erase mtd0 and write new image...
255         mtd -e "/dev/$MTD_DEVICE" write "/tmp/$MTD_BACKUP_FNAME" "/dev/$MTD_DEVICE" >/dev/null 2>&1 || {
256                 echo_warn "Could not write new U-Boot image into FLASH"
257
258                 newmd5="$(md5sum "/dev/$MTD_DEVICE" | awk '{print $1}')"
259
260                 [ "$MTD_BACKUP_MD5" = "$newmd5" ] && {
261                         echo_ok "Original '/dev/$MTD_DEVICE' partition content was not changed"
262                         return 0
263                 }
264
265                 echo_err "FATAL ERROR: '/dev/$MTD_DEVICE' and old U-Boot image are not equal"
266                 echo_err "DO NOT REBOOT OR POWER DOWN YOUR DEVICE NOW AND TRY AGAIN!"
267                 return 1
268         }
269
270         echo_ok "New U-Boot image successfully written into FLASH"
271
272         # Verify MD5 of mtd0 and prepared image
273         mtd verify "/tmp/$MTD_BACKUP_FNAME" "/dev/$MTD_DEVICE" 2>&1 | grep -q "Success" || {
274                 echo_err "FATAL ERROR: '/dev/$MTD_DEVICE' and new U-Boot image are not equal"
275                 echo_err "DO NOT REBOOT OR POWER DOWN YOUR DEVICE NOW AND TRY AGAIN!"
276                 return 1
277         }
278
279         echo_ok "'/dev/$MTD_DEVICE' and new U-Boot image are equal"
280
281         echo_info "Done! You can now reboot your device!"
282         echo ""
283 }
284
285 #======================
286 # Execution begins here
287 #======================
288
289 show_disclaimer     && \
290 find_new_uboot_file && \
291 backup_mtd_zero     && \
292 check_rw_status     && \
293 combine_images      && \
294 write_new_image
295
296 exit 0