Skip to content

Fix boot and shutdown issues on a Miyoo Flip with BaseOS/Add BaseOS support to Flip - #1881

Merged
CatalyticArkun merged 32 commits into
spruceUI:Developmentfrom
mxmgorin:flip-baseos-fixes
Oct 18, 2026
Merged

CatalyticArkun merged 32 commits into
spruceUI:Developmentfrom
mxmgorin:flip-baseos-fixes

Conversation

@mxmgorin

Copy link
Copy Markdown
Contributor

Changes:

  • Disable swap on the SD card before unmounting it during shutdown. The card was left dirty after every shutdown, causing BaseOS to run fsck ("REPAIRING SD CARD", ~14 s) on every boot. Applies to all devices.
  • Rebuild the Flip's 32-bit overlay image if it is not formatted as ext4. Images created without mkfs.ext4 on older BaseOS versions remained empty, leaving /usr/lib32 unavailable.
  • Remove the mount_muOS.sh call from the Flip's 32-bit chroot, where it always failed.

Tested on a Miyoo Flip running BaseOS 1.1.0.

@CatalyticArkun
CatalyticArkun self-requested a review October 17, 2026 19:25
@CatalyticArkun

Copy link
Copy Markdown
Contributor

We don't officially support BaseOS, but I have been looking into adding it. I'll take a look at this.

@CatalyticArkun
CatalyticArkun marked this pull request as draft October 17, 2026 19:27
@mxmgorin

mxmgorin commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks. For context, only one of the three fixes is BaseOS-specific. The swap fix applies to all devices, the card left dirty on each device, BaseOS just began to check it on start so it became hard to ignore. The chroot mount_muOS.sh fails on Miyoo Flip stock too.

Only the overlay image rebuild is BaseOS-related. Maybe it is better to split the PR, i just found them all while searching the issue with 'repairing cd' and thought to submit them together.

@CatalyticArkun

Copy link
Copy Markdown
Contributor

if something ends up being Spruce-specific we can probably merge. Worst case I'll just ask you to split it to a separate PR later.

@mxmgorin

Copy link
Copy Markdown
Contributor Author

I can split them now and keep only the BaseOS-specific fix in this PR, so the common fixes are not blocked. The more I think about it, the more logical that seems.

@CatalyticArkun

Copy link
Copy Markdown
Contributor

I might just push everything here together - as long as the commits are separate it's easy to tell what is what

@CatalyticArkun CatalyticArkun changed the title Fix boot and shutdown issues on a Miyoo Flip with BaseOS Fix boot and shutdown issues on a Miyoo Flip with BaseOS/Add BaseOS support to Flip Oct 17, 2026
@mxmgorin

Copy link
Copy Markdown
Contributor Author

Yes, the commits are fully separate and each message describes what it does. I also commented the less obvious things in the code.

@CatalyticArkun

Copy link
Copy Markdown
Contributor

Hardware notes from testing this PR on a Miyoo Flip running BaseOS-my355 1.1.0 (two cards), a stock Flip, and an RG35XX SP on BaseOS 1.4.0. The PR's three commits were tested on top of a local branch that adds the rest of the BaseOS support (rebased on Development e06f4b3). Each shutdown below went through spruce's own reboot (save_poweroff.sh --reboot).

This PR's commits

  1. Swap off before the unmount: confirmed. With a 64 MB swap file active, Development's shutdown left the card dirty, and BaseOS showed "REPAIRING SD CARD" at the next boot. With the swapoff, the next boot needed no repair, on BaseOS and on stock. This only bites when the "SD card swapfile" setting is on (default Off), so "every shutdown" applies to users who enabled it.
  2. No mount_muOS.sh inside the chroot: confirmed. In miyoo355_rootfs_32.img, /mnt/SDCARD is an empty directory (only /mnt/sdcard is bound), so the call failed on stock too, with /mnt/SDCARD/spruce/flip/mount_muOS.sh: No such file or directory in spruce.log. Nothing else chroots there, and muOS is mounted outside right after.
  3. Rebuild of a non-ext4 overlay image: looks right. The od check gives the right answer on GNU od, Debian busybox and the Flip's own busybox, for zero-filled, empty and real ext4 images. It wasn't exercised on a device because the images were valid.

