forked from jimrandomh/g2flash
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild_cfw.sh
More file actions
executable file
·188 lines (172 loc) · 7.75 KB
/
Copy pathbuild_cfw.sh
File metadata and controls
executable file
·188 lines (172 loc) · 7.75 KB
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
#!/usr/bin/env bash
#
# build_cfw.sh — one-shot setup + custom-firmware build for Even Realities G2.
#
# Does everything needed to go from a fresh clone to a flashable image:
# 1. creates a Python virtualenv (./venv) and installs the flasher's deps
# 2. downloads the stock G2 2.2.6.10 firmware from Even's CDN
# 3. verifies the download hashes as expected (refuses to proceed otherwise)
# 4. applies the committed patch set (patches/cfw_patches.json) to the stock
# image to produce the CFW image
# 5. verifies the patched image hashes as expected
#
# The patch set is split into two halves:
# * patches/gen_patches.py compiles the injected code with clang and emits the
# committed patches/cfw_patches.json (a list of offset/old/new byte patches).
# * patches/apply_patches.py replays that JSON onto the stock image with NO
# compiler — pure Python stdlib, so it runs anywhere (a phone, a fresh box).
# The build always APPLIES the committed JSON, so the pinned output hash is met
# regardless of what clang is (or isn't) installed. When a working clang cross-
# compiler is present we additionally REGENERATE the patch set and check it still
# matches the committed one — a reproducibility check. If clang is missing or
# can't cross-compile, we warn and skip that check rather than failing.
#
# The stock firmware is Even's, so we don't redistribute it — it's fetched at
# build time and patched locally. The build is fully deterministic: the committed
# JSON + the pinned output hash mean a successful run reproduces exactly the
# reviewed image.
#
# Usage:
# ./build_cfw.sh # full setup + build
# ./build_cfw.sh --skip-venv # build only, don't touch the venv
# ./build_cfw.sh --force-download # re-download the stock image even if cached
# ./build_cfw.sh --update-patches # regenerate & OVERWRITE patches/cfw_patches.json
# # from clang (use after editing patch sources)
# ./build_cfw.sh --help
#
# WARNING: flashing custom firmware voids your warranty and can brick the
# glasses. This script only BUILDS the image; see README.md for flashing.
set -euo pipefail
# ---- config (pinned) -------------------------------------------------------
FW_URL="https://cdn.evenreal.co/firmware/e28738432d7b612d625331b00383149b.bin"
BASE="g2_2.2.6.10.bin" # stock image (downloaded)
OUT="g2_2.2.6.10_cfw.bin" # patched image (produced)
PATCH_JSON="patches/cfw_patches.json" # committed patch set (applied to produce OUT)
GEN="patches/gen_patches.py" # clang: (re)generate the patch set
APPLY="patches/apply_patches.py" # no clang: replay the patch set onto BASE
BASE_SHA256="f4dfb0b49ad3de3c2daf17f8a27a157c3dc98411d6a0d3ab2cfd0918f41b9afa"
OUT_SHA256="cf929ae83ff351cfe81df97460560420fe05a744253e57da564be797df91f2a9"
SKIP_VENV=0
FORCE_DOWNLOAD=0
UPDATE_PATCHES=0
# ---- args ------------------------------------------------------------------
for arg in "$@"; do
case "$arg" in
--skip-venv) SKIP_VENV=1 ;;
--force-download) FORCE_DOWNLOAD=1 ;;
--update-patches) UPDATE_PATCHES=1 ;;
-h|--help)
awk 'NR==1{next} /^#/{sub(/^# ?/,""); print; next} {exit}' "$0"
exit 0 ;;
*)
echo "unknown option: $arg (try --help)" >&2
exit 2 ;;
esac
done
cd "$(dirname "$0")"
say() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
ok() { printf '\033[1;32m ✓\033[0m %s\n' "$*"; }
warn() { printf '\033[1;33m !\033[0m %s\n' "$*"; }
die() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
# Does clang look like a working thumbv7em cross-compiler? (compile a tiny TU)
clang_cross_ok() {
command -v clang >/dev/null 2>&1 || return 1
local tmp; tmp="$(mktemp -d)"
printf 'int f(int x){return x+1;}\n' > "$tmp/probe.c"
local rc=0
clang --target=thumbv7em-none-eabi -mthumb -ffreestanding -c \
"$tmp/probe.c" -o "$tmp/probe.o" >/dev/null 2>&1 || rc=1
rm -rf "$tmp"
return $rc
}
# ---- helpers ---------------------------------------------------------------
sha256() {
if command -v shasum >/dev/null 2>&1; then
shasum -a 256 "$1" | awk '{print $1}'
elif command -v sha256sum >/dev/null 2>&1; then
sha256sum "$1" | awk '{print $1}'
else
die "no sha256 tool found (need 'shasum' or 'sha256sum')"
fi
}
verify() { # path expected_hash label
local got; got="$(sha256 "$1")"
[ "$got" = "$2" ] || die "$3 hash mismatch
expected $2
got $got"
}
download() { # url dest
if command -v curl >/dev/null 2>&1; then
curl -fL --retry 3 --progress-bar -o "$2" "$1"
elif command -v wget >/dev/null 2>&1; then
wget -O "$2" "$1"
else
die "no downloader found (need 'curl' or 'wget')"
fi
}
# ---- 1. venv ---------------------------------------------------------------
if [ "$SKIP_VENV" -eq 1 ]; then
say "skipping venv setup (--skip-venv)"
else
command -v python3 >/dev/null 2>&1 || die "python3 not found"
if [ ! -d venv ]; then
say "creating virtualenv (./venv)"
python3 -m venv venv
else
say "reusing existing virtualenv (./venv)"
fi
say "installing dependencies (bleak, websocket-client)"
./venv/bin/python -m pip install --quiet --upgrade pip
./venv/bin/python -m pip install --quiet -r requirements.txt
ok "venv ready — flash with: ./venv/bin/python g2flash.py -c g2://local -f ..."
fi
# ---- 2/3. download + verify stock image ------------------------------------
if [ "$FORCE_DOWNLOAD" -eq 0 ] && [ -f "$BASE" ] && [ "$(sha256 "$BASE")" = "$BASE_SHA256" ]; then
say "stock image already present and verified ($BASE)"
else
say "downloading stock G2 2.2.6.10 firmware from Even's CDN"
download "$FW_URL" "$BASE"
verify "$BASE" "$BASE_SHA256" "stock firmware"
ok "stock image verified ($BASE)"
fi
# ---- 4a. (re)generate patch set with clang, if available -------------------
# The committed patches/cfw_patches.json is the source of truth; clang is only
# needed to (re)generate it. By default we regenerate to a temp file and check it
# still matches the committed set (a reproducibility check). --update-patches
# overwrites the committed file (developer workflow after editing patch sources).
[ -f "$PATCH_JSON" ] || [ "$UPDATE_PATCHES" -eq 1 ] || \
die "committed patch set missing ($PATCH_JSON) and --update-patches not given"
if [ "$UPDATE_PATCHES" -eq 1 ]; then
clang_cross_ok || die "--update-patches needs a working clang thumbv7em cross-compiler"
say "regenerating committed patch set with clang ($PATCH_JSON)"
python3 "$GEN" "$BASE" "$PATCH_JSON"
ok "patch set regenerated — review & commit $PATCH_JSON"
elif clang_cross_ok; then
say "clang found — regenerating patch set to check reproducibility"
TMP_JSON="$(mktemp)"
if python3 "$GEN" "$BASE" "$TMP_JSON" >/dev/null 2>&1; then
if diff -q "$PATCH_JSON" "$TMP_JSON" >/dev/null 2>&1; then
ok "clang reproduces the committed patch set exactly"
else
warn "clang output differs from the committed patch set (likely a clang"
warn "version difference) — using the committed $PATCH_JSON, which is pinned."
warn "If you meant to change the patches, run: ./build_cfw.sh --update-patches"
fi
else
warn "clang patch regeneration failed — using the committed $PATCH_JSON"
fi
rm -f "$TMP_JSON"
else
warn "no working clang cross-compiler — skipping regeneration"
warn "using the committed $PATCH_JSON (no compiler needed to apply it)"
fi
# ---- 4b/5. apply committed patch set + verify ------------------------------
say "applying committed patch set -> $OUT"
python3 "$APPLY" "$BASE" "$PATCH_JSON" "$OUT"
verify "$OUT" "$OUT_SHA256" "patched firmware"
ok "patched image verified ($OUT)"
echo
say "done. Custom firmware: $OUT"
echo " Flash it (voids warranty, can brick the device) with, e.g.:"
echo " ./venv/bin/python g2flash.py -c g2://local -f $OUT"
echo " See README.md for connection options and safety notes."