Skip to content

ambarella: s3l: enable overlayfs, so a flashed image keeps its settings - #2781

Merged
openipc-ai merged 2 commits into
OpenIPC:masterfrom
DeathCamel58:s3l-overlayfs
Nov 7, 2026
Merged

openipc-ai merged 2 commits into
OpenIPC:masterfrom
DeathCamel58:s3l-overlayfs

Conversation

@DeathCamel58

Copy link
Copy Markdown
Contributor

Problem

/init stacks an overlay on the rootfs to keep settings in rootfs_data, and skips it when the kernel has no overlay filesystem. The S3L kernel has none, so a flashed s3l image boots with a read-only root:

  • nothing persists;
  • /etc/fw_env.config can't be written, so fw_printenv/fw_setenv fail ("environment not initialized");
  • the first-boot setup can't save the root password.

Fix

Set CONFIG_OVERLAYFS_FS=y in br-ext-chip-ambarella/board/s3l/s3l.generic.config, where Kconfig places it (as in t31.generic.config).

It merges safely in either order with the linux PR. On today's ambarella-s3l kernel, olddefconfig drops the unknown option and nothing else in the config changes. With the overlayfs kernel, the config passes olddefconfig unchanged.

Testing

On an Amcrest IP4M-1026E (S3L, OV4689), flashed and booted from SPI-NOR with the overlayfs kernel:

  • rootfs_data mounts as jffs2, with overlayfs over /;
  • fw_printenv works, and settings survive reboots.

