In an attempt to kickstart my new years’ resolutions with a material purchase, I recently bought a Boox Go Color 7 Gen 2, a color E Ink tablet running Android.
Boox products reportedly phone home to send data to some Chinese servers, not to mention that the manufacturer is allegedly in breach of GPL. So, to make it easier to stomach this impulse purchase, we’re going to root this device and put it in virtual timeout via aggressive firewall policies to prevent it from phoning home.
This article was heavily inspired by fardjad’s “Taming an Onyx Tablet” Gist, as well as the generosity of the users of MobileRead forums, whom I thank. I’ve added some improvements, as well as some miscellaneous configuration that I ended up with. All the code is available permissively in my Github profile.
Why This Matters
Shipping an eReader with this level of telemetry and bloatware is really not necessary, nor asked for. Also, I don’t need Boox’s proprietary cloud sync, and dozen of unnecessary background services to drain battery.
On top of this, I live in Taiwan, and while I don’t accuse the manufacturer of nefarious intent, I’d rather derisk my setup, rather than have my device be part of a Chinese botnet or one of the 2.63 million daily cyberattacks in Taiwan coming from China1.
This is how I set up my Boox Go Color 7 Gen 2.
The First Challenge: Rooting the device, Broken Fastboot and Proprietary Firmware
In order to configure the system firewall, we will need to root the device. While I’d rather not have a rooted device to carry around, I think this is a worthy tradeoff, since this eReader that will mostly be used to read PDFs and the occasional HackerNews thread. No personal data to protect here, besides my reading habits.
I hit the first obstacle immediately: the Boox Go Color 7 Gen 2 has a broken fastboot implementation. While you can boot into fastboot mode, any write commands (fastboot flash) fail with “unknown command.” This is a known issue with Boox firmware past v3.52.
The only solution we have is to flash the patched Qualcomm EDL (Emergency Download) mode: a low-level partition access mode built into Qualcomm chipsets. Unlike fastboot (which runs from the device’s bootloader), EDL is a hardware-level recovery interface that bypasses the software stack entirely. When the device enters EDL mode, it appears as “Qualcomm HS-USB QDLoader 9008” and accepts raw partition writes through the Firehose protocol3.
The only catch to this process is that you need the correct EDL loader binary for your specific SoC. The loader acts as a firmware bridge, and will only initialise the Firehose protocol and enable partition access. Gen 1 and Gen 2 Boox devices use different loaders despite both being Qualcomm-based4.
Never factory reset a rooted Boox device. The encryption keys are stored in a partition that gets wiped, turning all your backed-up data into “GBs of random noise”4. Keep this in mind before doing anything destructive.
Part 1: Rooting with Magisk via EDL
The EDL Process
We needed the correct EDL loader for the Go Color 7 Gen 2. Finding the right loader is critical for this part of the process, but thanks to the work of the people at temblast.com, we have a comprehensive list of loaders for Boox devices 5.
Finding your loader:
- Comprehensive list: temblast.com/ref/onyxldr.htm (indexed by device model)
- Source repository: bkerler/Loaders on GitHub6
- For Go Color 7 Gen 2:
0000000000000000_bdaf51b59ba21d8a_fhprg.bin
Download and install the EDL tool7:
pipx install git+https://github.com/bkerler/edl.git
# Download the loader
curl -L -o gocolor7_loader.bin \
"https://github.com/bkerler/Loaders/raw/main/lenovo_motorola/0000000000000000_bdaf51b59ba21d8a_fhprg.bin"
# Enter EDL mode (device reboots to QDLoader 9008)
adb reboot edl
# IMPORTANT: Check which boot slot is active
sudo edl --loader=gocolor7_loader.bin printgpt | grep boot
# Read original boot partition (you should execute only one of these commands based on which boot partition was idenfitied above)
sudo edl --loader=gocolor7_loader.bin r boot_a boot_a.img
sudo edl --loader=gocolor7_loader.bin r boot_b boot_b.img
Now patch the boot image with Magisk89, and then pull the patched image back to your machine:
adb pull /storage/emulated/0/Download/magisk_patched_boot_a.img ./magisk_patched_boot_a.img
Finally, flash the Magisk-patched boot to ACTIVE slot
# (Check printgpt output - device may boot from B even if A was modified)
# You should only need to use one of these commands, but you can run both for redundancy
sudo edl --loader=gocolor7_loader.bin w boot_a magisk_patched_boot_a.img
sudo edl --loader=gocolor7_loader.bin w boot_b magisk_patched_boot_b.img
# Reset device
sudo edl --loader=gocolor7_loader.bin reset
The device uses A/B boot slots for seamless updates, similar to blue/green deployments. Both boot_a and boot_b exist, but only one slot is active. Checking printgpt first is critical—the device might boot from slot B even after you modify slot A4.
You now should have a rooted device, with Magisk showing an installed status
Detour: Working Around the Magisk IPC Bug
Boox firmware 4.1+ has an IPC bug in ActivityManagerService that crashes the Magisk app on boot10. The app freezes at the splash screen, making it impossible to grant root permissions through the normal UI flow.
When I first booted up the Boox after rooting it, I neglected granting superuser rights to the Magisk app, and the app was stuck being unable to start up as the Shell now rightfully didn’t have root access. This, in turn, prevented any app from calling addPackageDependency on UIDs > 2000, which Magisk uses for permission dialogs10.
To work around this, I installed a fresh app that was not on the deny list (Termux), granted it root, then used it to manipulate Magisk’s SQLite database:
# In Termux (after granting it root via popup)
su
/product/bin/magisk --sqlite "DELETE FROM policies WHERE uid=2000"
This removed Shell from the deny list, and allowed me to trigger the superuser grant prompt for Magisk.
Magisk’s policy database at /data/adb/magisk.db persists across app reinstalls. If you deny an app once, it stays denied even if you uninstall Magisk. You must clear it via SQLite or another root shell.
Part 2: Debloating the System
With root access secured, we now move onto phase 2, debloating:
adb shell pm list packages | sort
19 packages stood out as bloat:
Onyx telemetry & cloud:
com.onyx.aiassistant- AI assistant that phones homecom.onyx.android.ksync- Boox Cloud synccom.onyx.android.onyxotaservice- OTA update servicecom.onyx.appmarket- App storecom.onyx.igetshop- Shopping/promotional appcom.onyx.mail- Email client
Qualcomm bloat (on a WiFi-only eReader!):
com.qualcomm.qti.xrcb/xrvd.service- VR/AR servicescom.qualcomm.wfd.service- Miracast/wireless displayvendor.qti.imsrcs/imsdatachannel- IMS/VoLTEvendor.qti.iwlan- WiFi calling
You can use the Universal Android Debloater11, but I opted for just running adb shell scripts:
adb shell pm disable-user 0 com.onyx.aiassistant
Output:
Disabling com.onyx.android.ksync... OK
Disabling com.onyx.aiassistant... OK
Disabling com.onyx.android.onyxotaservice... OK
[...]
Disabled 18 packages (0 skipped)
Why pm disable-user instead of uninstall?12 It’s fully reversible without needing APKs. Perfect for experimentation without bricking the device (via removing the Boox keyboard without having a replacement for example).
Part 3: Firewall with AFWall+
Debloating removes apps, but what about system services that still run? The solution: AFWall+13, an iptables-based firewall that requires root.
I installed it via Obtainium14, and configured whitelist mode:
If you don’t want to manually type in all these URLs, you can send keys via adb shell input text '...' instead
Allowed apps (full internet access):
- Google Play Store / Services (for app installs)
- Magisk
- Syncthing
- Termux
- Obtainium
All other apps: LAN-only via custom iptables script:
# Allow private IP ranges
iptables -I OUTPUT -d 10.0.0.0/8 -j ACCEPT
iptables -I OUTPUT -d 172.16.0.0/12 -j ACCEPT
iptables -I OUTPUT -d 192.168.0.0/16 -j ACCEPT
iptables -I OUTPUT -d 127.0.0.0/8 -j ACCEPT
# Everything else hits AFWall's REJECT rules
This means Onyx system services can reach my local Syncthing server or Calibre library, but cannot phone home to China.
Testing the Firewall
# Test: Block China servers
adb shell su -c "ping -c 1 data.onyx-international.cn"
# Result: Destination Port Unreachable ✓
adb shell su -c "ping -c 1 push.boox.com"
# Result: 100% packet loss ✓
# Test: Allow LAN
adb shell su -c "ping -c 1 192.168.1.1"
# Result: 64 bytes from 192.168.1.1 ✓
Perfect. The device is now isolated from all WAN traffic except whitelisted apps.
Apps can detect and bypass VPN interfaces. AFWall+ works at the kernel level via netfilter, so there is no escape. Even if an app tries to bind to a specific interface or use raw sockets, the firewall catches it.
Part 4: Self-Hosted Syncthing
Finally, to get around Boox’s proprietary cloud sync solution, I can just integrate this Boox device into my existing Syncthing configuration and just sync my books over the network15.
On the Boox, I installed syncthing-android16 (the researchxxl fork). On my Framework 13 laptop running NixOS, I manage Syncthing declaratively:
# home/services/syncthing.nix
let
booxDeviceId = "XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX";
in {
services.syncthing = {
enable = true;
devices."Boox Go Color 7" = {
id = booxDeviceId;
addresses = [ "dynamic" ];
};
folders.Books = {
path = "/home/bogdan/Documents/Personal/Books";
devices = [ "Boox Go Color 7" ];
type = "sendreceive"; # Bidirectional sync
versioning = {
type = "trashcan";
params.cleanoutDays = "30";
};
};
};
}
On the Boox:
- Open Syncthing app
- Accept the device connection from Framework13
- Accept the Books folder share →
/storage/emulated/0/Books - Make sure Syncthing is allowed in AFWall+ (check WiFi box)
Now whenever I add a PDF to ~/Documents/Personal/Books on my laptop, it appears on the Boox within seconds. No cloud.
Conclusion
The Boox Go Color 7 Gen 2 is, in my opinion so far, decent hardware with questionable software. Was it worth doing all this work to not have cloud telemetry probes shoved up my… ports? Maybe, I certainly think so. But most importantly, it was fun, and I felt good doing it, so this afternoon project was a success for me.
China launched 2.63 million daily cyberattacks against Taiwan in 2025: NSB - Focus Taiwan ↩︎
Qualcomm EDL Mode Overview - Deep dive into EDL internals and Firehose protocol by Aleph Security ↩︎
MobileRead Forums: BOOX Go Color 7 (Gen II) EDL Mode and Firehose Loader Issues - Community documentation of EDL process, A/B boot slots, fastboot issues, and critical encryption warnings ↩︎ ↩︎ ↩︎
Temblast: Onyx Boox Firehose Loaders - Comprehensive list of EDL loaders for Boox devices ↩︎
bkerler/Loaders - Collection of Qualcomm EDL loaders for various devices ↩︎
edlclient - Qualcomm EDL (Emergency Download Mode) client for flashing and unbricking ↩︎
Magisk - The Magic Mask for Android: systemless root and module framework ↩︎
Magisk Issue #9319: NullPointerException in ActivityManagerService on Boox 4.1+ - Bug report and workarounds for IPC crash ↩︎ ↩︎
Universal Android Debloater - Cross-platform GUI tool with extensive safe-to-remove package lists ↩︎
Android Developer: ADB & Package Manager - Official documentation for
pmcommands ↩︎AFWall+ - Android Firewall+ (iptables-based frontend with whitelist mode) ↩︎
Obtainium - Get app updates directly from GitHub, F-Droid, or other sources ↩︎
GitHub - bruvduroiu/dotfiles - Personal dotfiles ↩︎
Syncthing-Fork for Android - Improved Android fork with better battery optimizations ↩︎