Files
Lian Duan a8a9a8502d Dual storage options eMMC & TF Card (#63)
* feat: support dual storage variants (eMMC + SDMMC/TF card) and upgrade jetkvm_app to 0.5.6

Introduce two separate build configurations for JetKVM V2 hardware
variants that differ only in storage medium:

  BoardConfig-EMMC-NONE-RV1106_JETKVM_V2.mk  → boots from eMMC  (mmcblk0, 13640M userdata)
  BoardConfig-SDMMC-NONE-RV1106_JETKVM_V2.mk → boots from TF card (mmcblk1, dynamic userdata)

DTS refactor:
- Extract all shared board peripherals (backlight, gmac, i2c1/AT24C02,
  i2c3/FT5x06, spi0/ST7789V, uart3, rtc, wdt, pwm5, sfc=disabled) into
  rv1106-jetkvm-v2.dtsi as a common base
- rv1106g-jetkvm-v2.dts becomes a thin file with only the eMMC node
- New rv1106g-jetkvm-v2-sdmmc.dts thin file with only the sdmmc node
- Verified: both DTBs compile correctly; eMMC DTB is binary-identical
  to upstream

Build system:
- Add sdmmc as a new RK_BOOT_MEDIUM type throughout project/build.sh:
  sd_parts device, parse_partition_file, rootfs bootarg, build_recovery,
  build_factory, build_uboot INI selection, and mount_part script
- sysdrv/Makefile: add sdmmc block for KERNEL_CMDLINE_FRAGMENT and env
  target using mmcblk1; restore emmc back to mmcblk0
- project/scripts/mk-tftp_sd_update.sh: recognize sdmmc alongside emmc
- tools/linux/Linux_Pack_Firmware/mk-update_pack.sh: add mmcblk0 to the
  boot medium list so eMMC update packages are correctly generated

U-Boot:
- android_ab.c: replace hardcoded mmcblk1 with dev_desc->devnum so the
  A/B root device path is correct for both eMMC (devnum=0) and SDMMC
  (devnum=1), matching the DTS alias assignments

jetkvm_app:
- Upgrade from 0.4.8 to 0.5.6 (SHA256 verified)
- Note: 0.5.6 switches from static to dynamic linking (ld-uClibc.so.0)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* ci: switch to ubuntu-22.04 runner and build both EMMC and SDMMC variants

- Replace buildjet-16vcpu-ubuntu-2204 with standard ubuntu-22.04 runner
- Use matrix strategy (fail-fast: false) to build EMMC and SDMMC in parallel
- Artifact names include board variant: OTA-Image-EMMC, Full-Image-EMMC, etc.
- buildkit upload remains EMMC-only

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: bake SKU identifier into system image for OTA targeting

Each build variant writes /etc/jetkvm-sku to the system partition so
the jetkvm_app can report the correct SKU when querying the OTA service:

  BoardConfig-EMMC  → RK_SKU=jetkvm-emmc
  BoardConfig-SDMMC → RK_SKU=jetkvm-sdmmc

Matches the SKU routing introduced in jetkvm/cloud-api#49, where the
OTA API serves variant-specific binaries under
{prefix}/{version}/skus/{sku}/ and defaults to legacy path for
unrecognised SKUs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: align OTA SKU names with cloud-api DEFAULT_SKU convention

  jetkvm-emmc  → jetkvm-v2       (matches cloud-api DEFAULT_SKU)
  jetkvm-sdmmc → jetkvm-v2-sdmmc

Ref: jetkvm/cloud-api@1958830

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(dts): remove contradictory cap-mmc-highspeed from sdmmc node

no-mmc prevents MMC protocol probing entirely, making cap-mmc-highspeed
dead and misleading. Only cap-sd-highspeed is relevant for TF card use.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: handle IGNORE mountpoint for sdmmc in mount_part script

Line 1601's guard only matched emmc, so SDMMC partitions with
IGNORE mountpoint (e.g. inactive A/B slot) would fall through to
return 1 instead of return 0, causing boot-time mount errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: add sdmmc to block-device filesystem tool checks in build_mkimg

erofs and squashfs paths were missing sdmmc, causing them to fall
through to ubifs (NAND-only tool). Latent with current ext4-only
config but would silently produce a corrupt image if fs type changed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(sdmmc): build dd-able SD card image for direct flashing

Adds build_sd_dd_image() that assembles a flat raw image from the
fixed-size partitions (env, idblock, uboot_a/b, boot_a/b, system_a/b)
plus a 256 MiB seed userdata.img containing install_to_userdata
content (jetkvm_app etc.). Layout follows the cmdline blkdevparts —
no MBR/GPT, since the kernel reads partitioning from u-boot env.

Why a seed userdata: the SDMMC partition spec terminates with
'-(userdata)' which build_mkimg skips, so jetkvm_app never landed in
update.img on SDMMC. The mount_part init script (project/build.sh
mount_part) calls resize2fs on first boot, which grows the 256 MiB
ext4 to the end of the SD card automatically.

Workflow: SDMMC artifact is now update_sd.img.zip (zip -9 of a sparse
~1.4 GiB image, ~45 MiB compressed). update.img remains the EMMC
artifact since RKDevTool still uses it for production flashing.

* fix(sdmmc): chown userdata seed root:root before mkfs.ext4

build_mkimg userdata is a no-op on SDMMC (partition size '-' → 0), so the
__RELEASE_FILESYSTEM_FILES chown that build_mkimg normally runs never fires.
Without it, mkfs.ext4 -d preserves the builder's uid/gid into the image, so
/userdata/jetkvm on the SD card depended on whoever ran the build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(sdmmc): tune userdata mkfs.ext4 so first-boot resize2fs scales to 1 TiB

The previous flags (mkfs default 1K block size, -O ^64bit,^huge_file) made
the first-boot resize hang on large cards:

  - 1K blocks × 8K-blocks-per-group → 128K block groups for 1 TiB. resize2fs
    has to write GD/bitmap entries for every new group; on slow SD random
    writes this stretches to many minutes.
  - Default inode_ratio at 1K = 2048 inodes/group → ~256M inodes after
    resize. ext4lazyinit kthread then zeroes ~32 GiB of inode tables in
    the background, saturating SD I/O long after mount returns.
  - resize_inode reserve = 256 GDT blocks × 32 entries = 8192 group
    descriptors, capping resize_inode-style growth at 64 GiB. Beyond that,
    resize2fs falls back to meta_bg, but ^64bit blocks the cleaner path.

Switch to: 4K blocks, -T largefile (1 inode/MiB), -O 64bit, and an explicit
-E resize= reservation covering 2 TiB. Measured on a 1 TiB sparse loop
(host mkfs.ext4 1.47.2): online resize drops from 40 s to 0.4 s, and the
post-mount lazy-itable workload drops from ~32 GiB to ~256 MiB of writes.

32 GiB minimum supported card capacity.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(sdmmc): include sdmmc in sysdrv build-medium switches

Three places in sysdrv/ branched on the boot medium but left sdmmc out:

  - Makefile.tools.board.mk: e2fsprogs was gated on BOOT_MEDIUM=emmc, so
    the SDMMC rootfs shipped without resize2fs/e2fsck/mke2fs. mount_part's
    first-boot resize2fs call then silently failed and userdata stayed
    locked at the 256 MiB seed size, never growing to fill the card.

  - Makefile.param: the RK_BOOT_MEDIUM whitelist that propagates BOOT_MEDIUM
    omitted sdmmc, so any sub-tool Makefile included Makefile.param
    standalone (dropbear, eudev, etc.) saw BOOT_MEDIUM unset for sdmmc.
    Currently benign because no sub-tool branches on BOOT_MEDIUM, but a
    latent footgun.

  - tools/pc/toolkits/get_part_info.sh: PARTITION_FIRST_NO=0 was applied
    only for emmc. mmcblk1pN is also 1-indexed, so sdmmc would produce
    off-by-one root=/dev/mmcblk1pN values via `make env -C sysdrv`. The
    project's build.sh path computes part_num itself and isn't affected,
    but the sysdrv path was wrong.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 23:55:26 +02:00
..
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00
2025-02-15 18:30:23 +01:00