This was repeated across two stock ↔ OpenIPC flash round trips. The kernel keeps the inode/file layout the prebuilt iav.ko expects (i_cdev 0x110, private_data 0x70; the same check as #2763).

/init stacks an overlay on the rootfs to keep settings in rootfs_data,
and skips it when the kernel has no overlay filesystem. The S3L kernel
had none, so a flashed s3l image booted with a read-only root: nothing
persisted, and /etc/fw_env.config could not be written, so
fw_printenv/fw_setenv failed.

CONFIG_OVERLAYFS_FS comes with the overlayfs v18 patch for the 3.10
ambarella-s3l kernel (the one OpenIPC carries for the 3.10 ingenic-t31
kernel). Until that kernel has it, olddefconfig drops the unknown option
and nothing else in the config changes.

Tested on an Amcrest IP4M-1026E, flashed and booted from flash: rootfs_data
mounts as jffs2 with overlayfs over /, fw_printenv works, and settings
survive reboots. With the patched kernel this config passes olddefconfig
unchanged, and the kernel keeps the inode/file layout the prebuilt iav.ko
expects.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Enable OverlayFS in the Ambarella S3L kernel configuration

🐞 Bug fix ⚙️ Configuration changes 🕐 Less than 10 minutes

Grey Divider

AI Description

• Enable OverlayFS so flashed S3L images can retain settings in rootfs_data.
• Restore writable-root behavior needed for first-boot setup and U-Boot environment tools.
Diagram

graph TD
  Config["S3L kernel config"] --> Kernel["OverlayFS kernel"] --> Init["Boot init"] --> Root["Writable root"]
  Flash[("rootfs_data")] --> Init
Loading
High-Level Assessment

Enabling the existing boot flow through the S3L kernel configuration is the narrowest approach; changing /init or adding another persistence mechanism would duplicate established behavior. The option only takes effect with an OverlayFS-capable S3L kernel; older kernels drop it during olddefconfig.

Files changed (1) +1 / -0

Other (1) +1 / -0
s3l.generic.configEnable built-in OverlayFS for S3L +1/-0

Enable built-in OverlayFS for S3L

• Adds CONFIG_OVERLAYFS_FS=y to the S3L kernel configuration. With an OverlayFS-capable kernel, this lets the existing boot script mount a persistent writable root; older kernels discard the unsupported option during olddefconfig.

br-ext-chip-ambarella/board/s3l/s3l.generic.config

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Informational

1. Overlay fix is inert until kernel lands 🐞 Bug ☼ Reliability
Description
The added CONFIG_OVERLAYFS_FS=y line in s3l.generic.config only takes effect if the kernel built
from the ambarella-s3l branch tarball defines that symbol, and olddefconfig drops unknown
symbols silently. Because OPENIPC_KERNEL resolves to a mutable branch name rather than a commit
SHA, the kernel can change without any edit here, so flashed S3L images keep a read-only root until
the kernel side lands and nothing in the build flags that.
Code

br-ext-chip-ambarella/board/s3l/s3l.generic.config[2095]

+CONFIG_OVERLAYFS_FS=y
Evidence
The kernel is fetched from a branch-named tarball and the config is consumed as-is, so the symbol's
presence depends on a repository outside this PR.

general/external.mk[11-11]
br-ext-chip-ambarella/configs/s3l_lite_defconfig[9-13]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
Issue description: CONFIG_OVERLAYFS_FS=y is added to the S3L kernel config, but the kernel comes from the mutable ambarella-s3l branch tarball, so the option is silently dropped until the kernel side adds overlayfs.
Fix Focus Areas:
- br-ext-chip-ambarella/board/s3l/s3l.generic.config[2095-2095]
- general/external.mk[11-11]
Recommended Fix: Either merge this only after the kernel branch containing the overlayfs patch is available, or pin OPENIPC_KERNEL for s3l to a commit SHA that has it. Also state in the PR that this change alone does not change boot behaviour.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can hide the parts of a finding you never read, like the evidence or the agent prompt

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@DeathCamel58

Copy link
Copy Markdown
Contributor Author

Goes with OpenIPC/linux#177, which adds overlayfs to the ambarella-s3l kernel. Either can merge first: until #177 is in, olddefconfig just drops the option.

@openipc-ai openipc-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The config line itself looks right, and I found no problem in the code. Two things are needed before this can merge, and both are about evidence, because nothing else covers this change: ci-matrix.py --stdin gives 0/123 boards for this path (S3L is in UNBUILT_FAMILIES) and the Firmware job was skipped. The green CI Gate says nothing about this config, the kernel link or the size cap. This review comes from reading the diff, /init and the selector; nothing was built or run on a camera.

Needed before merge

  1. Please paste the actual output from the Amcrest IP4M-1026E. The Testing section describes the results, and the tree asks for the output itself: /proc/mounts, the relevant dmesg lines, fw_printenv, and a setting surviving a reboot.
  2. Please paste the uImage size with overlayfs on. =y builds it into a kernel with a cap of about 2 MB on 8 MB NOR, and since CI doesn't build this board, neither CHECK_SIZE nor the headroom warning will run on it. A make BOARD=s3l_lite log against the #177 kernel showing the size line would cover this.

Merge order

  1. OpenIPC/linux#177 should land first. You're right that either order is safe at build time: ambarella-s3l has no fs/overlayfs/Kconfig yet, so olddefconfig drops the line. But the kernel comes from a branch-named tarball with no pinned SHA. If this lands first, merging #177 alone changes S3L boot behaviour at the next build, with no firmware commit to show it. With #177 first, the change is tied to this commit.

Worth checking, not blocking

  1. Sysupgrade from an existing read-only S3L image. Until now /init exited at grep -q overlay /proc/filesystems on these kernels, so S3L has never run the overlay code below it. Your flash round trips cover conversion from stock, including the first format of rootfs_data, but the PR doesn't mention an upgrade from an OpenIPC image. If you can try that, please include the result.
  2. The UBI image is untested. s3l_lite also sets BR2_TARGET_ROOTFS_UBI, and this config reaches that image too. From reading /init, a failed UBIFS mount falls back to tmpfs, so it should fail safely, but if you have no NAND S3L to test on, please say so in the description.

@openipc-ai openipc-ai mentioned this pull request Nov 7, 2026
7 tasks
@DeathCamel58

DeathCamel58 commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks. All five points are answered below, with output from the IP4M-1026E (UART console) and from builds at this PR's head, f97a0fc9. The S3L kernel tarball now carries overlayfs, so everything here runs against the merged kernel.

What was built.

  • make BOARD=s3l_lite at f97a0fc9, unmodified, with the kernel from the ambarella-s3l tarball (now including overlayfs, 0e5f7083d5).
  • The camera image: the same tree plus my s3l_lite_amcrest-ip4m1026e device profile (not upstream yet), built for NOR. Its kernel is 0e5f7083d5 plus ambarella: s3l: Amcrest IP4M-1026E, with the board DTB appended to the uImage linux#178 (the board DTB appended to the uImage, which this board needs to boot). The unit's own DSP microcode is added locally. Everything else is this branch.
  • Every boot below is a warm reboot. The camera went through the Dahua U-Boot's TFTP recovery once, to put a read-only image on it (point 4). After that, only sysupgrade and firstboot wrote the flash.

2. uImage size with overlayfs on.

The unmodified make BOARD=s3l_lite:

- uImage: [1587KB/2048KB]
- rootfs.squashfs: [3384KB/5120KB]

That's about 5 KB over the 1582 KB you measured at #2766. On the device profile, the same build with only CONFIG_OVERLAYFS_FS off gives uImage: [1599KB/2048KB] against [1604KB/2048KB] with it on, so overlayfs costs about 5 KB. That leaves about 444 KB of headroom on the 2 MB kernel slot.

4. Upgrading from a read-only S3L image.

I flashed an image identical to the camera image but with overlayfs off in the kernel, which is what an S3L image from current master looks like:

$ uname -v
#4 PREEMPT Sat Nov 7 00:42:37 EST 2026
$ grep -E " / " /proc/mounts
/dev/root / squashfs ro,relatime 0 0
$ grep overlay /proc/filesystems; echo "rc=$?"
rc=1
$ touch /etc/x
touch: /etc/x: Read-only file system
$ fw_printenv
Cannot open config file '/etc/fw_env.config': Read-only file system

Two things on that image are worth knowing, both of which this PR fixes:

  • It can't be claimed. openipc-claim runs passwd, which fails with passwd: /etc/passwd: Read-only file system / Password was not set., and loops. SSH stays closed and there is no shell on the console either. So a flashed S3L image from master is locked out from the first boot. To test the upgrade at all, my read-only image had a root password preset at build time (local only).
  • fw_printenv doesn't work, because /etc/fw_env.config is generated at runtime.

From there, I ran sysupgrade --kernel=/tmp/uImage.s3l --rootfs=/tmp/rootfs.squashfs.s3l with this PR's image (md5 checked against the build). It flashed from RAM and rebooted, and the overlay came up on the first boot:

$ cat /proc/mounts
rootfs / rootfs rw 0 0
/dev/root /rom squashfs ro,relatime 0 0
devtmpfs /dev devtmpfs rw,relatime,size=57500k,nr_inodes=14375,mode=755 0 0
/dev/mtdblock5 /overlay jffs2 rw,relatime 0 0
overlayfs / overlayfs rw,relatime,lowerdir=/,upperdir=/overlay 0 0
proc /proc proc rw,relatime 0 0
devpts /dev/pts devpts rw,relatime,gid=5,mode=620 0 0
tmpfs /dev/shm tmpfs rw,relatime 0 0
tmpfs /tmp tmpfs rw,relatime 0 0
tmpfs /run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0
sysfs /sys sysfs rw,relatime 0 0
none /sys/kernel/debug debugfs rw,relatime 0 0

One caveat, which comes from my test setup and not from the PR. Both of my images carried the same local build ID, so sysupgrade said Same version, nothing to update for the rootfs and wrote only the kernel. So the overlay above is the new kernel over the read-only image's rootfs, which is also the path a kernel-only upgrade takes. To get this PR's rootfs onto flash as well, I then ran the sysupgrade -n --force_ver with both files described under point 1. Two published builds would have different IDs, so a real upgrade writes both.

1. Output from the camera, on this PR's image (/rom has the flash build's TIME_STAMP=1794029903).

