Skip to content

hi3518ev300_lite: build vfat/fat into kernel to free 4 KB of rootfs#2163

Merged
widgetii merged 1 commit into
masterfrom
fix/hi3518ev300-lite-vfat-builtin
May 30, 2026
Merged

hi3518ev300_lite: build vfat/fat into kernel to free 4 KB of rootfs#2163
widgetii merged 1 commit into
masterfrom
fix/hi3518ev300-lite-vfat-builtin

Conversation

@widgetii

Copy link
Copy Markdown
Member

Summary

Nightly CI run 26667982165 failed for hi3518ev300_lite with rootfs.squashfs 5124 KB > 5120 KB cap (4 KB over). The lite variant has been parked at the cap for two weeks — the HISILICON_OPENSDK_TRIM_SP2308 finalize hook already drops three sensor .so files to keep this board buildable, and ~12 KB of accumulated drift since 2026-05-17 (a5614d9c) has now tipped it over.

This change flips two kernel symbols in hi3518ev300.generic.config from =m to =y:

-CONFIG_FAT_FS=m
+CONFIG_FAT_FS=y
-CONFIG_VFAT_FS=m
+CONFIG_VFAT_FS=y

Why these symbols specifically

general/overlay/etc/modules lists vfat as a boot-time autoload (loaded by general/overlay/etc/init.d/S35modules). vfat is the only .ko on this board that loads on every boot — so making it built-in is a pure layout shift, zero runtime cost. The other entry exfat belongs to the out-of-tree exfat-openipc package which is not enabled in this defconfig.

Every other =m symbol in this config (MAC80211, MT7601U, R8188EU, TUN, F2FS_FS, SCSI*, the CRYPTO_* family, etc.) is on-demand — USB-dongle insertion, WireGuard interface bring-up, USB-storage mount. Making any of those =y would burn unconditional kernel bytes for code that may never run on a given camera.

All NLS helpers vfat needs (NLS_CODEPAGE_437, NLS_ISO8859_1, NLS_ASCII) are already =y — no follow-up symbols needed.

Local build results

hi3518ev300_lite:

- uImage:          1873 → 1893 KB / 2048 KB  (155 KB headroom)
- rootfs.squashfs: 5124 → 5096 KB / 5120 KB  (24 KB headroom, was 4 KB over)

vfat.ko + fat.ko confirmed absent from output/target/lib/modules/; CONFIG_VFAT_FS=y / CONFIG_FAT_FS=y confirmed in built kernel .config; vfat_rename / namei_vfat.c strings present in vmlinux.

Cross-variant note

The same hi3518ev300.generic.config is referenced by hi3518ev300_ultimate_defconfig. Last passing CI had ultimate at uImage 1873/2048 (175 KB headroom) and rootfs.squashfs 7664/8192 (528 KB headroom); the same +20 KB kernel growth fits comfortably in both caps.

Test plan

  • CI passes for hi3518ev300_lite
  • CI passes for hi3518ev300_ultimate (shared kernel config)
  • After merge, sysupgrade-flashed hi3518ev300_lite camera mounts a FAT-formatted SD card / USB stick without manual modprobe vfat

Follow-up (separate PR)

