Hardware documentation, firmware, and distro-agnostic tooling for the reMarkable Paper Pro Move (codename chiappa, NXP i.MX 93).
Known integrations built on this layer: remarkable-nixos (NixOS).
| Product | reMarkable Paper Pro Move |
| Codename | chiappa (ferrari = Paper Pro without Move) |
| FCC ID | 2AMK2-RM03AA |
| SoC | NXP i.MX 93, 2× Cortex-A55 @ 1.7 GHz + Cortex-M33 |
| RAM | 2 GB LPDDR4 (Micron) |
| Storage | 64 GB eMMC (Kingston EMMC64G-TY29), GPT |
| Display | E Ink Gallery 3 (color), 1696×954, 264 DPI, 16-bit parallel RGB565 from LCDIFv3 |
| Touch | Elan SPI (elants_spi) |
| WiFi / BT / NFC | NXP IW611 combo (WiFi 6 / BT / NFC) |
| USB | USB-C OTG, ci_hdrc_imx (chipidea), CDC ECM gadget |
| PMIC | NXP PCA9451A |
| Charger | MAX77818 |
| Frontlight | AW99703 (I2C, PWM) |
| Accelerometer | ST LIS2DW12 (I2C) |
| Kernel | latest stable mainline Linux + the kernel/ series (the vendor OS runs an NXP BSP fork of 6.12.49, linux-imx-rm) |
| Bootloader | U-Boot 2025.04 (NXP ELE / AHAB) |
| HW revisions | DTBs for rev F–K; all six are byte-identical in current firmware |
| Vendor OS | Codex Linux 5.6 / image 3.27.1.0 (Yocto scarthgap) |
mmcblk0 64 GB whole device (GPT)
mmcblk0p1 100 MB vendor data / config (persistent across OS flashes)
mmcblk0p2 4.0 GB ext4 root_a ← A/B slot
mmcblk0p3 4.0 GB ext4 root_b ← A/B slot
mmcblk0p4 1.6 GB swap (dm-crypt, key from lpgpr bootkey)
mmcblk0p5 48 GB data / home
mmcblk0boot0 4 MB bootloader (imx-boot)
mmcblk0boot1 4 MB bootloader (imx-boot, redundant copy)
ELE (S400) → SPL → ATF (BL31) → U-Boot 2025.04 → rM_bootcmd
rM_bootcmd = run loadimage; run authimage; run mmcboot:
| Step | Action |
|---|---|
loadimage |
Load /boot/fitImage.ahab from active slot → RAM at 0x8FFFE000 |
authimage |
If unlocked=yes: skip AHAB auth. Otherwise: enforce auth_cntr |
mmcboot |
run mmcverity; run mmcswap; run mmcargs; bootm 0x90000000#${fit_config} |
imx-boot lives in the eMMC boot partitions (mmcblk0boot0/1). The FIT image
(fitImage.ahab, kernel + 6 rev DTBs, no ramdisk) lives in the active rootfs at
/boot/. U-Boot selects the DTB config matching the detected PCBA revision.
The U-Boot unlocked env var — the device's AHAB lifecycle state (a one-way
fuse: OEM Open → Closed → Locked) — gates both kernel authentication and the root
device:
unlocked |
Kernel auth | Root device |
|---|---|---|
yes (OEM Open) |
AHAB auth skipped — unsigned FITs boot | plain partition (/dev/mmcblk0pN) |
no (default) |
auth_cntr enforced — only reMarkable-signed FITs |
dm-verity (/dev/dm-0, read-only) |
Enabling Developer Mode
(vendor OS settings) moves the device to OEM Open / unlocked=yes — the
prerequisite for booting a custom kernel — and reveals the SSH/root password
(Settings → Help → About). It wipes user data, so do it first. A vendor recovery
flash does not re-lock the device. Full walkthrough:
docs/booting-a-custom-os.md.
reMarkable ships rm_recover (bundled uuu) which drives the NXP Serial Download
Protocol (USB SDP) — the device appears as 2edd:0140 "OC Blank 93" — then loads
imx-boot, enters U-Boot fastboot, and flashes eMMC. This path is independent of
the A/B slots and boot counters.
rm_recoveris a dynamically linked x86-64 ELF (glibc).- Recovery server:
https://device-recovery.cloud.remarkable.com/{device,host}/release-latest(current image3.27.1.0, machinechiappa). Object URLs are runtime-computed by the tool; userm_recover discover-deviceto confirm it sees the device. - Enter recovery mode: connect USB + hold the power button.
| Subsystem | Status | Notes |
|---|---|---|
| Boot + USB ECM networking | ✅ | configfs gadget, device at 10.11.99.1/24 |
| WiFi (IW611) | ✅ | sd_w61x_v1.bin.se required |
| Bluetooth | ✅ | uartspi_n61x_v1.bin.se required |
| NFC | ✅ | ctn730.fw required |
| Touch (Elan) | ✅ | elants_spi.bin; needs the runtime-PM udev fix (kernel/README) |
| Pen | ✅ | marker-asic.bin + marker-mcu.bin; same touch controller |
| Frontlight | ✅ | /sys/.../rm_frontlight sysfs |
| Accelerometer | ✅ | LIS2DW12 IIO driver |
| Battery / charging | ✅ | MAX77818; mind the power budget (docs/power.md) |
| E-ink display (Gallery 3, color) | ✅ | Via einkbridge — see E-ink display |
| Wayland on e-ink (VKMS) | ✅ | vkms_bridge + chiappa-compositor; requires CONFIG_DRM_VKMS=m |
| Suspend / wake | ✅ | Power button wake |
| A/B boot slots | ✅ | See A/B boot slots |
chiappa/
├── docs/
│ ├── hardware.md # component/driver map, partition + boot chain
│ ├── booting-a-custom-os.md # FIT + A/B slots, no-UART deploy, gotchas
│ ├── fitimage.md # FIT / AHAB container layout, rebuild procedure
│ ├── obtaining-vendor-blobs.md # extracting firmware + Qt/eink runtime
│ ├── eink.md # e-ink pipeline + low-level frame format
│ ├── power.md # charging budget, idle draw, low-battery pitfalls
│ └── recovery.md # SDP unbrick + non-destructive slot switch
├── kernel/ # Mainline kernel: patch series, config fragment + full config, README
├── eink/ # e-ink toolkit — see eink/README.md
│ ├── src/ # einkbridge.cpp, vkms_bridge.c, libfakekms.c, swtfb_fill.c, RE tools
│ ├── scripts/ # build-bridge.sh, build-bundle.sh, chiappa-compositor, RE helpers
│ ├── bridge.qml # display surface loaded by einkbridge
│ ├── 60-chiappa-touch.rules # touch-controller runtime-PM udev fix
│ └── bin/ # prebuilt aarch64 binaries
├── recovery/ # rm_recover wrapper, uuu scripts, slot-switch.uuu
└── firmware/
├── MANIFEST.md # sha256 BOM for every extracted file
├── extract.sh # Extracts firmware blobs from any production image
├── lib/firmware/ # Kernel firmware blobs (WiFi, BT, NFC, pen, touch, TEE)
├── waveforms/ # E-ink waveform + colortable files
└── images/ # Vendor production image archive
Vendor-extracted files (firmware blobs, waveforms, the Qt/eink runtime,
rm_recover, the production image, and the vendor device trees) are not committed — the paths above are populated by extracting them from your own device / firmware image (see docs/obtaining-vendor-blobs.md and docs/fitimage.md for the AHAB header).
The latest stable mainline Linux plus the patch series in
kernel/: apply the 0*.patch files in order (skipping 0003
on a tree that already has the i.MX93 PDFC driver), build with
kernel/config-chiappa-mainline.aarch64 as your complete .config (it is
generated from kernel/chiappa-mainline.config by regenerate-config.sh;
do not run olddefconfig on the fragment alone, it drops CONFIG_ARCH_MXC
and with it the whole i.MX platform). WiFi is NXP's out-of-tree mwifiex
driver, tag lf-6.18.37-2.1.0, with the patch in kernel/mwifiex/. See
kernel/README.md for what the series carries, how to
bump the kernel, and the bring-up checklist.
Notable config flags:
CONFIG_DRM_VKMS=m— virtual DRM device, required for Wayland compositorsCONFIG_USB_CONFIGFS_ECM=ywith the gadget built in — the headless USB link needs no modulesCONFIG_PSTORE_RAM=y+ aramoopsreservation in the DT — crash logs without a UART
None of the proprietary files (firmware, waveforms, the Qt/eink runtime) are committed — you extract them from your own device or firmware image. Full walkthrough: docs/obtaining-vendor-blobs.md.
Quickest path, straight from the vendor production image:
cd firmware/
./extract.sh images/remarkable-production-image-3.27.1.0-chiappa-public.ext4.verity.gz(or extract-vendor-data.sh <vendor-rootfs.img> if you already have a mounted
or decompressed rootfs.)
Then install firmware/lib/firmware/ → /lib/firmware/ and
firmware/waveforms/ → /usr/share/remarkable/ on the target.
The kernel build produces freescale/imx93-remarkable-chiappa.dtb from the
series' DTS; one DTB serves all PCBA revisions (the vendor firmware ships six
byte-identical DTBs for rev F–K, which only boot the vendor kernel).
See docs/fitimage.md for the AHAB container layout and how to
build a fitImage.ahab for an unlocked device.
See E-ink display below and docs/eink.md.
Two symmetric rootfs slots (A = mmcblk0p2, B = mmcblk0p3). U-Boot boots the
slot whose eMMC boot partition is enabled (boot0 → A, boot1 → B; switch with
mmc bootpart enable 1|2 0 /dev/mmcblk0) and records the booted slot in the
lpgpr SNVS registers. It keeps a per-slot error counter there that
auto-rolls-back after 3 unreset boots — your safety net while experimenting.
Rules of thumb: deploy to the inactive slot, never touch the active one; reset the counter after writing a slot; and reset it late in boot (after SSH is up) so it's a genuine "boot succeeded" signal. Full mechanism, deploy recipe, and the SDP non-destructive slot switch: docs/booting-a-custom-os.md, docs/recovery.md.
The pipeline is entirely in userspace — raw DRM scanout to /dev/dri/card0
shows nothing; the cumulus panel needs the vendor waveform engine
(libqsgepaper / SWTCON) driving temporally-encoded frame sequences.
einkbridge (a Qt Quick app on the epaper QPA) drives it and exposes an
rm2fb-compatible IPC (/dev/shm/swtfb + /tmp/swtfb.ipc) so KOReader and
other rm2fb-aware apps work unmodified. vkms_bridge extends this to Wayland
compositors via the VKMS writeback connector (needs CONFIG_DRM_VKMS=m + kernel
patches 0002/0003).
Full pipeline, frame format, IPC structs, build/bundle steps, and the SWTCON constraints: docs/eink.md and eink/README.md.
MIT, except kernel/ (patches + config derived from the Linux
kernel — GPL-2.0-only, see kernel/LICENSE).
Vendor-extracted artifacts (firmware, waveforms, the Qt/eink runtime, and the
vendor device trees — whose corresponding source is not published) are never
part of this repo; you extract them from your own device.