Found along the way (coming as separate commits on top)

  • Session restart during shutdown. BaseOS's init respawns /sbin/frontend-session as soon as spruce's session dies. It relaunches the updater and, once stage 2 has unmounted the card, mounts it again read-write. Once it even started fsck.fat on a card that had only been lazily detached. On the XX line it's the same script name since BaseOS 1.3.0 (it used to be nextui-session), so the existing XX shield does nothing on current images. Both now get a shield, and the shim runs from /tmp so it doesn't pin anything itself.

  • Stage 2's clean unmount failed on every Flip and XX shutdown tested on Development, swap or not.

    • Mounts stacked on the card (the 32-bit chroot, muOS, the /usr overlay's ext4 image and binds of their files) were never torn down, because the old steps matched mount sources, and those show up as /dev/loopN.
    • A daemon whose cwd is exactly the mount point was missed by the holder sweep.
    • Stage 2 itself ran from the /usr overlay.

    With the fixes it's "unmounted cleanly after 0 retries" on the BaseOS Flip (with swap), the stock Flip (with swap) and the RG35XX SP.

  • The Flip under BaseOS.

    • Flip.cfg's SD_DEV (/dev/mmcblk1p1) is BaseOS's U-Boot partition there, and USB Storage Mode would export it; the card is mmcblk2p1 (or mmcblk1p5 with one card).
    • The firmware check offers a Miyoo NAND update, because /usr/miyoo/version reads "BaseOS 1.1.0".
    • btmanager and hardwareservice don't exist on BaseOS.
    • The branch detects BaseOS in Flip.cfg and leaves the stock path unchanged; checked on the stock Flip.
  • Smaller. The lib binds skip names BaseOS doesn't ship (libanl.so.1). The firmware app can update BaseOS-my355 from its own releases; they ship no SHA256SUMS, so the download is checked against GitHub's asset digest.

For BaseOS-my355 (@apommel), optional, since spruce now shields its session

  • mount-frontend checks /proc/mounts before repairing. A card that was lazily unmounted but is still held, by a swap file for instance, isn't listed, so fsck.fat ran on a filesystem still in use. Checking that the block device isn't busy first (an O_EXCL open fails while it is) would avoid that.
  • rcK unmounts everything but never runs swapoff, so a frontend's swap file on the card always leaves it dirty.

Moved from AnbernicXXCommon.sh to utils/baseos_session_shield.sh; it now
takes the inittab session path. The XX shim it writes is byte-identical.
Flip.cfg flags BaseOS and reads the card from /proc/mounts (mmcblk1p1 is
U-Boot there); skip vendor fw/UI/services; shield frontend-session twice.
The Flip uses Flip.cfg's SD_DEV, not mmcblk1p1 (BaseOS U-Boot); an empty
device now means unsupported instead of a grep that matches every mount.
BaseOS 1.3.0 renamed /sbin/nextui-session to /sbin/frontend-session, so the
shutdown shield matched nothing on current images; shield both names.
Strict path: unmount by mountinfo parentage incl. card-backed loops, detach them,
catch mappings by device, and re-run under a static busybox if the shell maps the card.
A failed clean umount listed no holder on the XX line; the errno says why.
Strict path: this process's own card fds are closed (10 and up included), process roots
are swept, and the dump names stage 2 itself and processes stuck exiting.
bind_glibc.sh and bind-new-libmali.sh bind only over names that exist (BaseOS-my355
lacks libanl.so.1, among others) and log the skipped names on one line.
baseos_fw_needs_update serves XX and the BaseOS Flip; each cfg names its BaseOS project. The
updater takes any BaseOS device, and checks a release without SHA256SUMS by GitHub's digest.
On the BaseOS Flip even a static /bin/sh runs out of the /usr overlay whose upper is a card loop
(loop2 pinned in V1/V2). The failure dump now lists every live process with exe and cwd.
busybox takes its applet from argv[1] only when named busybox, so the stage-2 re-run never fired
(V2b). The shim now runs and sleeps from /tmp too: started from /usr it pinned the overlay.
The strict sweep matched only paths under "$SD_MOUNTPOINT/", so a daemon with cwd exactly at the
mount point survived and kept it busy (XX X4, Flip V3b). The dump skips kernel threads.
Stock Flip: /data -> userdata, a card bind, so stage 2 logged onto the card and pinned it
itself. Key lines also go to /dev/kmsg, which console-ramoops keeps across a warm reboot.
device_init sets printk to 3, so level-4 lines never reached the console that
console-ramoops records (.94 S2 kept none).
Flip.cfg sources FlipBaseOS.cfg and Flip.sh ends by sourcing FlipBaseOS.sh, which replaces
whole functions; stock Flip.sh keeps the vendor code plus two hooks. PLATFORM stays Flip.
platform/*.cfg names platforms (only *Common.cfg is partial), so the layer is now
platform/baseos/my355.cfg + device_functions/baseos/my355.sh. No behaviour change.
@apommel

apommel commented Oct 18, 2026

Copy link
Copy Markdown

Thanks for the work there and the detailed feedback. Here's what I can do on BaseOS side for the next version:

  • Do not clean a dirty but in use FAT partition, as a safety mechanism.
  • Run swapoff in rcK.
  • Unmount /usr overlay in rcK, as Spruce uses an overlay and it was keeping the card busy.
  • Add SHA256SUMS to my releases for the FW updater.

With that, you should be able to remove the session shim if you remove the card unmount. The session restart happens because you unmount the card during shutdown, and BaseOS does not know it's shutting down so attempts to start it again. With the new rcK, SpruceOS no longer needs to unmount the card itself and it can just call poweroff/reboot, and BaseOS would do the full shutdown cleanly. You can also keep the shim, and it should work fine.

I have made a quick beta with those changes, you can make some tests with it:
https://github.com/apommel/baseos-my355/releases/tag/v1.2.0-beta.1

Its rcK turns swap off, detaches the /usr overlay and unmounts the card
(1.2.0-beta.1), so a plain power-off skips stage 2; 1.1.0 and USB export keep it.
A version like 1.2.0-beta.1 blocked every offer; it now compares by its x.y.z
and counts as older than the release of the same number.
…he file

A SHA256SUMS without the asset passed unchecked; baseos-my355 ships one from
1.2.0, and older releases still have only the GitHub digest.
@mxmgorin

Copy link
Copy Markdown
Contributor Author

Tested on a Miyoo Flip with BaseOS-my355 1.2.0-beta.1 and a swap file on the SD card. Spruce's reboot, power-off, and a plain reboot (rcK only) all left the card clean. The overlay and lib binds work too. Everything looks good.

On 1.2.0-beta.1 it offered releases/latest (1.1.0), which BaseOS refuses at boot.
Both now use baseos_version_older: x.y.z first, a pre-release before its release.
GitHub serves release files by a 302; curl -sf without -L saved it as an empty file
(rc 0), so the SHA256SUMS check never ran. The downloader follows it, with its TLS retry.
The log line now shows which sum was checked, so a report proves a real comparison.
A child exiting ends the busybox shell's own sleep at once: after a USB session the 10 s
grace for init lasted 0.4 s and reboot -f preempted BaseOS's rcK. Forcing is logged to kmsg.
A process holding a file through spruce's /usr overlay shows no card path, so the sweep
missed it and USB export was refused; fdinfo mnt_id (and exe/cwd opened here) now link it.
unmount_all lazily detaches the busy /usr overlay, which leaves mountinfo, so stage 2 saw only
the card (flip-91 B2: nothing found). Stage 1 now exports SPRUCE_CARD_MNT_IDS first; quiet skips.
…r1881/push

The baseosUpdate.sh and firmwareUpdate.sh conflicts take Development's side (REPO and the
finish message by BASEOS_TARGET); the digest fallback, redirect-following SHA256SUMS fetch,
pre-release ordering and the stage 1/2 unmount changes are kept.
baseos_repo (helperFunctions) feeds the update check and baseosUpdate.sh, replacing the
cfgs' BASEOS_REPO and BASEOS_UPDATE_FINISH; TARGET_BASEOS_VERSION stays in Flip.cfg. Stock
Flip.sh drops its BaseOS branch (pre-releases never offered): the my355 layer replaces it.
Each pass names its victims (pid:comm) even when the umount then succeeds: B2/B3 on flip-91
unmounted cleanly at 0 retries and nothing recorded which holders the sweep took.
@CatalyticArkun
CatalyticArkun marked this pull request as ready for review October 18, 2026 18:58
@CatalyticArkun
CatalyticArkun merged commit 3a08646 into spruceUI:Development Oct 18, 2026
1 check failed
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.

3 participants