Skip to content

RetroStone2 Pro storage (eMMC, M.2 SATA, starter card), game covers, multi-disc, memory speed, model detection - #12

Merged
PaddleStroke merged 9 commits into
PaddleStroke:mainfrom
KurdtNervanna:pro-storage-upstream
Oct 23, 2026
Merged

PaddleStroke merged 9 commits into
PaddleStroke:mainfrom
KurdtNervanna:pro-storage-upstream

Conversation

@KurdtNervanna

Copy link
Copy Markdown
Contributor

This is the work proposed in #11, now complete and tested on a RetroStone2 Pro. It is based on the current main
(0.1.3 + the version bump) and merges cleanly. The other boards are untouched.

What it adds

RetroStone2 Pro storage (Settings > Storage; docs/pro-storage.md)

  • Fix: in 0.1.2 the Internal eMMC / M.2 SATA switches wrote /boot/rsos.env, but boot.cmd reads rsos_overlays
    from the U-Boot environment, so they had no effect. They now go through rsos-storage overlay (fw_setenv).
  • Regular or Pro, found at the first start: boot.cmd probes U-Boot's mmc 1 (the eMMC U23) once, when
    rsos_model is empty, and saves rsos_model=pro|regular. A Pro gets the emmc and sata overlays on that same
    start; a regular unit loses emmc. The menu hides the internal storage on a regular unit and offers "Detect the
    model again".
  • Install to internal storage (with or without the games, or update an existing install). The A20 boot ROM does
    not start this eMMC 5.0 by itself (Samsung AGND3R, EXT_CSD_REV 7; confirmed on hardware with breadcrumbs in AXP209
    data registers, U-Boot patch 0003). So the SD card can become a starter card: it keeps the SPL/U-Boot and the
    RETROSTONE partition, and U-Boot's bootcmd falls back to the system on mmc 1 (rsos_sysdev). The kernel learns
    the environment disk from rsos.envdev. Make this SD card a full system again undoes it.
  • Game libraries on several disks: the eMMC, the SD card (when it is not the system disk) and an M.2 SATA SSD
    are mounted under /run/rsos/media/<name> and merged into the game lists (loader.c, games_merge). Import games
    gets Copy games to. Move games between drives uses a new move_games import option: files are deleted
    only after the whole copy is synced, and files the plan sees as identical are compared byte for byte first
    (test_import_move).

Game lists (Settings > Game lists)

  • Download game covers from the libretro thumbnail server, as RetroArch does: a new rsos-covers helper reusing
    the updater's HTTPS client, with No-Intro/normalized/prefix matching and 400 px JPEGs in
    roms/<sys>/media/covers/. It can also run in the background.
  • Group multi-disc games (.m3u).
  • Rename this game (game options): the game's saves, states, cover, favorite and play time follow the new name.

Memory speed (Settings > Power): an opt-in DRAM clock of 432 or 480 MHz (U-Boot patch 0004 in
dram_sun5i_auto.c, which is the file sun7i builds). The faster speed starts as a trial: rsos-boot-ok runs a
memory test before confirming it, and a boot that freezes falls back to the normal speed. The trial state is kept
in AXP209 REG0D.

System information > Credits: generated from the git history (scripts/support/update-credits.sh).

System update: the update repository and the trusted key are now build options,
BR2_RETROSTONE_UPDATE_REPO and BR2_RETROSTONE_UPDATE_PUBKEY. The defaults are unchanged (this repository and
frontend/assets/update.pub). This lets a fork publish its own signed updates without patching the code.

Testing

  • Hardware (RetroStone2 Pro, 32 GB M.2 SATA SSD): these were tested on the console and work:

    • the switches
    • install to the eMMC, starting through the starter card, and back to a full SD system
    • M.2 erase, import to it, and playing from it
    • moving games and renaming
    • covers, also in the background
    • multi-disc grouping
    • both memory speed levels with the trial and fallback

    The model detection is new and has not been on hardware yet.

  • Tests: make check-ui check-loader check-transfer check-update pass (check-transfer: 669 tests). In
    boot-ab-qemu-test.sh, cases 14/15 were added for the model probe, and all 45 checks pass. The test U-Boot keeps
    the Cubieboard device tree, because uboot.fragment now selects the A20 eMMC one.

