-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathswap-root.sh
222 lines (204 loc) · 5.49 KB
/
swap-root.sh
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
#!/bin/bash
# Require bash due to builtin read
die() {
>&2 echo "${1}"
exit 1
}
exit_success() {
exit 0
}
# Parse arguments
cmd_update=""
cmd_state=""
cmd_commit=""
cmd_cancel=""
cmd_rollback=""
cmd_counter=""
image=""
print_usage() {
echo "Usage: ${1} [OPTIONS] COMMAND ARGS..."
echo
echo "Commands:"
echo " update IMAGE Write IMAGE to not-used rootfs partition"
echo " state Return current state"
echo " NORMAL: Normal boot"
echo " SWAPPING: Swap in progress"
echo " ROLLBACK: Bootloader performed rollback"
echo " INIT: swap initiated (this boot)"
echo " commit Commit change from state \"SWAPPING\" or \"ROLLBACK\" to \"NORMAL\""
echo " Commit from state \"NORMAL\" returns success."
echo " rollback Rollback from SWAPPING to NORMAL"
echo " cancel Cancel from INIT to NORMAL"
echo " has-manual-counter Check if counter is controlled by firmware"
echo " 0: controlled by firmware"
echo " 1: has to be manually incremented by caller"
echo " counter [VALUE] Read or write counter. Writing counter not allowed when has-manual-counter is false"
echo ""
echo "Options:"
echo " -c/--container IMAGE is of type CONTAINER"
echo " -h/--help: This help message"
}
while [ $# -gt 0 ]; do
case $1 in
-c|--container)
container="yes"
shift # past argument
;;
-h|--help)
print_usage
exit 1
;;
update)
[ $# -gt 1 ] || die "Invalid arguments for command update"
cmd_update="true"
image="${2}"
shift # past argument
shift # past value
;;
state)
cmd_state="true"
shift # past argument
;;
commit)
cmd_commit="true"
shift # past argument
;;
cancel)
cmd_cancel="true"
shift # past argument
;;
rollback)
cmd_rollback="true"
shift # past argument
;;
has-manual-counter)
echo "no"
exit 0
;;
counter)
cmd_counter="true"
shift # past argument
;;
*)
die "Invalid argument"
;;
esac
done
current_root_label="$(findmnt -no PARTLABEL /)" || die "Failed finding current root partition label"
case "${current_root_label}" in
rootfs1)
new_root_label="rootfs2"
;;
rootfs2)
new_root_label="rootfs1"
;;
*)
# Early abort wanted in case of non-rootfs boot
die "Unsupported root partition: ${current_root}"
;;
esac
state="UNKNOWN"
part="$(nvram --sys --get SYS_BOOT_PART)" || die "Failed reading nvram variable SYS_BOOT_PART"
swap="$(nvram --sys --get SYS_BOOT_SWAP)" || die "Failed reading nvram variable SYS_BOOT_SWAP"
attempts="0"
if [ "$part" = "$swap" ]; then
attempts="$(nvram --sys --get SYS_BOOT_ATTEMPTS)"
if [ $? -ne 0 ]; then
state="NORMAL"
else
state="ROLLBACK"
fi
else
attempts="$(nvram --sys --get SYS_BOOT_ATTEMPTS)"
if [ $? -ne 0 ]; then
state="INIT"
else
state="SWAPPING"
fi
fi
if [ "$state" = "UNKNOWN" ]; then
die "Could not determine state"
fi
# COMMAND state
if [ "$cmd_state" = "true" ]; then
echo "$state"
exit_success
fi
# COMMAND commit
if [ "$cmd_commit" = "true" ]; then
if [ "$state" = "NORMAL" ]; then
exit_success
fi
if [ "$state" != "SWAPPING" -a "$state" != "ROLLBACK" ]; then
die "Invalid state \""$state"\" for commit"
fi
NVRAM_SYSTEM_UNLOCK=16440 nvram --sys \
--del SYS_BOOT_ATTEMPTS \
--set SYS_BOOT_PART ${swap} || die "Failed setting nvram variables"
exit_success
fi
# COMMAND cancel
if [ "$cmd_cancel" = "true" ]; then
if [ "$state" != "INIT" ]; then
die "Invalid state \""$state"\" for cancel"
fi
NVRAM_SYSTEM_UNLOCK=16440 nvram --sys --set SYS_BOOT_SWAP "$part" || die "Failed setting nvram variable SYS_BOOT_SWAP"
exit_success
fi
# COMMAND rollback
if [ "$cmd_rollback" = "true" ]; then
if [ "$state" != "SWAPPING" ]; then
die "Invalid state \""$state"\" for rollback"
fi
NVRAM_SYSTEM_UNLOCK=16440 nvram --sys --set SYS_BOOT_SWAP "$part" || die "Failed setting nvram variable SYS_BOOT_SWAP"
exit_success
fi
# COMMAND update
if [ "$cmd_update" = "true" ]; then
if [ "$state" != "NORMAL" ]; then
die "Invalid state \""$state"\" for update"
fi
echo "Current root: ${current_root_label}"
echo "New root: ${new_root_label}"
echo "Partition device and install images.."
device="$(lsblk -pno pkname $(findmnt -no SOURCE /))" || die "Failed getting device name"
if [ "$container" = "yes" ]; then
# Install container
read -r -d '' config <<- EOM
images:
- name: image
type: raw-sparse
target: "label-raw:${new_root_label}"
EOM
printf '%s\n' "$config"
printf '%s\n' "$config" | install-image-container --device "$device" --any-pubkey --conf - --images "image=partition.rootfs" "$image" || die "Failed installation"
else
# Legacy mode with tar.bz2 installed to ext4 partition
read -r -d '' config <<- EOM
partitions:
- label: "${new_root_label}"
type: ext4
images:
- name: image
type: tar.bz2
target: "label:${new_root_label}"
EOM
printf '%s\n' "$config"
printf '%s\n' "$config" | image-install --device "$device" --force-unmount --config - "image=${image}" || die "Failed installation"
fi
echo "Success!"
NVRAM_SYSTEM_UNLOCK=16440 nvram --sys --set SYS_BOOT_SWAP "$new_root_label" || die "Failed setting nvram variable SYS_BOOT_SWAP"
echo "Image written to new root partition."
echo "Reboot to swap"
exit_success
fi
# COMMAND counter
if [ "$cmd_counter" = "true" ]; then
if [ "x$attempts" = "x" ]; then
echo 0
else
echo "$attempts"
fi
exit_success
fi
die "Should not be here"