/proc/mounts is as above. dmesg:

$ dmesg | grep -iE "overlay|jffs2|mtd|Kernel command"
[    0.000000] Kernel command line: console=ttyS0,115200 panic=20 root=/dev/mtdblock4 rootfstype=squashfs init=/init mtdparts=amba_spinor:768k(boot)ro,128k(env),64k(partition)ro,2048k(kernel),8192k(rootfs),15872k(rootfs_data),-(dahua)ro
[    0.493752] jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
[    0.557721] 7 cmdlinepart partitions found on MTD device amba_spinor
[    0.564102] Creating 7 MTD partitions on "amba_spinor":
[    1.404614] jffs2: notice: (77) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) found.

(overlayfs v18 logs nothing when it mounts.)

fw_printenv, with the serial number, MACs and HWID redacted:

bootdelay=3
baudrate=115200
ipaddr=192.168.1.108
serverip=192.168.1.1
[... Dahua's stock recovery variables (dk/dr/du/dw/up/...) unchanged ...]
bootargs=console=ttyS0,115200 mem=118M root=/dev/mtdblock5 rootfstype=squashfs init=/linuxrc
upgrade=https://github.com/OpenIPC/builder/releases/download/latest/s3l_lite_amcrest-ip4m1026e-nor.tgz
sysbackup=0
oload=sf read 0x2000000 0xf0000 0x200000
oboot=bootm 0x2000000
bootcmd=run oload oboot
sensor=ov4689

A setting surviving a reboot. The claim's root password and a marker file in /etc both survive a reboot:

$ echo pr2781-$(date +%s) > /etc/pr2781-marker; sync; cat /etc/pr2781-marker
pr2781-1794031502
$ reboot
[... warm reboot ...]
$ cat /etc/pr2781-marker
pr2781-1794031502
$ ls -la /overlay/etc
-rw-r--r--    1 root     root             0 Nov  7 06:04 custom.ok
-rw-r--r--    1 root     root            11 Nov  7 06:05 fake-hwclock.data
-rw-r--r--    1 root     root            32 Nov  7 06:04 fw_env.config
-rw-r--r--    1 root     root           340 Nov  7 06:04 passwd
-rw-r--r--    1 root     root           356 Nov  7 02:03 passwd-
-rw-r--r--    1 root     root            18 Nov  7 06:05 pr2781-marker
-rw-------    1 root     root           174 Nov  7 06:04 shadow
-rw-------    1 root     root           140 Nov  7 02:03 shadow-

firstboot and sysupgrade -n, which you asked for on OpenIPC/linux#177. Both runs were on this image.

  • remount,ro is refused, as you expected from super.c:608:
    $ mount -o remount,ro /overlay; echo "remount,ro rc=$?"
    mount: mounting /dev/mtdblock5 on /overlay failed: Resource busy
    remount,ro rc=255
    
  • firstboot (sysupgrade -n with no image, so the overlay stays mounted while it's erased) prints the warning and erases live:
    OverlayFS
    Erase overlay partition
    Could not remount /mnt/overlay read-only; erasing it live.
    
    After the reboot the settings are really gone. The marker is missing (cat: can't open '/etc/pr2781-marker': No such file or directory), and root's password was reset, so the console showed the first-boot claim prompt again.
  • sysupgrade -n --force_ver --kernel=... --rootfs=... takes the other path. A rootfs write hands PID 1 over to the RAM root first (Handing PID 1 over to the RAM root. / Flashing from RAM (pid 1)), which releases the overlay, so there's no remount warning. That run, too, ended with the marker gone and the claim prompt back.

So a live erase does happen, but only on firstboot and other wipes that don't rewrite the rootfs. In both cases the camera came back clean.

5. UBI. I have no NAND S3L to test on, so the rootfs.ubifs path is untested.

3. Merge order: the kernel side is merged, so that's settled.

@openipc-ai openipc-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this answers everything I asked for and more, so I'm approving it. The upgrade path and the firstboot run are what I was most concerned about, and both came back clean.

What I checked myself, with this PR merged onto current master (b08259fb0) and the kernel at 7022a237. I didn't run this on a camera:

  • CONFIG_OVERLAYFS_FS=y survives olddefconfig next to CONFIG_LBDAF=y.
  • iav.ko's offset still holds: inode.i_cdev is 0x110, sizeof(struct inode) is 0x128, and file.private_data is 0x70. I checked because #2778 showed that CI can't catch this.
  • uImage is 1587/2048 KB, the same as your number.

Your findings:

  • A read-only image can't be claimed. I hadn't realised that, and it's the strongest reason for this PR: it means a flashed S3L image from master is locked out from the first boot. Since #2783, those are the images the nightly would publish.
  • firstboot erases live. It's the fallback sysupgrade was written to accept, and your run came back clean. It's one run on one camera, and the same applies to T31 and the other branches with this overlayfs. Nothing to change here.
  • UBI: untested, as you said. From reading /init, a failed mount falls back to tmpfs, so it should fail safely.

One thing outside this PR: master doesn't fit right now. With #2782's microcode and #2785's Majestic together, make BOARD=s3l_lite stops at rootfs.squashfs: [5516KB/5120KB], 396 KB over, with or without this PR. Your 3384 KB was measured before those two landed. I'm raising this separately, so you don't need to do anything, but this PR's S3L CI job will fail until it's fixed.

@openipc-ai
openipc-ai merged commit db7011f into OpenIPC:master Nov 7, 2026
29 checks passed
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