The lite variant remains within ~25 KB of the cap with the temporary TRIM_SP2308 block still removing SP2308 + SC500AI + GC5603. The underlying drift (most likely hisilicon-opensdk bump #2156 or unpinned majestic master) warrants a bisect + compaction pass so those sensors can be restored.

🤖 Generated with Claude Code

Nightly CI run 26667982165 (job 78605352324) tipped the lite variant
over the 5120 KB NOR rootfs cap by 4 KB (5124/5120). The HISILICON_OPENSDK_TRIM_SP2308
finalize hook already trims three sensor .so files on this variant and
the cap has been creeping for two weeks.

vfat is the only kernel module on this board that auto-loads at boot
(/etc/modules → S35modules), so flipping CONFIG_VFAT_FS and its FAT_FS
dependency from =m to =y removes vfat.ko + fat.ko from rootfs at zero
runtime cost — the module was going to be loaded anyway. All required
NLS helpers (NLS_CODEPAGE_437, NLS_ISO8859_1, NLS_ASCII) are already =y.

Local build hi3518ev300_lite:
- uImage:        1873 → 1893 KB / 2048 KB (155 KB headroom)
- rootfs.squashfs: 5124 → 5096 KB / 5120 KB (24 KB headroom, was 4 KB over)

The same hi3518ev300.generic.config is shared with hi3518ev300_ultimate;
last passing CI had it at uImage 1873/2048 and rootfs.squashfs 7664/8192
so the +20 KB kernel growth fits comfortably in both caps.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@widgetii widgetii merged commit 747829a into master May 30, 2026
98 checks passed
@widgetii widgetii deleted the fix/hi3518ev300-lite-vfat-builtin branch May 30, 2026 10:19
widgetii added a commit to OpenIPC/firmware-explorer that referenced this pull request Jun 5, 2026
…droom overflow projection (#3)

v0.2 shipped per-build sizes shards; v0.3 added the Kconfig configurator;
v0.4 finally reads across the retention window. The Drift tab catches
"package X grew between two specific nightlies" — useful but you need
to already suspect a regression to pick the right two builds. TrendsView
watches the slope: if a package has been growing 4 KB/week for the last
14 days, it surfaces at the top of a leaderboard before the rootfs cap
overflows.

This is the direct answer to PR OpenIPC/firmware#2163's pain point —
"~12 KB of accumulated drift since 2026-05-17 has now tipped it over."
With historical trends, the bisect step that PR had to do becomes
visible from the dashboard.

Data shape

  scripts/prebuild.mts now walks every (build × platform) sizes shard
  once per source after the per-tag download loop, accumulates
  per-platform series into one PlatformAccumulator, and writes a
  per-platform aggregated file at:

      public/data/<source>/trends/trends.<platform>.json

  Schema (matches src/lib/timeseries.ts TrendsFile verbatim):

      {
        schema: 1,
        source, platform, generated_at,
        packages: { <name>: [{build_id, built_at, bytes}, ...] },
        modules:  { <name>: [{build_id, built_at, bytes}, ...] },
        headroom_rootfs: [{build_id, built_at, used_kb, cap_kb, headroom_kb}, ...],
        headroom_kernel: [{...}, ...]
      }

  Every series ships sorted by built_at ascending. Defensive against
  partial shards: missing `headroom` blocks are skipped per build, not
  fatal. New FsHooks.read so the test memFs can serve readback inside
  the same in-memory state the gh-download mock writes into.

Per-platform file: ~16 KB raw / ~1.5 KB gzipped on a board with 31
packages × 2 builds of data. Storage scales linearly with retention;
~80 KB raw at full 90-build retention. Total dist/data/firmware/trends/
across all 96 platforms today: 1.8 MB raw. Well under the plan's
~4 MB-gzipped envelope.

UI

  TrendsView (new "Trends" tab between "Drift vs another build" and
  "Configure (what-if)"):

    * Header summary: builds count + date range covered
    * Two HeadroomChart sections — rootfs and kernel — that draw the
      used-bytes curve against the cap line. When projectOverflow(...)
      returns a non-null projection within 60 days, an amber badge
      surfaces "projected overflow in 7d (2026-06-12)". Linear
      regression: minimise (kb - (slope*day + intercept))^2, solve for
      kb=0. Sub-zero slope only — flat/growing returns null (no
      overflow projected).
    * Controls strip: window selector (7/14/30/90d), packages|modules
      toggle, "min weekly delta KB" filter to surface only the
      noteworthy growers.
    * Growers leaderboard sorted by absolute byte delta in window,
      newest 20. Each row gets an inline Sparkline (180×28 SVG
      polyline, colour by direction: amber=grow, green=shrink), plus
      a click-to-expand large sparkline (760×140) with axis labels.

  Sparklines are hand-rolled SVG — no chart lib. d3-hierarchy is
  already in the bundle (treemap) but doesn't transitively ship
  d3-scale/d3-shape; rather than add ~20 KB of charting deps for
  polylines and axes, the component pads + scales manually. Drop-in
  swap to a charting lib is easy if interactive zoom becomes a thing
  later.

Tests

  tests/trends.test.ts (12 cases):
    * growthInWindow: window filtering, sort-on-input-order tolerance,
      first/last point semantics, < 2 points → null
    * bytesPerDay: window-endpoint slope, insufficient data → null
    * topGrowers: absolute-delta ordering, limit, skip insufficient,
      per-day rate
    * projectOverflow: flat/growing returns null, shrinking-at-known
      rate gives the expected days-to-zero

  tests/bundle.test.ts gains the same-origin invariant for
  trends/...json URLs — the regression guard for the original v0.1
  CORS bug class now covers trends URLs too.

  tests/prebuild.test.ts memFs updated with `read` so the runPrebuild
  cases still pass; defensive `headroom?.rootfs` guards in emitTrends
  let the minimal-shard fixtures run through trends emission without
  exploding.

Numbers

  - 63 active tests (was 46 in v0.3, +12 trends + adjustments)
  - JS bundle: 181 KB raw / 58 KB gzipped (+9 KB vs v0.3; under 250 KB
    perf budget)
  - Initial launch byte budget unchanged: ~60 KB gzipped (trends are
    lazy-loaded on Trends-tab click, ~1.5 KB gzipped per platform)
  - 96 trends files emitted today; 1.8 MB raw total

Roadmap from README

  v0.4 (this) shipped → v0.5 (build-request flow, optional, depends on
  v0.3 fragment) remains. Maintenance backlog (cache eviction, 404 UX,
  drift URL state, picker search, data-window header indicator)
  unchanged.

Co-authored-by: Claude Opus 4.7 (1M context) <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.

1 participant