-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathwatch-image
executable file
·236 lines (217 loc) · 7.28 KB
/
watch-image
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#! /bin/bash
# Copyright (C) 2023 Ed Beroset <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
VERSION="1.2"
function showVersion {
echo "watch-image v${VERSION}"
}
declare -a devices=("anthias" "bass" "beluga" "catfish" "dory" "firefish" "harmony" "hoki" "koi" "inharmony" "lenok" "minnow" "mooneye" "narwhal" "nemo" "pike" "ray" "smelt" "sparrow" "sparrow-mainline" "sprat" "sturgeon" "sawfish" "skipjack" "swift" "tetra" "triggerfish" "wren")
# assume we're not saving
save=false
# assume we're not restoring
restore=false
# assume we're not in dryrun mode
dryrun=false
# assume we're not in quiet mode
quiet=false
# the codename is initially invalid
valid=false
function showHelp {
showVersion
cat << EOF
./watch-image codename [option]
Save/restore boot partition from watch running AsteroidOS. By default, uses
"SSH Mode" but can also use "ADB Mode."
Available options:
-d or --dissect separates previously saved image into one file per partition
-h or --help prints this help screen and quits
-a or --adb uses ADB command to communicate with watch
-p or --port specifies a port to use for ssh and scp commands
-R or --remote specifies the remote (watch) name or address for ssh and scp commands
-i or --image FN uses FN as the file name of the image
-r or --restore restore the boot partition of the watch
-s or --save save the entire watch image (may be 4G or more!)
-q or --quiet don't emit messages describing the action
-N or --dryrun don't actually flash, just show what would happen
-v or --version displays the version of this program
EOF
}
function getParts {
local imagefile="$1"
# The following line looks complex and it is.
# It uses sfdisk to get a list of partitions, with the device, start, sectors and name fields.
# Then awk processes only the lines that have data, translating back into /dev/mmcblk0pXX
# which are the names of the partitions on the watch.
# Lines look like this:
# /dev/mmcblk0p21 199776 65536 boot
sfdisk -l -o Device,Start,Sectors,Name "${imagefile}" | awk '/'"${imagefile}"'[^:]/{gsub(/'"${imagefile}"'/,"/dev/mmcblk0p"); print}'
}
function findPart {
local whichpart="$1"
shift
local parts=("$@")
for mypart in "${parts[@]}" ; do
IFS=" " read -r -a onepart <<< "${mypart}"
if [ "${onepart[3]}" = "${whichpart}" ] ; then
echo "${mypart}"
break
fi
done
}
function restorePartition {
local whichpart="$1"
local imagefile="$2"
local mypart
local parts
mapfile -t parts < <(getParts "${imagefile}")
IFS=" " read -r -a mypart <<< "$(findPart "${whichpart}" "${parts[@]}")"
if [ "${ADB}" = true ] ; then
echo "Restoration of partition is not yet supported in ADB mode."
else
if [ "${dryrun}" = "true" ] ; then
echo "I would have written the ${mypart[3]} partition (starting at ${mypart[1]}, containing ${mypart[2]} sectors) to ${mypart[0]}"
else
[ "${quiet}" = "true" ] || echo "Writing the ${mypart[3]} partition (starting at ${mypart[1]}, containing ${mypart[2]} sectors) to ${mypart[0]}"
dd if="${imagefile}" skip="${mypart[1]}" count="${mypart[2]}" | ssh -p "${WATCHPORT}" root@"${WATCHADDR}" "dd of=${mypart[0]}"
fi
fi
}
function dissectImage {
local imagefile="$1"
local mypart
local parts
mapfile -t parts < <(getParts "${imagefile}")
for onepart in "${parts[@]}" ; do
IFS=" " read -r -a mypart <<< "${onepart}"
if [ "${dryrun}" = "true" ] ; then
echo "I would have written the ${mypart[3]} partition (starting at ${mypart[1]}, containing ${mypart[2]} sectors) to ${mypart[3]}.img"
else
[ "${quiet}" = "true" ] || echo "Writing the ${mypart[3]} partition (starting at ${mypart[1]}, containing ${mypart[2]} sectors) to ${mypart[3]}.img"
dd if="${imagefile}" skip="${mypart[1]}" count="${mypart[2]}" of="${mypart[3]}.img"
fi
done
}
function saveImage {
local imagefile="$1"
if [ "${ADB}" == true ] ; then
adb pull /dev/mmcblk0 "${imagefile}"
else
ssh -p "${WATCHPORT}" root@"${WATCHADDR}" "dd if=/dev/mmcblk0" | dd "of=$(pwd)/${imagefile}" bs=4096 status=progress
fi
}
# These are the defaults for SSH access
WATCHPORT=22
WATCHADDR=192.168.2.15
# Assume no ADB unless told otherwise
ADB=false
while [[ $# -gt 0 ]] ; do
case $1 in
-a|--adb)
ADB=true
shift
;;
-p|--port)
WATCHPORT="$2"
shift
shift
;;
-R|--remote)
WATCHADDR="$2"
shift
shift
;;
-d|--dissect)
dissect=true
shift
;;
-h|--help)
showHelp
exit 1
;;
-i|--image)
imagefile="$2"
shift
shift
;;
-r|--restore)
restore=true
shift
;;
-s|--save)
save=true
shift
;;
-q|--quiet)
quiet=true
shift
;;
-N|--dryrun)
dryrun=true
shift
;;
-v|--version)
showVersion
shift
;;
*)
for device in "${devices[@]}"; do
[ "$1" == "${device}" ] && valid=true
done
if [[ "${valid}" = true ]]; then
codename=$1
else
echo "Ignoring unknown option $1"
fi
shift
;;
esac
done
if [ "${valid}" = "false" ] ; then
echo "You must specify a valid device name."
showHelp
exit 0
fi
if [ -z "${imagefile}" ] ; then
imagefile=original-${codename}.img
fi
if [ "${save}" = "true" ] ; then
if [ "${dryrun}" == "true" ] ; then
echo "I would have copied from /dev/mmcblk0 to ${imagefile}"
if [[ -f ${imagefile} ]] ; then
echo "but ${imagefile} already exists -- will not overwrite"
fi
else
if [[ -f ${imagefile} ]] ; then
echo "Error: ${imagefile} already exists -- will not overwrite"
exit 2
fi
[ "${quiet}" = "true" ] || echo "Copying from /dev/mmcblk0 to ${imagefile}"
saveImage "${imagefile}"
fi
fi
if [ "${restore}" = "true" ] ; then
if [[ ! -f ${imagefile} ]] ; then
echo "Error: ${imagefile} does not exist"
exit 2
fi
restorePartition "boot" "${imagefile}"
fi
if [ "${dissect}" = "true" ] ; then
if [[ ! -f ${imagefile} ]] ; then
echo "Error: ${imagefile} does not exist"
exit 2
fi
dissectImage "${imagefile}"
fi