Skip to content

Buildroot package for nfs root#2191

Open
tinylabs wants to merge 15 commits into
OpenIPC:masterfrom
tinylabs:br-package-nfs-root
Open

Buildroot package for nfs root#2191
tinylabs wants to merge 15 commits into
OpenIPC:masterfrom
tinylabs:br-package-nfs-root

Conversation

@tinylabs

Copy link
Copy Markdown

Kernel NFS root package

Changes

  • net/ipv4/ipconfig.c
    • Kernel patch to override random MAC generation for early kernel network path used by NFS root mounting.
  • /init
    • Allow mounting nfs root as readonly with configurable tmpfs overlay.
  • /inittab
    • Respect hostname if passed on command line which can be fetched by u-boot over dhcp.
  • /etc/init.d/S40network
    • Avoid re-initializing eth0 when already brought up by kernel during nfs root mounting.
  • /etc/init.d/S45setupenv
    • Helper to configure core services (NTP, DNS) from buildroot variables or default route if missing.
      • Note: Could potentially receive them via another udhcpc request and check the options instead. Without reconfiguring eth0.
    • Change root password on firstboot (nfs rw) or every boot (nfs ro).
    • Generate and stuff ssh key into uboot env as base64 for nfs ro case. Restore key on boot if it exists instead of regen.
  • contrib/make_nfsroot (probably the wrong location for it)
    • Helper to compile nfs root builds without changing each defconfig.
    • All args are optional except defconfig.
    • Saves and restores general/openipc.fragment.
    • Pass file with BR2 packages to include those in the root nfs build.

Testing

Compile

./contrib/make_nfsroot gk7205v300_lite_defconfig
- uImage: [1817KB/16384KB]
- Build time: 00:39

NFS-root build complete
-----------------------
kernel: [1.8M]   output/images/uImage.gk7205v300
rootfs: [15M]    output/images/rootfs.gk7205v300.tar
Usage: ./contrib/make_nfsroot <defconfig> [--passwd <password>] [--tz <iana-timezone>] [--ntp <ntp server>] [--dns <dns server>] [--pkgs <br package file>]

Notes

  • Feature is completely gated by buildroot package. Entire change set should be no-op if BR2_PACKAGE_OPENIPC_NFS_ROOT is not included.
  • Currently checks BR2_PACKAGE_OPENIPC_NFS_ROOT in Makefile to skip flash packaging as NFS builds have no limit. Kernel size set to 16MB arbitrarily.
  • Logs requested by @widgetii showing the override path and the output when device tree mac is set.
    bootargs_override.log
    boot_dtb_wins.log

@tinylabs tinylabs marked this pull request as draft June 12, 2026 03:16
@tinylabs tinylabs marked this pull request as ready for review June 12, 2026 18:44
@tinylabs

Copy link
Copy Markdown
Author

Quick note for testing. I did find a reliable way to tag/identify individual cameras without solely referencing the MAC address. bootp_vci (option 60) can be set in the uboot env which will get sent during the initial DHCP request. This can be a useful key when deciding which kernel/rootfs to serve to the device.

tinylabs added 2 commits June 12, 2026 23:21
…nel ip autoconf is dhcp. Use static mac_pton helper for older linux kernel support.
@tinylabs

Copy link
Copy Markdown
Author

Sorry for the regression failure! That copy rule slipped through.

Fixes

  • Fixed openipc_ethaddr.c getting pulled in when feature not enabled.
  • Added compile time check during kernel patch phase to explicitly error when the feature is enabled on a kernel that is older than 4.5 (when eth_platform_get_mac_address was introduced).
  • Add static mac_pton helper for older kernel support without messing with kernel header changes as branches may have diverged.
  • Start udhcpc daemon when early kernel ip config used DHCP. Needed to maintain future leases (TESTED).

All gated CI regressions should pass now.

  • Targets with kernels older than 4.5 will fail with a clear error ONLY when the feature is enabled.

Any feedback would be appreciated once it passes CI tests.

@widgetii widgetii left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is the package-based redesign that came out of the #2168 discussion — replacing the per-vendor MAC-driver patches with an opt-in package — and it executes that direction well: one ipconfig.c patch at the early-network layer, fully opt-in via BR2_PACKAGE_OPENIPC_NFS_ROOT, attached through Buildroot's linux-kernel-extension infra. The added NFS RO/RW overlay init, DNS/NTP/hostname, SSH-key persistence to u-boot env, timezone derivation, and the make_nfsroot helper round it out nicely.

