Overview
The player
Device |
ODEJOI X91, 64 GB (Amazon B0FJC6PH93; part numbers X91 and ODX66). Built by RUIZU. |
Chip |
Actions ATJ2157 (ARM Cortex-M4 class), confirmed by the upgrade-mode signature |
Memory |
Under 300 KiB in all: a main region 0x100000 to 0x138000 (224 KiB) and two small ones at 0x200000 and 0x300000 |
Screen |
128 x 160, RGB565 |
Storage |
Intel NAND, ID |
Bluetooth |
Actions ATS2851 module (inferred from the shared build tree) |
Keys |
power, return, up, menu, next, play, down, prev, volume up and down |
Software |
Actions “US215A” SDK on uC/OS-II, firmware line |
USB |
|
Programs are bank-switched: each keeps only 0.6 to 2 KiB of code in memory and loads the rest from flash on demand. That rules out Rockbox and any system that needs its whole core in RAM.
What was done
Dump. No firmware for this player is published. It was read over USB with
actions_flash, twice, and verified file by file.Write path. The vendor’s flashing sequence, replayed on Linux, was rehearsed read-only, then used to write the unchanged image, then a modified one. Every write is read back and compared. See Reading and writing the firmware.
Graphite. A new interface built on top of the stock firmware in 27 stages: pictures, typeface, layouts, menus, settings, program patches and new program code in C (playlist editing, a search with a T9 keypad, naming playlists). See The Graphite design.
Tooling.
x91_tool.pydumps the firmware and flashes a theme;design/build.pybuilds every theme’s image from the stock dump in one go, deterministically.Release 1.0. The stages merged into that one build; its images are the stage 27 images, byte for byte.
Every stage up to 27 (search, “Add songs”, “New playlist” and “Rename” with names typed on the keypad) has been flashed and tested on the device; the last stage 24 rebuild only as part of the stage 25 to 27 images. Release 1.0 is the tested stage 27 image in each theme. See History.
The firmware in one page
Image. One “LFI” container of 137 files: programs (
.AP), drivers (.DRV), resources (.STY), menus (.MCG), settings (CONFIG.BIN), fonts (.FON), codecs (.AL), code-page tables (.TBL). Three levels of additive checksums. Size and file positions never change. The firmware image (LFI)Programs. A resident part plus code banks, each bank with its own address; banks of one group share a RAM window and replace each other there. The shared interface code (status bar, lists, menus, screensaver, key filter) is linked into every program separately. Programs (.AP), Shared interface code
Resources. Pictures (RGB565), strings in 28 languages, and layout tables (scenes, picture boxes, text boxes, number boxes, list boxes, sliders). An id with bit 15 set refers to
COMMON.STY. Resources, menus and fontsDisplay driver.
DRV_UI.DRV, reached withsvc 6: list boxes, text, numbers, pictures with transparency, screen rotation. Display driver (DRV_UI.DRV)Music.
MUSIC.APdrives the screens;MENGINE.APplays, controlled by messages;PLAYLIST.APbuilds the libraries (MUSIC.LIB,M3U.LIB). Music: program, engine and libraries
Constraints
The image is exactly 19,871,232 bytes and every file keeps its length and position; the boot loader rejects anything else.
No hardware key for upgrade mode is known. Recovery from a bad firmware goes through USB-drive mode, so
CONFIG.AP,UDISK.AP,FWUPDATE.AP, the drivers and the boot record are never modified (Hardware, boot and upgrade mode).There is no free space in the code. Patches rewrite existing code more compactly (Program patches); new code goes into the zero-filled tails of code banks (New program code (design/playlist)).