forked from Asmageddon/airbreak-plus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
patch-airsense
executable file
·322 lines (266 loc) · 8.88 KB
/
patch-airsense
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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
#!/bin/bash
die() { echo >&2 "$*" ; exit 1 ; }
IN=$1
OUT=$2
DEBUG_PATCH=""
if [ -z "$IN" -o -z "$OUT" ]; then
die "Usage: $0: stm32.bin stm32-unlocked.bin"
fi
if [ ! -r "$IN" ]; then
die "$IN: can not open input file"
fi
patch() {
offset=`printf "%d" $1`
if [ $DEBUG_PATCH ] ; then
printf "patching %08x\n" $1
fi
dd bs=1 seek=$offset conv=notrunc of="$OUT" status=none
}
check_hash() {
HASH=$(sha256sum $IN | awk '{print $1}')
if [[ $HASH == "6790b548e0b37c57bc118772d4a04a599c0b74b16cd92e821071b9c7ba5ab711" ]] ; then
echo "$IN: VAuto 37051-SX567-0401 binary identified"
elif [[ $HASH == "533b91127aa22e05b933db203ad56c449dc12a8c3fd62f57bd88c472a8061775" ]] ; then
echo "$IN: AutoSet 37028-SX567-0401 binary identified"
else
die "$IN: Unidentified binary. Confirm its version is 0401 and that its binary has the same section layout"
fi
}
cp "$IN" "$OUT" || die "$OUT: copy failed"
patch_tamper() {
# patch the jump instruction that checks for tamper
printf '\xc0\x46' | patch 0xf0 \
|| die "startup patch failed"
}
patch_strings() {
# and add a message so that we know this is a modified firmware
printf 'HACKED!' | patch 0x17500 || die failed
printf 'My Options OwO\x00' | patch 0x17588 # Overwrites the French string, which will be broken. No biggie :P
}
BUILD_FLAGS=0
patch_direct() {
BIN_FILE=$1
ADDR=$2
if [ -r $BIN_FILE ] ; then
printf "Including $BIN_FILE..."
cat $BIN_FILE | patch $ADDR || die " patching failed"
echo " success!"
else
die " file not found, did you run make?"
fi
}
# BIN_FILE - file
# ADDR - address in the patched binary to point to
# PTR_ADDR - address of the +1 pointer in the binary
# PTR_TARGET is +1 relative to ADDR, and byte order is reversed(little-endian)
patch_pointer() {
BIN_FILE=$1
ADDR=$2
PTR_ADDR=$3
PTR_TARGET=$4
if [ -r $BIN_FILE ]; then
printf "Including $BIN_FILE..."
cat $BIN_FILE | patch $ADDR || die " patching failed"
printf "$PTR_TARGET" | patch $PTR_ADDR || die " pointer fixup failed"
echo " success!"
fi
}
patch_code_common() {
echo "Patching common_code.c"
patch_direct build/common_code.bin 0xfe000
}
patch_code_graph() {
echo "Patching graphing code"
patch_pointer build/graph.bin 0xfcd40 0xf9c88 '\x41\xcd\x0f\x08'
}
# Replaces not_called_during_loop
patch_code_squarewave() {
echo "Patching Squarewave"
patch_pointer build/squarewave.bin 0xfd000 0xf9778 '\x01\xd0\x0f\x08'
}
patch_code_squarewave_asv() {
echo "Patching Squarewave ASV"
patch_pointer build/squarewave_asv.bin 0xfd000 0xf9778 '\x01\xd0\x0f\x08'
}
# patch_code_squarewave_pav() {
# patch_pointer build/squarewave_pav.bin 0xfd000 0xf9778 '\x01\xd0\x0f\x08'
# }
patch_code_asv_task_wraper() {
echo "Patching ASV task wrapper"
patch_pointer build/asv_task_wrapper.bin 0xfdf00 0xf44e0 '\x01\xdf\x0f\x08'
}
patch_wrapper_limit_max_pdiff() {
echo "Patching wrapper for pressure_limit_max_diff"
patch_pointer build/wrapper_limit_max_pdiff.bin 0xfee00 0xf93d0 '\x01\xee\x0f\x08'
}
patch_code() {
if [[ $PATCH_CODE == 1 ]] ; then
BUILD_FLAGS=$(( BUILD_FLAGS | (1 << 0) ))
echo "Patching code"
patch_code_common
patch_code_graph
if [[ $PATCH_S_ASV == 1 ]] ; then
patch_code_squarewave_asv
elif [[ $PATCH_S == 1 ]] ; then
patch_code_squarewave
fi
if [[ $PATCH_ASV_TASK_WRAPPER == 1 ]] ; then
patch_code_asv_task_wraper
fi
if [[ $PATCH_VAUTO_WRAPPER == 1 ]] ; then
patch_wrapper_limit_max_pdiff
fi
fi
}
unlock_ui_limits() {
BUILD_FLAGS=$(( BUILD_FLAGS | (1 << 1) ))
# patch UI limits to range between 1 and 30
printf '\xdc\x05\x00\x00\x32\x00' | patch 0x4fa8 || die failed
printf '\xdc\x05\x00\x00\x32\x00' | patch 0x4fc4 || die failed
printf '\xdc\x05\x00\x00\x32\x00' | patch 0x7eb0 || die failed
printf '\xdc\x05\x00\x00\x32\x00' | patch 0x7ee8 || die failed
printf '\xdc\x05\x00\x00\x32\x00' | patch 0x7ecc || die failed
}
asv_unlock_ps_range () {
BUILD_FLAGS=$(( BUILD_FLAGS | (1 << 7) ))
# Disable the ASV and ASVAuto PS range check to allow Max PS < (Min PS + 5)
#
# Update PS validation logic without disabling other checks.
printf '\x00' | patch 0x76c08
printf '\x00' | patch 0x76c34
printf '\x00' | patch 0x76cca
# Update variable config to allow Max PS to be set below 5
printf '\x00' | patch 0x8074
printf '\x00' | patch 0x8100
}
extra_debug() {
BUILD_FLAGS=$(( BUILD_FLAGS | (1 << 2) ))
# set config variable 0xc value to 4 == enable more debugging data on display
# Default in VAuto is \x0e, all enabled is \x0f
# 1000 - ti min, ti max, ti, I:E, spont cyc (doesn't fit graph)
# 0100 - leak MV, RR, tv (default in this script)
# 0010 - bar thingy
# 0001 - fancy but useless round display
printf '\x04' | patch 0x84a8 || die failed
}
extra_modes() {
BUILD_FLAGS=$(( BUILD_FLAGS | (1 << 3) ))
# ---> This is the real magic <---
# add more mode entries, set config 0x0 mask to all bits high
# AutoSet default is 0x3, which only enables mode 1 (CPAP) and 2 (AutoSet)
# Autoset = 03 00, For Her = 03 08
# 1. 1 = CPAP
# 2. 2 = AutoSet
# 3. 4 = ???
# 4. 8 = S
# 5. 16 = ???
# 6. 32 = ???
# 7, 64 = VAuto
# 8, 128 = ASV
# 9, 256 = ASVAuto
# 49 00 = 0x01001001 = CPAP, VAuto, S
# 81 01 = 0x10000001 = CPAP, ASV, ASVAuto
# 2048 = AutoSet for her?
printf '\xff\xff' | patch 0x8590 || die failed
}
# Try enabling extra menu items
extra_menu() {
BUILD_FLAGS=$(( BUILD_FLAGS | (1 << 4) ))
printf '\x01\x20' | patch 0x66470
}
# If you want all menu items to always be visible, let this section run
all_menu() {
BUILD_FLAGS=$(( BUILD_FLAGS | (1 << 5) ))
# force status bit 5 always on -- always editable
printf '\x01\x20' | patch 0x6e502
# force status bit 4 always on -- this makes all the inputs show up, regardless of mode
printf '\x01\x20' | patch 0x6e4c4
}
gui_config () {
BUILD_FLAGS=$(( BUILD_FLAGS | (1 << 6) ))
# enable all of the editable options in the settings menu
# by turning on bit 1 of the config entries. All of these variables
# are listed in the gui_create_menus function
GUI_CONFIG=0x4ef4
GUI_CONFIG_SIZE=0x1c
GUI_CONFIG_OFFSET=30
for var in \
0x2f 0x1ec 0x1ed 0x24 0x25 0x1d3 0x1d6 0x1d5 0x1d7 0x26 \
0x1d9 0x1e0 0x1e1 0x1e2 0x1e5 0x1e4 0x1e6 0x1e7 0x1e9 0x1ea 0x1eb \
; do
# set config byte 0 bit 0, 1 and 2, which makes it active
ADDR=`perl -e "printf '%d', $GUI_CONFIG + ($var - $GUI_CONFIG_OFFSET) * $GUI_CONFIG_SIZE"`
printf '\x07\x00' | patch $ADDR
done
}
gui_config_all () {
BUILD_FLAGS=$(( BUILD_FLAGS | (1 << 7) ))
# Enable more settings and reported values by enabling bit 1 for all config variables
printf "patching 00004ef4 -> 0000833c (bit 0 for all 479 config variables)..."
for var in {0..478}
do
perl -p -0777 -i -e "substr(\$_, 0x4ef4 + ($var * 0x1c), 1) |= chr(1)" "$OUT"
done
printf " done.\n"
}
custom_palette() {
BUILD_FLAGS=$(( BUILD_FLAGS | (1 << 7) ))
# Selected item color
printf '\xCC\x33\x00\x00' | patch 0xf271c
# Whites
for addr in \
0xf26f8 0xf2714 0xf2720 0xf2738 0xf273c 0xf2740 0xf274c 0xf2768 0xf2774 0xf278c 0xf2790 0xf2794 \
; do
printf '\xFF\xBB\x44\x00' | patch $addr
done
# Bright grays (highlights mostly)
for addr in 0xf26fc 0xf2704 0xf2750 0xf2758 0xf276c ; do
printf '\x96\x48\x48\x00' | patch $addr
done
# Mid grays (buttons)
for addr in 0xf2700 0xf2754 ; do
printf '\x64\x32\x32\x00' | patch $addr
done
# Low grays (disabled, backgrounds)
for addr in 0xf2708 0xf270c 0xf2728 0xf2744 0xf275c 0xf2760 0xf277c 0xf2798 ; do
printf '\x40\x20\x20\x00' | patch $addr
done
# Blacks
for addr in 0xf2710 0xf272c 0xf2748 0xf2764 0xf2780 0xf279c ; do
printf '\x08\x00\x08\x00' | patch $addr
done
}
asv_disable_backup_rate () {
echo "Patching ASV backup rate"
BUILD_FLAGS=$(( BUILD_FLAGS | (1 << 7) ))
# Add ASV task wrapper function to empty high flash space.
# This function suppresses the backup rate by overriding the breath percentage as needed, and then calls the normal ASV task.
# cat backupRate.bin | patch 0xff000 || die "backupRate patch failed"
#
# Expanded binary patch inline so it doesn't need to be compiled.
printf '\x09\x4b\xd3\xf8\x08\x38\x01\x2b\x0b\xd1\x08\x4b\xdf\xed\x08\x7a\x93\xed\x27\x7a\xb4\xee\xe7\x7a\xf1\xee\x10\xfa\xc8\xbf\xc3\xed\x27\x7a\x04\x4b\x18\x47\x00\xbf\x00\xe0\x00\x20\x00\xea\x00\x20\x48\xe1\x7a\x3f\x65\x34\x0e\x08' | patch 0xff000
# Patch ASV task to point to the wrapper function.
printf '\x01\xf0\x0f\x08' | patch 0xf44e0
}
check_hash
patch_tamper
patch_strings
if [[ $PATCH_BACKUP_RATE == 1 ]] ; then
asv_disable_backup_rate
fi
patch_code # Handled based on environmental variables, no need to comment out
# gui_config_all
unlock_ui_limits # 2
extra_debug # 4
extra_modes # 8
extra_menu # 16
# all_menu # 32
gui_config # 64
asv_unlock_ps_range
custom_palette #128
# echo "Built with FLAGS=$BUILD_FLAGS"
#FLAGSTR=$(printf 'FLAGS=0x%02x' $BUILD_FLAGS)
#printf $FLAGSTR | patch 0x17588
#COMMIT_HASH=$(git log -n1 --format=format:"%H" | head -c 7)
#printf 'GIT=%s\x00' $COMMIT_HASH | patch 0x17764
sha256sum $OUT