Not included: the fork's own update settings (its repository and signing key), which stay on the fork.

Builds of this branch: https://github.com/KurdtNervanna/RetroStoneOS/releases

🤖 Generated with Claude Code

KurdtNervanna and others added 9 commits October 20, 2026 18:23
… credits

Pro storage (eMMC U23, M.2 SATA J1), docs/pro-storage.md:
- Settings > Storage: the Internal eMMC and M.2 SATA switches now set
  rsos_overlays in the U-Boot environment (0.1.2 wrote /boot/rsos.env,
  which boot.cmd never reads, so they did nothing).
- rsos-storage helper: install RetroStoneOS to the eMMC (the SD layout,
  boot loader written last, everything read back), game disks (the eMMC or
  microSD the system does not run from, the M.2 SSD) mounted and merged into
  the game lists, hotplug, erase a disk for games, Import games > Copy
  games to, a per-boot eMMC report and storage.log on the card.
- The A20 boot ROM does not start this eMMC 5.0 (proven with AXP209
  breadcrumbs, U-Boot patch 0003), so the SD card can become a starter card
  (boot loader + games): U-Boot falls back to the eMMC's boot.scr
  (rsos_sysdev), its environment stays on the card (rsos.envdev,
  /dev/rsos-disk). "Make this SD card a full system again" undoes it.
- U-Boot: Lime-eMMC DT and MMC_SUNXI_SLOT_EXTRA=2; boot.cmd and the boot
  command follow the boot / system disk; board.ini data_disk = auto.