CI: green as of 1266d36 — 103 checks pass, CI Gate success. Worth noting the earlier 28-board build failure was real (not the wireguard/squashfs tarball drift from #2168): the pre-fix LINUX_PRE_BUILD_HOOKS += OPENIPC_NFS_ROOT_SYNC_ETHADDR_SOURCE ran the openipc_ethaddr.c cp on every board → cp: ... drivers/net/ethernet/openipc_ethaddr.c: No such file or directory on boards that don't enable the package / old kernels. Moving it into the Kconfig-gated extension PREPARE_KERNEL hook fixed it, and the green matrix empirically confirms the no-op-when-disabled property. 👍 Also verified DT-MAC-wins holds by construction (eth_platform_get_mac_address() checks DT/ACPI before the arch_get_platform_mac_address() fallback).

A few things before merge:

1. repack gate only sees the cmdline var, not the fragment. The top Makefile does include $(CONFIG) (board defconfig) and never sources the merged .config, so ifeq ($(BR2_PACKAGE_OPENIPC_NFS_ROOT),y) in repack is only true when the var is passed on the make line (which make_nfsroot does). But the description also advertises enabling via general/openipc.fragment — that path leaves the gate false, so a plain make BOARD=… runs the normal NOR repack and CHECK_SIZE fails on the missing rootfs.squashfs. The kernel-side gating is fine (it reads .config); only the repack gate has this gap. Either source the var from .config in the Makefile, or document make_nfsroot as the only supported enable path.

2. S40network never brings up lo on the NFS-root path. The is_nfs_root branch returns after "leaving eth0/lo as configured by kernel", but kernel ip-autoconfig brings up eth0, not loopback. Base S40network always runs ifup lo. Anything binding 127.0.0.1 will break — please ifup lo explicitly on the NFS path.

3. overlay/init duplicates general/overlay/init. The flash-overlay branch is copied verbatim with an elif … nfs branch appended; late-overlay rsync replaces the base /init, so it works but the two will drift. Consider making the NFS branch additive or factoring the shared logic. (Also a couple of trailing-whitespace lines in the new init.)

4. ether_addr_copy(dev->dev_addr, mac) and dev_addr const-ness. net_device.dev_addr became const in Linux 5.17 (writes must go via eth_hw_addr_set()). CI passing means current targets are < 5.17, so this is fine today — just a flag for whoever bumps the neo kernel later.

Minor: the default_mac sentinel correctly matches the 00:00:23:34:45:66 overlay fallback and the ether_addr_equal form addresses the earlier #2168 nit 👍; the s|…| sed password substitution escapes / & \ but not the | delimiter (safe since crypt/base64 hashes can't contain |, but worth a comment); and consider noting the baked-in default 12345 root password as not-for-production in the Kconfig help.

Lastly — could you drop the two boot logs into the PR description: one with ethaddr= on the cmdline showing the resulting ip link MAC, and one showing the DT MAC winning with no ethaddr=? That lets reviewers confirm both paths without rebuilding the matrix.

@tinylabs

Copy link
Copy Markdown
Author

1. repack not seeing fragment definitions.
Agreed, I have a note in make_nfsroot explaining this problem but the proper solution should be for repack to see all definitions including those in general/openipc.fragment. I've updated Makefile to fix this.

2. S40network never brings up lo on the NFS-root path.
For the early kernel network config flow it actually does bring up lo. If I try to bring it up in userspace I see:
ip: RTNETLINK answers: File exists
I tested with netcat and I can bind to 127.0.0.1 and receive data from another ssh session so it is indeed working. Currently during shutdown it complains that lo isn't configured due to it not being configured in userspace. I believe the correct solution is to not bring it down at all for this nfs rootfs use case.

3. overlay/init duplicates general/overlay/init.
I was trying not to touch the default overlay at all to make the entire package a no-op when not selected but that will have challenges when the default overlay drifts as you mentioned. I'm happy to merge them if you prefer as the changes are orthogonal with some shared code. I was able to revert the inittab overlay changes in a previous commit so now we're just left with /init and /etc/init.d/S40network. Going a step further if we integrated the S40network changes that would allow us to remove the overlay mechanism all together. Thoughts?

4. ether_addr_copy(dev->dev_addr, mac) and dev_addr const-ness.
Agreed, we may as well future proof it now rather than kick the can down the road. I'll update the kernel patch to provide a compatibility function that should work across kernels.

// Provide copy mechanism for kernels missing eth_hw_addr_set
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0)
static inline void eth_hw_addr_set(struct net_device *dev, const u8 *addr)
{
    ether_addr_copy(dev->dev_addr, addr);
}
#endif

5. Password hash substitution and defaults.
I'll add a comment for the hash substitution in the post processing script. I chose the plaintext default at 12345 to try and maintain current behavior on the webui. That way if someone builds with make_nfsroot and doesn't supply a password the webui redirect which forces a password change will be consistent on first login. Any password passed to make_nfsroot will execute the password change path. Including '12345' since the script with hash it and the salt will be different causing the match to fail. I could bake in a comparison the hash of '12345' but that seems more opaque and confusing. Open to other suggestions...

Log files
Understood, I'll add those.

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