Onyx Boox Note Air (1st gen)¶
Tier: testing · Codename: onyx-noteair
Hardware¶
Status means the GlassineOS mainline kernel (Linux 7.x, sdm660 family branch). "Works" carries the date it was last verified on hardware; "untested" means the support is written but has not run on a device yet. Pins, supplies and register details live in the board device tree in the kernel repository.
Core¶
| Component | What it is | Mainline status |
|---|---|---|
| SoC | Qualcomm Snapdragon 636 (SDM636, sdm660 family) | works, verified 2026-09-27 |
| CPU | 8 × Kryo 260: 4 performance (Cortex-A73 class) + 4 efficiency (Cortex-A53 class). Linux boots on an efficiency core, so CPU 0 is an efficiency core. ARMv8.0 without LSE atomics: binaries built for newer cores can die with SIGILL. | works, verified 2026-09-27 |
| CPU frequency | Stock maximum 1612.8 MHz (efficiency) and 1804.8 MHz (performance). Mainline caps both clusters at 1401.6 MHz for now (open-loop voltage control). | works (capped), verified 2026-09-28 |
| CPU idle | The firmware accepts only OS-initiated PSCI, so cluster idle needs an OS-initiated power-domain hierarchy in the device tree. | works, verified 2026-09-29 |
| RAM | 3 GB LPDDR4 (about 2.7 GB usable under Linux) | works, verified 2026-09-27 |
| Storage | eMMC, about 32 GB (29.1 GiB usable). The vendor kernel runs it at HS400 with enhanced strobe and command queueing. No microSD slot. | works at HS200, verified 2026-09-27; HS400 not tried |
| Storage encryption engine | Qualcomm inline crypto engine (ICE) for the eMMC. Android's stock encryption keeps its key in TrustZone, which is why stock encryption can't be used from another OS. | not used |
| GPU | Adreno 509 (a5xx family), firmware from the device's vendor partition | partial: the e-ink engine uses it, verified 2026-09-29; browser hardware rendering faults |
| PMICs | Qualcomm PM660 + PM660L, regulators controlled through the RPM | works, verified 2026-09-27 |
| Suspend | s2idle down to the lowest SoC power state (XO shutdown) | works, verified 2026-10-01 |
Display¶
The Note Air has no e-ink timing controller chip. The CPU (or the GPU) computes every waveform frame and streams it to the panel over the display link, the same design as the reMarkable 2. GlassineOS does this in its user-space e-ink engine.
| Component | What it is | Mainline status |
|---|---|---|
| Panel | E Ink, 10.3 inch, 1872 × 1404 (227 ppi). Onyx calls it ES103TC2; the waveform names the film ES103TD1C1. 16 visible grey levels. | works, verified 2026-09-27 |
| Display link | SoC display engine → DSI (command mode, 2 lanes) → Toshiba TC358762 DSI-to-parallel bridge → panel source and gate drivers, about 85 frames per second | works, verified 2026-09-27; needs GlassineOS kernel patches |
| Panel power | Maxim MAX17135 high-voltage supply (panel rails + VCOM). VCOM is calibrated at the factory and stored inside the chip. | works, verified 2026-09-27; controlled only by the GlassineOS panel driver |
| Waveform | Standard E Ink waveform file with 8 modes (including A2) over 14 temperature ranges. It is the device's own vendor file: GlassineOS reads it from the device and never ships it. | works, verified 2026-09-27 |
| Panel temperature | The panel has no sensor; the engine uses the battery temperature | works, verified 2026-09-27 |
| Frontlight | TI LM3630A, two LED strings: warm and cold | works, verified 2026-09-28 |
Input¶
| Component | What it is | Mainline status |
|---|---|---|
| Touch | Cypress/Parade TrueTouch (cyttsp5 family), I2C, 10 contacts | works, verified 2026-09-28 |
| Pen | Wacom EMR digitizer, HID over I2C: 4096 pressure levels, hover, tilt, eraser | works, verified 2026-09-28 |
| Buttons | Only a power button. There are no volume keys. | works, verified 2026-09-27 |
| Cover | Hall sensor for the magnetic cover; wakes the device. The bootloader also reads it at power-on. | works, verified 2026-09-30 |
| LED | Red and blue LEDs visible through a pinhole in the power button (PM660L). The blue one also lights in the crash-dump mode and in recovery. A green channel exists but gives no visible light. | red works, verified 2026-09-27; blue untested on mainline |
Power¶
| Component | What it is | Mainline status |
|---|---|---|
| Battery | 3000 mAh, 4.40 V maximum charge voltage | works, verified 2026-09-27 |
| Charger | PM660 charger, 1.5 A maximum | works, verified 2026-09-28 |
| Fuel gauge | PM660 fuel gauge | works, verified 2026-09-27 |
| USB | One USB-C port, USB 2.0 high speed. Linux runs it as a device (gadget) only: Type-C role detection is not wired up. | works, verified 2026-09-27 |
Radios and audio¶
| Component | What it is | Mainline status |
|---|---|---|
| Wi-Fi | Qualcomm WCN3990, 2.4 and 5 GHz. Its firmware runs on the modem processor and comes from the device's own modem partition. | works, verified 2026-09-28 |
| Bluetooth | WCN3990 Bluetooth core on a UART. The chip has no address of its own; the system assigns one. | works incl. audio, verified 2026-10-01 |
| Modem | No SIM or mobile data. The modem processor still runs, because Wi-Fi depends on it. | works, verified 2026-09-27 |
| Speaker | One speaker (mono), Awinic AW88194 smart amplifier fed by the audio DSP | works, verified 2026-10-03 |
| Microphone | Digital microphones through the SoC's digital codec. No headphone jack. | untested on mainline |
| Orientation sensor | STMicroelectronics LSM6DSM accelerometer and gyroscope. It sits behind the sensor core on the audio DSP, not on a bus Linux can reach directly: Linux talks to the sensor core over QMI (qcom_smgr, IIO device qcom-smgr-accel; look it up by name, the number changes), and the sensor core needs its registry (sns.reg, copied from persist). The registry lists Qualcomm's reference sensor set; only the LSM6DSM probes. |
works, verified 2026-10-12 |
Not in the device: volume keys, microSD slot, headphone jack, vibration motor, NFC, ambient light sensor. The vendor device tree describes a haptics block and an NFC controller from the reference design; neither is fitted. No serial console pads are known, so debugging runs over USB (network gadget and SSH) and the kernel's crash log in reserved RAM.
Partitions and boot chain¶
Boot chain¶
PBL (boot ROM) → XBL (Qualcomm, closed source: reads the partition table, checks
the bootloader's signature) → ABL (the Android bootloader, a UEFI application in the
abl partition) → Linux, from boot_a, boot_b or recovery.
- Secure boot is not enforced. The bootloader is unlocked and the secure-boot fuses are not blown. Even the stock ABL is signed with Qualcomm's public test keys, so XBL accepts a self-built ABL signed the same way. It must use signing format v5: an image signed with v3 is rejected without any message and the device drops into emergency download mode (EDL). Verified on hardware 2026-03-26.
- GlassineOS replaces the ABL with a modified build of Qualcomm's open-source bootloader. What it changes compared to stock:
| Change | Why |
|---|---|
| Graphical fastboot menu disabled | The menu cannot draw on the e-ink panel and blocks USB, so fastboot never appears |
| Cover closed at power-on (held ~3 s) → fastboot | A way into the bootloader that needs no working OS (stock has no such mode) |
fastboot oem reboot-edl, fastboot oem reboot-recovery |
Reach EDL and recovery from fastboot |
Separate recovery partition also boots on an A/B layout |
Stock A/B bootloaders only boot boot_<slot> |
| System partition and its verity device follow the slot | Stock code hard-wired slot A's system partition |
- Boot images use the Android boot image format, header version 0, page size 4096,
with a gzip-compressed kernel and the device tree appended to it. The ABL selects the
device tree by msm-id
0x159and board-id8. A kernel stored uncompressed is rejected with error0x50. Verified on hardware 2026-09-27. - Kernel command line: the ABL appends
androidboot.*, root and dm-verity arguments meant for Android, plusskip_initramfson normal boots (not on recovery boots). Mainline Linux ignores them. - Reboot reason: kept in a PMIC power-on register, 1 = recovery, 2 = bootloader (the
same values the mainline
qcom-pondriver writes). The ABL clears it after reading, so a reboot into recovery happens once.
Partition table¶
The eMMC holds 61,071,360 sectors of 512 bytes, with a GPT. XBL reads the table; if the primary copy is damaged it uses the backup copy at the end of the disk, and Linux then repairs the primary. Verified on hardware 2026-06-01.
Stock layout¶
As shipped (firmware 3.5): one slot, 48 partitions, numbered in disk order. Start is the first 512-byte sector. Read from a factory backup taken 2026-03-16.
| # | Name | Start | Size | Content |
|---|---|---|---|---|
| 1 | xbl |
131072 | 3.5 MiB | second-stage bootloader (XBL) |
| 2 | xblbak |
138240 | 3.5 MiB | backup copy of XBL |
| 3 | tz |
145408 | 4 MiB | TrustZone |
| 4 | rpm |
153600 | 512 KiB | RPM power-manager firmware |
| 5 | hyp |
154624 | 512 KiB | hypervisor |
| 6 | pmic |
155648 | 512 KiB | PMIC configuration |
| 7 | fsg |
156672 | 2 MiB | modem settings, factory copy (unit-specific) |
| 8 | boot |
262144 | 64 MiB | Android kernel |
| 9 | recovery |
393216 | 64 MiB | Android recovery |
| 10 | system |
524288 | 3 GiB | Android system; also holds the e-ink waveform |
| 11 | vendor |
6815744 | 800 MiB | Android vendor files; also GPU and audio firmware |
| 12 | cache |
8519680 | 256 MiB | Android cache |
| 13 | keymaster |
9043968 | 1 MiB | TrustZone application |
| 14 | cmnlib |
9046016 | 1 MiB | TrustZone library |
| 15 | cmnlib64 |
9048064 | 1 MiB | TrustZone library |
| 16 | mdtpsecapp |
9050112 | 4 MiB | Qualcomm anti-theft (MDTP) |
| 17 | mdtp |
9058304 | 32 MiB | Qualcomm anti-theft (MDTP) |
| 18 | modem |
9123840 | 110 MiB | modem, Wi-Fi and audio DSP firmware |
| 19 | dsp |
9349120 | 16 MiB | DSP firmware |
| 20 | abl |
9381888 | 1 MiB | Android bootloader (ABL) |
| 21 | dip |
9383936 | 1 MiB | Qualcomm system data |
| 22 | devinfo |
9385984 | 4 KiB | Qualcomm system data |
| 23 | apdp |
9385992 | 256 KiB | Qualcomm debug policy |
| 24 | msadp |
9386504 | 256 KiB | Qualcomm debug policy |
| 25 | dpo |
9387016 | 1 KiB | Qualcomm system data |
| 26 | splash |
9387024 | 32.6 MiB | boot logo |
| 27 | limits |
9453872 | 4 KiB | Qualcomm system data |
| 28 | toolsfv |
9453880 | 1 MiB | Qualcomm system data |
| 29 | logfs |
9568256 | 8 MiB | firmware logs |
| 30 | ddr |
9699328 | 1 MiB | memory training data |
| 31 | sec |
9701376 | 16 KiB | Qualcomm system data |
| 32 | bluetooth |
9701408 | 1 MiB | Bluetooth firmware |
| 33 | fsc |
9830400 | 1 KiB | modem settings (unit-specific) |
| 34 | ssd |
9830408 | 8 KiB | TrustZone secure storage |
| 35 | modemst1 |
9830424 | 2 MiB | modem settings (unit-specific) |
| 36 | modemst2 |
9834520 | 2 MiB | modem settings (unit-specific) |
| 37 | persist |
9838616 | 32 MiB | unit calibration (unit-specific) |
| 38 | misc |
9904152 | 1 MiB | boot control block (recovery requests) |
| 39 | keystore |
9906200 | 512 KiB | Android keystore |
| 40 | devcfg |
9907224 | 1 MiB | TrustZone device configuration |
| 41 | frp |
9909272 | 512 KiB | Android factory-reset protection |
| 42 | logdump |
9910296 | 64 MiB | crash logs |
| 43 | sti |
10041368 | 2 MiB | Qualcomm system data |
| 44 | storsec |
10092544 | 128 KiB | TrustZone secure storage |
| 45 | rawdump |
10223616 | 128 MiB | crash dump area |
| 46 | vbmeta |
10485760 | 64 KiB | Android verified-boot metadata |
| 47 | onyxconfig |
10616832 | 32 MiB | Onyx settings; survives a data wipe |
| 48 | userdata |
10682368 | 24.03 GiB | Android data (to sector 61071326) |
Development layout (A/B)¶
Adds a second slot for Linux. Nothing moves: boot, system and vendor are renamed in
place, and the new partitions come from the end of userdata. The table grows from 48
to 64 entries. Verified on hardware 2026-06-02.
| Change from stock | Partitions |
|---|---|
| Renamed, same position | 8 boot → boot_a, 10 system → system_a, 11 vendor → vendor_a |
| Shrunk | 48 userdata now ends at sector 53009407: 20.18 GiB. Android keeps its data here; GlassineOS keeps /home here too. |
| New | 49 boot_b (start 53009408, 64 MiB): GlassineOS kernel · 50 system_b (start 53140480, 3 GiB): GlassineOS root file system · 51 vendor_b (start 59431936, 800 MiB): copy of vendor_a |
| Unchanged | everything else, including the unsuffixed 9 recovery (TWRP, or a one-time test boot) |
The layout GlassineOS will install is not final (see Decisions).
Never write¶
xbl, xblbak, tz, rpm, hyp, pmic, devcfg, keymaster, cmnlib, cmnlib64,
modem, dsp, bluetooth, persist, modemst1, modemst2, fsg, fsc,
onyxconfig, sec, storsec, splash. The partitions marked unit-specific hold data
that exists only on this device and cannot be recreated. onyxconfig survives a data
wipe; leave it alone. Writable during installation and development: boot*, system*,
vendor*, recovery, userdata, misc, abl.
Slots¶
Slot state lives in GPT attribute bits of boot_a and boot_b: bits 48–49 priority, 50
active, 51–53 retries left, 54 boot successful, 55 unbootable.
- The ABL boots the active slot with the highest priority. It does not look at the unbootable bit when choosing.
- A slot marked unbootable falls back to the other slot, if that one is marked successful, followed by a cold reset.
- Nothing on the device marks a boot as successful. A slot without the successful bit
uses up its 7 retries and then falls back, so the slot you want must be pinned:
active, priority 3, successful (
0x007Fin the top bytes). - The ABL clears the active bit of the slot it is not booting.
Verified on hardware 2026-06-03.
How GlassineOS boots¶
How this device maps onto the boot flow:
| Boot flow | Note Air |
|---|---|
| GlassineOS slot | slot B, pinned: kernel in boot_b, root file system on system_b |
| Vendor slot | slot A: stock Android 10 |
| Test partition | recovery (holds either a test image or TWRP, not both) |
| One-shot request | PMIC reboot reason, cleared by the ABL after reading |
| Way in without an OS | cover closed at power-on → fastboot |
| Role marker | skip_initramfs, which the ABL adds on normal boots but not on recovery boots. The GlassineOS kernel drops the other Android arguments the ABL adds and keeps this one in a renamed form. |
| Data partition | userdata, shared with Android |
| Crash log | RAM at 0x9f800000, 512 KiB, the stock layout with error correction off: the stock kernel and mainline read each other's log. A warm reset or a long press keeps it; a cold power-off erases it. Verified on hardware 2026-09-27. |
Device-specific early services:
- Watchdog timeout 20 s; the initramfs waits up to 15 s for
system_b, because the eMMC appears at about the time the initramfs starts. - GPU firmware comes from
vendor_b(the slot's copy ofvendor_a), the sensor calibration frompersist. - Wi-Fi needs the modem. Its helpers serve the modem's settings from RAM copies (the originals are never written), provide its firmware files and service locations, and answer its diagnostics channel. Without that answer, the modem stops Wi-Fi within seconds.
- The Wi-Fi MAC comes from a per-unit file (see Firmware).
Daily boot and test boot verified on hardware 2026-10-01.
Getting in and getting out¶
Modes and how to reach them¶
| Mode | How to enter | What it is for |
|---|---|---|
| Normal boot | Power on | Boots the active slot |
| Fastboot | Close the cover, then power on and hold about 3 s. From Linux: reboot bootloader (untested) |
Bootloader commands; needs no working OS. Only with the GlassineOS bootloader. Cover route verified 2026-10-04. |
| Recovery | reboot recovery (Linux), adb reboot recovery (Android), fastboot oem reboot-recovery |
Boots the recovery partition once |
EDL (USB 05c6:9008) |
adb reboot edl from Android, or fastboot oem reboot-edl |
Qualcomm emergency download: read and write any partition |
Crash dump (USB 05c6:900e) |
Only after a crash | Read the RAM; cannot write anything |
The "hold power, then press it five times" recovery sequence found online does not work on this device.
A long press on power (about 13 s) is a reset, not a way to stay off: the device turns off and boots again.
Fastboot¶
getvar (single variables, not all), reboot and the oem commands above work.
fastboot flash and fastboot boot hang at "Sending" with every bootloader version
tried, stock included; the cause is unknown. Partitions are written from a running
system with dd, or over EDL. fastboot erase misc is refused.
EDL¶
- Use the SDM636 "peek" firehose loader. The standard OEM firehose loader starts, then hangs while reading the partition table and never writes. Verified 2026-06-02.
- Only the first operation after entering EDL detects the 512-byte sector size reliably; later operations in the same session can fail with "512 vs 4096". Enter EDL again for each operation that writes sectors.
- Erasing over EDL fails for the same reason; erase from a running system instead.
- On a Linux host, blacklist the
qcserialdriver (it takes the device away from the EDL tool), start the tool before plugging in, and never run two tools on the device at once. - Without a working bootloader the software routes are gone. A USB cable with D+ shorted to ground then reaches EDL only if the battery is fully drained and the device starts cold with the cable attached. Test points on the board are not known.
Crash-dump mode¶
After a kernel crash the device can stop in Qualcomm's crash-dump mode (USB 05c6:900e).
It holds the RAM, including the kernel log of the crash: read a RAM dump first (read-only,
about 2 minutes; unplug and replug if it stalls after "sahara"), then long-press power.
Undoing each step¶
| Step | How to undo it |
|---|---|
| Bootloader replaced | Write the previous bootloader (or the stock one from your backup) over EDL |
| Partition table changed | Write the saved partition table back from Linux with dd, backup copy first, then the primary; read both back before rebooting |
| Default slot changed | Pin the other slot again (from Linux or Android) |
| New Linux boot image | The previous image is kept and can be written back |
| Recovery replaced | Write TWRP back to recovery |
| Anything else | Restore the full backup over EDL. Make a full backup of every partition before the first change. |
- Boots into recovery every time: a stale request in the boot control block (left by
Android after a failed data mount, a reset loop or the encryption lockout). A reset does
not clear it. Zero the first 2 KiB of
miscfrom Linux or as the first EDL operation. - Recovery hangs before its USB comes up: open the cover and power-cycle; the device boots normally.
Status¶
GlassineOS on the mainline kernel is the daily system on this device; it has not been released. The per-component detail is in Hardware.
| Feature | State | Last verified on hardware | Known issues |
|---|---|---|---|
| Boot (mainline kernel) | works | 2026-10-01 | — |
| Display / e-ink engine | works | 2026-10-01 | — |
| Touch | works | 2026-09-28 | a stray tap after resume (fix written, untested) |
| Pen | works | 2026-09-28 | — |
| Suspend / resume | works | 2026-10-01 | suspend current not yet measured; USB needs a reset after resume |
| Wi-Fi | works | 2026-09-28 | — |
| Bluetooth | works | 2026-10-01 | — |
| Audio | partial | 2026-10-03 | speaker works; microphone untested |
| Battery / charging | works | 2026-09-28 | — |
| CPU frequency scaling | partial | 2026-09-28 | capped at 1401.6 MHz |
| GPU | partial | 2026-09-29 | browser hardware rendering faults |
| Orientation sensor | works | 2026-10-12 | — |
| Updates | no | — | no update mechanism yet |
| Recovery | partial | 2026-06-08 | TWRP (vendor kernel) works and can be put back; the recovery partition currently serves test boots; a mainline recovery is planned |
| kexec | no | 2026-09-27 | the one attempt hung |
Pitfalls¶
Each entry: what not to do, what happens, what to do instead. Most crashes end in crash-dump mode; see Getting in and getting out for the way out.
Display and panel¶
| Don't | What happens | Instead |
|---|---|---|
| Write the MAX17135's VCOM or timing registers | They are stored in its non-volatile memory; a wrong VCOM can damage the panel. Its vendor driver rewrites that memory when the timings differ from its own. | Read VCOM only. The only register to write is the rail-enable register (0x09). Never bind a generic MAX17135 driver. |
| Keep panel high voltage on while the display link is slow, stalled or repeating frames | Each waveform phase lasts too long and over-drives the panel (pulsing, washed-out updates) | Raise high voltage only on a healthy link; never resend a drive frame; never read the scan-out buffer through write-combined memory while streaming |
| Copy power-rail assignments from a reference board | Our first board file put the display link's analog supply on the wrong regulator; the display died whenever Wi-Fi or Bluetooth released the shared one | Check every rail against the vendor device tree. The link's analog supply is PM660 L6, shared with the Wi-Fi radio and Bluetooth amplifier. |
| Talk to the TC358762 bridge over I2C while frames stream | Undefined bridge state | Configure it only with the link idle |
Things that crash the SoC¶
All of these end in crash-dump mode, verified on hardware between 2026-09-25 and 2026-10-03:
| Don't | Instead |
|---|---|
Read /sys/kernel/debug/gpio |
Some pins belong to TrustZone; read each device's own state |
Read the display PHY clocks or clk_summary while the display is off |
Read clocks only with the display on |
Read RPM data or code RAM through /dev/mem |
Only the RPM message RAM is safe to read live |
| Unbind GLINK/rpmsg devices (APR, fastrpc, QRTR) through sysfs | Unbind platform drivers only |
| Stop the modem processor | Leave it running: Wi-Fi depends on it, and a stopped modem crashes the next suspend. A stopped audio DSP does not start again. |
| Run new GPU code unattended | GPU hangs could freeze the SoC; the GlassineOS kernel fixes the known causes, but run new GPU work supervised |
Suspend and debugging¶
no_console_suspendresets the device on suspend, without a crash log. Don't use it.- The SoC watchdog does not count while suspended, so it cannot catch a suspend hang.
- Arm the watchdog before kexec or any test boot; without it a hang needs a long press.
- A cold power-off erases the crash log (kept in reserved RAM). A warm reset keeps it, and so did a long press in our tests. Capture logs after warm resets.
Storage, slots and data¶
| Don't | What happens | Instead |
|---|---|---|
Format userdata with mke2fs across the whole partition |
Android cannot set up encryption (no room for the 16 KiB footer) and hangs at boot | Format it with TWRP's Format Data, which leaves the room |
Shrink userdata in the partition table without reformatting |
Android reports "Encryption failed" | Reformat after shrinking |
Format Data or enable Android encryption while GlassineOS keeps /home on userdata |
GlassineOS user data is erased or locked | Back up /home first |
| Mount a slot's system partition read-write | Its contents no longer match its verity tree; that slot won't boot under enforced verity | Write the whole partition image back with dd |
| Write a partition table where no slot is active | The ABL finds nothing to boot | Keep exactly the slot you want active and pinned; read the table back before rebooting |
Write a modem storage partition (modemst1, modemst2, fsg, fsc) |
Unit-specific radio settings are lost | Serve them from RAM copies (rmtfs -r) |
| Use linux-firmware's generic WCN3990 Wi-Fi files | They are built for another SoC | Use the device's own files (see Firmware) |
Bricks¶
- Never write
xblor any partition from the "never write" list in Partitions. - Never flash bootloaders or firehose loaders made for UFS devices (such as the Note Air 2).
- Don't flash with a low battery: a power loss during a bootloader write leaves only the drained-battery EDL route.
- In bootloader code, never access hardware registers that the UEFI memory map doesn't cover: one such read stopped the bootloader before USB came up (red LED), and only the drained-battery EDL route got the device back. The GPIO block must be read through its "south tile" address range; the flat range is blocked and hangs the boot.
Stock Android (slot A)¶
- A reset loop that offers a factory reset can come from Onyx's app freezer
(
eac_configon theonyxconfigpartition) freezing a core Android component. Wiping data doesn't fix it, becauseonyxconfigsurvives the wipe. - The RIL daemon keeps the device from deep sleep on this Wi-Fi-only tablet (holds a wakelock for nearly all of the uptime); stopping it costs nothing.
Firmware¶
GlassineOS ships none of this. The installer and the running system read it from the device's own partitions. Several files exist only on this unit; never write those partitions.
| Partition | Contains | Needed by |
|---|---|---|
modem (vfat) |
Modem firmware and its authenticator, the Wi-Fi firmware that runs on the modem processor, the Wi-Fi board data, the audio DSP image | Wi-Fi (the modem must run for Wi-Fi), audio |
dsp |
DSP firmware | audio DSP |
bluetooth (vfat) |
WCN3990 Bluetooth ROM patch and settings (NVM) | Bluetooth |
vendor_a |
GPU zap shader (signed), GPU microcode, speaker amplifier settings | GPU, speaker |
system_a |
/waveform/eink_waveform.wbf: the panel's waveform, a standard E Ink file (85 Hz, 8 modes × 14 temperature ranges, including A2) |
the e-ink engine; without it nothing is drawn |
persist |
Unit calibration (Wi-Fi, sensors) and the modem's writable data | Wi-Fi, sensor DSP |
modemst1, modemst2, fsg, fsc |
Modem settings, unique to the unit | modem (served from RAM copies) |
If Android is ever removed, the waveform and the vendor files must be copied first: they live on Android's partitions.
What else the firmware needs at runtime:
- Wi-Fi: the modem processor,
rmtfs(modem storage), a TFTP server, the protection domain mapper, and a DIAG-over-QRTR receiver. Without that receiver the modem's watchdog restarts it 10–20 s after Wi-Fi starts. ath10k also needs afirmware-5.binfeature file and a per-board firmware directory set in the device tree. Don't use linux-firmware's generic WCN3990 files; they are built for another SoC. - Wi-Fi MAC address: it is not stored in any partition. Stock Android gets it from the Wi-Fi chip at runtime; mainline Linux does not, and without help picks a new random address on every boot (routers then hand out a new lease each time). The installer reads the address on stock Android before migrating and saves it in the new system, which sets it at boot. Each unit has its own: never put one in a device tree or an image.
- Bluetooth: the chip has no address of its own; the system must assign one before the adapter comes up.
- GPU: the vendor microcode lacks the marker the kernel needs for multiple ring buffers; GlassineOS uses linux-firmware's A530 microcode for that and keeps the vendor copy as a fallback (not yet verified on hardware).
- Audio: the audio DSP must be running before the sound card binds.
Verified on hardware 2026-09-27 to 2026-10-01 unless marked.