Game lists:
- Download game covers: rsos-covers (the updater's HTTPS client) gets box
  art from thumbnails.libretro.com, matched by file name, 400 px JPEG in
  roms/<system>/media/covers/, shown when gamelist.xml has no image.
- Group multi-disc games: the missing .m3u for "(Disc N)" sets.

Memory speed (Settings > Power): 384 / 432 / 480 MHz DRAM, chosen by the
SPL from an AXP209 register (U-Boot patch 0004) with the DDR3-1066F timings
for that clock; every faster start is a trial confirmed after a memory test
(rsos-memtest), any start that is not confirmed falls back by itself. The
shutdown time stamps moved to REG04-0C.

System information > Credits from the git history
(scripts/support/update-credits.sh). rsos-uipreview: --storage-helper and a
sleep: token for helper processes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
B on the cover download page lets it go on in the background (a toast says
so, and another one with the counts when it is done; the lists take the
covers at the next return to the carousel, their scan caches dropped).
Download game covers while one runs shows its page again; no other storage
task starts meanwhile. The storage tasks and the cover download keep the
console from its idle power-off (ui_storage_busy). rsos-covers runs at
nice 10, below a game that is played meanwhile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Settings > Storage > Move games between drives: pick the drive the games
come from (the system disk or a game disk), and the import screen opens
with that drive as its source: per-system counts, what is already there,
the space check, progress, the duplicate questions. "Copy games to" never
offers the source itself, there is no Eject for the console's own drives,
and "Delete from <drive> after copying" turns the copy into a move.

transfer: import option move_games. The game files (roms/: games,
gamelist.xml, media) that are on the destination at the end, copied or
already there with the same bytes (the plan's "identical" is checked byte
for byte first), are deleted from the source once everything was flushed
(a power cut leaves a game on both drives, never on neither). A differing
file kept by the answer stays; BIOS files, saves and themes never move;
nothing is deleted when the source is the destination. Test:
test_import_move.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Game options > Rename this game: the keyboard with the file name without
its extension; the file is renamed in its folder (the extension kept),
and what goes by its name follows: its cover (media/covers/), its saves
and save states (<data>/saves|states/<system>/<name>.*), its favorite,
play time and per-game settings (gamedb_rename). Names the card's file
system cannot hold, an empty name or a taken one are refused. Then, when
it has no cover and a network is there: "Look for a cover with the new
name now?" (one game's cover download, covers_start_one).

rsos-uipreview: type:<text> fills the on-screen keyboard
(ui_debug_type_text).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
boot.cmd probes U-Boot's mmc 1 (the eMMC U23, fitted on the Pro only) once,
when rsos_model is empty, and saves rsos_model=pro|regular. A Pro gets the
overlays emmc and sata on that same start (the internal storage and the M.2
slot work without a setting); a regular unit loses emmc, keeping sata and the
others. Settings > Storage shows This console > Model (also in System
information), hides the Internal storage section on a regular unit and
offers "Detect the model again" (rsos-storage redetect clears rsos_model).
A unit that runs from the eMMC or answers with one counts as a Pro anyway.

boot-ab-qemu-test.sh: cases 14 and 15 (regular, and a Pro through a test
boot.scr whose probe finds an eMMC); the test U-Boot keeps the Cubieboard's
own device tree (uboot.fragment selects the A20 eMMC one since the eMMC
boot work). 45 passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BR2_RETROSTONE_UPDATE_REPO (GitHub <owner>/<name>, default
PaddleStroke/RetroStoneOS) and BR2_RETROSTONE_UPDATE_PUBKEY (default
frontend/assets/update.pub), passed to the frontend as RSOS_UPDATE_REPO and
RSOS_UPDATE_PUBKEY. Nothing changes for the original project; a fork that
signs its own releases can point its images at them (docs/updates.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PaddleStroke added a commit that referenced this pull request Oct 23, 2026
Review of PR #12 (peripherals off by default, OTA-updated Pro):
- boot.cmd: the first start probes mmc 1 and saves rsos_model=pro or
  regular, nothing else: rsos_overlays stays the user's (the eMMC and
  the M.2 SATA slot stay off by default for a fast start; Settings >
  Storage turns them on). The probe runs only when rsos_sysdev is set,
  i.e. with this system's bootcmd: an older U-Boot (a card updated over
  the air) has no mmc 1 and would take a Pro for a regular unit.
- bootcmd: the card's slots are loaded first, exactly as before (no
  extra ext4 lookup on a normal start); mmc 1 is tried the same way only
  when neither card slot has a boot.scr (starter card).
- boot-ab-qemu-test.sh: cases 14/15 expect the overlays untouched; new
  case 16: an older bootcmd (no rsos_sysdev) does not probe. 47/47.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PaddleStroke
PaddleStroke merged commit ac2ba78 into PaddleStroke:main Oct 23, 2026
PaddleStroke added a commit that referenced this pull request Oct 23, 2026
…ll card

Review of PR #12:
- board-hooks.sh: "rsos-storage boot" runs only when the eMMC controller
  (1c11000.mmc, emmc overlay) or the SATA controller (1c18000.sata) is
  enabled, or the system is not on mmcblk0: a RetroStone2 with both off
  (the default) starts nothing.
- report (the eMMC diagnostics) is a manual command now ("rsos-storage
  report"), never at boot; it reads the AXP209 breadcrumbs itself
  (REG0E-0F, which the boot logger never clears), so rcS no longer runs
  "axpstamp raw" on every boot.
- sd-starter refuses unless the card's own U-Boot at 8 KiB is this
  system's and its saved bootcmd has the mmc 1 fallback (rsos_sysdev):
  an old card updated over the air would otherwise no longer start.
  New progress reason "oldbootloader".
- sd-full is power-cut safe: the old file systems of the card's slots
  lose their superblock before their MBR entries come back; slot A is
  copied and verified without its first 4 KiB, the data copied, then
  the first 4 KiB written last and read back (zeroed again on a
  mismatch), then the boot state.
- overlay, redetect, sd-starter, sd-full and the carried-over overlays
  take /run/rsos/bootenv.lock (rsos-boot-ok's and the updater's lock).
- rcS: /dev/rsos-disk falls back to /dev/mmcblk0 when RSOS_DISK is empty.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PaddleStroke

Copy link
Copy Markdown
Owner

Thank you very much for this PR, @KurdtNervanna! The Pro storage, the starter card trick, game covers, multi-disc grouping, rename and the memory speed trial are careful, well-documented work, and the A/B update and rollback logic still passes all its QEMU tests. We'd like this in 0.1.4, so instead of sending you a list of changes we made the remaining fixes ourselves, as extra commits on top of yours (your commits and authorship are unchanged). Here is what we changed and why:

Merge with main: main moved (input, transfer, Raspberry Pi, release notes). One conflict, in loader.c (Refresh game lists): we kept your ui_invalidate_system() (it also clears the library drives' caches) together with main's reset of the empty-folder shortcut.

Boot (boot.cmd, uboot.fragment)

  • The first-start probe now saves rsos_model only and never changes rsos_overlays. The project rule is "peripherals off by default": the eMMC and the M.2 SATA slot stay off until the user turns them on in Settings > Storage, so every RetroStone2 starts as fast as before. Turning them on automatically meant SATA link bring-up, mounts and a game-list reload on every boot of a Pro.
  • The probe only runs with the new bootcmd (rsos_sysdev set). A Pro updated over the air keeps its old U-Boot, which has no mmc 1, so it would have been saved as "regular" (and lost a user-set emmc overlay).
  • The bootcmd loads the card's boot.scr first, exactly as before, and tries mmc 1 only when neither card slot has one. A normal start no longer does an extra ext4 lookup.
  • QEMU: cases 14 and 15 updated, plus a new case 16 for the old bootcmd. 47/47 pass.

No storage work on every boot

  • rsos-storage boot only runs when the eMMC controller (1c11000.mmc) or the SATA controller (1c18000.sata) is enabled, or the system is not on the microSD.
  • The eMMC report is now a manual command, rsos-storage report. It reads the AXP209 breadcrumbs itself (REG0E/0F, which the boot logger never clears), so rcS no longer runs axpstamp raw on every boot.
  • The menu no longer runs rsos-storage refresh when it starts. It polls /sys/block every 10 s instead of every 2 s, and Settings > Storage runs a refresh when it opens.

Brick and data-loss edges

  • sd-starter refuses (and changes nothing) unless the card's own U-Boot is this system's and its saved bootcmd has the mmc 1 fallback. On a card flashed with an older version and then updated, it would otherwise leave a console that no longer starts.
  • On the install's done page, "Keep SD as it is" is now preselected, and "Use as starter card" opens the same CANCEL-first confirmation as the menu item.
  • sd-full is now safe against a power cut. The old file systems on the card's slots lose their superblock before their partition entries come back. Slot A is then copied and verified without its first 4 KiB, which are written last and read back, before the boot state. If the power is cut at any point before that, the card is still a starter card.
  • Group multi-disc games skips systems whose emulator doesn't take .m3u files (there the playlist would hide the discs behind an entry that can't start). It writes each playlist to a temporary file, syncs it, then renames it.
  • Move games: nothing is deleted if a file failed, a differing file was kept, or the copy was cancelled. gamelist.xml is never deleted. Before each deletion we lstat the source and its copy, and refuse for a link, a missing copy, or the same inode. A folder with a file whose bytes differ keeps all its files, so a .cue stays with its .bin. The summary says when games stayed on the source drive. test_transfer covers each of these cases.

Smaller fixes

  • /dev/rsos-disk falls back to /dev/mmcblk0 when RSOS_DISK is empty.
  • The Move games dialog keeps its own copies of the drive paths.
  • overlay, redetect, sd-starter, sd-full and the carried-over overlays take /run/rsos/bootenv.lock, the lock that rsos-boot-ok and the updater use.

Translations, docs: po/rsos.pot is regenerated, so check-i18n passes. The new strings are translated into French. The other languages show English for now, as usual until they are translated. We updated docs/pro-storage.md (the model probe, off by default, a freshly flashed 0.1.4 card needed for the Pro storage, the hardware checklist), added a 0.1.4 release-notes entry, and added the doc to the README's table.

Left for later (not blockers, we'll track them): rename collisions, hardening the cover images (very large PNGs, an integer overflow, locking, cancel), running the memory test on the first trial only, a check byte in REG0D so that a stale register after reflashing can't start a trial nobody asked for, the flicker when the library reloads, and translations into the other languages. One hardware check is also still needed: a boot-time comparison with 0.1.3 on a freshly flashed regular RetroStone2.

Thanks again, this is a great addition to the RetroStone2 Pro!

PaddleStroke added a commit that referenced this pull request Oct 23, 2026
…ter card

Review of PR #12:
- storage_init() takes the block devices as they are as the baseline
  (no "rsos-storage refresh" when the menu starts); /sys/block is polled
  every 10 s instead of 2 s, and Settings > Storage runs one refresh
  when it opens. The model is read again from the status file when it
  was not there at start.
- The install's done page preselects "Keep SD as it is"; "Use as starter
  card" opens the same CANCEL-first confirmation as the menu item.
- Group multi-disc games skips the systems whose cores take no .m3u (the
  playlist would hide the discs behind an entry that cannot start) and
  writes each playlist to a temporary file, fsync, rename.
- Move games between drives keeps its own copy of the drive roots (a
  refresh rewrites the status the pointers pointed into).
- "oldbootloader": the starter card refused, flash a new card first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PaddleStroke added a commit that referenced this pull request Oct 23, 2026
Review of PR #12 (move_games, Settings > Storage > Move games between
drives):
- no source is deleted when a file failed, a differing file was kept or
  the run was cancelled or stopped (and not when out of memory);
- gamelist.xml is never deleted;
- before each unlink, lstat() of the source and of its copy: refused
  for a link, a missing copy, or the same device and inode;
- a folder with a game file whose bytes differ from the destination's
  keeps all its files (a .cue and its .bin, .m3u and discs, together);
- the summary says when games stayed on the source drive
  (transfer_progress.move_held).
test_transfer: the kept, failed, cancelled, link, same-inode, cue/bin
and gamelist.xml cases (726 passed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PaddleStroke added a commit that referenced this pull request Oct 23, 2026
The 128 new or changed UI strings of PR #12 (Pro storage, covers,
multi-disc, memory speed, rename, move games, credits) are in
po/rsos.pot, and translated in fr.po (appended, the project's way since
3395717: no po-update churn in the 21 other catalogs, which show the
English for these strings until they are translated).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@KurdtNervanna

KurdtNervanna commented Oct 23, 2026 via email

Copy link
Copy Markdown
Contributor Author

KurdtNervanna added a commit to KurdtNervanna/RetroStoneOS that referenced this pull request Oct 23, 2026
PaddleStroke#12 went into 0.1.4 with the maintainer's fixes
on top: the model probe saves rsos_model only (the eMMC and SATA stay off
until Settings > Storage turns them on) and only with the new bootcmd; no
storage work at boot with the disks off; safe starter/full card; Move
games never deletes after a failure; the Atari 800 core; the held-button
fixes.

Conflicts: boot.cmd (comment: rsos_model informative + this branch's
rsos_cpuspeed), storage.c (both forward declarations), pro-storage.md
(the multi-disc paragraph: plain disc words + the m3u-capable systems
only), rsos.pot (make pot). QEMU: the CPU speed case is now 17 (upstream
added 16, the old bootcmd); 53/53 pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants