Compare commits

...
323 Commits
Author SHA1 Message Date
Mattias WalströmandGitHub f539da7e99 Merge pull request #1489 from kernelkit/disable-release-tests
Temporarily disable release regression tests
2026-05-04 10:05:45 +02:00
Joachim Wiberg 3a6e70ba26 .github: temporarily disable release regression tests
The regression tests do not pass for some reason, could be faulty test
runner (Lifeboat) -- container and DHCP tests failing since Apr 30), so
tests are disabled until the runner is fixed.

[skip ci]

Issue #1392

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-05-04 09:33:46 +02:00
Joachim WibergandGitHub 9406fd0e04 Merge pull request #1487 from kernelkit/releng 2026-04-30 18:53:48 +02:00
Joachim Wiberg 52ef3e2ded .github: set INFIX_RELEASE when running release tests
Without INFIX_RELEASE, make test resolves INFIX_ARTIFACT to the
unversioned infix-x86_64, but release builds produce versioned
artifacts (infix-x86_64-v26.04.0-rc1.qcow2 etc.), causing the
test environment to fail with "No such file or directory".

[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-30 18:34:35 +02:00
Joachim WibergandGitHub 3d1d73543e Merge pull request #1486 from kernelkit/release-tests
Run regression tests as part of release workflow
2026-04-30 16:08:51 +02:00
Tobias WaldekranzandGitHub 4c0996b52b Merge pull request #1483 from saba8814/fix/uboot-aux-env-first-var-import
fix: import first variable from auxiliary environment
2026-04-30 14:45:44 +02:00
Joachim Wiberg e49682645c .github: run regression tests as part of release workflow
Add an x86_64 regression test job to release.yml that runs after the
build and gates publishing — the release job now requires both build
and test to succeed.

Update test.yml's artifact restore step to use a glob so it handles
both the unversioned CI artifact name (infix-x86_64.tar.gz) and the
versioned release artifact name (infix-x86_64-26.04.0.tar.gz).

Fixes #1392

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-30 13:45:35 +02:00
Joachim WibergandGitHub a3c6ec0cd5 Merge pull request #1484 from kernelkit/releng
Release preparations
2026-04-30 13:14:04 +02:00
Joachim Wiberg 25fcfba0cb doc: update ChangeLog for v26.04.0 release
[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-30 11:08:02 +02:00
Joachim Wiberg 5defdfdeac doc: add section on dummy interfaces
Fixes #769

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-30 11:08:02 +02:00
Joachim Wiberg 624bfd927c doc: add section on static mutlicast filters
Fixes #790

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-30 11:08:01 +02:00
Joachim Wiberg 4d8b2e5370 confd: warn if multicast flooding is disabled
Fixes #520

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-30 11:08:01 +02:00
Joachim Wiberg 6aed1f7df4 confd: add support for static ARP and neighbor cache
Add support for static ARP (IPv4) and neighbor cache (IPv6) entries per
interface.  Static entries are installed as permanent kernel neighbor
table entries that are never evicted by normal ARP/NDP aging.

Fixes #819

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-30 11:08:00 +02:00
Joachim Wiberg 7dd746d586 Fix BPi-R64 onboard WiFi probing
The mt7622 soc has a built-in wmac, same driver as the mt7615, but
it lacked MODULE_DEVICE_TABLE() so udev could not autoload driver
and firmware.

This commit also adds the wmac+bluetooth specific firmware.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-30 11:07:31 +02:00
Joachim Wiberg b1ad0f1656 package/mcd: bump and add support for per-bridge mcast router ports
Fixes #395

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-30 11:02:56 +02:00
Ejub Sabic 29222e18e9 uboot: import first variable from auxiliary environment
The U-Boot env file is generated by
mkenvimage, which prefixes the variable data with a 4-byte CRC32 by default.
ixpreboot.sh previously imported it with `env import -b` as per uboot docs(-b assume binary format (’0’ separated, “00” terminated).),
which treats the buffer as raw binary and does not strip the CRC.
As a result the first variable's name is parsed a part of CRC.
Later variables import correctly because by then the parser is past the CRC.
Switching to `env import -c` as per uboot docs (-c assume checksum protected environment format.)
makes U-Boot validate and strip the CRC before parsing, so the first variable imports under its real name.

Tested on:
- QEMU

Signed-off-by: Ejub Sabic <ejub1946@outlook.com>
2026-04-29 23:27:37 +02:00
Joachim Wiberg f9ea5567c4 package/finit: bump to v4.17
https://github.com/finit-project/finit/releases/tag/4.17

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-29 17:33:14 +02:00
Joachim WibergandGitHub 413d8e4599 Merge pull request #1485 from kernelkit/bpi-r3-pcifixes
Bpi r3 pcifixes
2026-04-29 17:22:23 +02:00
Mattias Walström 507bb38bdc feature-wifi: Enable 802.11 mesh (802.11s) 2026-04-29 15:47:30 +02:00
Mattias Walström 5cb17d69d4 bpi-r3: Enable the PCI clock in device tree 2026-04-29 15:43:24 +02:00
Joachim WibergandGitHub 6c6dc7711e Merge pull request #1480 from saba8814/test/dhcp-client-hostname-not-resent
test & fix: add DHCPv4 client hostname resend regression test, fix  hostname resend
2026-04-28 19:46:47 +02:00
Ejub Sabic 4f2683090e doc: updated documentation for issue #1439
Signed-off-by: Ejub Sabic <ejub1946@outlook.com>
2026-04-28 18:06:49 +02:00
Ejub Sabic 08ca47fdab fix: dhcp client host name resend
Signed-off-by: Ejub Sabic <ejub1946@outlook.com>
2026-04-28 18:00:32 +02:00
Ejub Sabic 17965bf4cc test: add DHCPv4 client hostname resend regression test
Signed-off-by: Ejub Sabic <ejub1946@outlook.com>
2026-04-28 18:00:28 +02:00
Joachim WibergandGitHub 82ffb0f4bc Merge pull request #1481 from kernelkit/kernel-upgrade-28e7d3e7-b875-4444-a0ed-a6c18cefd76d
Upgrade to kernel 6.18.25
2026-04-28 12:39:25 +02:00
Joachim WibergandGitHub 2788eb6d1a Merge pull request #1482 from kernelkit/random-infamy-id-in-ci
test: avoid infamy0 race in CI by using random container names
2026-04-28 11:43:58 +02:00
Richard Alpe ba05c2e56d test: avoid infamy0 race in CI by using random container names
GitHub Actions sets $CI=true; treat it like -r so parallel jobs
don't all try to claim "infamy0" and clobber each other.
2026-04-28 10:06:04 +02:00
ael-bot c7cdf6b018 Upgrade Linux kernel to 6.18.25 2026-04-27 16:47:37 +00:00
Tobias WaldekranzandGitHub efa665de9c Merge pull request #1472 from kernelkit/gptp
ptp: initial support for IEEE 1588/802.1AS PTP/gPTP
2026-04-25 23:15:45 +02:00
Joachim Wiberg 4ece445c44 doc: update ChangeLog
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-24 14:30:09 +02:00
Joachim Wiberg e1e2ada4b4 confd: fix review comments and code cleanup
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-24 14:30:09 +02:00
Joachim Wiberg 95bd795347 test: add some basic ptp tests
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-24 14:29:58 +02:00
Joachim Wiberg 3426c2527b Add phc2sys companion service for BC/TC instances
On multi-chip DSA hardware (e.g., boards with multiple mv88e6xxx
chips), each switch chip has its own independent PHC device.  With
boundary_clock_jbod enabled, ptp4l starts but only disciplines the
active slave port's PHC — the others drift.

Automatically start phc2sys -a alongside any BC or TC instance using
hardware timestamping.  It subscribes to ptp4l's UDS socket, tracks
BMCA, and disciplines all non-active PHCs to match the active one.
On single-chip hardware it is a harmless no-op.

CLOCK_REALTIME is intentionally left untouched.  Syncing the system
clock to PTP (phc2sys -rr), feeding the PHC from GPS/NTP (ts2phc,
phc2sys reverse), and full multi-source coordination (timemaster) are
planned as follow-on phases; see the issue tracker for the roadmap.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-23 14:19:10 +02:00
Joachim Wiberg 45b06dd670 Initial support for IEEE 1588/802.1AS PTP/gPTP
Remaining work:
- phc2sys YANG model (infix-phc2sys.yang, instance-index + servo params)
- ts2phc YANG model (GPS/PPS → PHC → ptp4l GM path)
- timemaster coordination (Phase 3, after phc2sys YANG is stable)
- show ptp network (YANG action or background-polled topology container)
- CMLDS (requires upstream linuxptp + 802.1ASdm foundation)
- Full 12-bit sdoId, fault log, performance monitoring

Backported patches from linuxptp master:
- port: fix unicast negotiation recovery after FAULT_DETECTED
- udp: fix port-specific ptp/p2p_dst_ipv4 configuration
- pmc: avoid race conditions in agent update
- phc2sys: wait until pmc agent is subscribed (startup race)
- fix MAC driver incorrect SIOCGHWTSTAMP adjustment flags
- pmc_agent: longer update interval when not subscribed
- phc2sys: don't disable pmc agent with -s/-d/-w options
- port_signaling: respect ptp_minor_version in message header
- port: refresh link status on faults
- uds: copy server socket ownership in pmc clients (non-root pmc)
- uds: don't call chmod() on client socket
- port: allow mixing wildcard and exact clock identities
- Add pidfile support to ptp4l, phc2sys, and timemaster

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-23 14:19:09 +02:00
Joachim Wiberg 73b6e5cc91 patches/ethtool: backport support for --json -T (show time stamping)
This is used by the next commit that adds initial support for PTP/gPTP.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-23 14:19:09 +02:00
Joachim Wiberg b93795c0aa board/common: add rauc upgrade bundle for ext4 images
NOTE: this is intended only for use on devboards like EspressoBin where
      the onboard bootloader only understands fat and ext2 file systems.
      To enable, use 'make apply-ext4'

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-23 14:19:09 +02:00
Joachim Wiberg 5979f4e3c9 board/aarch64: fix bpi-r4 dip switch values
Inverted values for eMMC and SPI NAND.  Also use ABCD instead of
Position as column name to match board markings.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-23 14:19:08 +02:00
Joachim Wiberg 2397e7684c board/aarch64: drag Marvell ESPRESSObin in from the cold
- Add a board README to explain how to get Infix running
- Update mkimage.sh to allow creating images without boot loader

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-23 14:19:07 +02:00
Joachim WibergandGitHub 43d6dbc63f Merge pull request #1478 from kernelkit/upgrade-buildroot 2026-04-23 13:00:41 +02:00
Mattias Walström 8ebdf9f119 Upgrade Buildroot to 2025.02.13 (LTS)
A lot of CVEs fixed.

Full changelog: https://github.com/buildroot/buildroot/blob/2025.02.x/CHANGES

Signed-off-by: Mattias Walström <lazzer@gmail.com>
2026-04-23 10:44:43 +02:00
Mattias WalströmandGitHub 3aef9930fe Merge pull request #1479 from kernelkit/kernel-upgrade-39c18ac9-3f99-4a96-bc62-daf538881c51
Upgrade to kernel 6.18.24
2026-04-23 09:50:44 +02:00
ael-bot 3ea1161f5f Upgrade Linux kernel to 6.18.24 2026-04-23 05:42:15 +00:00
Joachim WibergandGitHub 091618c527 Merge pull request #1476 from kernelkit/misc
Fix two regressions and add developer build helpers
2026-04-22 16:27:47 +02:00
Joachim WibergandGitHub 7647d2a542 Merge pull request #1477 from kernelkit/cosmetic-test-name-changes
test: normalize test case names
2026-04-21 21:47:49 +02:00
Richard Alpe f996dbd6ef test: lowercase minor words in test case names
Signed-off-by: Richard Alpe <richard@bit42.se>
2026-04-21 14:20:58 +02:00
Richard Alpe ff02190df8 test: normalize suite/case names to title case
Signed-off-by: Richard Alpe <richard@bit42.se>
2026-04-21 11:06:59 +02:00
Richard Alpe c6f7b61683 test: add names to cases called from top level suite
Signed-off-by: Richard Alpe <richard@bit42.se>
2026-04-21 11:06:57 +02:00
Joachim Wiberg dbc3ba0c83 doc: update ChangeLog
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-20 13:03:29 +02:00
Joachim Wiberg d039af7234 Fix #1458: 'show ntp tracking' does not show reference id properly
admin@gateway:~$ chronyc tracking
Reference ID    : C23ACD14 (svl1.ntp.netnod.se)
Stratum         : 2
Ref time (UTC)  : Sun Apr 19 20:28:40 2026
System time     : 0.000000000 seconds fast of NTP time
Last offset     : -17.822519302 seconds
RMS offset      : 17.822519302 seconds
Frequency       : 1064.750 ppm slow
Residual freq   : +0.581 ppm
Skew            : 0.794 ppm
Root delay      : 0.018065268 seconds
Root dispersion : 0.000200240 seconds
Update interval : 0.0 seconds
Leap status     : Normal

vs

admin@gateway:/> show ntp tracking
Reference ID        : 194.58.205.20
Stratum             : 2
Ref time (UTC)      : Sun Apr 19 20:28:40 2026
System time         : 0.000000 seconds slow of NTP time
Last offset         : -17.822519302 seconds
RMS offset          : 17.822519302 seconds
Frequency           : 1064.750 ppm slow
Residual freq       : +0.581 ppm
Skew                : 0.794 ppm
Root delay          : 0.018065 seconds
Root dispersion     : 0.000188 seconds
Update interval     : 0.0 seconds
Leap status         : Normal

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-20 13:03:28 +02:00
Joachim Wiberg 59028c4800 Fix #1466: 'show container' shows no output
A container's command line, as reported by podman, may comtain environment
variables, which the current regexp (added in ed4fe58) does not support.

Extend the regexp to allow environment variables and add an operational,
config false, 'cmdline' leaf node to allow any characters to be reported
for the full command line in the operational output.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-20 13:02:37 +02:00
Joachim Wiberg 2603b0ea1b Add support for developer config snippets
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-19 22:31:15 +02:00
Joachim Wiberg 4212a38c3b .github: bump GitHub Actions to Node.js 24 compatible versions
Fixes #1437

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-19 22:31:15 +02:00
Joachim Wiberg bb72cfd8e3 doc: add missing image to device discovery section
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-19 22:31:14 +02:00
Joachim WibergandGitHub a06786d36c Merge pull request #1475 from kernelkit/kernel-upgrade-dfbe850e-9e05-4f30-b9b5-bd9399c6b718
Upgrade to kernel 6.18.23
2026-04-18 15:22:29 +02:00
ael-bot 16a173e20b Upgrade Linux kernel to 6.18.23 2026-04-18 10:07:02 +00:00
Mattias WalströmandGitHub 6c38666229 Merge pull request #1473 from kernelkit/add-qualcomm 2026-04-17 18:59:32 +02:00
Mattias Walström b940e14eb7 Add Qualcomm WiFi 6E support
And replace lspci from busybox with pci-utils (for all platforms
except arm (32bit).
2026-04-17 13:32:16 +02:00
Joachim WibergandGitHub 1774e08219 Merge pull request #1471 from kernelkit/kernel-upgrade-f52bac45-222b-4dda-86d4-50b617297422 2026-04-11 23:47:16 +02:00
ael-bot 5950e665ab Upgrade Linux kernel to 6.18.22 2026-04-11 13:23:07 +00:00
Joachim WibergandGitHub fadffef6cd Merge pull request #1470 from kernelkit/bpi-r4-support
Add support for Banana Pi BPI-R4
2026-04-10 14:05:07 +02:00
Joachim Wiberg 69d599e2ab board/aarch64: add missing mmc partconf command to BPi-R64 U-Boot
Also, simplify board README a bit now that we know that you don't need
to flip the boot switch to program eMMC.

[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-10 11:19:35 +02:00
Joachim Wiberg 6c879d81d1 configs/sama7g54: fix U-Boot build system selection
Missing BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y caused Buildroot to default
to legacy Makefile build system, which requires BR2_TARGET_UBOOT_BOARDNAME
instead of BR2_TARGET_UBOOT_BOARD_DEFCONFIG, resulting in a build error.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-10 11:19:35 +02:00
Joachim Wiberg e5b5b6203b legal: add missing hash files and fix date-cpp hash filename
Add missing *.hash files for all board packages using the ix-board macro;
they declare LICENSE_FILES = LICENSE but had no hash file, producing a
warning during make legal-info.

Fix the date-cpp package where the hash file was named date.hash instead
of date-cpp.hash (package name is derived from the directory, not the mk
filename), causing Buildroot to skip the hash check entirely.

Add hash files for local-site packages confd-test-mode, netd, and
onieprom that declared LICENSE_FILES but provided no hash.

Also, rename package/date-cpp/date.mk to date-cpp.mk.  Buildroot derives
the package name from the directory name, so the mk file must match. To
handle the archive name different we set DATE_CPP_SOURCE.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-10 11:19:34 +02:00
Joachim Wiberg 31df56308b board: add support for Banana Pi BPI-R4
Add board support for the BananaPi BPI-R4 router board, based on the
MediaTek MT7988A (Filogic 880) SoC with quad-core Cortex-A73 CPU.

The BPI-R4 is the successor to the BPI-R3 but uses entirely different
silicon: the internal switch runs at 2.5 GbE per port, the two SFP+
uplinks use native USXGMII at up to 10 Gbps, and WiFi is provided by
a MediaTek MT7996E PCIe module supporting tri-band WiFi 7 (2.4/5/6 GHz).

Two board variants, BPI-R4-2g5 and BPI-R4P, replace one SFP+ cage with
a 2.5 GbE RJ45 port (using the MT7988A internal 2.5G PHY); the R4P adds
an optional PoE daughterboard on that port.  Both use the upstream
mt7988a-bananapi-bpi-r4-2g5 device tree.

Interfaces:
- Standard R4:  eth1 (gmac1/sfp2 LAN cage) → sfp2, eth2 (gmac2/sfp1 WAN cage) → sfp1
- R4-2g5/R4P:  eth1 (2.5G PHY) → wan, eth2 (gmac2/sfp1 WAN cage) → sfp1

Factory reset / WPS button (GPIO14, active-low): detected by U-Boot at
boot for factory reset; reused by Linux as KEY_WPS_BUTTON at runtime.

eMMC install note: the MT7988A eMMC (pins 38-49) and SD card (pins 32-37)
use separate physical pads so there is no electrical bus sharing, unlike
some BPi-R3 configurations.  However, a single MMC controller
(mmc@11230000) handles both, so only one is active per boot session.
The eMMC install procedure therefore still requires an intermediate SPI
NAND bootloader step until a Linux-side install path is tested.

SD card build (bpi_r4_sd_boot_defconfig) now uses the new
mt7988a_bpir4_sd U-Boot defconfig with cap-sd-highspeed enabled,
giving 50 MHz SD transfers instead of the previous 25 MHz legacy mode.

Also adds MT7988/MT7996 firmware support to the buildroot linux-firmware
package, for 2.5 GbE port PHY and WiFi7 extension board, and updates the
aarch64_defconfig, aarch64_minimal_defconfig, the arch README, CI
boot/image workflows, mkimage.sh, and the ChangeLog.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-04-10 11:19:34 +02:00
Joachim WibergandGitHub 19c8c80294 Merge pull request #1468 from kernelkit/fix-rpi-display
linux: Fix stability of Raspberry pi display 1
2026-04-05 05:55:02 +02:00
Mattias Walström db422ecc5e Update Changelog for new release cycle 2026-04-04 20:04:43 +02:00
Mattias Walström 5b870a273e aarch64: dts: rpi-4: Add correct syntax to change GPU mem 2026-04-04 20:04:43 +02:00
Mattias Walström e29e2093ab linux: Fix stability of Raspberry pi display 1
This fix the instability of the display on soft reboots,
previous it required a powercycle to get display to work properly

Add patches from rpi-linux, and a small fixup from me.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
2026-04-04 20:04:43 +02:00
Mattias WalströmandGitHub d5df85afad Merge pull request #1467 from kernelkit/kernel-upgrade-ab8a1129-6fcc-4662-a366-1f0a309d1c13 2026-04-02 18:29:25 +02:00
ael-bot 003aee9b53 Upgrade Linux kernel to 6.18.21 2026-04-02 11:57:37 +00:00
Joachim WibergandGitHub 12a50a8523 Merge pull request #1463 from kernelkit/fix-dhcp-client-test
test: dhcp: client_default_gw: Add longer timeout for test
2026-03-31 15:49:55 +02:00
Joachim Wiberg bae80ba9d8 doc: bump release date
Issue #1461 turned out to just be a flaky test, the change in this
commit only bumps the release date.

[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-31 15:41:08 +02:00
Mattias Walström addd89e07e test: dhcp: client_default_gw: Add longer timeout for test
This fix #1461
2026-03-31 12:26:46 +02:00
Joachim WibergandGitHub 9014d7edb7 Merge pull request #1462 from kernelkit/changelog-update 2026-03-31 11:36:17 +02:00
Joachim Wiberg c0475fc886 doc: update ChangeLog for v26.01.0, add missing entries
Add several entries that were missing from the original release notes,
most notably the SBSA watchdog fix for CN913x (Marvell Octeon) platforms
and the BPI-R3 watchdog fix, plus show keystore, ixll scan, show system
temperature, WiFi signal strength inversion fix, and follow command fix.

[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-31 10:37:26 +02:00
Joachim WibergandGitHub de3a44e58d Merge pull request #1460 from kernelkit/releng
Documentation update and prep. for v26.03.0

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-30 16:03:59 +02:00
Joachim Wiberg 996c857e20 doc: update ChangeLog for v26.03.0
[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-30 14:43:19 +02:00
Joachim Wiberg 823bba0ece doc: add migration script reminder to Developer's Guide
When a YANG model change breaks existing startup configs, a migration
script must be included or devices in the field may be left unbootable
after upgrade.  Add a dedicated section explaining when scripts are
needed, where they live, and how they work.

Fixes #1459

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-30 14:43:18 +02:00
Joachim Wiberg 93bff6260e Add project links to User Guide and update SUPPORT.md
Fixes #1456

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-30 14:43:09 +02:00
Joachim WibergandGitHub cdc28ffe00 Merge pull request #1453 from kernelkit/discovery-docs
mDNS discovery improvements
2026-03-26 14:20:12 +01:00
Mattias WalströmandGitHub 9b9ba63d09 Merge pull request #1455 from kernelkit/kernel-upgrade-a38bf031-1a49-4f5f-87c2-053f45c2ca81
Upgrade to kernel 6.18.20
2026-03-25 16:32:31 +01:00
Joachim WibergandGitHub 5b1211365b Merge pull request #1454 from kernelkit/add-migrate-script
Add migration script for confd: prevent IP addresses on bridge ports
2026-03-25 14:50:17 +01:00
ael-bot e51daefe99 Upgrade Linux kernel to 6.18.20 2026-03-25 11:59:13 +00:00
Mattias Walström 1659ca2a05 Add migration script for confd: prevent IP addresses on bridge ports
Unfortunatly the fix was entered in 25.10, but confd was not stepped
up until 25.11, so this should be for 25.10 but now it is for confd
version 1.6 (infix 25.11), as close as we can get.

this is a follwup for commit 7e37fc49a3

confd: prevent IP addresses on bridge ports

Bridge ports should not have IP addresses configured. The IP address
should be configured on the bridge interface itself, not its member ports.

Add YANG must expression to enforce this rule at configuration time.

Fixes #1122
2026-03-25 11:12:47 +01:00
Joachim Wiberg e2d1ed275b doc: update network.local screenshot and freshen up cli examples
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-22 20:23:45 +01:00
Joachim Wiberg 5ed71fa10d utils: ixll scan: show spinner while waiting for avahi-browse
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-22 20:23:45 +01:00
Joachim Wiberg cfcc83f15d netbrowse: add operational backend and fix TXT record parsing
Add a second discovery backend that reads mDNS neighbor data directly
from the sysrepo operational datastore via `copy operational-state -x
/mdns`, selectable with --backend operational.

Add an auto backend (the new default) that tries the operational data
first and falls back to avahi-browse if the `copy` command is
unavailable or mDNS is disabled (visible via "enabled": false in the
JSON).  This makes the service work correctly in all configurations
without manual tuning.

Refactor TXT record parsing into parseTxt() and service/host assembly
into buildHosts(), shared by both backends.  Extract fetchOpRoot() and
parseOperational() so scanOperational() and scanAuto() share the same
JSON fetch/decode and host-building logic without duplication.

Fix a bug where TXT values containing semicolons were truncated
(parts[9] → strings.Join(parts[9:], ";")), and apply decode() to TXT
values so avahi \DDD escapes are resolved.  Add Apple device model
support via the am= (RAOP/AirPlay 1) and model= (AirPlay 2) TXT keys.

Display the last-updated timestamp in 24-hour format regardless of the
browser's locale.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-22 20:23:44 +01:00
Joachim Wiberg e168633f4e statd: reliable avahi client reconnect
Add reliable avahi client reconnect via explicit free+recreate, reduced
log verbosity (single 10s warning instead of 3×2s loop).  Also, binary
TXT record filtering (UTF-8 + XML validity), and finally add a SIGHUP
handler for on-demand reconnect.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-22 20:23:44 +01:00
Joachim Wiberg 8d164216fc package/mdns-alias: bump to v1.2
Handles Avahi daemon startup race and runtime restarts gracefully.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-22 20:23:43 +01:00
Joachim Wiberg 4cb2d28e3c package/klish: only show banner in interactive mode
Meaning, skip the CLI help message in non-interactive mode, allowing for:

admin@gateway:~$ klish -c 'show mdns'
Enabled         : yes
Domain          : local
Deny            : wan

HOSTNAME           ADDRESS        LAST SEEN  SERVICES
Living-Room.local  192.168.0.139  18:50:52   trel(57249) sleep-proxy(61936) raop(7000) srpl-tls(853)
firefly-4.local    192.168.0.122  18:50:46   workstation(9)
gimli.local        192.168.0.200  18:50:46   device-info(0)
infix.local        192.168.0.1    18:50:47   https(443) workstation(9) ssh(22) https(443)

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-22 20:23:43 +01:00
Joachim Wiberg 3a7ef41629 package/skeleton-init-finit: adjust mdns daemon's pid file path
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-22 20:23:42 +01:00
Joachim Wiberg 1558b6bf7e .github: coverity: use matching sysrepo + libyang versions
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-22 20:23:42 +01:00
Joachim WibergandGitHub 349a89ba52 Merge pull request #1381 from kernelkit/copilot/fix-ipv6-ping-windows
Document Windows IPv6 multicast ping limitations with community verification request
2026-03-20 20:09:06 +01:00
copilot-swe-agent[bot]andJoachim Wiberg 55e9a57ae3 doc: update Windows device discovery documentation
Infix now advertises _workstation._tcp, making devices appear
automatically in Windows Explorer's Network folder (Win 10 1709+).
Lead with this, show .local hostname usage for ping/SSH, and demote
the IPv6 multicast ping caveat to a note.

[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 20:08:20 +01:00
Joachim WibergandGitHub 15d6947207 Merge pull request #1412 from kernelkit/initviz
Optimize boot time and consolidate confd into a single daemon                                                             

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 19:17:47 +01:00
Joachim Wiberg e536deab65 doc: update ChangeLog, sorting fixes in number order
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 17:06:18 +01:00
Joachim Wiberg a556abbdfc doc: expand test-arch with physical device test mode instructions
Also, update testing-overview.svg to support dark mode view.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 17:06:17 +01:00
Joachim Wiberg d3dc47ac8e .github: add libavahi-client-dev to Coverity Scan dependencies
statd now uses avahi-client for mDNS neighbor tracking, so the
native build needs libavahi-client-dev to satisfy pkg-config.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 17:06:17 +01:00
Joachim Wiberg cf08b577ed test: gps_simple: wait for full position data before has_fix()
has_fix() only checks that fix-mode is set (2d/3d), but altitude and
other fields may not yet be populated in the operational datastore when
gpsd is still processing its first NMEA cycles after boot.  Calling
verify_position() immediately after has_fix() passes can therefore race
and fail with:

  KeyError: 'altitude'

This manifests reliably on the second GPS receiver (gps1) after reboot,
because it is initialized slightly later than gps0 and hits the window
where fix-mode is set but altitude has not yet appeared.

  not ok 11 - Verify gps1 position is near the coordinates
  # Traceback (most recent call last):
  #   File "test/case/hardware/gps_simple/test.py", line 29, in verify_position
  #     alt = float(state["altitude"])
  #                 ~~~~~^^^^^^^^^^^^
  # KeyError: 'altitude'

Add has_position() to infamy/gps.py, which gates on fix-mode AND all
position fields (latitude, longitude, altitude, satellites-used) being
present.  Replace the has_fix() polls in both the pre- and post-reboot
verify steps with has_position().

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 17:05:36 +01:00
Joachim Wiberg 1c6c7724b9 test: iface_phys_address: use chassis MAC and add until() guards
Replace fragile SSH+jq approach for reading the chassis MAC with a
NETCONF query to ietf-hardware:hardware/component[name='mainboard'],
reading phys-address directly from the YANG model.

Also add until() polling to the chassis MAC and chassis+offset MAC
verification steps, consistent with the reset-to-default steps.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:17 +01:00
Joachim Wiberg 94a036be3a test/infamy: retry copy() on ConnectionError in restconf transport
A service restart triggered by finit during sysrepo callbacks can drop
an in-flight HTTP connection, causing copy("candidate", "running") to
fail with RemoteDisconnected.  Add retry logic consistent with the
existing PATCH retry pattern in put_config_dict().

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:17 +01:00
Joachim Wiberg 281f027749 test/infamy: wait for transport reachability after test_reset()
test_reset() triggers a config reload which causes services such as
rousette to restart.  Wait for the transport to become reachable again
before returning from attach(), preventing subsequent API calls from
racing with a still-restarting backend.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:16 +01:00
Joachim Wiberg 4dee5e4f1f package/rousette: silence rousette warnings in log
Add --log-level command line option to filter out log messages from
lower log levels.  Then fix the annoying CzechLight warning message
and useless "NACM config validation" log.  Then add audit trail as
we have in netopeer2-server, and finish off by stripping redundant
fields from log message: timestamp, identity, and log level.

Fixes #892

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:16 +01:00
Joachim Wiberg e9f165ebd8 patches/libnetconf2: silence netopeer2-server warnings in log
Fixes #1446

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:16 +01:00
Joachim Wiberg abad3cedc6 confd: actually fix stratum-weight semantics and flaky test
The setting 'stratumweight 0.0' disables stratum in Chrony source
selection (pure distance-based), making client_stratum_selection
non-deterministic on a LAN.  Setting it to 1.0 gives srv1 a 1-second
effective advantage per stratum level, which no realistic distance
fluctuation can overcome.

Also correct the YANG descriptions in infix-system and infix-ntp which
had the semantics backwards — claiming 0.0 "ensures lower stratum is
always preferred" when in fact higher values do that.

Fixes #1361

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:15 +01:00
Joachim Wiberg 7b4e9b3366 confd: skip bootstrap on restart using a sentinel file
After a successful bootstrap confd writes a sentinel to /run/confd.boot
If Finit restarts confd — whether after a crash or a clean exit — the
sentinel is found and the destructive bootstrap phases are skipped:

 - gen-config fork (factory/failure configs already exist)
 - wipe_sysrepo_shm() (other daemons, e.g. statd, are live)
 - sr_install_factory_config() (datastores are already initialised)
 - sr_replace_config(NULL, NULL) (running datastore is consistent)
 - bootstrap_config() / load startup-config (not needed; sysrepo has
   the right state; plugins resync via SR_EV_ENABLED on re-subscribe)

On restart confd reconnects to sysrepo, re-initialises plugins (which
re-subscribe and receive SR_EV_ENABLED to resync with the live running
datastore), then enters the steady-state event loop.

The sentinel lives on tmpfs so a real reboot always produces a clean
slate.  Crash-loop protection is delegated to Finit's max-restarts (10).

As a side-effect this also enables a future "run-once" mode for resource
constrained systems: confd can exit after bootstrap and the sentinel
ensures any later restart just re-attaches without re-bootstrapping.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:15 +01:00
Joachim Wiberg ed1d6b7d5c confd: replace systemf() shell-outs with POSIX/libite/libsrx APIs
Replace remaining systemf() calls that invoke simple file-system
operations with direct C API equivalents, eliminating unnecessary
fork/exec overhead:

 - mkdir -p     → mkpath() from libite
 - ln -sf       → erase() + symlink() from libite/POSIX
 - rm -rf       → rmrf() from libsrx helpers
 - rm -f dir/*  → rmrf() + mkpath() to clear and recreate the dir

Files updated: dagger.c, containers.c, firewall.c, services.c, system.c

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:14 +01:00
Joachim Wiberg 0ee3159ac6 confd: replace initctl shell-outs with direct finit_ C API
Add a finit_enable/disable/reload() family in core.c that directly
manipulates Finit's service state without fork+exec overhead:

  finit_enable(svc)  -- create symlink in /etc/finit.d/enabled/
  finit_disable(svc) -- remove symlink from /etc/finit.d/enabled/
  finit_delete(svc)  -- remove both symlink and service entirely
  finit_reload(svc)  -- utimensat() on .conf to schedule reload

Printf-style variants (finit_enablef/disablef/reloadf) handle
template instance names such as container@foo and hostapd@wlan0.

All systemf("initctl ... enable/disable/touch ...") call sites across
containers, dhcp-server, firewall, hardware, ntp, routing, services,
syslog, and system are converted to the new API.

As a related cleanup in services.c, drop the remaining srx_enabled()
calls in favour of reading the already-fetched config tree directly
via lydx_is_enabled(lydx_get_xpathf(config, ...)), eliminating the
last sysrepo round-trips from that module.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:14 +01:00
Joachim Wiberg bc6313d2db confd: services: only enable/disable or touch on actual changes
Previously svc_enadis() would call 'initctl enable + touch' for every
config change event, even when the service's enabled state was unchanged.
This caused rousette to be unnecessarily restarted on every test_reset(),
racing with the active RESTCONF connection on slow hardware.

Replace svc_enadis() and svc_change() with svc_enable() which only
manages nginx symlinks and calls 'initctl enable/disable' -- never touch.
Each handler now checks the diff for the specific leaf that changed:

- If /enabled appears in diff: call svc_enable() to start or stop it
- If other config leaves changed with service already enabled: touch only

This ensures rousette, ttyd, netbrowse, avahi, sshd, and lldpd are only
restarted when their configuration actually requires it.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:13 +01:00
Joachim Wiberg 0884227afa confd: optimize, skip dagger generation when no change
Save a few CPU cycles by skipping a new dagger generation when no
interfaces have been modified/added/deleted.

Uses d->next_fp as the sentinel: NULL means no claim was made for this
transaction.  dagger_evolve() and dagger_abandon() now NULL it after
fclose, so subsequent unclaimed transactions also get the clean early
return.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:12 +01:00
Joachim Wiberg 7f2fbc8bbf statd: avahi: rename avahi subsystem to mdns
The operator sees Infix through YANG models and should not need to know
which library implements a given feature.  Rename the public-facing
parts of the avahi module to use the mdns vocabulary:

- Log strings: "avahi: ..." → "mdns: ..."
- Public API:  avahi_ctx_init/exit → mdns_ctx_init/exit
- Main type:   struct avahi_ctx → struct mdns_ctx
- statd field: statd.avahi → statd.mdns

Internal types (struct avahi_neighbor, avahi_service, …) and file names
(avahi.c, avahi.h) are kept as-is — developers debugging at the C level
benefit from knowing the underlying implementation.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:12 +01:00
Joachim Wiberg fee552196a statd: avahi: suppress transient mDNS daemon restart errors
When the mdns service is stop-started (e.g. after a config change),
statd's avahi client fires AVAHI_CLIENT_FAILURE momentarily.  With
AVAHI_CLIENT_NO_FAIL the client reconnects automatically, but the
immediate ERROR log is misleading:

  ERROR: avahi: client failure: Daemon connection failed

New behavior:
- On AVAHI_CLIENT_FAILURE: start a 2 s deferred timer (no immediate log)
- Timer fires up to 3 times (~6 s total); on the 3rd attempt, check if
  mDNS is enabled in the running config via a temporary sysrepo session
- Log ERROR only if the daemon is still down AND mDNS is enabled
- On AVAHI_CLIENT_S_RUNNING: cancel the timer, reset the counter, and
  log NOTE "mDNS daemon reconnected" if a failure had been seen

This silences the error entirely when the operator has disabled mDNS
(expected), and defers it by ~6 s for a brief restart (self-heals
before the timer fires).

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:11 +01:00
Joachim Wiberg adee27f923 Minor, consolidate naming and adjust avahi + mdns-alias conditions
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:11 +01:00
Joachim Wiberg 9472e08262 confd: clean up, simplify use common log framework
- Use same log frameworks as reset of confd
 - Use existing primitives from libite + libsrx
 - Drop remaining pthreads
 - Coding style fixes

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:10 +01:00
Joachim Wiberg d3c091e746 statd: optimize yanger invocation time and reduce command overhead
Replace logging + logging.handlers with a lightweight syslog wrapper,
and argparse with manual argv parsing.  On a sama7g54, this cuts yanger
startup from ~770ms to ~470ms by eliminating ~300ms of stdlib imports.

Also batch external command invocations:

 - ietf_routing: two sysctl calls instead of two per interface
 - ietf_hardware: one ls per hwmon device instead of six
 - bridge: fetch mctl querier data once instead of once per VLAN

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:10 +01:00
Joachim Wiberg 5583b97da9 confd: fix duplicate keystore log messages at boot
Only install the keys on CHANGE event, fixes this annoying issue:

Nov 5 01:32:10 ix confd[2011]: Installing HTTPS gencert certificate "self-signed"
Nov 5 01:32:10 ix confd[2011]: Installing SSH host key "genkey".
Nov 5 01:32:11 ix confd[2011]: Installing HTTPS gencert certificate "self-signed
Nov 5 01:32:11 ix confd[2011]: Installing SSH host key "genkey".

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:09 +01:00
Joachim Wiberg 9e7cdf492f confd: replace sysrepo threads with libev event loop
Use SR_SUBSCR_NO_THREAD for all subscriptions and integrate sysrepo
event pipes into a libev event loop.  This eliminates approximately 30
per-subscription threads, reducing overhead on embedded ARM hardware.

A temporary poll-based "event pump" thread handles callback dispatch
during bootstrap (where sr_replace_config blocks waiting for callbacks),
then exits.  After bootstrap, the single-threaded libev loop takes over
for steady-state event processing.

Note, the confd-test-mode plugin still requires use of threads so we do
not create deadlocks when calling sr_replace_config().

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:09 +01:00
Joachim Wiberg 929f53d270 board/aarch64: enable root hub transaction translator for ehci/ohci
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:08 +01:00
Joachim Wiberg 1966d104c9 board/arm: relocate rpi2 kernel config to board support package
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:08 +01:00
Joachim Wiberg 3507cd5601 doc: document new 'gencert' default https cert
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:07 +01:00
Joachim Wiberg 97c26d36bf confd: migrate https cert from /cfg/ssl to ietf-keystore
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:07 +01:00
Joachim Wiberg 06361032d2 confd: add support for user configurable https certificate
- Add x509-public-key-format identity to crypto-types
 - Add certificate node to web services container
 - Use certificate from ietf-keystore as web cert

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:07 +01:00
Joachim Wiberg f61e1580cd configs: drop wifi and gps support from minimal builds
Neither the Raspberry Pi 2B or the Microchip SAMA7G54-EK board have WiFi
hardware by default so drop WiFi, and GPS, support to allow for smaller
builds with only the bare essentials in kernel and system.

Minimal builds in general don't need WiFi or GPS either, so let's disable
them from all.  This may become a central theme going forward, keeping
the minimal builds ... minimal.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:06 +01:00
Joachim Wiberg 8d87465876 board/common: fix race between confd bootstrap and test_reset RPC
netopeer2 and rousette were starting as soon as confd had a PID, while
confd was still loading the startup config via sr_replace_config().  This
held a write lock on the running datastore.  A test calling test/reset
shortly after the NETCONF port opened would have its own sr_replace_config()
block on that lock for up to 60 s, at which point sysrepo timed out the
whole RPC with "SHM event 'rpc' processing timed out".

Fix by adding the usr/bootstrap condition to both management servers so
they don't accept connections until confd signals that bootstrap is complete.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:06 +01:00
Joachim Wiberg f257ab58d4 board/common: probe for wifi radios
Relocate probe of wifi radios from gen-hardware to 00-probe.  This saves
one python invocation and some precious CPU cycles at boot.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:05 +01:00
Joachim Wiberg 07f23ec4f5 board/common: move hostname.d setup at runtime to build-time
Follow-up to 90f619b which first introduced the /etc/hostname.d concept.

This commit moves the setup of /etc/hostname.d to post-build.sh dropping
the initial call to the hostname activation script a bit, since it is
called anyway after bootstrap has finished.  The scrip is also given a
bit of a refrehs, reducing overhead and needless log messages.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:05 +01:00
Joachim Wiberg 4ca53f8ec2 confd: consolidate gen-config to start earlier
Allow confd to start even earlier at boot and call 'gen-config' as a
background task, pending on it to complete before we load the sysrepo
factory datastore.

Also, add Finit style progress to console so users can see the phases
of the bootstrap process.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:04 +01:00
Joachim Wiberg 4bc08e7323 Drop useless logger processes, these services already use syslog
Note, rousette does not support SIGHUP, so let's mark it as such.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:04 +01:00
Joachim Wiberg 9c2a90c07a statd: move start to runlevel 2 to save CPU cycles at bootstrap
Also, we don't need to start a logger process for statd, it behaves
nicely and uses syslog.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:03 +01:00
Joachim Wiberg 3deb021bce board/common: postpone start of dbus to after confd bootstrap
Infix technically does not need to start dbus and dnsmasq before confd
has loaded the system startup-config.  So we move it in time to save
some CPU cycles for confd & C:o.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:03 +01:00
Joachim Wiberg 77a7915e1f confd: replace sysrepo-plugind + bootstrap + load with single daemon
On single-core Cortex-A7, the YANG bootstrap and config loading is the
dominant boot bottleneck.  The current sequence spawns three serial
phases (bootstrap, sysrepo-plugind, load), each performing independent
sr_connect()/sr_disconnect() cycles, and every sysrepoctl/sysrepocfg
invocation is a fork+exec that rebuilds SHM from scratch.

Replace all three with a single confd binary that does one sr_connect()
and performs all datastore operations in-process:

 - Wipe stale /dev/shm/sr_* for a clean slate
 - sr_install_factory_config() from the generated JSON
 - Smart migration: compare config version via libjansson, only
   fork+exec the migrate script when versions actually differ
 - Load startup-config (or test-config) via lyd_parse_data() +
   sr_replace_config(), mirroring what sysrepocfg -I does internally
 - On failure: revert to factory-default, load failure-config, set
   login banners (Fail Secure mode)
 - On first boot: copy factory-default to running, export to file
 - dlopen plugins and enter event loop

The bootstrap shell script is split: config generation (gen-hostname,
gen-interfaces, etc.) stays in the new gen-config script, while all
sysrepo operations move into the C daemon.  The finit boot sequence
collapses from 5 stanzas to 2 (gen-config -> confd).

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:03 +01:00
Joachim Wiberg 3b85fdff87 doc: minor fixes
- Markdown syntax
 - Grammar fixes
 - Use lowdown's admonition syntax
 - Update examples

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:02 +01:00
Joachim Wiberg ea5071a264 package/finit: backport upstream fixes
Backport fixes from upstream post v4.16 release.  Mainly to fix
mdns-alias crash+restart counter issue when avahi-daemon has to
be restarted.  Finit did not properly clear the dependency that
mdns-alias had on avahi-daemon, causing it to crash and have its
restart counter incremented.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:02 +01:00
Joachim Wiberg 50be4d1a43 package/initviz: new package
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:01 +01:00
Joachim Wiberg 63c3d244ae board/arm: trim kernel defconfig
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:01 +01:00
Joachim Wiberg 7050f400d5 board/arm: sama7g54-ek: enable sdmcc high speed modes
For details, see:
 - https://github.com/linux4sam/u-boot-at91/commit/23ac019
 - https://github.com/linux4sam/linux-at91/commit/5b35500

U-Boot patches imported and refreshed in local KernelKi fork of U-Boot,
see https://github.com/kernelkit/u-boot/tree/v2025.01-kkit

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:00 +01:00
Joachim Wiberg 23cbfd6f4e board/arm: disable u-boot environment, use aux partition
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:00 +01:00
Joachim Wiberg e2bb1cfbe0 board/arm: fix rauc system.conf 2026-03-20 16:17:59 +01:00
Joachim Wiberg 95abdac7ee board/arm: update board list with Microchip SAMA7G54 eval kit
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:17:59 +01:00
Joachim Wiberg 0a7bd76ede configs/sama7g54_ek_*_boot_defconfig: switch to upstream U-Boot
The v2025.01 release supports the Microchip SamA7G5* eval kit(s), which
means we can enjoy the same patch level of U-Boot as other Infix boards

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:17:59 +01:00
Joachim Wiberg f8ef10ff2f board/common: optimize busybox for speed, drop fork+exec for applets
- The biggest changes are syncing with latest BusyBox (busybox-update-config)
 - Disable optimize for size
 - Enable feature "SH_NOFORK" which allows /bin/sh to call applet_main()
   directly without having to fork+exec busybox

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:17:58 +01:00
Joachim WibergandGitHub 2137a3bf75 Merge pull request #1452 from kernelkit/kernel-upgrade-b6b7879b-4015-4b73-a84d-a83dd6049546 2026-03-19 18:36:41 +01:00
ael-bot b38c039be1 Upgrade Linux kernel to 6.18.19 2026-03-19 16:35:18 +00:00
Joachim WibergandGitHub 63f9e8a939 Merge pull request #1451 from kernelkit/frr
Bump FRR to 10.5.3

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-18 17:58:04 +01:00
Mattias Walström be85775e50 Bump FRR to 10.5.3
For change log, see:
     https://github.com/FRRouting/frr/releases/tag/frr-10.5.3
2026-03-18 16:18:44 +01:00
Mattias WalströmandGitHub 2fea1e4a2b Merge pull request #1450 from kernelkit/upgrade-buildroot
Bump buildroot to 2025.02.12 (LTS)
2026-03-18 14:18:43 +01:00
Mattias Walström fcf9782a8c Bump buildroot to 2025.02.12 (LTS)
Alot of CVE fixes, see https://github.com/buildroot/buildroot/blob/2025.02.x/CHANGES
2026-03-17 21:48:51 +01:00
Mattias WalströmandGitHub f1584f5937 Merge pull request #1449 from kernelkit/kernel-upgrade-399f2582-484c-438e-b83c-92bd62c5dd9f
Upgrade to kernel 6.18.18
2026-03-17 08:18:27 +01:00
ael-bot 3d67876136 Upgrade Linux kernel to 6.18.18 2026-03-16 15:04:32 +00:00
Joachim WibergandGitHub 0f01012c07 Merge pull request #1447 from kernelkit/refactor-actions
Move local GitHub actions to kernelkit/actions repo

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-16 15:48:54 +01:00
Joachim WibergandClaude Sonnet 4.6 63f46d4d43 .github: move local actions to kernelkit/actions repo
Fixes a regression from 0c11cea where local composite actions
(.github/actions/) were referenced with relative paths. When spins
reuse our reusable workflows, GitHub resolves relative action paths
in the context of the calling repo, not infix — breaking the build.

Replace all uses of ./.github/actions/{cache-restore,podman-cleanup}
with kernelkit/actions/{cache-restore,podman-cleanup}@v1 (new repo).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 14:38:58 +01:00
Joachim WibergandGitHub 5487344034 Merge pull request #1444 from kernelkit/another-netd-fixup 2026-03-13 07:15:27 +01:00
Joachim Wiberg 3e762e6111 confd: Use ERRNO() instead of ERROR() after POSIX API failures
Replace ERROR() with ERRNO() in all error paths following POSIX API
calls (fopen, rename, realloc, fmkpath, etc.), removing redundant
manual strerror(errno) formatting where present.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-12 22:27:52 +01:00
Joachim Wiberg af15e65087 package/netd: ensure /etc/net.d exists at boot
Before netd starts confd might want to create .conf file for it to run,
so we sort of depend on /etc/net.d existing at boot.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-12 22:08:25 +01:00
Joachim WibergandGitHub 03b4466e09 Merge pull request #1443 from kernelkit/kernel-upgrade
Upgrade Linux kernel to 6.18.17

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-12 19:19:32 +01:00
Mattias Walström a1903a893a Upgrade Linux kernel to 6.18.17 2026-03-12 15:08:12 +01:00
Joachim WibergandGitHub b9cbbb053d Merge pull request #1440 from kernelkit/default-route-at-boot
Fix missing default route at boot

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-12 13:49:34 +01:00
Joachim Wiberg 49c66ee957 doc: update ChangeLog
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-12 12:07:57 +01:00
Joachim Wiberg 43f3bf0322 board/common: make dnsmasq authoritative, drop redundant options
Set dhcp-authoritative so clients with unexpired leases are not NAKed
after a router crash or factory reset that clears the lease database.

Drop the untagged suppress directives for options 3 (router) and 6
(dns-server): they conflict with the global options confd writes to
dnsmasq.d/, causing spurious "Ignoring duplicate dhcp-option" warnings.
Per-subnet tagged options already suppress auto-detection, and without
an active dhcp-range there is nothing to suppress anyway.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-12 12:07:57 +01:00
Joachim Wiberg ba8d1f6b4a confd: fix DHCP client hostname reporting, rpi-%m -> rpi-c0-ff-ee
Ensure we translate the hostname before we generate the udhcpc command
line options, otherwise we'll send '-x hostname:rpi-%m' to udhcpc.

Also update all board specific factory configs with the missing setting
'"value": "auto"' for the DHCP hostname option.  This to match what we
already do when we infer options when enabling a DHCP client in the CLI.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-12 12:07:56 +01:00
Joachim Wiberg 221fea13a2 netd: watch conf.d with inotify, retry on backend failure
Two races could prevent DHCP-learned default routes from being installed
at boot:

1. The signal from the DHCP client script could be lost leaving conf.d
   updated but frr.conf stale.

2. Even when the signal was received, 'vtysh -b' could fail because the
   FRR daemon chain (mgmtd→zebra→staticd) writes PID files before being
   fully operational, causing netd to give up with no retry.

Fix both by refactoring netd to use libev:

- Use an inotify watch of CONF_DIR, so netd reacts directly to file
  changes without depending on signal delivery.

- On backend_apply() failure, schedule a retry in 5s and call pidfile()
  unconditionally so dependent services are not blocked waiting for the
  Finit condition 'pid/netd' to be satisfied.

We also take this opportunity to rename /etc/netd/conf.d/ to /etc/net.d/
The extra /etc/netd/ directory level served no purpose — nothing else
lives there.  Flatten to /etc/net.d/ which reads more naturally as the
drop-in directory for network configuration snippets.

Also, reduce logging a bit since each netd backend already logs success
or fail which is sufficient to know that a configuration change has been
applied or not.

Finally, with the new inotify processing in netd it's redundant to call
'initctl reload netd' from the udhcpc script, in fact it will only cause
unnecessary overhead, so we drop it.

Fixes #1438

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-12 12:07:49 +01:00
Joachim WibergandGitHub cb243304ad Merge pull request #1436 from kernelkit/ospf-neighbor-must-expression
OSPF neighbor must expression

[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-11 12:33:12 +01:00
Joachim Wiberg fc757a439a doc: amend static neighbors to new OSPF point-to-multipoint
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-11 11:16:02 +01:00
Joachim Wiberg 757afe5206 confd: follow-up to OSPF point-to-multipoint
Add a must expression to ensure users do not set static neighbors when
the interface type is not point-to-multipoint or non-broadcast.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-11 11:16:01 +01:00
Joachim WibergandGitHub 5b7b0bc249 Merge pull request #1430 from kernelkit/bpi-r64
Add support for Banana Pi BPi-R64

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-11 09:48:44 +01:00
Joachim WibergandGitHub d04f493f08 Merge pull request #1435 from kernelkit/ospf-point-to-multipoint
Followup OSPF point-to-multipoint
2026-03-11 09:30:35 +01:00
Mattias Walström f0b220b6e7 Followup OSPF point-to-multipoint
[skip ci]
2026-03-11 09:12:48 +01:00
Joachim WibergandGitHub f35e3b3ec3 Merge pull request #1429 from kernelkit/ospf-point-to-multipoint
ospf: add point-to-multipoint and hybrid interface type support

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-10 15:15:11 +01:00
Mattias Walström 312b856fba ospf: add point-to-multipoint and hybrid interface type support 2026-03-10 12:44:47 +01:00
Joachim Wiberg 4deaee0b8e doc: update changelog with BPi-R64 and RPi-400 support
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-10 12:11:33 +01:00
Joachim Wiberg 121abe7891 .github: add bpi-r64 to image builder
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-10 12:11:11 +01:00
Joachim Wiberg cc10b70f19 wifi: add Mediatek MT7615 firmware
Used in BPI-MT7615 802.11ac PCIe WiFi card for the BPi-R64 router board.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-10 12:11:11 +01:00
Joachim Wiberg 6560af1b94 board: add support for Banana Pi BPI-R64
Add board support for the BananaPi BPi-R64 router board, based on the
MediaTek MT7622 SoC and MT7531 Gigabit Ethernet switch.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-10 12:11:10 +01:00
Joachim Wiberg 784b911253 patches/genimage: add gpt-protective-first option for hybrid MBR
In a hybrid MBR the conventional layout (used by gdisk and others) is:

  MBR[0] = 0xEE  (GPT protective, covers whole disk)
  MBR[1..3] = user-selected GPT partitions with legacy type codes

genimage currently appends the 0xEE entry after the data partitions,
producing the opposite order.  This is fine for most platforms, but
breaks firmware that detects GPT by inspecting only MBR entry 0: seeing
a non-0xEE type there it falls into pure-MBR mode and cannot look up
GPT partitions by name.

The TF-A partition driver (drivers/partition/partition.c) exhibits
exactly this behaviour: load_mbr_header() copies entry[0] and checks
type == 0xEE to select between MBR and GPT mode.  The MediaTek MT7622
platform (BananaPi BPI-R64) is a concrete example where this matters.

On the other hand, Raspberry Pi firmware scans all MBR slots for a
bootable FAT32 partition.  If slot 0 holds a 0xEE protective entry the
firmware switches to GPT detection, looks for an EFI System Partition
UUID, and reports "no bootable partitions" when none is found.

Add an opt-in hdimage option `gpt-protective-first = true` that places
the 0xEE entry at slot 0 and shifts data partitions to slots 1..3.
The default (false) preserves the existing genimage behaviour so that
platforms like Raspberry Pi continue to work without any changes.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-10 12:11:10 +01:00
Joachim Wiberg 35ba2ca37f board/aarch64: add dedicated RPi 400 product configuration
The Raspberry Pi 400 shares hardware with the RPi 4B but differs in one
important way: it has an internal keyboard and mouse connected through a
VIA Labs USB hub on the VL805 xHCI controller.  Break the symlink to
raspberrypi,4-model-b and maintain a dedicated product directory.

Factory config changes from the 4B default:
- USB1/USB2/USB3 all unlocked: USB2 carries the internal keyboard hub
  and USB3 the superspeed companion; all are unlocked as this is a
  desktop device
- DHCP vendor-class corrected to "Raspberry Pi 400"

Also add interface-quirks.json for the eth0 PHY detach behaviour and
the smsc95xx broken flow-control quirk (inherited from the 4B config
but now explicit), and remove the spurious bootable flag from the
primary and secondary rootfs partitions in genimage.cfg.in.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-10 12:11:09 +01:00
Joachim Wiberg e16f0a2504 board/aarch64: enable HDMI display output on RPi4
Remove console=map:0 from the [pi4] section which was suppressing HDMI
output and disabling the display getty.  Making it really difficult to
use it as a regular console.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-10 12:11:09 +01:00
Joachim Wiberg 799fd93cac board/common: fix authorization cascade for internal USB hubs
Two related problems prevented devices behind an intermediate hub (e.g.
the VIA Labs hub on the RPi 400's VL805 xHCI) from being authorized
when confd unlocks a USB bus:

1. Cascade ordering: usb_authorize() ran nftw() with FTW_DEPTH, which
   visits children before the root-hub entry.  The hub was authorized
   while authorized_default was still 2, so when the kernel probed the
   hub's children it immediately denied them.  Fix: write
   authorized_default=1 on the bus before entering nftw.

2. Slow/async probe: hub port enumeration is asynchronous — devices
   behind a hub may appear in sysfs after nftw has already finished.
   Fix: add a udev rule that catches usb_device add events on buses
   where authorized_default=1 is already set on any ancestor root hub
   and authorizes them immediately.

The ATTRS{} matcher in udev walks the full sysfs parent chain, so
authorized_default=1 on the root hub is visible even for devices several
hubs deep.  Buses still locked at authorized_default=0 are left alone.

Also expand the docstring in generic_usb_ports() to document the
design: each root hub gets its own uniquely-named entry (USB, or USB1/
USB2/... when multiple) so buses can be individually controlled, and
boards needing finer control should use DT usb-ports annotations.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-10 12:11:08 +01:00
Joachim Wiberg 726a3132e3 board/common: optimize sysctl-sync-ip-conf, drop filtering loop
Replace the costly read-only filter loop (awk+tr per line) with a
stderr redirect, use /sys/class/net/ instead of ip+jq, and batch
all sysctl writes into a single call.

Reduces boot time by ~4s on 32-bit Arm systems.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-10 12:11:08 +01:00
Joachim Wiberg 6994e5dd63 board/common: mnt: drop tune2fs and speed up mounting
Calling tune2fs for ext4 partitions at boot costs more than one second
boot time on 32-bit Arm systems, with very little gain.  Dropping this
restores the default periodic fsck *and* saves boot time.

Instead of calling sgdisk four times, call it only when resizing and
instead use sysfs to find named paritions.  Saves seconds on boards
with weaker CPU and slow media.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-10 12:11:05 +01:00
Joachim WibergandGitHub 5bb21e5221 Merge pull request #1432 from kernelkit/kernel-upgrade-c773e829-0c4b-45bc-ab56-a3c57307ccfb
Upgrade to kernel 6.18.16
2026-03-10 12:10:50 +01:00
ael-bot 04eef91c0d Upgrade Linux kernel to 6.18.16 2026-03-10 04:53:43 +00:00
Joachim WibergandGitHub 6c8eeb2a5f Merge pull request #1425 from kernelkit/mdns-fixes
Mdns fixes
2026-03-09 19:26:41 +01:00
Joachim Wiberg 784be611de doc: update ChangeLog with fixes and enw features
[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:26:13 +01:00
Joachim Wiberg cdd56e6a2d doc: document how to add a default route
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:26:05 +01:00
Joachim Wiberg 4b39b2c2d3 board: relocate SafeXcel firmware selection to Marvell BSPs
The MVEBU SafeXcel Crypto Engine firmware (linux-firmware minifw) was
originally added in 70c12c3 to the generic aarch64 defconfigs to silence
kernel probe failures on Marvell Armada SoCs (37xx, 7k, 8k, CN913x):

  crypto-safexcel f2800000.crypto: Firmware load failed.
  crypto-safexcel f2800000.crypto: HW init failed (-2)

It was then accidentally dropped in 0e2d12e (kernel upgrade to 6.18),
which rebased on a tree that predated the firmware addition.

Rather than restoring it to the generic defconfigs, move it to the two
Marvell board Config.in files where it actually belongs — consistent
with how RTL8169 firmware was handled for the Raspberry Pi CM4 IoT
Router Board Mini in 68313773.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:26:04 +01:00
Joachim Wiberg b2c729dc7d utils: fix kernel-upgrade.sh clobbering existing ChangeLog entries
The awk insertion path used getline to peek at the line right after the
"### Changes", but only printed it when NF == 0 (blank line).  If the
section already had a non-blank entry (e.g. a Buildroot upgrade line),
getline consumed it silently and the kernel line was written in its
place.

Fix by adding the missing else branch so the consumed line is always
re-emitted — blank lines before the new entry, non-blank lines after it.

Also demote the missing-UNRELEASED guard from exit 1 to a warning with
return 0, so the workflow doesn't abort when a new release cycle hasn't
had its ChangeLog section opened yet.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:26:04 +01:00
Joachim Wiberg 290c03b2b5 cli: add 'ssh' commands to log onto other devices and manage keys
Add three SSH-related commands to the operational CLI:

  ssh [user <name>] [port <num>] <host>
      Connect to a remote device over SSH, running as the
      CLI user (not root) by dropping privileges before exec.

  set ssh known-hosts <host> <keytype> <pubkey>
      Pre-enroll a host public key received out-of-band (e.g.
      via email after a factory reset) into ~/.ssh/known_hosts,
      avoiding a TOFU prompt on first connect.

  no ssh known-hosts <host>
      Remove a stale host key entry using ssh-keygen -R, e.g.
      after a device factory reset causes a key mismatch.

Tab completion is provided for key types (ssh-ed25519,
ecdsa-sha2-nistp256, etc.) and for known host names/IPs.

A new run_as_user() helper is introduced alongside the existing
run(), factoring out the fork+setuid+execvp pattern used by
infix_shell() so it can be shared across the SSH functions.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:26:03 +01:00
Joachim Wiberg b9a8014e41 patches: lift iptables name length limit in firewalld
A legacy name length limit in firewalld triggered problems with longer
policy names.  This patch to firewalld lifts that limit by checking the
backend in use, no limit for nftables.

Fixes #1389

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:26:03 +01:00
Joachim Wiberg 27a07d0179 statd: silence 'show firewall' when firewall is disabled
Fixes #1416

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:26:02 +01:00
Joachim Wiberg 2d9f973e82 statd: add operational support for mDNS neighbors
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:25:59 +01:00
Joachim Wiberg 09c649f0b3 test: update gps test spec.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:25:29 +01:00
Joachim Wiberg 982e610fef test: infamy: always emit the "1..N" plan line before exiting
Always emit the "1..N" plan line before exiting with error so test
harnesses don't report "test error, no plan" for failed or aborted
tests.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:25:29 +01:00
Joachim Wiberg 9ea1e82728 package/skeleton-init-fint: increase zebra netlink buffer
Increase Zebra NETLINK buffer to fix reported issues with zebra being
out of sync with kernel routes and interface changes.

Also, try '-a' option to allow other processes to delete zebra routes.

Other changes in this commit:
 - Minor fixes to Finit service files for consistency
 - Empty daemon.conf stub files to silence bogus mgmtd errors at startup
 - Relocate all skeleton files from board/common to separate from files
   that are actual Infix additions and what's package system integration

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:25:29 +01:00
Joachim Wiberg 7a23181b96 board/common: serve network.local over plain HTTP (port 80)
network.local is a discovery/browse page, not a management interface.
Serving it over HTTP eliminates the self-signed certificate warning
browsers show for .local mDNS names without changing the security
posture of the actual device management pages (still HTTPS-only).

The new port-80 server_name block takes precedence over the catch-all
HTTP → HTTPS redirect in default.conf.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:25:28 +01:00
Joachim Wiberg 0489fb5403 netbrowse: skip loopback addresses when displaying device IP
avahi-browse returns 127.0.0.1 (or ::1) when resolving services on the
same machine netbrowse is running on. These addresses are meaningless
for display and misleading as click targets. Skip the entire 127.x/::1
range and link-local (fe80:) when choosing the preferred address for a
host card; the card addr field is simply omitted if no routable address
is seen.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:25:28 +01:00
Joachim Wiberg 585907daae netbrowse: show IP, product/version on cards; sun/moon theme icons
- IP address shown in soft parens on the card header line, e.g.
  "infix.local (192.168.1.10)"; IPv4 preferred over IPv6, link-local
  skipped
- Product name and OS version (from mDNS TXT records "product=" and
  "ov=") shown as a secondary line below the header when available
- Theme toggle icons changed from ◐/●/○ to ◐/☽/☀ (system/dark/light)
- browse.go: introduce Host struct (addr, product, version, other, svcs)
  replacing the flat []Service map; scan() now returns map[string]Host
- Search also matches against IP, product, and version fields

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:25:27 +01:00
Joachim Wiberg 62559655dc netbrowse: modernize UI with card layout and theme support
Replace the Go template + table layout with a fetch-based design:
serve browse.html as static HTML, add /data JSON endpoint.

New UI features:
- Card-per-device grid with color-coded service badges
- Dark/light/system theme toggle (persisted to localStorage)
- Live search (press / to focus)
- Auto-refresh toggle with 30 s countdown, off by default
- Empty/error states and device count in footer
- IBM Plex Mono throughout

Download the latin-subset woff2 files (weights 400/500/600) from
fonts.gstatic.com (IBM Plex Mono v20) and serve them locally via
the existing //go:embed static mechanism, eliminating the Google
Fonts dependency for air-gapped and offline deployments.

  Source:  https://github.com/IBM/plex
  Files:   fonts.gstatic.com/s/ibmplexmono/v20/
  License: SIL Open Font License 1.1 (static/fonts/LICENSE.txt)
	     Copyright © 2017 IBM Corp.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:25:27 +01:00
Joachim Wiberg c68db78309 netbrowse: fix device detection in default view
Apple devices (e.g. Apple TV) publish vv=1 in their AirPlay/RAOP TXT
records, causing a false positive with our Infix platform marker.
Tighten the filter to require vv=1 together with at least one management
service type (ssh, https, http, netconf, restconf), which Apple devices
never advertise. Keep on=Infix as a fallback for older firmware that
predates vv=1.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:25:26 +01:00
Joachim Wiberg 87c671b4cc netbrowse: fix DNS-SD service name decoding
avahi's parseable output uses \DDD decimal escape sequences, not octal.
The previous decoder treated them as octal, causing digits 8 and 9 to
fall through undecoded (e.g. \058 → ':' and \091 → '[' were shown
literally). Also handle \X non-digit escapes (e.g. \. → '.') used for
dots in service instance names.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:25:26 +01:00
Joachim Wiberg 571edefa9d confd: add configurable mDNS hostname (avahi host-name)
Add a `hostname` leaf to the `mdns` YANG container with default `"%h"`,
allowing operators to override the avahi host-name used for mDNS A/AAAA
records without reflashing. The default expands to DEFAULT_HOSTNAME from
os-release, preserving existing behaviour for unconfigured deployments.

Format specifiers %h/%i/%m are supported via the existing hostnamefmt()
infrastructure, which is also fixed to copy the const fmt argument to a
local buffer before modification (UB when called with a libyang-owned
string).

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:25:18 +01:00
Joachim Wiberg 1282352359 confd: improve mDNS service records
Use avahi's %h wildcard in service names so each device's hostname is
included, avoiding collision suffixes (#2, #3) when multiple Infix
devices are on the same network.

Skip TXT records whose JSON value is null rather than emitting empty
key= fields. Add _workstation._tcp (with chassis MAC) and
_device-info._tcp (with model= from product-name) as always-on records
tied to mDNS being active.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:24:37 +01:00
Joachim Wiberg 89c95d6baa confd: relocate generation of mdns service records to C
Simplify and consolidate generation of mdns service records from an
external script to C. This reduces fork + exec and saves two seconds
of boot time on single core Cortex-A7 systems.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:24:36 +01:00
Joachim Wiberg e255828418 confd: fix mDNS CNAME conflict by flipping the table
Instead of publishing A/AAAA records for $(hostname).loocal with a CNAME
infix.local, we flip it around to take advantage of the mDNS conflict
resolution rules.  This gives us infix.local for one device ont the LAN
and infix-2.local for the next.

Update all service records to *not* advertise hostname, but instead to
let Avahi imply that from the advertised A/AAAA and CNAME records.

Fixes #1387

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:24:36 +01:00
Joachim Wiberg e2c29cb1a7 utils: add fleet management commands to ixll
Introduce libfleet.sh and a new 'fleet' subcommand to ixll for managing
and operating enrolled Infix devices via RESTCONF.

Device configuration is stored in ~/.config/infix/config.json
(chmod 600): and organised by profile, allowing bulk operations across
groups of devices (e.g. all aarch64 targets).

New commands:

  ixll fleet enroll [-d] [-p profile] [-u user] [-w password] <name> <address>
  ixll fleet list
  ixll fleet upgrade <name|profile> <url>
  ixll fleet backup  [-o dir] <name|profile>
  ixll fleet reboot  <name|profile>

Upgrade runs in parallel across a fleet and shows a live per-device
progress bar by polling the infix-system:install-bundle RPC and the
installer state from the YANG operational data store.

The global -A flag (admin/admin) is honoured as a credential fallback
for devices enrolled without an explicit password.

Also fix a pre-existing typo: ">2" → ">&2" in the error path.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:24:36 +01:00
Joachim Wiberg 707731d23e utils: drop serial n:o from mdns scan output
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:24:35 +01:00
Joachim Wiberg ff4a346fd4 utils: ignore errors from avahi-browse
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:24:35 +01:00
Joachim Wiberg ba801be402 package/netbrowse: bump to v2.0
Replaces gunicorn+flask app with Go program, same function otherwise.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:24:34 +01:00
Joachim Wiberg debee83b15 package/mdns-alias: bump to v1.1
Fixes #1387

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 19:24:27 +01:00
Joachim WibergandGitHub b078a570ec Merge pull request #1378 from kernelkit/copilot/fix-client-stratum-selection 2026-03-09 19:21:57 +01:00
Joachim Wiberg a712fd5907 confd: new NTP setting stratum-weight
This patch adds support for chronyd's stratumpweight both in the NTP
client (ietf-system) and client+server (ietf-ntp) should fix the flaky
NTP stratum test.

Also, make sure to *not* 'rm -rf /etc/chrony/conf.d/*' in system.c to
prevent clobbering settings potentially made in ntp.c

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-09 18:03:15 +01:00
Mattias WalströmandGitHub 30b12d1467 Merge pull request #1417 from kernelkit/gps
Gps refactor
2026-03-05 11:00:17 +01:00
Mattias Walström 6534086d89 bpi-r3: dts: apply patch from OpenWRT
Reserve more memory for ATF
2026-03-05 08:21:54 +01:00
Mattias Walström 57961ac0a5 GPS: Refactor, do not use hotplug depend and move to finit
Also remove caching of GPS data in operational, gpsd now depend
on its GPS device <dev/gps0> instead of hotplug magic.
2026-03-05 08:21:34 +01:00
Mattias Walström 565a07a0b2 test: Add GPS test
Only possible to run on virtual Qemu instances right now.
2026-03-05 08:21:34 +01:00
Mattias Walström 054faa6763 GPS: Disable GPS in _minimal config 2026-03-05 08:21:34 +01:00
Mattias Walström 3d86d5f6e2 yang: add feature flags for wifi and gps in infix-hardware 2026-03-05 08:21:33 +01:00
Mattias Walström 5518574fee buildroot: Upgrade gpsd version 2026-03-05 08:21:30 +01:00
Joachim WibergandGitHub 434248a6de Merge pull request #1428 from kernelkit/revert-1406-upgrade-buildroot
Revert "Upgrade buildroot to 2026.02.0"
2026-03-05 08:19:45 +01:00
Mattias WalströmandGitHub 082bcd1712 Revert "Upgrade buildroot to 2026.02.0" 2026-03-04 19:47:11 +01:00
Joachim WibergandGitHub 0bedde52d3 Merge pull request #1410 from saba8814/issue-782-dhcp-ntp-dns
Issue 782 dhcp ntp dns
2026-03-04 13:52:12 +01:00
Joachim WibergandGitHub b315e444fd Merge pull request #1406 from kernelkit/upgrade-buildroot
Upgrade buildroot to 2026.02.0
2026-03-04 13:50:37 +01:00
Mattias Walström a8094c8026 Upgrade buildroot to 2026.02 (LTS) 2026-03-04 11:45:06 +01:00
Mattias Walström afa01489e6 test: Add parameter -j to watchdogctl
This is required to get the output as JSON data, since the upgrade
of buildroot (and watchdogd)
2026-03-04 11:45:04 +01:00
Mattias Walström 26320cc771 package: nghttp2-asio: Fix cmake version compatibility 2026-03-04 11:45:02 +01:00
Mattias Walström 7990ae4e9d Adapt to changes i new version of shadow
Shadow installs a pam.d/login file that is
broken for us, override with our own.
2026-03-04 11:45:00 +01:00
Mattias Walström 2671873b6f buildroot: Update the patches to reflect the upgraded buildroot 2026-03-04 11:44:58 +01:00
Mattias Walström e64d29196d Remove local package podman
It is now included in buildroot
2026-03-04 11:44:56 +01:00
Mattias Walström b446d92b0d Remove local packet lowdown
It is now included in buildroot
2026-03-04 11:44:54 +01:00
Mattias Walström e7cb85edf3 Remove local libyang-cpp and sysrepo-cpp
It has been included in buildroot
2026-03-04 09:53:03 +01:00
Mattias Walström 000c04cc8c gps: Remove setting BR2_PACKAGE_GPSD_OCEANSERVER
It is no longer supported in buildroot
2026-03-04 09:53:03 +01:00
Mattias Walström 6e5283f5d1 confd: ntp: Adapt to changes in chrony 4.8
In 4.8 local clocks is not synced by default,
waitsync is set to 300, this set it to 0.
2026-03-04 09:53:03 +01:00
Mattias Walström 8fcb291f5e bpi-r3: dts: apply patch from OpenWRT
Reserve more memory for ATF
2026-03-04 09:53:02 +01:00
Mattias WalströmandGitHub 7ccddc086b Merge pull request #1422 from kernelkit/container-fixes
Container and Coverity fixes
2026-03-01 10:21:58 +01:00
Joachim Wiberg fb9a1fa1a5 Update ChangeLog for v26.02 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-01 08:29:13 +01:00
Joachim Wiberg 386ca9618e confd: ensure DHCP client is not started before netd
This is a follow-up to c559b8f2 (new-frr) where netd now is responsible
for funneling static routes, as well as routes from DHCP clients, into
the kernel via Frr.

For this to work, in particular at boot, any DHCP client must wait for
netd to have started or any default routes learned will be lost.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-01 08:29:06 +01:00
Joachim Wiberg abe571d32c confd: silence Coverity false positive resource leak
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-01 07:00:06 +01:00
Joachim Wiberg 131177f3c9 confd: check return value and drop redundant assignment
Found by Coverity Scan:
 - check rename() return value
 - drop redundant ripd_enabled assignment

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-01 07:00:06 +01:00
Joachim Wiberg c3d396b5fe copy: fix null dst dereference and uninit uri_i in curl()
Found by Coverity Scan

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-01 07:00:05 +01:00
Joachim Wiberg b341d37267 Update URL from kernelkit.org to www.kernelkit.org
DNS does not allow CNAME records at an apex domain (e.g. kernelkit.org),
so GitHub Pages cannot reliably redirect kernelkit.github.io to it.  A
www subdomain can carry a CNAME pointing directly to kernelkit.github.io,
giving GitHub full control over the mapping and making the redirect work.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-01 06:59:48 +01:00
Joachim Wiberg cbe8315508 cli: simplify 'show bfd [peer_addr]' -> 'show bfd [peer]'
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-01 06:59:48 +01:00
Joachim Wiberg a5687bda7f cli: add support for --reset-volumes on container upgrade
The weird `if env | grep -q 'reset-volumes'` construct is due to Klish
not sanitizing names before constructing variables, which leads to env
variables with '-' in them, not allowed in POSIX sh.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-01 06:58:21 +01:00
Joachim Wiberg 8fac3720fb board/common: fix container force option for upgrade
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-01 06:57:36 +01:00
Joachim Wiberg a4715debe8 cli: fix 'container upgrade <tab>' command completion
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-01 06:57:36 +01:00
Mattias WalströmandGitHub da06ca14d4 Merge pull request #1421 from kernelkit/kernel-upgrade-25b449b5-0348-4f93-94a0-a0602c90ced5
Upgrade to kernel 6.18.15
2026-02-28 08:12:36 +01:00
ael-bot 9946357285 Upgrade Linux kernel to 6.18.15 2026-02-28 04:28:07 +00:00
Mattias WalströmandGitHub f5ad6bc9ea Merge pull request #1415 from kernelkit/add-yang-check
Add yang check
2026-02-27 13:58:27 +01:00
Joachim WibergandGitHub 1698ad6197 Merge pull request #1420 from kernelkit/fix-hash 2026-02-27 12:30:22 +01:00
Joachim Wiberg b3e158fce5 copy: use scp(1) for scp:// and sftp:// transfers
curl's SCP/SFTP backend (libssh2) does not support interactive password
prompting — it fails with an authentication error unless credentials are
supplied non-interactively.

Replace the curl path for SSH URIs with native scp(1), which inherits
the TTY and prompts the user for a password as expected.  Both scp://
and sftp:// URIs are handled by parsing the URI into a [user@]host:path
argument.  Port is extracted if present and passed via -P.  If no user
is embedded in the URI, the -u flag value (remote_user) is used instead.
Host-key verification is skipped with -o StrictHostKeyChecking=no, the
same trade-off already made by the test framework.

When the destination URI ends with '/', a meaningful remote filename is
derived from the source: the datastore's on-disk filename (e.g.,
startup-config.cfg), the datastore short-name for in-memory stores, or
the source file's own basename for plain file copies.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-27 11:14:00 +01:00
Mattias Walström 5762c75727 test: Upgrade docker for GPS tests 2026-02-27 11:06:31 +01:00
Mattias Walström bb5240e48b test: usb: remove unused import 2026-02-27 11:06:31 +01:00
Mattias Walström 002c7791ec CI: Run unit test once, not once per platform 2026-02-27 11:06:30 +01:00
Mattias Walström 147ffe602f Change hash for license file in 6.18 kernel 2026-02-27 11:06:30 +01:00
Joachim Wiberg d08c3416ec package/finit: bump to v4.16 GA
One change since -rc1 which was to drop shutdown debugging. For a full
ChangeLog see https://github.com/finit-project/finit/releases/tag/4.16

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-27 11:04:45 +01:00
Mattias WalströmandJoachim Wiberg c4f24caa94 yanger: Adapt to new stricter pattern for publish 2026-02-27 08:35:21 +01:00
Mattias WalströmandJoachim Wiberg 19a0151f68 confd: ntp: Minor cleanup 2026-02-27 08:35:20 +01:00
Mattias WalströmandJoachim Wiberg bbbb84fba7 sysrepo: Do not report old errors
This is a bug introduced in sysrepo 4.x
2026-02-27 08:35:20 +01:00
Mattias WalströmandJoachim Wiberg ed4fe58fda confd: Add YANG pattern constraints for string leaves
Add input validation patterns to string-type leaves in container,
firewall, DHCP, and interface YANG models.  Also use mkdtemp() for
temporary key files in keystore.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
2026-02-27 08:35:17 +01:00
Tobias WaldekranzandGitHub d7812c2ea5 Merge pull request #1418 from kernelkit/simplify-build
Simplify build
2026-02-27 08:33:46 +01:00
Tobias WaldekranzandGitHub ffa23fb9be Merge pull request #1419 from kernelkit/kernel-upgrade-890bedee-6ca0-4d50-8353-0185cdf0222e
Upgrade to kernel 6.18.14
2026-02-27 08:15:50 +01:00
ael-bot 4cf9fd02db Upgrade Linux kernel to 6.18.14 2026-02-27 04:52:28 +00:00
Joachim Wiberg a5c807abe0 test/infamy: make until() exception-safe
Any exception raised by fn() propagated immediately out of the retry
loop, effectively making until() a single-shot call the moment any
transient error occurred.

Fix by wrapping fn() in a try/except inside the loop and treating any
exception as a "not yet" result.  The last exception is preserved and
re-raised if all attempts are exhausted, so failure output is still
meaningful.  Also fix a missing newline at end of file.

Fixes #1403

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-26 19:05:43 +01:00
Joachim Wiberg b5a292d7dd test/infamy: catch TimeoutError in curl() to allow retries
Python's urllib.request wraps OSError in URLError during the connection
phase, but NOT during response reading (getresponse()).  This means a
timeout that fires after the TCP handshake completes, e.g. when a service
accepts the connection but hasn't sent a response yet, propagates as a
bare TimeoutError that bypasses the exception handler, killing the entire
until() retry loop on the first attempt.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-26 13:43:41 +01:00
Joachim Wiberg 4522d9f217 package/netd: rename NETD_FRR to NETD_FRR_GRPC, select FRR_GRPC
Rename BR2_PACKAGE_NETD_FRR to BR2_PACKAGE_NETD_FRR_GRPC to match the
naming convention of the other FRR backends (VTYSH, CONF) and make the
intent self-evident.

Have the gRPC backend select BR2_PACKAGE_FRR_GRPC so FRR is built with
gRPC support when — and only when — this backend is chosen.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-26 13:43:40 +01:00
Mattias WalströmandGitHub c559b8f2e0 Merge pull request #1384 from kernelkit/new-frr 2026-02-25 18:09:01 +01:00
Joachim Wiberg 4a31df1059 netd: add vtysh -b backend
This is a simpler approach than both grpc and watchfrr.  Since we only
really need dynamic handling of static routes (for DHCP), we can track
changes made and maintain a "diff engine" for the resulting frr.conf.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-24 06:59:32 +01:00
Joachim Wiberg 965906e2ff netd: add support for frr.conf backend with waitfrr service
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-24 06:59:31 +01:00
Joachim Wiberg bcc444f0fe patches/frr: zebra: don't resolve nexthop via inactive route
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-24 06:59:31 +01:00
Joachim Wiberg 949f43853d package/finit: bump to 4.16-rc1
Drop backported fixes.

Details at https://github.com/finit-project/finit/releases/tag/4.16-rc1

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-24 06:59:31 +01:00
Joachim Wiberg e63275d3a1 test: wait for multicast filter to bite
Also, update test description a bit.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-24 06:59:30 +01:00
Joachim Wiberg 2abee79c18 test: minor fix, missing format string
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-24 06:59:30 +01:00
Joachim Wiberg a844ba7d8c test: wait for static route before must_reach()
Not all systems are equally quick, let's give it while to set before
bailing out because we test too soon.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-24 06:59:29 +01:00
Joachim Wiberg e8c9c70e37 test: fix flaky tests, retry until()
In the ongoing campaign against load-bearing sleep() and pure luck.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-24 06:59:29 +01:00
Joachim Wiberg 924567f30b board/common: simplify netd reload
With the latest backported fixes to Finit, we no longer need to remove
/run/netd.pid to trigger a reload (restart) of staticd.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-24 06:59:28 +01:00
Joachim Wiberg 0e21dc894b package/finit: backport fixes from upstream
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-24 06:59:28 +01:00
Mattias WalströmandJoachim Wiberg f187fee89b package: Add python-spy
You can use it to inspect python applications, to inspect
executiontime.
2026-02-24 06:59:28 +01:00
Mattias WalströmandJoachim Wiberg 845e7c13fe yanger: Wi-Fi: Add missing radio component in operational 2026-02-24 06:59:27 +01:00
Mattias WalströmandJoachim Wiberg 8c9e36ba5d Upgrade FRR to 10.5.1
This includes adding a netd-daemon since FRR has gone towards all
daemons should be configured from mgmtd using YANG, netd uses gRPC to
reconfigure in mgmtd

Signed-off-by: Enable grpc
2026-02-24 06:59:07 +01:00
Mattias WalströmandJoachim Wiberg a1a02f2727 utils: bump-gns3: Fix syntax after qcow image was renamed 2026-02-24 06:42:52 +01:00
Ejub Sabic 1a1d917cd6 test: add dhcp combination test and integrate into suite 2026-02-22 15:08:34 +01:00
Mattias WalströmandGitHub 3ffbef74a8 Merge pull request #1407 from kernelkit/add-support-for-bpi-r3-mini
Add support for bpi r3 mini
2026-02-22 13:11:11 +01:00
Mattias Walström 34805dca65 doc: Update Changelog with BPI-r3-mini 2026-02-22 11:52:05 +01:00
Mattias Walström 8b95c10e39 bananapi-bpi-r3: README: Add information about bpi-r3-mini
The important part is that it needs a special flow to go from
vendor firmware to Infix.
2026-02-22 11:52:05 +01:00
Mattias Walström 16e72e8741 boards: Add new board bpi-r3-mini
This is a simple two port router board, with the same
WiFi chips as BPI-r3.

The bootloader shall be the same as the BPI-r3, the bootloader
now probes which of the two is booting by checking for the PHYS
that only exist on BPI-r3-mini.
2026-02-22 11:52:05 +01:00
Joachim WibergandGitHub cf591c9813 Merge pull request #1411 from kernelkit/probe-dtb-early
init: Move all copy of files to before udev triger is run
2026-02-22 08:09:12 +01:00
Mattias Walström 51b0488e66 test: Return fail if make test fails
$? needs to be $$? inside a make rule to expand the
bash variable.
2026-02-21 12:23:04 +01:00
Mattias Walström 4aa0ab73b3 init: Move all copy of files to before udev triger is run
This since we may copy udev-rules dependeing on platforms,
this fix #1357

Also remove all workaround scripts we have added for this
purpose.
2026-02-21 09:25:25 +01:00
Joachim WibergandGitHub ef7ed89443 Merge pull request #1409 from kernelkit/bump-buildroot2 2026-02-20 17:32:13 +01:00
Mattias Walström 84860e313f config: Remove legacy settings 2026-02-20 13:53:24 +01:00
Mattias Walström 0e590e9cbf Upgrade buildroot to 2025.02.11 (LTS)
2025.02.11, released February 20, 2026

	avahi: CVE-2021-3468, CVE-2023-38469, CVE-2023-38470, CVE-2023-38471,
	  CVE-2023-38472, CVE-2023-38473, CVE-2024-52615, CVE-2024-52616,
	  CVE-2025-68276, CVE-2025-68468, CVE-2025-68471, CVE-2026-24401
	bind: CVE-2025-13878
	busybox: CVE-2025-46394, CVE-2025-60876
	expat: CVE-2026-24515, CVE-2026-25210
	glibc: CVE-2025-15281, CVE-2026-0861, CVE-2026-0915
	gnutls: CVE-2025-14831, CVE-2026-1584
	haproxy: CVE-2025-11230
	intel-microcode: CVE-2024-24853, CVE-2025-31648
	libopenssl: CVE-2025-11187, CVE-2025-15467, CVE-2025-15468,
	  CVE-2025-66199, CVE-2025-68160, CVE-2025-69418, CVE-2025-69419,
	  CVE-2025-69420, CVE-2025-69421, CVE-2026-22795, CVE-2026-22796
	libpng: CVE-2026-22695, CVE-2026-22801, CVE-2026-25646
	libtasn1: CVE-2025-13151
	libvpx
	linux-pam: CVE-2024-10963
	nginx: CVE-2025-53859
	nodejs: CVE-2025-27210, CVE-2025-55130, CVE-2025-55131, CVE-2025-55132,
	  CVE-2025-59465, CVE-2025-59466, CVE-2026-21637
	python-django: CVE-2025-13473, CVE-2025-14550, CVE-2026-1207, CVE-2026-1285,
	 CVE-2026-1287, CVE-2026-1312
	python-urllib3: CVE-2026-21441
	strongswan: CVE-2025-62291
	tor: TROVE-2025-016
	vim: CVE-2025-66476
	webkitgtk
2026-02-20 13:53:23 +01:00
Joachim WibergandGitHub 8d647a8e43 Merge pull request #1408 from kernelkit/kernel-upgrade-5201d390-057f-48d7-84f8-8c48fe75926d 2026-02-19 20:47:06 +01:00
ael-bot 6fee172c85 Upgrade Linux kernel to 6.18.13 2026-02-19 17:02:17 +00:00
Joachim WibergandGitHub 5c0a4c099e Merge pull request #1405 from kernelkit/kernel-upgrade-652fbc25-5bae-4cb9-a897-5afe6d25e872 2026-02-16 19:29:23 +01:00
ael-bot 3fe7fa5548 Upgrade Linux kernel to 6.18.12 2026-02-16 17:01:34 +00:00
Joachim WibergandGitHub 2120709b68 Merge pull request #1404 from kernelkit/kernel-upgrade-f5acaddd-eaf7-4ee4-8b43-d7c6c60d2f9d
Upgrade to kernel 6.18.11

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-16 14:21:08 +01:00
ael-bot 13a50c8b0c Upgrade Linux kernel to 6.18.11 2026-02-16 10:25:51 +00:00
Mattias WalströmandGitHub 48718d764b Merge pull request #1401 from kernelkit/kernel-upgrade-1acd358b-2cf7-4127-8f0e-ca47d21998b9
Upgrade to kernel 6.18.10
2026-02-12 10:59:00 +01:00
ael-bot ae8a93c4cf Upgrade Linux kernel to 6.18.10 2026-02-11 13:28:31 +00:00
Joachim WibergandGitHub cbde057bf8 Merge pull request #1399 from kernelkit/gps 2026-02-10 21:04:34 +01:00
Joachim Wiberg f3e058f203 doc: update ChangeLog, initial GPS receiver support
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-10 16:49:41 +01:00
Joachim Wiberg c16eeaa9f4 doc: add section on GPS receivers and GPS reference clock
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-10 16:49:41 +01:00
Joachim Wiberg 681251f899 statd: support gps reference clocks in 'show <hardware|ntp>'
This patch adds a background gps monitor to statd because the gpspipe
program, normally used to interface with gpsd, slows down access to the
operational datastore with *seconds*.

This background monitor is not load bearing for how chrony accesses the
gps + nmea information from gpsd, this is handled separately in SHM.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-10 16:49:40 +01:00
Joachim Wiberg eb1763d49f confd: add gps support to ietf-hardware and ietf-ntp
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-10 16:49:40 +01:00
Joachim Wiberg 867239c7b8 package/feature-gps: new feature package
Enable gpsd and override package defaults to integrate in Infix.

 - Sync with rules disabled downstream in Debian project to prevent
   clashes with common vendor/device ids used for other device types
 - Start gpsd instance with '-n' to ensure /dev/shm is udpated for chrony

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-08 16:37:54 +01:00
Mattias WalströmandGitHub 0f1aa30574 Merge pull request #1398 from kernelkit/kernel-upgrade-0b031c70-632a-47dc-a372-f31cd93c53e1 2026-02-07 07:52:39 +01:00
ael-bot 89146b739a Upgrade Linux kernel to 6.18.9 2026-02-07 04:39:24 +00:00
Joachim WibergandGitHub 7bcbd3c51b Merge pull request #1376 from kernelkit/copilot/review-issue-947
Document VETH pair limitation with containers
2026-02-06 15:58:20 +01:00
Joachim Wiberg 91374a1155 Fix trailing whitespace in YANG descriptions
[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-06 15:57:42 +01:00
Joachim Wibergandtroglobit 3966f8ed0e Document VETH pair limitation with containers
Add documentation noting that at least one side of a VETH pair must
remain in the host namespace. Both ends cannot be assigned to different
containers.

Updates:
- container.md: Added IMPORTANT note in Container Host Interface section
- infix-if-veth.yang: Added note in module description
- infix-if-container.yang: Added note in host identity description

Fixes: #947
Related: #941

Co-authored-by: troglobit <183517+troglobit@users.noreply.github.com>
2026-02-06 15:56:51 +01:00
Joachim WibergandGitHub f708f9b1ed Merge pull request #1397 from kernelkit/sama7g54
Add support for Microchip SamA7G54 Eval Kit

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-06 14:49:50 +01:00
Joachim Wiberg 055c8dd1ae doc: update ChangeLog, support for Microchip SAMA7G54-EK
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-06 13:30:21 +01:00
Joachim Wiberg fd4cda35b5 configs: add missing fdt_add_pubkey to bootloader defconfigs
Follow-up to c152c5f361

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-06 13:30:21 +01:00
Joachim Wiberg a7a630e0d9 utils: allow creating bootloader-only images
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-06 13:30:20 +01:00
Joachim Wiberg 0c8ce332d1 utils: support SamA7G65 in mkimage.sh
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-06 13:30:20 +01:00
Joachim Wiberg 3d088f3e2b Add support for Microchip SAMA7G54-EK Evaluation Kit
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-06 13:30:20 +01:00
Joachim WibergandGitHub b691868a83 Merge pull request #1385 from kernelkit/arm-actions
Arm 32-bit actions
2026-02-05 10:40:48 +01:00
Joachim Wiberg d1659dbbc1 test: fix missing IPv6 forwarding on tunnel in tunnel_basic
Enable IPv6 forwarding on the left DUT's tunnel interface, matching
the IPv4 tunnel config.  Without it, IPv6 packets are not forwarded
through the tunnel, causing all tunnel_basic IPv6 tests to fail.

Regression introduced when fixing issue #515 in 717c1c0.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-05 08:50:22 +01:00
Joachim Wiberg 8973dc488b test: ensure result of tests is the exit code of the rule
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-05 08:50:22 +01:00
Joachim Wiberg f71bb73375 board/arm: add missing rootfs (empty) overlay
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-05 08:50:21 +01:00
Joachim Wiberg 0c11cea07b .github: refactor, simplify, and reduce duplication in actions
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-05 08:50:21 +01:00
Joachim Wiberg 65b674855a .github: add rpi2 bootloader and SD card image builds
Add Raspberry Pi 2B to the bootloader build matrix and raspberrypi-rpi2
to the SD card image builder, enabling full RPi 2B image creation.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-05 08:50:09 +01:00
Joachim Wiberg 71ec4fa220 .github: add arm_defconfig and arm_minimal_defconfig builds
Catch ARM 32-bit build regressions early by adding arm targets
to the familty of Infix image and release builds.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-05 08:50:09 +01:00
Mattias WalströmandGitHub f47bf0e0b1 Merge pull request #1395 from kernelkit/run-fix
Fix extration of rootfs.squashfs in release tarball
2026-02-03 15:13:18 +01:00
Joachim Wiberg e7108f52cf board/common: fix extration of rootfs.squashfs in release tarball
[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-02-03 15:05:20 +01:00
805 changed files with 41866 additions and 7892 deletions
+4 -2
View File
@@ -1,8 +1,10 @@
Limited free support is only available using the online resources of the
project on GitHub, and Discord, see <https://github.com/kernelkit>:
project on GitHub, and Discord, see <https://github.com/kernelkit/infix>:
&nbsp;&nbsp; :house: <https://www.kernelkit.org> — home page, blog, news, howto's and tutorials
&nbsp;&nbsp; :package: <https://github.com/kernelkit/infix/releases/latest> — latest release
&nbsp;&nbsp; :speech_balloon: <https://github.com/orgs/kernelkit/discussions>
&nbsp;&nbsp; :bug: <https://github.com/kernelkit/infix/issues>
&nbsp;&nbsp; :bug: <https://github.com/kernelkit/infix/issues>
Support contracts, development of new features, fast-tracking of reviews
and contributions, customer branding of Infix, and even customer specific
+3 -3
View File
@@ -16,7 +16,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Validate release version format
id: validate
@@ -170,7 +170,7 @@ jobs:
fi
- name: Upload signed artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: signed-infix-${{ steps.validate.outputs.file_version }}
path: ${{ steps.download_signed.outputs.signed_filename }}
@@ -212,4 +212,4 @@ jobs:
---
**Next Steps:** The signed release can now be distributed with cryptographic verification of authenticity.
EOF
EOF
+14 -20
View File
@@ -19,10 +19,17 @@ jobs:
- aarch64_qemu_boot
- bpi_r3_sd_boot
- bpi_r3_emmc_boot
- bpi_r4_sd_boot
- bpi_r4_emmc_boot
- bpi_r64_sd_boot
- bpi_r64_emmc_boot
- cn9130_crb_boot
- fireant_boot
- nanopi_r2s_boot
- rpi2_boot
- rpi64_boot
- sama7g54_ek_emmc_boot
- sama7g54_ek_sd_boot
env:
MAKEFLAGS: -j5
steps:
@@ -34,7 +41,7 @@ jobs:
ls -la ./
- name: Checkout infix repo
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
ref: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.branch || github.ref }}
clean: true
@@ -63,24 +70,11 @@ jobs:
echo "Building ${defconfig}_defconfig, version ${version}-${rev}, artifact ${archive} ..."
- name: Restore Cache of dl/
uses: actions/cache@v4
- uses: kernelkit/actions/cache-restore@v1
with:
path: dl/
key: dl-boot-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
restore-keys: |
dl-boot-
dl-
- name: Restore Cache of .ccache/
uses: actions/cache@v4
with:
path: .ccache/
key: ccache-boot-${{ matrix.defconfig }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
restore-keys: |
ccache-boot-${{ matrix.defconfig }}-
ccache-boot-
ccache-
target: ${{ matrix.defconfig }}
dl-prefix: dl-boot
ccache-prefix: ccache-boot
- name: Configure ${{ matrix.defconfig }}_defconfig
run: |
@@ -102,7 +96,7 @@ jobs:
mv images ${{ steps.vars.outputs.dirname }}
tar cfz ${{ steps.vars.outputs.archive }} ${{ steps.vars.outputs.dirname }}/
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
path: output/${{ steps.vars.outputs.archive }}
name: artifact-${{ matrix.defconfig }}
@@ -114,7 +108,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v7
with:
pattern: "artifact-*"
merge-multiple: true
+29 -2
View File
@@ -8,9 +8,13 @@ on:
type: choice
required: true
options:
- raspberrypi-rpi2
- raspberrypi-rpi64
- bananapi-bpi-r3
- bananapi-bpi-r4
- bananapi-bpi-r64
- friendlyarm-nanopi-r2s
- microchip-sama7g54-ek
default: 'raspberrypi-rpi64'
jobs:
@@ -19,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
clean: true
fetch-depth: 0
@@ -49,6 +53,11 @@ jobs:
- name: Set bootloader and target based on board
run: |
case "${{ inputs.board }}" in
raspberrypi-rpi2)
echo "BOOTLOADER=rpi2-boot" >> $GITHUB_ENV
echo "ARCH=arm" >> $GITHUB_ENV
echo "BUILD_EMMC=false" >> $GITHUB_ENV
;;
raspberrypi-rpi64)
echo "BOOTLOADER=rpi64-boot" >> $GITHUB_ENV
echo "ARCH=aarch64" >> $GITHUB_ENV
@@ -60,11 +69,29 @@ jobs:
echo "ARCH=aarch64" >> $GITHUB_ENV
echo "BUILD_EMMC=true" >> $GITHUB_ENV
;;
bananapi-bpi-r4)
echo "BOOTLOADER_SD=bpi-r4-sd-boot" >> $GITHUB_ENV
echo "BOOTLOADER_EMMC=bpi-r4-emmc-boot" >> $GITHUB_ENV
echo "ARCH=aarch64" >> $GITHUB_ENV
echo "BUILD_EMMC=true" >> $GITHUB_ENV
;;
bananapi-bpi-r64)
echo "BOOTLOADER_SD=bpi-r64-sd-boot" >> $GITHUB_ENV
echo "BOOTLOADER_EMMC=bpi-r64-emmc-boot" >> $GITHUB_ENV
echo "ARCH=aarch64" >> $GITHUB_ENV
echo "BUILD_EMMC=true" >> $GITHUB_ENV
;;
friendlyarm-nanopi-r2s)
echo "BOOTLOADER=nanopi-r2s-boot" >> $GITHUB_ENV
echo "ARCH=aarch64" >> $GITHUB_ENV
echo "BUILD_EMMC=false" >> $GITHUB_ENV
;;
microchip-sama7g54-ek)
echo "BOOTLOADER_SD=sama7g54-ek-sd-boot" >> $GITHUB_ENV
echo "BOOTLOADER_EMMC=sama7g54-ek-emmc-boot" >> $GITHUB_ENV
echo "ARCH=arm" >> $GITHUB_ENV
echo "BUILD_EMMC=true" >> $GITHUB_ENV
;;
*)
echo "Error: Unknown board ${{ inputs.board }}"
exit 1
@@ -250,7 +277,7 @@ jobs:
fi
- name: Upload images as artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: images-${{ inputs.board }}
path: |
+9 -31
View File
@@ -20,24 +20,16 @@ jobs:
runs-on: [self-hosted, release]
strategy:
matrix:
target: [aarch64, x86_64]
target: [aarch64, arm, x86_64]
fail-fast: false
steps:
- name: Cleanup podman state
run: |
set -x
podman ps -a || true
podman stop -a || true
podman rm -a -f || true
podman volume prune -f || true
podman system prune -a -f || true
podman system migrate || true
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
clean: true
submodules: recursive
- uses: kernelkit/actions/podman-cleanup@v1
- name: Set Release Variables
id: vars
run: |
@@ -48,24 +40,10 @@ jobs:
echo "dir=infix-$target" >> $GITHUB_OUTPUT
echo "tgz=infix-$target.tar.gz" >> $GITHUB_OUTPUT
- name: Restore Cache of dl/
if: ${{ inputs.use_cache }}
uses: actions/cache@v4
- uses: kernelkit/actions/cache-restore@v1
with:
path: dl/
key: dl-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
restore-keys: |
dl-
- name: Restore Cache of .ccache/
if: ${{ inputs.use_cache }}
uses: actions/cache@v4
with:
path: .ccache/
key: ccache-${{ matrix.target }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
restore-keys: |
ccache-${{ matrix.target }}-
ccache-
target: ${{ matrix.target }}
enabled: ${{ inputs.use_cache }}
- name: Configure & Build
env:
@@ -108,12 +86,12 @@ jobs:
ln -s ${{ steps.vars.outputs.dir }} images
tar cfz ${{ steps.vars.outputs.tgz }} ${{ steps.vars.outputs.dir }}
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
name: artifact-${{ matrix.target }}
path: output/*.tar.gz
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
name: artifact-disk-image-${{ matrix.target }}
path: output/images/*.qcow2
+6 -30
View File
@@ -78,18 +78,9 @@ jobs:
rm -rf ./* || true
rm -rf ./.??* || true
ls -la ./
- name: Cleanup podman state
run: |
set -x
podman ps -a || true
podman stop -a || true
podman rm -a -f || true
podman volume prune -f || true
podman system prune -a -f || true
podman system migrate || true
- name: Checkout infix repo
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
repository: ${{ env.INFIX_REPO }}
ref: ${{ env.INFIX_BRANCH != '' && env.INFIX_BRANCH || github.ref }}
@@ -98,6 +89,8 @@ jobs:
submodules: recursive
token: ${{ secrets.CHECKOUT_TOKEN || github.token }}
- uses: kernelkit/actions/podman-cleanup@v1
- name: Run pre-build script
if: ${{ inputs.pre_build_script != '' }}
run: |
@@ -127,22 +120,9 @@ jobs:
echo "tgz=${name}-${target}.tar.gz" >> $GITHUB_OUTPUT
echo "Building target ${target}_defconfig"
- name: Restore Cache of dl/
uses: actions/cache@v4
- uses: kernelkit/actions/cache-restore@v1
with:
path: dl/
key: dl-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
restore-keys: |
dl-
- name: Restore Cache of .ccache/
uses: actions/cache@v4
with:
path: .ccache/
key: ccache-${{ env.TARGET }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
restore-keys: |
ccache-${{ env.TARGET }}-
ccache-
target: ${{ env.TARGET }}
- name: Configure ${{ env.TARGET }}
run: |
@@ -153,10 +133,6 @@ jobs:
podman rm -af || true
pkill -9 -f rootlessport || true
- name: Unit Test ${{ env.TARGET }}
run: |
make test-unit
- name: Prepare parallel build
id: parallel
run: |
@@ -202,7 +178,7 @@ jobs:
ln -s ${{ steps.vars.outputs.dir }} images
tar cfz ${{ steps.vars.outputs.tgz }} ${{ steps.vars.outputs.dir }}
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
path: output/${{ steps.vars.outputs.tgz }}
name: artifact-${{ env.TARGET }}
+2 -2
View File
@@ -12,7 +12,7 @@ jobs:
steps:
- name: Check out infix repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ secrets.KERNEL_UPDATE_TOKEN }}
@@ -103,7 +103,7 @@ jobs:
- name: Create pull request
if: steps.check.outputs.new_release == 'true'
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
github-token: ${{ secrets.KERNEL_UPDATE_TOKEN }}
script: |
+16 -6
View File
@@ -8,13 +8,15 @@ on:
env:
PROJECT_NAME: Infix
CONTACT_EMAIL: troglobit@gmail.com
LIBYANG_VERSION: 4.2.2
SYSREPO_VERSION: 4.2.10
jobs:
coverity:
if: ${{github.repository_owner == 'kernelkit'}}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Fetch latest Coverity Scan MD5
id: var
env:
@@ -25,7 +27,7 @@ jobs:
-O coverity-latest.tar.gz.md5
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
- uses: actions/cache@v4
- uses: actions/cache@v5
id: cache
with:
path: coverity-latest.tar.gz
@@ -55,16 +57,24 @@ jobs:
sudo apt-get -y update
sudo apt-get -y install pkg-config libjansson-dev libev-dev \
libcrypt-dev libglib2.0-dev libpcre2-dev \
libuev-dev
libuev-dev libavahi-client-dev
- name: Build dependencies
run: |
git clone https://github.com/CESNET/libyang.git
git clone -b v${LIBYANG_VERSION} --depth 1 https://github.com/CESNET/libyang.git
for p in patches/libyang/${LIBYANG_VERSION}/*.patch; do
git -C libyang apply < "$p"
done
mkdir libyang/build
(cd libyang/build && cmake .. && make all && sudo make install)
git clone https://github.com/sysrepo/sysrepo.git
git clone -b v${SYSREPO_VERSION} --depth 1 https://github.com/sysrepo/sysrepo.git
for p in patches/sysrepo/${SYSREPO_VERSION}/*.patch; do
git -C sysrepo apply < "$p"
done
mkdir sysrepo/build
(cd sysrepo/build && cmake .. && make all && sudo make install)
git clone https://github.com/troglobit/libite.git
(cd libite && ./autogen.sh && ./configure && make && sudo make install)
make dep
@@ -88,7 +98,7 @@ jobs:
https://scan.coverity.com/builds?project=${PROJECT_NAME}
- name: Upload build.log
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: coverity-build.log
path: cov-int/build-log.txt
+2 -2
View File
@@ -24,12 +24,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v6
with:
python-version: '3.x'
+2 -2
View File
@@ -33,7 +33,7 @@ jobs:
mtools
- name: Checkout infix repo
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
repository: ${{ github.repository }}
ref: ${{ github.ref }}
@@ -77,7 +77,7 @@ jobs:
ln -s Infix-x86_64 images
tar cfz Infix-x86_64.tar.gz Infix-x86_64
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
path: output/Infix-x86_64.tar.gz
name: artifact-x86_64
+4 -16
View File
@@ -44,23 +44,11 @@ jobs:
checkout:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Restore Cache of dl/
uses: actions/cache@v4
- uses: actions/checkout@v6
- uses: kernelkit/actions/cache-restore@v1
with:
path: dl/
key: dl-netconf-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
restore-keys: |
dl-netconf-
dl-
- name: Restore Cache of .ccache/
uses: actions/cache@v4
with:
path: .ccache/
key: ccache-x86_64-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
restore-keys: |
ccache-x86_64-
ccache-
target: x86_64
dl-prefix: dl-netconf
- name: Disk inventory (2/2) ...
run: |
echo "df -h ========================================================================="
+4 -12
View File
@@ -48,20 +48,12 @@ jobs:
contents: write
discussions: write
steps:
- name: Cleanup podman state
run: |
set -x
podman ps -a || true
podman stop -a || true
podman rm -a -f || true
podman volume prune -f || true
podman system prune -a -f || true
podman system migrate || true
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: 'true'
- uses: kernelkit/actions/podman-cleanup@v1
- name: Set Release Variables
id: rel
run: |
@@ -86,7 +78,7 @@ jobs:
echo "pre=${{ steps.rel.outputs.pre }}"
echo "latest=${{ steps.rel.outputs.latest }}"
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v7
with:
pattern: "artifact-*"
merge-multiple: true
+16 -16
View File
@@ -43,6 +43,11 @@ on:
type: string
default: ''
description: 'Optional script to run after checkout (for spin customization)'
release:
required: false
type: string
default: ''
description: 'Release version (e.g. v26.04.0), sets INFIX_RELEASE so make test finds versioned artifacts'
secrets:
CHECKOUT_TOKEN:
required: false
@@ -60,18 +65,8 @@ jobs:
name: Regression Test ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.name || inputs.name }} ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.target || inputs.target }}
runs-on: [self-hosted, regression]
steps:
- name: Cleanup podman state
run: |
set -x
podman ps -a || true
podman stop -a || true
podman rm -a -f || true
podman volume prune -f || true
podman system prune -a -f || true
podman system migrate || true
- name: Checkout infix repo
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
repository: ${{ env.INFIX_REPO }}
ref: ${{ env.INFIX_BRANCH != '' && env.INFIX_BRANCH || github.ref }}
@@ -80,6 +75,8 @@ jobs:
submodules: recursive
token: ${{ secrets.CHECKOUT_TOKEN || github.token }}
- uses: kernelkit/actions/podman-cleanup@v1
- name: Run pre-test script
if: ${{ inputs.pre_test_script != '' }}
run: |
@@ -101,7 +98,7 @@ jobs:
run: |
make ${{ env.TARGET }}_defconfig
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v7
with:
pattern: "artifact-*"
merge-multiple: true
@@ -113,12 +110,15 @@ jobs:
ls -l
mkdir -p output
mv ${name}-${target}.tar.gz output/
tarfile=$(ls ${name}-${target}*.tar.gz | head -1)
mv "$tarfile" output/
cd output/
tar xf ${name}-${target}.tar.gz
ln -s ${name}-${target} images
tar xf "$tarfile"
ln -s "${tarfile%.tar.gz}" images
- name: Regression Test ${{ env.TARGET }}
env:
INFIX_RELEASE: ${{ inputs.release }}
run: |
if [ -n "$NINEPM_CONF" ]; then
export NINEPM_PROJ_CONFIG="${GITHUB_WORKSPACE}/$NINEPM_CONF"
@@ -139,7 +139,7 @@ jobs:
make test-dir="$(pwd)/$TEST_PATH" test-report
- name: Upload Test Report as Artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: test-report
path: output/images/test-report.pdf
+19 -3
View File
@@ -1,4 +1,4 @@
name: Kernelkit Trigger
name: CI
on:
pull_request:
@@ -28,6 +28,7 @@ jobs:
outputs:
x86_64_target: ${{ steps.set-targets.outputs.x86_64_target }}
aarch64_target: ${{ steps.set-targets.outputs.aarch64_target }}
arm_target: ${{ steps.set-targets.outputs.arm_target }}
steps:
- run: |
echo "Triggering build, logging meta data ..."
@@ -43,25 +44,40 @@ jobs:
| grep -q "ci:main"; then
echo "x86_64_target=x86_64_minimal" >> $GITHUB_OUTPUT
echo "aarch64_target=aarch64_minimal" >> $GITHUB_OUTPUT
echo "arm_target=arm_minimal" >> $GITHUB_OUTPUT
else
echo "x86_64_target=x86_64" >> $GITHUB_OUTPUT
echo "aarch64_target=aarch64" >> $GITHUB_OUTPUT
echo "arm_target=arm" >> $GITHUB_OUTPUT
fi
unit-test:
needs: check-trigger
uses: ./.github/workflows/unit-test.yml
with:
name: "infix"
target: ${{ needs.check-trigger.outputs.x86_64_target }}
build-x86_64:
needs: check-trigger
needs: [check-trigger, unit-test]
uses: ./.github/workflows/build.yml
with:
name: "infix"
target: ${{ needs.check-trigger.outputs.x86_64_target }}
build-aarch64:
needs: check-trigger
needs: [check-trigger, unit-test]
uses: ./.github/workflows/build.yml
with:
name: "infix"
target: ${{ needs.check-trigger.outputs.aarch64_target }}
build-arm:
needs: [check-trigger, unit-test]
uses: ./.github/workflows/build.yml
with:
name: "infix"
target: ${{ needs.check-trigger.outputs.arm_target }}
test-run-x86_64:
needs: [check-trigger, build-x86_64]
uses: ./.github/workflows/test.yml
+116
View File
@@ -0,0 +1,116 @@
name: unit-test
on:
workflow_dispatch:
inputs:
target:
description: "Build target (e.g. aarch64 or aarch64_minimal)"
default: "x86_64"
type: string
parallel:
description: 'Massive parallel build of each image'
default: true
type: boolean
name:
description: "Name (for spin overrides)"
default: "infix"
type: string
infix_repo:
description: 'Repo to checkout (for spin overrides)'
default: kernelkit/infix
type: string
infix_branch:
description: 'Branch/tag/commit to checkout (for spin overrides)'
default: ''
type: string
workflow_call:
inputs:
target:
required: true
type: string
name:
required: true
type: string
infix_repo:
required: false
type: string
default: kernelkit/infix
infix_branch:
required: false
type: string
default: ''
description: 'Branch/tag/commit to checkout (for spin overrides). Defaults to github.ref if not specified'
parallel:
required: false
type: boolean
default: true
pre_build_script:
required: false
type: string
default: ''
description: 'Optional script to run after checkout (for spin customization)'
secrets:
CHECKOUT_TOKEN:
required: false
description: 'Token for cross-repository access'
env:
NAME: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.name || inputs.name }}
TARGET: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.target || inputs.target }}
INFIX_REPO: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.infix_repo || inputs.infix_repo }}
INFIX_BRANCH: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.infix_branch || inputs.infix_branch }}
jobs:
unit-tests:
name: Build ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.name || inputs.name }} ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.target || inputs.target }}
runs-on: [ self-hosted, latest ]
env:
PARALLEL: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.parallel == 'true' || github.event_name != 'workflow_dispatch' && inputs.parallel == true }}
strategy:
fail-fast: false
steps:
- name: Cleanup Build Folder
run: |
ls -la ./
rm -rf ./* || true
rm -rf ./.??* || true
ls -la ./
- name: Checkout infix repo
uses: actions/checkout@v6
with:
repository: ${{ env.INFIX_REPO }}
ref: ${{ env.INFIX_BRANCH != '' && env.INFIX_BRANCH || github.ref }}
clean: true
fetch-depth: 0
submodules: recursive
token: ${{ secrets.CHECKOUT_TOKEN || github.token }}
- uses: kernelkit/actions/podman-cleanup@v1
- name: Run pre-build script
if: ${{ inputs.pre_build_script != '' }}
run: |
cat > ./pre-build.sh << 'EOF'
${{ inputs.pre_build_script }}
EOF
chmod +x ./pre-build.sh
bash ./pre-build.sh
- uses: kernelkit/actions/cache-restore@v1
with:
target: ${{ env.TARGET }}
- name: Configure ${{ env.TARGET }}
run: |
make ${{ env.TARGET }}_defconfig
- name: Cleanup stale containers and ports
run: |
podman rm -af || true
pkill -9 -f rootlessport || true
- name: Unit Test ${{ env.TARGET }}
run: |
make test-unit
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v6
with:
pattern: "artifact-*"
merge-multiple: true
+1 -1
View File
@@ -2,6 +2,7 @@
.claude
.gdb_history
.claude
AGENTS.md
/.backup
/.ccache
/dl
@@ -11,4 +12,3 @@
/test/.log
/local.mk
/test/spec/Readme.adoc
+22 -3
View File
@@ -9,8 +9,10 @@ O ?= output
# otherwise treat it as relative to ./buildroot.
override O := $(if $(filter /%,$O),$O,$(CURDIR)/$O)
config := $(O)/.config
bmake = $(MAKE) -C buildroot O=$(O) $1
config := $(O)/.config
bmake = $(MAKE) -C buildroot O=$(O) $1
SNIPPETS_DIR := $(CURDIR)/configs/snippets
MERGE_CONFIG := $(CURDIR)/buildroot/support/kconfig/merge_config.sh
all: $(config) buildroot/Makefile
@@ -26,6 +28,23 @@ $(config):
@echo "'make <board>_defconfig' before building an image."
@exit 1
apply-%: $(SNIPPETS_DIR)/%.conf | $(config)
@KCONFIG_CONFIG=$(config) $(MERGE_CONFIG) -m $(config) $<
@+$(call bmake,olddefconfig)
@echo "Applied snippet: $<"
list-snippets:
@echo "Available snippets (use 'make apply-<name>'):"
@ls $(SNIPPETS_DIR)/*.conf 2>/dev/null | sed 's|.*/||; s|\.conf$$||; s|^| |'
dev: | $(config)
@for s in $(SNIPPETS_DIR)/*.conf; do \
KCONFIG_CONFIG=$(config) $(MERGE_CONFIG) -m $(config) $$s; \
echo "Applied snippet: $$s"; \
done
@+$(call bmake,olddefconfig)
@+$(call bmake,all)
%: | buildroot/Makefile
@+$(call bmake,$@)
@@ -44,4 +63,4 @@ test:
buildroot/Makefile:
@git submodule update --init
.PHONY: all check coverity dep test cyclonedx
.PHONY: all check coverity dep test cyclonedx list-snippets dev
+8 -7
View File
@@ -85,12 +85,12 @@ interfaces {
admin@infix-12-34-56:/config/interface/eth0/> <b>leave</b>
admin@infix-12-34-56:/> <b>show interfaces</b>
<u>INTERFACE PROTOCOL STATE DATA </u>
eth0 ethernet UP 52:54:00:12:34:56
ipv4 192.168.2.200/24 (static)
ipv6 fe80::5054:ff:fe12:3456/64 (link-layer)
lo ethernet UP 00:00:00:00:00:00
ipv4 127.0.0.1/8 (static)
ipv6 ::1/128 (static)
eth0 ethernet UP 52:54:00:12:34:56
ipv4 192.168.2.200/24 (static)
ipv6 fe80::5054:ff:fe12:3456/64 (link-layer)
admin@infix-12-34-56:/> <b>copy running startup</b>
</code></pre>
@@ -114,6 +114,7 @@ containers for any custom functionality you need.
- **x86_64** - Run in VMs or on mini PCs for development and testing
- **Marvell CN9130 CRB, EspressoBIN** - High-performance ARM64 platforms
- **Microchip SparX-5i** - Enterprise switching capabilities
- **Microchip SAMA7G54-EK** - ARM Cortex-A7
- **NXP i.MX8MP EVK** - Highly capable ARM64 SoC
- **StarFive VisionFive2** - RISC-V architecture support
@@ -167,13 +168,13 @@ APIs.
[0]: https://www.kernel.org
[1]: https://buildroot.org/ "Buildroot Homepage"
[2]: https://www.sysrepo.org/ "Sysrepo Homepage"
[3]: https://kernelkit.org/infix/latest/cli/introduction/
[4]: https://kernelkit.org/infix/
[5]: https://github.com/kernelkit/infix/releases
[3]: https://www.kernelkit.org/infix/latest/cli/introduction/
[4]: https://www.kernelkit.org/infix/
[5]: https://github.com/kernelkit/infix/releases/latest
[Latest Build]: https://github.com/kernelkit/infix/releases/tag/latest "Latest build"
[License]: https://en.wikipedia.org/wiki/GPL_license
[License Badge]: https://img.shields.io/badge/License-GPL%20v2-blue.svg
[Release]: https://github.com/kernelkit/infix/releases
[Release]: https://github.com/kernelkit/infix/releases/latest
[Release Badge]: https://img.shields.io/github/v/release/kernelkit/infix
[GitHub]: https://github.com/kernelkit/infix/actions/workflows/build.yml/
[GitHub Status]: https://github.com/kernelkit/infix/actions/workflows/build.yml/badge.svg
+2
View File
@@ -2,6 +2,8 @@ if BR2_aarch64
source "$BR2_EXTERNAL_INFIX_PATH/board/aarch64/alder-alder/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/aarch64/bananapi-bpi-r3/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/aarch64/bananapi-bpi-r4/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/aarch64/bananapi-bpi-r64/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/aarch64/freescale-imx8mp-evk/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/aarch64/friendlyarm-nanopi-r2s/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/aarch64/marvell-cn9130-crb/Config.in"
+8 -5
View File
@@ -4,8 +4,11 @@ aarch64
Board Specific Documentation
----------------------------
- [Banana Pi R3](banana-pi-r3/)
- [Marvell CN9130-CRB](cn9130-crb/)
- [Microchip SparX-5i PCB135 (eMMC)](sparx5-pcb135/)
- [NanoPi R2S](r2s/)
- [Raspberry Pi 64-bit](raspberry-pi64/)
- [Banana Pi BPi-R3](bananapi-bpi-r3/)
- [Banana Pi BPi-R4](bananapi-bpi-r4/)
- [Banana Pi BPi-R64](bananapi-bpi-r64/)
- [Marvell CN9130-CRB](marvell-cn9130-crb/)
- [Marvell ESPRESSObin](marvell-espressobin/)
- [Microchip SparX-5i PCB135 (eMMC)](microchip-sparx5-pcb135/)
- [NanoPi R2S](friendlyarm-nanopi-r2s/)
- [Raspberry Pi 64-bit](raspberrypi-rpi64/)
+1
View File
@@ -1,5 +1,6 @@
config BR2_PACKAGE_ALDER_ALDER
bool "Alder"
depends on BR2_aarch64
select BR2_PACKAGE_LINUX_FIRMWARE_INSIDE_SECURE_MINIFW
help
Alder
@@ -0,0 +1,2 @@
# Locally calculated
sha256 d2f96418893ac66156d0e691cda189b0d85ae1d814065d1d9aa1845383100f46 LICENSE
+1
View File
@@ -5,6 +5,7 @@ config BR2_PACKAGE_BANANAPI_BPI_R3
select BR2_PACKAGE_LINUX_FIRMWARE
select BR2_PACKAGE_LINUX_FIRMWARE_MEDIATEK
select BR2_PACKAGE_LINUX_FIRMWARE_MEDIATEK_MT7986
select BR2_PACKAGE_LINUX_FIRMWARE_AIROHA_EN8811H
select SDCARD_AUX
help
Build Banana PI R3 support
+86 -51
View File
@@ -1,20 +1,29 @@
# Banana Pi BPI-R3
# Banana Pi BPI-R3 / BPI-R3 Mini
<img src="bananapi-bpi-r3.webp" alt="The board" width=800 padding=10>
## Overview
The Banana Pi R3 is a high-performance networking board with full Infix
support for all enabled features including switched Ethernet ports, WiFi,
and SFP interfaces.
The Banana Pi BPI-R3 and BPI-R3 Mini are high-performance networking
boards with full Infix support for all enabled features including
Ethernet, WiFi, and SFP interfaces.
Both boards share the same SoC and most peripherals. The key
differences are:
| Feature | BPI-R3 | BPI-R3 Mini |
|-----------------|--------------------|-------------------------|
| Ethernet switch | Yes (4x LAN + WAN) | No (WAN/LAN ports only) |
| SD card slot | Yes | No |
### Hardware Features
- MediaTek MT7986 ARM Cortex-A53 quad-core processor @ 2.0 GHz
- 2 GB DDR4 RAM
- 8 GB eMMC storage + microSD card slot
- 5x Gigabit Ethernet ports (4x LAN, 1x WAN)
- 2x SFP cages for fiber connectivity (1G/2.5G)
- 8 GB eMMC storage
- microSD card slot (BPI-R3 only)
- 5x Gigabit Ethernet ports with switch core (BPI-R3 only)
- 2x SFP cages for fiber connectivity (1G/2.5G) (BPI-R3 only)
- Dual-band WiFi (2.4 GHz + 5 GHz)
- USB 3.0 port
- Mini PCIe slot
@@ -23,16 +32,16 @@ and SFP interfaces.
Infix comes preconfigured with:
- **LAN ports** (lan1-lan4): Bridged for internal networking
- **LAN ports** (lan1-lan4): Bridged for internal networking (BPI-R3 only)
- **WAN port**: DHCP client enabled for internet connectivity
- **SFP ports** (sfp1, sfp2): Available for configuration
- **SFP ports** (sfp1, sfp2): Available for configuration (BPI-R3 only)
- **WiFi interfaces** (wifi0, wifi1): Available for configuration
## Getting Started
### Quick Start with SD Card
### BPI-R3: Quick Start with SD Card
The easiest way to get started is using an SD card:
The easiest way to get started with the BPI-R3 is using an SD card:
> [!NOTE]
> SD card boot works but we have observed stability issues. For production
@@ -49,73 +58,63 @@ The easiest way to get started is using an SD card:
- Connect to LAN port or console (115200 8N1)
- Default login: `admin` / `admin`
### BPI-R3 Mini: Getting Started
The BPI-R3 Mini does not have an SD card slot, so you must install
directly to eMMC. See [Installing to eMMC — BPI-R3
Mini](#bpi-r3-mini) below.
### Boot Switch Reference
The BPI-R3 has a 4-position DIP switch that controls boot media:
<img align="right" src="bootstrap-switch.webp" alt="DIP switches" width=200 padding=10>
| Position | Mode | Description |
|----------|-------------|---------------------------------------|
| 0000 | SD card | Boot from microSD card |
| 0110 | eMMC | Boot from internal eMMC (recommended) |
| 1010 | SPI NAND | Boot from SPI NAND (advanced users) |
| ABCD | Mode | Description |
|------|----------|---------------------------------------|
| 0000 | SD card | Boot from microSD card |
| 0101 | SPI NAND | Boot from SPI NAND (advanced users) |
| 1001 | eMMC | Boot from internal eMMC (recommended) |
> [!NOTE]
> Switch position is read from left to right: "0" = OFF, "1" = ON.
> Switch position is read from left to right: "0" = OFF, "1" = ON.
> When the DIP switch is in the "UP" position it is OFF(0).
## Advanced: Installing to eMMC
## Installing to eMMC
For production deployments or better performance, you can install Infix
to the internal eMMC storage. This is more complex but provides faster
boot times and eliminates the external SD card.
to the internal eMMC storage.
> [!IMPORTANT]
> While Infix boots on both SD card and eMMC, we have observed stability
> issues with SD cards on this platform. **eMMC is recommended** for
> reliable operation.
### Why Use eMMC?
**Advantages:**
- More reliable than SD card (stability issues observed with SD cards)
- Faster boot and better performance
- No external SD card to manage
- More robust for industrial/embedded deployments
**Disadvantages:**
- More complex installation process
- Requires intermediate NAND boot step
- Harder to recover from errors
> While Infix boots on both SD card and eMMC on the BPI-R3, we have
> observed stability issues with SD cards on this platform. **eMMC is
> recommended** for reliable operation.
### Prerequisites
- FTDI USB-to-serial cable (3.3V) for console access
- microSD card with Infix (for initial boot)
- USB flash drive (FAT32 formatted)
- microSD card with Infix, for initial boot (BPI-R3 only)
- Downloaded files (see below)
### Required Files
Download and place these files on a FAT32-formatted USB drive:
1. **Intermediate NAND bootloader** (from Frank-W's U-Boot):
- [bpi-r3_spim-nand_bl2.img][5] (BL2 loader)
- [bpi-r3_spim-nand_fip.bin][6] (FIP image)
2. **Infix eMMC image:**
1. **Infix eMMC image:**
- [infix-bpi-r3-emmc.img][3] (Complete system image)
3. **eMMC bootloader** (extracted from):
2. **eMMC bootloader** (extracted from):
- [bpi-r3-emmc-boot-2025.01-latest.tar.gz][4]
- Extract `bl2.img` from the tarball to your USB drive
3. **Intermediate NAND bootloader** (BPI-R3 only, from Frank-W's U-Boot):
- [bpi-r3_spim-nand_bl2.img][5] (BL2 loader)
- [bpi-r3_spim-nand_fip.bin][6] (FIP image)
> [!WARNING]
> The following process involves multiple boot mode changes. Take your
> time verify each step carefully.
> time and verify each step carefully.
### Installation Steps
### BPI-R3
#### Step 1: Boot from SD card
@@ -151,6 +150,7 @@ From the U-Boot prompt:
usb start
fatload usb 0:1 0x50000000 infix-bpi-r3-emmc.img
setexpr blocks ${filesize} / 0x200
mmc dev 0
mmc write 0x50000000 0x0 ${blocks}
```
@@ -177,13 +177,48 @@ mmc partconf 0 1 1 0
Your BPI-R3 should now boot Infix from internal eMMC storage!
### BPI-R3 Mini
The BPI-R3 Mini does not have an SD card slot, so you have to go
through the factory-installed Linux (OpenWRT) to flash the Infix
bootloader and OS to eMMC.
#### Step 1: Boot from NAND (factory default)
<img src="r3mini_nandboot2.png" alt="BPI-R3 Mini NAND boot switch position" width=400>
1. Ensure boot switches are set to NAND mode (factory default)
2. Place `infix-bpi-r3-emmc.img` and `bl2.img` on a USB drive
3. Power on and boot into Linux
4. Mount the USB drive to `/mnt`
#### Step 2: Flash Infix to eMMC
From the Linux shell:
```
echo 0 > /proc/sys/kernel/printk
dd if=/mnt/infix-bpi-r3-emmc.img of=/dev/mmcblk0
echo 0 > /sys/block/mmcblk0boot0/force_ro
dd if=/mnt/bl2.img of=/dev/mmcblk0boot0
sync
```
#### Step 3: Boot from eMMC
<img src="r3mini_emmcboot.png" alt="BPI-R3 Mini eMMC boot switch position" width=400>
1. Power off the board
2. Set boot switches to eMMC mode (see image above)
3. Power on
## Troubleshooting
### Board won't boot
- Verify boot switch positions (check twice!)
- Ensure power supply provides adequate current (12V/2A recommended)
- Try booting from SD card with switches at **0000**
- Try booting from SD card with switches at **0000** (BPI-R3 only)
### Can't break into U-Boot
@@ -195,9 +230,9 @@ Your BPI-R3 should now boot Infix from internal eMMC storage!
- Boot from NAND (**1010**) and verify eMMC image was written
- Check USB drive contents - ensure all files are present
- Re-run Step 5 (eMMC boot configuration)
- Re-run the eMMC boot configuration step
### Reverting to SD card
### Reverting to SD card (BPI-R3 only)
Simply set boot switches back to **0000** and boot from SD card. The
eMMC installation does not affect SD card functionality.
@@ -228,8 +263,8 @@ make aarch64
./utils/mkimage.sh -odt emmc bananapi-bpi-r3
```
[0]: https://kernelkit.org/posts/flashing-sdcard/
[1]: https://kernelkit.org/infix/latest/
[0]: https://www.kernelkit.org/posts/flashing-sdcard/
[1]: https://www.kernelkit.org/infix/latest/
[2]: https://github.com/kernelkit/infix/releases/download/latest-boot/infix-bpi-r3-sdcard.img
[3]: https://github.com/kernelkit/infix/releases/download/latest-boot/infix-bpi-r3-emmc.img
[4]: https://github.com/kernelkit/infix/releases/download/latest-boot/bpi-r3-emmc-boot-2025.01-latest.tar.gz
@@ -0,0 +1,2 @@
# Locally calculated
sha256 dbe4eae8debbba8135297e15f24aeefef0b4c03781f3f9328db4398d58a728b3 LICENSE
@@ -9,6 +9,7 @@ define BANANAPI_BPI_R3_LINUX_CONFIG_FIXUPS
$(call KCONFIG_ENABLE_OPT,CONFIG_MEDIATEK_WATCHDOG)
$(call KCONFIG_ENABLE_OPT,CONFIG_MEDIATEK_GE_PHY)
$(call KCONFIG_ENABLE_OPT,CONFIG_REALTEK_PHY)
$(call KCONFIG_SET_OPT,CONFIG_AIR_EN8811H_PHY,m)
$(call KCONFIG_ENABLE_OPT,CONFIG_NET_VENDOR_MEDIATEK)
$(call KCONFIG_ENABLE_OPT,CONFIG_NET_MEDIATEK_SOC)
$(call KCONFIG_SET_OPT,CONFIG_NET_DSA_MT7530,m)
+1 -1
View File
@@ -1 +1 @@
dtb-y += mediatek/mt7986a-bananapi-bpi-r3-sd.dtb mediatek/mt7986a-bananapi-bpi-r3-emmc.dtb
dtb-y += mediatek/mt7986a-bananapi-bpi-r3-sd.dtb mediatek/mt7986a-bananapi-bpi-r3-emmc.dtb mediatek/mt7986a-bananapi-bpi-r3-mini.dtb
@@ -1,2 +1,4 @@
#include <arm64/mediatek/mt7986a-bananapi-bpi-r3.dts>
#include "mt7986a-bananapi-bpi-r3.dtsi"
#include "mt7986a-bananapi-bpi-r3-emmc.dtsi"
@@ -0,0 +1,12 @@
#include <arm64/mediatek/mt7986a-bananapi-bpi-r3-mini.dts>
#include "mt7986a-bananapi-bpi-r3.dtsi"
#include "mt7986a-bananapi-bpi-r3-emmc.dtsi"
&phy0 {
compatible = "ethernet-phy-id03a2.a411";
};
&phy1 {
compatible = "ethernet-phy-id03a2.a411";
};
@@ -0,0 +1,2 @@
#include "mt7986a-bananapi-bpi-r3.dtsi"
#include "mt7986a-bananapi-bpi-r3-emmc.dtsi"
@@ -1,2 +1,4 @@
#include <arm64/mediatek/mt7986a-bananapi-bpi-r3.dts>
#include "mt7986a-bananapi-bpi-r3.dtsi"
#include "mt7986a-bananapi-bpi-r3-sd.dtsi"
@@ -1,5 +1,3 @@
#include <arm64/mediatek/mt7986a-bananapi-bpi-r3.dts>
/ {
chosen {
infix {
@@ -10,6 +8,33 @@
};
};
};
/*
From 236317dd4e55512933dcdaec3d0b4a0824f5e5bd Mon Sep 17 00:00:00 2001
From: Shiji Yang <yangshiji66@outlook.com>
Date: Sun, 10 Aug 2025 18:11:01 +0800
Subject: [PATCH] arm64: dts: mediatek: mt7986: increase ATF reserved memory to
256 kiB
The latest Mediatek open-source Trusted Firmware-A project has
reserved 256 KiB for BL2 and BL31. It is better to increase the
reserved memory region in the Linux kernel to protect the data.
https://github.com/openwrt/openwrt/blob/main/target/linux/mediatek/patches-6.12/199-arm64-dts-mediatek-mt7986-increase-ATF-reserved-memo.patch
*/
&secmon_reserved {
reg = <0 0x43000000 0 0x40000>;
};
/*
* The T-PHY's pcie-phy sub-node only claims clk40m ("ref") in the SoC
* dtsi. CLK_TOP_PCIE_PHY_SEL ("da_ref") is left unclaimed, so the
* kernel's clk_disable_unused late_initcall gates it — killing the
* PCIe REFCLK output to the endpoint mid-probe. Wire it here so the
* clock stays enabled while the PHY is active.
*/
&pcie_port {
clocks = <&clk40m>, <&topckgen CLK_TOP_PCIE_PHY_SEL>;
clock-names = "ref", "da_ref";
};
&cpu_thermal {
/delete-node/ trips;
@@ -51,6 +51,11 @@ image #INFIX_ID##VERSION#-bpi-r3-#TARGET#.img {
size = 4096s
}
partition en8811h_fw {
size = 10M
image = "en8811h-fw.bin"
}
partition aux {
partition-uuid = D4EF35A0-0652-45A1-B3DE-D63339C82035
image = "aux.ext4"
Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

@@ -21,21 +21,21 @@
{
"name": "radio0",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "2.4GHz",
"channel": "auto"
}
},
{
"name": "radio1",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "2.4GHz",
"channel": "auto"
}
},
{
"name": "radio1",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "5GHz",
"channel": "auto"
}
}
}
]
},
"ietf-interfaces:interfaces": {
@@ -130,7 +130,8 @@
"id": "domain"
},
{
"id": "hostname"
"id": "hostname",
"value": "auto"
},
{
"id": "dns-server"
@@ -179,7 +180,7 @@
}
}
},
"infix-interfaces:bridge-port": {
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
@@ -195,7 +196,7 @@
}
}
},
"infix-interfaces:bridge-port": {
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
}
@@ -1,3 +0,0 @@
#!/bin/sh
udevadm control --reload-rules
udevadm trigger --subsystem-match=net --action=add
@@ -0,0 +1,446 @@
{
"ieee802-dot1ab-lldp:lldp": {
"infix-lldp:enabled": true
},
"ietf-hardware:hardware": {
"component": [
{
"name": "USB",
"class": "infix-hardware:usb",
"state": {
"admin-state": "unlocked"
}
},
{
"class": "infix-hardware:usb",
"name": "USB2",
"state": {
"admin-state": "unlocked"
}
},
{
"name": "radio0",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "2.4GHz",
"channel": "auto"
}
},
{
"name": "radio1",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "5GHz",
"channel": "auto"
}
}
]
},
"ietf-interfaces:interfaces": {
"interface": [
{
"name": "br0",
"type": "infix-if-type:bridge",
"ietf-ip:ipv4": {
"address": [
{
"ip": "192.168.0.1",
"prefix-length": 24
}
]
}
},
{
"name": "lan",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "lo",
"type": "infix-if-type:loopback",
"ietf-ip:ipv4": {
"address": [
{
"ip": "127.0.0.1",
"prefix-length": 8
}
]
},
"ietf-ip:ipv6": {
"address": [
{
"ip": "::1",
"prefix-length": 128
}
]
}
},
{
"name": "wan",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv4": {
"infix-dhcp-client:dhcp": {
"option": [
{
"id": "ntp-server"
},
{
"id": "broadcast"
},
{
"id": "domain"
},
{
"id": "hostname",
"value": "auto"
},
{
"id": "dns-server"
},
{
"id": "router"
},
{
"id": "netmask"
},
{
"id": "vendor-class",
"value": "Banana Pi BPI-R3"
}
]
}
},
"ietf-ip:ipv6": {
"infix-dhcpv6-client:dhcp": {
"option": [
{
"id": "ntp-server"
},
{
"id": "client-fqdn"
},
{
"id": "domain-search"
},
{
"id": "dns-server"
}
]
}
}
},
{
"name": "wifi0-ap",
"type": "infix-if-type:wifi",
"infix-interfaces:wifi": {
"radio": "radio0",
"access-point": {
"ssid": "Infix",
"security": {
"secret": "wifi"
}
}
},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "wifi1-ap",
"type": "infix-if-type:wifi",
"infix-interfaces:wifi": {
"radio": "radio1",
"access-point": {
"ssid": "Infix5Ghz",
"security": {
"secret": "wifi"
}
}
},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
}
]
},
"ietf-keystore:keystore": {
"asymmetric-keys": {
"asymmetric-key": [
{
"name": "genkey",
"public-key-format": "infix-crypto-types:ssh-public-key-format",
"public-key": "",
"private-key-format": "infix-crypto-types:rsa-private-key-format",
"cleartext-private-key": "",
"certificates": {}
}
]
},
"symmetric-keys": {
"symmetric-key": [
{
"name": "wifi",
"cleartext-symmetric-key": "aW5maXhpbmZpeA==",
"key-format": "infix-crypto-types:passphrase-key-format"
}
]
}
},
"ietf-netconf-acm:nacm": {
"enable-nacm": true,
"read-default": "permit",
"write-default": "permit",
"exec-default": "permit",
"groups": {
"group": [
{
"name": "admin",
"user-name": [
"admin"
]
},
{
"name": "operator",
"user-name": []
},
{
"name": "guest",
"user-name": []
}
]
},
"rule-list": [
{
"name": "admin-acl",
"group": [
"admin"
],
"rule": [
{
"name": "permit-all",
"module-name": "*",
"access-operations": "*",
"action": "permit",
"comment": "Allow 'admin' group complete access to all operations and data."
}
]
},
{
"name": "operator-acl",
"group": [
"operator"
],
"rule": [
{
"name": "permit-system-rpcs",
"module-name": "ietf-system",
"rpc-name": "*",
"access-operations": "exec",
"action": "permit",
"comment": "Operators can reboot, shutdown, and set system time."
}
]
},
{
"name": "guest-acl",
"group": [
"guest"
],
"rule": [
{
"name": "deny-all-write+exec",
"module-name": "*",
"access-operations": "create update delete exec",
"action": "deny",
"comment": "Guests cannot change anything or exec rpcs."
}
]
},
{
"name": "default-deny-all",
"group": [
"*"
],
"rule": [
{
"name": "deny-password-access",
"path": "/ietf-system:system/authentication/user/password",
"access-operations": "*",
"action": "deny",
"comment": "No user except admins can access password hashes."
},
{
"name": "deny-keystore-access",
"module-name": "ietf-keystore",
"access-operations": "*",
"action": "deny",
"comment": "No user except admins can access cryptographic keys."
},
{
"name": "deny-truststore-access",
"module-name": "ietf-truststore",
"access-operations": "*",
"action": "deny",
"comment": "No user except admins can access trust store."
}
]
}
]
},
"ietf-netconf-server:netconf-server": {
"listen": {
"endpoints": {
"endpoint": [
{
"name": "default-ssh",
"ssh": {
"tcp-server-parameters": {
"local-bind": [
{
"local-address": "::"
}
]
},
"ssh-server-parameters": {
"server-identity": {
"host-key": [
{
"name": "default-key",
"public-key": {
"central-keystore-reference": "genkey"
}
}
]
}
}
}
}
]
}
}
},
"ietf-system:system": {
"hostname": "bpi-%m",
"ntp": {
"server": [
{
"name": "default",
"udp": {
"address": "pool.ntp.org"
}
}
]
},
"authentication": {
"user": [
{
"name": "admin",
"password": "$factory$",
"infix-system:shell": "bash"
}
]
},
"infix-system:motd-banner": "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCBPUyDigJQgSW1tdXRhYmxlLkZyaWVuZGx5LlNlY3VyZQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQub3JnCictJy0tLSctJwo="
},
"infix-dhcp-server:dhcp-server": {
"option": [
{
"id": "ntp-server",
"address": "auto"
},
{
"id": "dns-server",
"address": "auto"
},
{
"id": "router",
"address": "auto"
}
],
"subnet": [
{
"subnet": "192.168.0.0/24",
"pool": {
"start-address": "192.168.0.100",
"end-address": "192.168.0.250"
}
}
]
},
"infix-firewall:firewall": {
"default": "wan",
"zone": [
{
"name": "lan",
"action": "accept",
"interface": [
"br0"
]
},
{
"name": "wan",
"action": "drop",
"interface": [
"wan"
],
"service": [
"dhcpv6-client"
]
}
],
"policy": [
{
"name": "lan-to-wan",
"action": "accept",
"ingress": [
"lan"
],
"egress": [
"wan"
],
"masquerade": true
}
]
},
"infix-meta:meta": {
"version": "1.7"
},
"infix-services:mdns": {
"enabled": true
},
"infix-services:ssh": {
"enabled": true,
"hostkey": [
"genkey"
],
"listen": [
{
"name": "ipv4",
"address": "0.0.0.0",
"port": 22
},
{
"name": "ipv6",
"address": "::",
"port": 22
}
]
},
"infix-services:web": {
"enabled": true,
"console": {
"enabled": true
},
"netbrowse": {
"enabled": true
},
"restconf": {
"enabled": true
}
}
}
@@ -0,0 +1,2 @@
ACTION=="add", SUBSYSTEM=="net", DEVPATH=="/devices/platform/soc/15100000.ethernet/net/eth0", NAME="lan"
ACTION=="add", SUBSYSTEM=="net", DEVPATH=="/devices/platform/soc/15100000.ethernet/net/eth1", NAME="wan"
@@ -3,6 +3,9 @@ CONFIG_BOOTDELAY=2
# CONFIG_MMC_PCI is not set
CONFIG_ENV_IS_NOWHERE=y
# CONFIG_ENV_IS_IN_MMC is not set
CONFIG_MULTI_DTB_FIT=y
CONFIG_OF_LIST="mt7986a-bpi-r3-sd mt7986a-bpi-r3-emmc mt7986a-bpi-r3-mini"
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_MTK=y
@@ -26,8 +29,17 @@ CONFIG_MTD_SPI_NAND=y
CONFIG_MTK_SPIM=y
CONFIG_MTK_SNOR=y
CONFIG_DM_MDIO=y
CONFIG_DM_ETH_PHY=y
CONFIG_PHY_ETHERNET_ID=y
CONFIG_PHY_AIROHA=y
CONFIG_PHY_AIROHA_EN8811H=y
CONFIG_PHY_AIROHA_FW_IN_MMC=y
CONFIG_CMD_SF=y
CONFIG_CMD_USB=y
CONFIG_CMD_MTD=y
CONFIG_CMD_MDIO=y
CONFIG_CMD_MTDPARTS=y
CONFIG_CMD_DM=y
@@ -15,6 +15,10 @@
scriptaddr = "0x48000000";
ramdisk_addr_r = "0x4A000000";
en8811h_fw_part = "0#en8811h_fw";
en8811h_fw_dm_dir = "EthMD32.dm.bin";
en8811h_fw_dsp_dir = "EthMD32.DSP.bin";
/* This is a development platform, keep
* developer mode statically enabled.
*/
+11
View File
@@ -0,0 +1,11 @@
config BR2_PACKAGE_BANANAPI_BPI_R4
bool "Banana Pi R4"
depends on BR2_aarch64
select BR2_PACKAGE_FEATURE_WIFI
select BR2_PACKAGE_LINUX_FIRMWARE
select BR2_PACKAGE_LINUX_FIRMWARE_MEDIATEK
select BR2_PACKAGE_LINUX_FIRMWARE_MEDIATEK_MT7988
select BR2_PACKAGE_LINUX_FIRMWARE_MEDIATEK_MT7996
select SDCARD_AUX
help
Build Banana PI R4 support
+13
View File
@@ -0,0 +1,13 @@
Copyright (c) 2026 The KernelKit Authors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+360
View File
@@ -0,0 +1,360 @@
# Banana Pi BPI-R4 / BPI-R4-2g5 / BPI-R4P
<img src="banana_pi_bpi-r4_poe.jpg" alt="The board" width=800 padding=10>
## Overview
The Banana Pi BPI-R4 is a high-performance networking board built around the
MediaTek MT7988A SoC (Filogic 880). It is a successor to the BPI-R3 and
represents a significant step up: the CPU switches from in-order Cortex-A53
cores to out-of-order Cortex-A73 cores, and the MT7531 switch is now part of
the SOC. The base model comes with two SFP+ cages supporting 1.25/2.5/5/10
Gbps, and the R4P model comes with one SFP+ cage and one 2.5 Gbps RJ45 jack,
which with an optional PoE board means the board can act as PD. Unlike the
BPi-R3, however, there is no on-board WiFi support, that requires an external
tri-band WiFi 7 (IEEE 802.11be) card.
### Variants
| **Feature** | **BPI-R4** | **BPI-R4-2g5** | **BPI-R4P** |
|------------------|------------------|-------------------|---------------------------|
| 1G switch ports | wan, lan1lan3 | lan0lan3 | lan0lan3 |
| 2.5G RJ45 (WAN) | — | wan | wan (PoE input) |
| SFP+ port(s) | sfp1, sfp2 (10G) | sfp1 (10G) | sfp1 (10G) |
| Linux DT | bpi-r4 | bpi-r4-2g5 | bpi-r4-2g5 (same) |
On the standard BPI-R4 the four 1G switch ports are labeled `wan`, `lan1`, `lan2`,
and `lan3`. On the R4-2g5 and R4P, the port that would otherwise be `wan` on the
switch is relabeled `lan0` via a device tree overlay, since the actual WAN port on
those variants is the dedicated 2.5G internal PHY on the separate RJ45 jack.
The BPI-R4P is mechanically and electrically identical to the BPI-R4-2g5
with an additional PoE daughterboard header. From a Linux kernel and
Infix perspective the two boards are treated identically.
### SoC: MediaTek MT7988A vs MT7986 (BPI-R3)
The MT7988A (Filogic 880) and MT7986 (Filogic 820) may look similar from
their part numbers, but they are built on entirely different silicon with
distinct system architectures:
| **Aspect** | **MT7988A (BPI-R4)** | **MT7986 (BPI-R3)** |
|------------------|--------------------------|---------------------------|
| CPU cores | 4x Cortex-A73 @ 1.8 GHz | 4x Cortex-A53 @ 2.0 GHz |
| CPU architecture | ARMv8-A, out-of-order | ARMv8-A, in-order |
| Internal switch | 1 Gbps per port | 1 Gbps per port |
| Uplinks | USXGMII (native 10 Gbps) | USXGMII (native 2.5 Gbps) |
| WiFi | MT7996E PCIe module | MT7915E (built-in) |
| WiFi standard | WiFi 7 (802.11be) | WiFi 6 (802.11ax) |
| WiFi bands | 2.4 / 5 / 6 GHz | 2.4 / 5 GHz |
| Hardware crypto | EIP-197 NPU | EIP-93 |
| PCIe slots | 4 (2x mPCIe, 2x M.2) | 1 mPCIe |
| Boot ROM offset | Sector 1024 (0x80000) | Sector 1024 (0x80000) |
### Hardware Features
- **SoC:** MediaTek MT7988A (Filogic 880)
- **CPU:** Quad-core ARM Cortex-A73, up to 1.8 GHz
- **RAM:** 4 GB DDR4
- **Storage:** 8 GB eMMC, microSD card slot, SPI NAND flash
- **Ethernet switch:** 4-port 1 GbE (10/100/1000) internal DSA switch
- **SFP+ ports:** 2x 10 Gbps USXGMII (standard R4) or 1x SFP+ (R4-2g5/R4P)
- **WiFi:** optional MediaTek MT7996E PCIe module — tri-band WiFi 7 (2.4/5/6 GHz)
- **USB:** 1x USB 3.0 (xHCI)
- **PCIe:** 2x mPCIe (SIM2/SIM3), 1x M.2 Key-B (SIM1), 1x M.2 Key-M (SSD)
- **RTC:** PCF8563 on I2C
- **Fan:** PWM-controlled cooling with thermal management
- **Console:** UART at 115200 8N1 (3.3 V, USB-to-serial adapter required)
### Default Network Configuration
Infix ships with the following factory defaults.
**Standard BPI-R4:**
- **LAN bridge** (`br0`, 192.168.0.1/24): `lan1`, `lan2`, `lan3` (1G switch ports)
- **WAN port** (`wan`): DHCP client, used for internet uplink (1G switch port)
- **SFP+ ports** (`sfp1`, `sfp2`): Present but unconfigured
**BPI-R4-2g5 and BPI-R4P:**
- **LAN bridge** (`br0`, 192.168.0.1/24): `lan0`, `lan1`, `lan2`, `lan3` (1G switch ports)
- **WAN port** (`wan`): DHCP client, used for internet uplink (2.5G internal PHY)
- **SFP+ port** (`sfp1`): Present but unconfigured
> [!NOTE]
> If an optional WiFi 7 (MT7996E) PCIe card is installed, the radio interfaces
> are bridged into the LAN as access points. WiFi is not included with the board
> and is not part of the factory default configuration.
## Getting Started
<img align="right" src="console-header.png" alt="Console header pins" width=200 padding=10>
### Quick Start with SD Card
1. **Download the SD card image:** [infix-bpi-r4-sdcard.img][2]
2. **Flash the image to an SD card:** see [this guide][0]
3. **Set boot switches to SD card mode** (see Boot Switch Reference below)
4. **Insert the SD card, connect power and a serial console (115200 8N1)**
5. Default login: `admin` / `admin`
### Boot Switch Reference
<img align="right" src="bootstrap-sw3.png" alt="DIP switches" width=140 padding=10>
The BPI-R4 has a 2-position DIP switch (SW3) that selects the boot media.
Switch positions are printed on the board near the SD card slot.
| A | B | Boot media (SW3) |
|-----|-----|------------------|
| OFF | ON | SPI NAND |
| ON | OFF | eMMC |
| ON | ON | SD card |
> [!NOTE]
> "OFF" = switch in the UP position = logical 0.
## Installing to eMMC
For production use or better reliability, install Infix to the internal
eMMC storage.
> [!IMPORTANT]
> The MT7988A has a single MMC controller that can only operate in one mode
> (SD or eMMC) per boot session. The SD card U-Boot cannot switch to eMMC
> mode mid-session, so an intermediate NAND bootloader step is required to
> write the eMMC — the same approach as BPi-R3.
>
> The MT7988A boot chain is: **BROM → BL2 → FIP (BL31 + U-Boot)**. The FIP
> (Firmware Image Package) bundles ARM Trusted Firmware (BL31) and U-Boot
> together; it is not just a U-Boot binary. When BL2 runs, it loads the FIP
> from a fixed offset and hands off to BL31, which then jumps into U-Boot.
>
> The factory SPI NAND contains a minimal recovery U-Boot that only supports
> TFTP — it has no USB command. You cannot use it to load files from a USB
> drive. Similarly, the factory eMMC ships with a basic OpenWRT image.
> You must first flash a full-featured U-Boot (from Frank-W) to SPI NAND via
> the SD card U-Boot before you can write the eMMC.
>
> This process involves three boot mode changes and multiple flash operations.
> Take your time and verify each step carefully.
### Prerequisites
- USB-to-serial adapter (3.3 V) for console access
- USB flash drive (FAT32 formatted)
- microSD card with Infix SD image, for initial boot
- Downloaded files (see below)
### Required Files
Place these files on a FAT32-formatted USB drive:
1. **Infix eMMC image:** [infix-bpi-r4-emmc.img][3]
2. **eMMC bootloader** (from): [bpi-r4-emmc-boot-2026.01-latest.tar.gz][4]
- Extract `bl2.img` from the tarball to your USB drive
3. **Intermediate NAND bootloader** from Frank-W's U-Boot (for BPI-R4, SPI NAND):
- [bpi-r4_spim-nand_bl2.img][13] — BL2 first-stage loader
- [bpi-r4_spim-nand_fip.bin][14] — FIP image (BL31 + U-Boot)
### Step 1: Boot from SD card
1. Set boot switches to **SD card mode** (SW3: A=ON, B=ON)
2. Insert the SD card with the Infix image
3. Power on and break into U-Boot (press Ctrl-C during countdown)
### Step 2: Flash intermediate NAND bootloader
This installs a full-featured U-Boot to SPI NAND so the board can load files
from USB in the next step. From the SD card U-Boot prompt:
```
usb start
mtd erase spi-nand0
fatload usb 0:1 0x50000000 bpi-r4_spim-nand_bl2.img
mtd write spi-nand0 0x50000000 0x0 0x100000
fatload usb 0:1 0x50000000 bpi-r4_spim-nand_fip.bin
mtd write spi-nand0 0x50000000 0x580000 0x200000
```
### Step 3: Boot from NAND
1. Power off the board
2. Set boot switches to **SPI NAND mode** (SW3: A=OFF, B=ON)
3. Power on — you should boot into U-Boot again
### Step 4: Write Infix image to eMMC
From the U-Boot prompt:
```
usb start
fatload usb 0:1 0x50000000 infix-bpi-r4-emmc.img
setexpr blocks ${filesize} / 0x200
mmc write 0x50000000 0x0 ${blocks}
```
### Step 5: Configure eMMC boot partition
Write the BL2 bootloader to the eMMC boot partition:
```
mmc partconf 0 1 1 1
mmc erase 0x0 0x400
fatload usb 0:1 0x50000000 bl2.img
mmc write 0x50000000 0x0 0x400
mmc partconf 0 1 1 0
```
### Step 6: Boot from eMMC
1. Power off the board
2. Set boot switches to **eMMC mode** (SW3: A=ON, B=OFF)
3. Remove the SD card (optional, recommended to verify eMMC boot)
4. Power on
Your BPI-R4 should now boot Infix from internal eMMC storage.
## Troubleshooting
### Board won't boot
- Verify boot switch positions — double-check against the wiki
- Ensure the power supply provides adequate current (12 V / 3 A recommended)
- Check the serial console output at 115200 8N1
### Can't break into U-Boot
- Connect the serial console before powering on
- Press Ctrl-C immediately when boot messages appear
- Try power cycling and pressing Ctrl-C repeatedly during the countdown
### eMMC boot fails after installation
- Boot from NAND (SW3=ON) and verify the eMMC write completed without errors
- Re-run the `mmc partconf` sequence — a missed step is the most common
cause of failure
- Use `mmc info` to confirm the eMMC is detected
### No network connectivity
The interface names on BPI-R4 differ from BPI-R3. Confirm what Linux
has created with `ip link` and compare with the factory configuration:
- `wan`, `lan1``lan3`: 1G switch ports (standard R4)
- `wan`, `lan0``lan3`: on R4-2g5/R4P, `wan` is the 2.5G internal PHY; `lan0``lan3` are 1G switch ports
- `sfp1` (and `sfp2` on standard R4): 10G SFP+ cage(s)
If interface renames look wrong, check `dmesg | grep renamed` and if
you spot any errors, please report as an issue to the Infix tracker
on GitHub.
## Board Variants
### BPI-R4
The base model BPi-R4 ports look like this, the `wan` port is the same physical
switch port as `lan0` on the R4-2g5/R4P, but here it serves as the WAN port in
the factory default configuration.
```
.-.
| | .-----.-----.-----.-----.
| | _______ _______ | | | | | .---.
| | | | | | | | | | | | | .-----.
'-' '-------' '-------' '-----'-----'-----'-----' '---' '-----'
USB1 sfp1 sfp2 wan lan1 lan2 lan3 DC12V PD20V
```
### BPI-R4-2g5 and BPI-R4P
These variants substitute one SFP+ cage for an internal 2.5 Gbps PHY
connected to a standard RJ45 jack. From a kernel perspective they use
the `mt7988a-bananapi-bpi-r4-2g5` device tree.
The BPI-R4P additionally supports an optional PoE input daughterboard on
the 2.5 Gbps RJ45 port. The PoE circuitry is passive with respect to
Linux — no special kernel driver is required for basic operation.
For these board variants, the WAN role moves to the dedicated 2.5G internal PHY,
so all four switch ports become LAN ports (`lan0``lan3`) instead of three:
```
.-.
| | .-----. .-----.-----.-----.-----.
| | _______ | | | | | | | .---.
| | | | | | | | | | | | | .-----.
'-' '-------' '-----' '-----'-----'-----'-----' '---' '-----'
USB1 sfp1 wan lan0 lan1 lan2 lan3 DC12V PD20V
```
### Selecting the Board Variant
U-Boot cannot automatically distinguish the standard R4 from the R4-2g5/R4P at
boot time (the on-board EEPROM is not programmed from factory). Instead, the
variant is read from the persistent U-Boot environment on the `aux` partition,
and you have to set it manually using `fw_setenv` from a UNIX shell:
```bash
# For BPI-R4-2g5 or BPI-R4P (1x SFP+ + 1x 2.5 Gbps RJ45):
sudo fw_setenv BOARD_VARIANT 2g5
# To revert to the standard BPI-R4 (2x SFP+) clear the setting:
sudo fw_setenv BOARD_VARIANT
```
> [!IMPORTANT]
> The change takes effect on the next reboot. No re-flashing is required, but
> you may want to do a factory reset to activate the changes in your system
> `startup-config`: `sudo factory -y` from shell, or the CLI.
`fw_setenv` writes to the `uboot.env` file on the aux partition. U-Boot
reads this at every boot (before loading the kernel) and selects the
matching device tree:
| `BOARD_VARIANT` | Device tree loaded |
|-----------------|-----------------------------------|
| *(unset)* | `mt7988a-bananapi-bpi-r4.dtb` |
| `2g5` | `mt7988a-bananapi-bpi-r4-2g5.dtb` |
## Additional Resources
- [Infix Documentation][1]
- [Official BPI-R4 Page][7]
- [BPI-R4 Forum][8]
- [Frank-W's site][9]
- [Release Downloads][10]
- [Bootloader Builds][11]
## Building Custom Images
```bash
# Build bootloaders for SD and eMMC
make x-bpi-r4-sd-boot
make x-bpi-r4-emmc-boot
# Build main system
make aarch64
# Create SD card image
./utils/mkimage.sh -od bananapi-bpi-r4
# Create eMMC image
./utils/mkimage.sh -odt emmc bananapi-bpi-r4
```
[0]: https://www.kernelkit.org/posts/flashing-sdcard/
[1]: https://www.kernelkit.org/infix/latest/
[2]: https://github.com/kernelkit/infix/releases/download/latest-boot/infix-bpi-r4-sdcard.img
[3]: https://github.com/kernelkit/infix/releases/download/latest-boot/infix-bpi-r4-emmc.img
[4]: https://github.com/kernelkit/infix/releases/download/latest-boot/bpi-r4-emmc-boot-2026.01-latest.tar.gz
[7]: https://docs.banana-pi.org/en/BPI-R4/BananaPi_BPI-R4
[8]: https://forum.banana-pi.org/
[9]: https://wiki.fw-web.de/doku.php?id=en:bpi-r4:start
[10]: https://github.com/kernelkit/infix/releases/tag/latest
[11]: https://github.com/kernelkit/infix/releases/tag/latest-boot
[12]: https://github.com/frank-w/u-boot/releases
[13]: https://github.com/frank-w/u-boot/releases/download/CI-BUILD-2026-01-bpi-2026.01-2026-01-15_2013/bpi-r4_spim-nand_bl2.img
[14]: https://github.com/frank-w/u-boot/releases/download/CI-BUILD-2026-01-bpi-2026.01-2026-01-15_2013/bpi-r4_spim-nand_fip.bin
Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

@@ -0,0 +1,2 @@
# Locally calculated
sha256 d48246c717b505cc11df95171f2fd548b389e1a463f1af4c68d0b69fe0d1009b LICENSE
@@ -0,0 +1,49 @@
define BANANAPI_BPI_R4_LINUX_CONFIG_FIXUPS
$(call KCONFIG_ENABLE_OPT,CONFIG_ARCH_MEDIATEK)
$(call KCONFIG_ENABLE_OPT,CONFIG_MACH_MT7988)
$(call KCONFIG_ENABLE_OPT,CONFIG_PINCTRL_MT7988)
$(call KCONFIG_ENABLE_OPT,CONFIG_SERIAL_8250_MT6577)
$(call KCONFIG_SET_OPT,CONFIG_I2C_GPIO,y)
$(call KCONFIG_SET_OPT,CONFIG_MTK_THERMAL,m)
$(call KCONFIG_SET_OPT,CONFIG_MTK_LVTS_THERMAL,m)
$(call KCONFIG_ENABLE_OPT,CONFIG_MTK_UART)
$(call KCONFIG_ENABLE_OPT,CONFIG_MEDIATEK_WATCHDOG)
$(call KCONFIG_ENABLE_OPT,CONFIG_MEDIATEK_GE_PHY)
$(call KCONFIG_ENABLE_OPT,CONFIG_MEDIATEK_GE_SOC_PHY)
$(call KCONFIG_ENABLE_OPT,CONFIG_NET_VENDOR_MEDIATEK)
$(call KCONFIG_ENABLE_OPT,CONFIG_NET_MEDIATEK_SOC)
$(call KCONFIG_SET_OPT,CONFIG_NET_DSA_MT7530,m)
$(call KCONFIG_SET_OPT,CONFIG_MT7996E,m)
$(call KCONFIG_SET_OPT,CONFIG_PCIE_MEDIATEK_GEN3,m)
$(call KCONFIG_ENABLE_OPT,CONFIG_MTK_SCPSYS)
$(call KCONFIG_ENABLE_OPT,CONFIG_MMC_MTK)
$(call KCONFIG_SET_OPT,CONFIG_I2C_MT65XX,m)
$(call KCONFIG_SET_OPT,CONFIG_USB_XHCI_MTK,m)
$(call KCONFIG_SET_OPT,CONFIG_PHY_MTK_TPHY,m)
$(call KCONFIG_SET_OPT,CONFIG_PHY_MTK_XSPHY,m)
$(call KCONFIG_SET_OPT,CONFIG_PHY_MTK_XFI_TPHY,m)
$(call KCONFIG_SET_OPT,CONFIG_PCS_STANDALONE,y)
$(call KCONFIG_SET_OPT,CONFIG_PCS_MTK_USXGMII,y)
$(call KCONFIG_SET_OPT,CONFIG_PWM_MEDIATEK,m)
$(call KCONFIG_SET_OPT,CONFIG_SENSORS_PWM_FAN,m)
$(call KCONFIG_SET_OPT,CONFIG_NVMEM_MTK_EFUSE,m)
$(call KCONFIG_SET_OPT,CONFIG_MEDIATEK_2P5GE_PHY,m)
$(call KCONFIG_SET_OPT,CONFIG_CRYPTO_DEV_SAFEXCEL,m)
endef
LINUX_DTS_MT7988 = $(LINUX_DIR)/arch/arm64/boot/dts/mediatek
define BANANAPI_BPI_R4_KERNEL_DTBS_INSTALL_TARGET
@$(call MESSAGE,"Installing kernel DTBs and DTBOs for BPI-R4")
$(foreach f, \
mt7988a-bananapi-bpi-r4.dtb \
mt7988a-bananapi-bpi-r4-2g5.dtb \
mt7988a-bananapi-bpi-r4-sd.dtbo \
mt7988a-bananapi-bpi-r4-emmc.dtbo, \
$(INSTALL) -D $(LINUX_DTS_MT7988)/$(f) \
$(TARGET_DIR)/boot/mediatek/$(f)$(sep))
endef
BANANAPI_BPI_R4_POST_INSTALL_TARGET_HOOKS += BANANAPI_BPI_R4_KERNEL_DTBS_INSTALL_TARGET
$(eval $(ix-board))
$(eval $(generic-package))
Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

@@ -0,0 +1,2 @@
dtb-y += infix/bananapi,bpi-r4.dtbo
dtb-y += infix/bananapi,bpi-r4-2g5.dtbo
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/dts-v1/;
/plugin/;
/ {
compatible = "bananapi,bpi-r4-2g5";
};
/*
* On the 2g5 variant, GMAC1 uses the internal 2.5G PHY (eth1 renamed to
* "wan" by udev). The switch's port0, which is labeled "wan" in the base
* DTS, would cause a name collision when the switch driver registers it.
* Rename it to "lan0" here so the kernel names it correctly from the start.
*/
&gsw_port0 {
label = "lan0";
};
/*
* The upstream mt7988a.dtsi sets compatible = "ethernet-phy-ieee802.3-c45"
* on the internal 2.5G PHY node. That gives genphy_c45 (built-in) OF-match
* priority over the PHY-ID-based mtk-2p5ge driver, leaving the PHY powered
* down and unclaimed. Replace it with the standard ethernet-phy-idXXXX.XXXX
* form so of_get_phy_id() registers the PHY as C22 with explicit ID 0x00339c11.
* mtk-2p5ge then matches via PHY_ID_MATCH_VENDOR(0x00339c00) instead of
* genphy_c45 winning via OF-match.
* Note: /delete-property/ is not used because U-Boot fdt apply does not
* implement property deletion in overlays.
*/
&int_2p5g_phy {
compatible = "ethernet-phy-id0033.9c11";
};
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/dts-v1/;
/plugin/;
/ {
compatible = "bananapi,bpi-r4", "mediatek,mt7988a";
};
/*
* The upstream mt7988a-bananapi-bpi-r4.dtsi sets stdout-path = "serial0:..."
* but the aliases node there only has ethernet entries. Linux resolves
* stdout-path by looking in /aliases, so we must add serial0 here.
* Path references in overlay aliases cannot use &label, so use the full path.
*/
&{/} {
aliases {
serial0 = "/soc/serial@11000000";
};
chosen {
infix {
/* Default admin user password: 'admin' */
factory-password-hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A";
usb-ports = <&ssusb1>;
usb-port-names = "USB";
};
};
};
@@ -0,0 +1,81 @@
image cfg.ext4 {
empty = true
temporary = true
size = 128M
ext4 {
label = "cfg"
use-mke2fs = true
features = "uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
# The /var partition will be expanded automatically at first boot
# to use the full size of the SD-card or eMMC media.
image var.ext4 {
empty = true
temporary = true
size = 128M
ext4 {
label = "var"
use-mke2fs = true
features = "uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
image #INFIX_ID##VERSION#-bpi-r4-#TARGET#.img {
hdimage {
partition-table-type = "gpt"
gpt-no-backup = true
}
# BL2 bootloader partition (MediaTek official location)
partition bl2 {
image = "bl2.img"
offset = 1024s # 0x80000 = sector 1024
size = 4M # 0x400000
bootable = true
}
# Factory/calibration data (sectors 9216-13311)
partition factory {
offset = 4608K # 0x480000
size = 2M # 0x200000
}
# FIP partition - BL31 + U-Boot (sectors 13312-17407)
partition fip {
image = "fip.bin"
offset = 13312s
size = 4096s
}
partition aux {
partition-uuid = D4EF35A0-0652-45A1-B3DE-D63339C82035
image = "aux.ext4"
}
partition primary {
partition-type-uuid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4
bootable = true
size = 250M
image = "rootfs.squashfs"
}
partition secondary {
partition-type-uuid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4
bootable = true
size = 250M
image = "rootfs.squashfs"
}
partition cfg {
partition-uuid = 7aa497f0-73b5-47e5-b2ab-8752d8a48105
image = "cfg.ext4"
}
partition var {
partition-uuid = 8046A06A-E45A-4A14-A6AD-6684704A393F
image = "var.ext4"
}
}
@@ -0,0 +1,5 @@
label Infix (aarch64)
kernel /boot/Image
fdtdir /boot
fdtoverlays /boot/mediatek/mt7988a-bananapi-bpi-r4-emmc.dtbo /boot/infix/bananapi,bpi-r4.dtbo /boot/infix/bananapi,bpi-r4-2g5.dtbo
append ${bootargs_root} ${bootargs_log} usbcore.authorized_default=2 -- ${bootargs_user}
@@ -0,0 +1,5 @@
label Infix (aarch64)
kernel /boot/Image
fdtdir /boot
fdtoverlays /boot/mediatek/mt7988a-bananapi-bpi-r4-sd.dtbo /boot/infix/bananapi,bpi-r4.dtbo /boot/infix/bananapi,bpi-r4-2g5.dtbo
append ${bootargs_root} ${bootargs_log} usbcore.authorized_default=2 -- ${bootargs_user}
@@ -0,0 +1,5 @@
label Infix (aarch64)
kernel /boot/Image
fdtdir /boot
fdtoverlays /boot/mediatek/mt7988a-bananapi-bpi-r4-emmc.dtbo /boot/infix/bananapi,bpi-r4.dtbo
append ${bootargs_root} ${bootargs_log} usbcore.authorized_default=2 -- ${bootargs_user}
@@ -0,0 +1,5 @@
label Infix (aarch64)
kernel /boot/Image
fdtdir /boot
fdtoverlays /boot/mediatek/mt7988a-bananapi-bpi-r4-sd.dtbo /boot/infix/bananapi,bpi-r4.dtbo
append ${bootargs_root} ${bootargs_log} usbcore.authorized_default=2 -- ${bootargs_user}
@@ -0,0 +1,404 @@
{
"ieee802-dot1ab-lldp:lldp": {
"infix-lldp:enabled": true
},
"ietf-hardware:hardware": {
"component": [
{
"name": "USB",
"class": "infix-hardware:usb",
"state": {
"admin-state": "unlocked"
}
}
]
},
"ietf-interfaces:interfaces": {
"interface": [
{
"name": "br0",
"type": "infix-if-type:bridge",
"ietf-ip:ipv4": {
"address": [
{
"ip": "192.168.0.1",
"prefix-length": 24
}
]
}
},
{
"name": "lan0",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "lan1",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "lan2",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "lan3",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "lo",
"type": "infix-if-type:loopback",
"ietf-ip:ipv4": {
"address": [
{
"ip": "127.0.0.1",
"prefix-length": 8
}
]
},
"ietf-ip:ipv6": {
"address": [
{
"ip": "::1",
"prefix-length": 128
}
]
}
},
{
"name": "wan",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv4": {
"infix-dhcp-client:dhcp": {
"option": [
{
"id": "ntp-server"
},
{
"id": "broadcast"
},
{
"id": "domain"
},
{
"id": "hostname",
"value": "auto"
},
{
"id": "dns-server"
},
{
"id": "router"
},
{
"id": "netmask"
},
{
"id": "vendor-class",
"value": "Banana Pi BPI-R4"
}
]
}
},
"ietf-ip:ipv6": {
"infix-dhcpv6-client:dhcp": {
"option": [
{
"id": "ntp-server"
},
{
"id": "client-fqdn"
},
{
"id": "domain-search"
},
{
"id": "dns-server"
}
]
}
}
}
]
},
"ietf-keystore:keystore": {
"asymmetric-keys": {
"asymmetric-key": [
{
"name": "genkey",
"public-key-format": "infix-crypto-types:ssh-public-key-format",
"public-key": "",
"private-key-format": "infix-crypto-types:rsa-private-key-format",
"cleartext-private-key": "",
"certificates": {}
}
]
}
},
"ietf-netconf-acm:nacm": {
"enable-nacm": true,
"read-default": "permit",
"write-default": "permit",
"exec-default": "permit",
"groups": {
"group": [
{
"name": "admin",
"user-name": [
"admin"
]
},
{
"name": "operator",
"user-name": []
},
{
"name": "guest",
"user-name": []
}
]
},
"rule-list": [
{
"name": "admin-acl",
"group": [
"admin"
],
"rule": [
{
"name": "permit-all",
"module-name": "*",
"access-operations": "*",
"action": "permit",
"comment": "Allow 'admin' group complete access to all operations and data."
}
]
},
{
"name": "operator-acl",
"group": [
"operator"
],
"rule": [
{
"name": "permit-system-rpcs",
"module-name": "ietf-system",
"rpc-name": "*",
"access-operations": "exec",
"action": "permit",
"comment": "Operators can reboot, shutdown, and set system time."
}
]
},
{
"name": "guest-acl",
"group": [
"guest"
],
"rule": [
{
"name": "deny-all-write+exec",
"module-name": "*",
"access-operations": "create update delete exec",
"action": "deny",
"comment": "Guests cannot change anything or exec rpcs."
}
]
},
{
"name": "default-deny-all",
"group": [
"*"
],
"rule": [
{
"name": "deny-password-access",
"path": "/ietf-system:system/authentication/user/password",
"access-operations": "*",
"action": "deny",
"comment": "No user except admins can access password hashes."
},
{
"name": "deny-keystore-access",
"module-name": "ietf-keystore",
"access-operations": "*",
"action": "deny",
"comment": "No user except admins can access cryptographic keys."
},
{
"name": "deny-truststore-access",
"module-name": "ietf-truststore",
"access-operations": "*",
"action": "deny",
"comment": "No user except admins can access trust store."
}
]
}
]
},
"ietf-netconf-server:netconf-server": {
"listen": {
"endpoints": {
"endpoint": [
{
"name": "default-ssh",
"ssh": {
"tcp-server-parameters": {
"local-bind": [
{
"local-address": "::"
}
]
},
"ssh-server-parameters": {
"server-identity": {
"host-key": [
{
"name": "default-key",
"public-key": {
"central-keystore-reference": "genkey"
}
}
]
}
}
}
}
]
}
}
},
"ietf-system:system": {
"hostname": "bpi-%m",
"ntp": {
"server": [
{
"name": "default",
"udp": {
"address": "pool.ntp.org"
}
}
]
},
"authentication": {
"user": [
{
"name": "admin",
"password": "$factory$",
"infix-system:shell": "bash"
}
]
},
"infix-system:motd-banner": "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCBPUyDigJQgSW1tdXRhYmxlLkZyaWVuZGx5LlNlY3VyZQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQub3JnCictJy0tLSctJwo="
},
"infix-dhcp-server:dhcp-server": {
"option": [
{
"id": "ntp-server",
"address": "auto"
},
{
"id": "dns-server",
"address": "auto"
},
{
"id": "router",
"address": "auto"
}
],
"subnet": [
{
"subnet": "192.168.0.0/24",
"pool": {
"start-address": "192.168.0.100",
"end-address": "192.168.0.250"
}
}
]
},
"infix-firewall:firewall": {
"default": "wan",
"zone": [
{
"name": "lan",
"action": "accept",
"interface": [
"br0"
]
},
{
"name": "wan",
"action": "drop",
"interface": [
"wan"
],
"service": [
"dhcpv6-client"
]
}
],
"policy": [
{
"name": "lan-to-wan",
"action": "accept",
"ingress": [
"lan"
],
"egress": [
"wan"
],
"masquerade": true
}
]
},
"infix-meta:meta": {
"version": "1.7"
},
"infix-services:mdns": {
"enabled": true
},
"infix-services:ssh": {
"enabled": true,
"hostkey": [
"genkey"
],
"listen": [
{
"name": "ipv4",
"address": "0.0.0.0",
"port": 22
},
{
"name": "ipv6",
"address": "::",
"port": 22
}
]
},
"infix-services:web": {
"enabled": true,
"console": {
"enabled": true
},
"netbrowse": {
"enabled": true
},
"restconf": {
"enabled": true
}
}
}
@@ -0,0 +1,5 @@
# The mtk-2p5ge PHY driver uses MDIO PHY ID matching, not OF compatible
# matching. udev auto-loading is based on MODALIAS, which for DT-described
# devices is "of:N...C<compatible>" — a format that never matches the driver's
# "mdio:..." module alias. Match on OF_COMPATIBLE_0 explicitly instead.
ACTION=="add", SUBSYSTEM=="mdio_bus", ENV{OF_COMPATIBLE_0}=="ethernet-phy-id0033.9c11", RUN+="/sbin/modprobe -b mtk-2p5ge"
@@ -0,0 +1,2 @@
ACTION=="add", SUBSYSTEM=="net", DEVPATH=="/devices/platform/soc/15100000.ethernet/net/eth1", NAME="wan"
ACTION=="add", SUBSYSTEM=="net", DEVPATH=="/devices/platform/soc/15100000.ethernet/net/eth2", NAME="sfp1"
@@ -0,0 +1,396 @@
{
"ieee802-dot1ab-lldp:lldp": {
"infix-lldp:enabled": true
},
"ietf-hardware:hardware": {
"component": [
{
"name": "USB",
"class": "infix-hardware:usb",
"state": {
"admin-state": "unlocked"
}
}
]
},
"ietf-interfaces:interfaces": {
"interface": [
{
"name": "br0",
"type": "infix-if-type:bridge",
"ietf-ip:ipv4": {
"address": [
{
"ip": "192.168.0.1",
"prefix-length": 24
}
]
}
},
{
"name": "lan1",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "lan2",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "lan3",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "lo",
"type": "infix-if-type:loopback",
"ietf-ip:ipv4": {
"address": [
{
"ip": "127.0.0.1",
"prefix-length": 8
}
]
},
"ietf-ip:ipv6": {
"address": [
{
"ip": "::1",
"prefix-length": 128
}
]
}
},
{
"name": "wan",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv4": {
"infix-dhcp-client:dhcp": {
"option": [
{
"id": "ntp-server"
},
{
"id": "broadcast"
},
{
"id": "domain"
},
{
"id": "hostname",
"value": "auto"
},
{
"id": "dns-server"
},
{
"id": "router"
},
{
"id": "netmask"
},
{
"id": "vendor-class",
"value": "Banana Pi BPI-R4"
}
]
}
},
"ietf-ip:ipv6": {
"infix-dhcpv6-client:dhcp": {
"option": [
{
"id": "ntp-server"
},
{
"id": "client-fqdn"
},
{
"id": "domain-search"
},
{
"id": "dns-server"
}
]
}
}
}
]
},
"ietf-keystore:keystore": {
"asymmetric-keys": {
"asymmetric-key": [
{
"name": "genkey",
"public-key-format": "infix-crypto-types:ssh-public-key-format",
"public-key": "",
"private-key-format": "infix-crypto-types:rsa-private-key-format",
"cleartext-private-key": "",
"certificates": {}
}
]
}
},
"ietf-netconf-acm:nacm": {
"enable-nacm": true,
"read-default": "permit",
"write-default": "permit",
"exec-default": "permit",
"groups": {
"group": [
{
"name": "admin",
"user-name": [
"admin"
]
},
{
"name": "operator",
"user-name": []
},
{
"name": "guest",
"user-name": []
}
]
},
"rule-list": [
{
"name": "admin-acl",
"group": [
"admin"
],
"rule": [
{
"name": "permit-all",
"module-name": "*",
"access-operations": "*",
"action": "permit",
"comment": "Allow 'admin' group complete access to all operations and data."
}
]
},
{
"name": "operator-acl",
"group": [
"operator"
],
"rule": [
{
"name": "permit-system-rpcs",
"module-name": "ietf-system",
"rpc-name": "*",
"access-operations": "exec",
"action": "permit",
"comment": "Operators can reboot, shutdown, and set system time."
}
]
},
{
"name": "guest-acl",
"group": [
"guest"
],
"rule": [
{
"name": "deny-all-write+exec",
"module-name": "*",
"access-operations": "create update delete exec",
"action": "deny",
"comment": "Guests cannot change anything or exec rpcs."
}
]
},
{
"name": "default-deny-all",
"group": [
"*"
],
"rule": [
{
"name": "deny-password-access",
"path": "/ietf-system:system/authentication/user/password",
"access-operations": "*",
"action": "deny",
"comment": "No user except admins can access password hashes."
},
{
"name": "deny-keystore-access",
"module-name": "ietf-keystore",
"access-operations": "*",
"action": "deny",
"comment": "No user except admins can access cryptographic keys."
},
{
"name": "deny-truststore-access",
"module-name": "ietf-truststore",
"access-operations": "*",
"action": "deny",
"comment": "No user except admins can access trust store."
}
]
}
]
},
"ietf-netconf-server:netconf-server": {
"listen": {
"endpoints": {
"endpoint": [
{
"name": "default-ssh",
"ssh": {
"tcp-server-parameters": {
"local-bind": [
{
"local-address": "::"
}
]
},
"ssh-server-parameters": {
"server-identity": {
"host-key": [
{
"name": "default-key",
"public-key": {
"central-keystore-reference": "genkey"
}
}
]
}
}
}
}
]
}
}
},
"ietf-system:system": {
"hostname": "bpi-%m",
"ntp": {
"server": [
{
"name": "default",
"udp": {
"address": "pool.ntp.org"
}
}
]
},
"authentication": {
"user": [
{
"name": "admin",
"password": "$factory$",
"infix-system:shell": "bash"
}
]
},
"infix-system:motd-banner": "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCBPUyDigJQgSW1tdXRhYmxlLkZyaWVuZGx5LlNlY3VyZQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQub3JnCictJy0tLSctJwo="
},
"infix-dhcp-server:dhcp-server": {
"option": [
{
"id": "ntp-server",
"address": "auto"
},
{
"id": "dns-server",
"address": "auto"
},
{
"id": "router",
"address": "auto"
}
],
"subnet": [
{
"subnet": "192.168.0.0/24",
"pool": {
"start-address": "192.168.0.100",
"end-address": "192.168.0.250"
}
}
]
},
"infix-firewall:firewall": {
"default": "wan",
"zone": [
{
"name": "lan",
"action": "accept",
"interface": [
"br0"
]
},
{
"name": "wan",
"action": "drop",
"interface": [
"wan"
],
"service": [
"dhcpv6-client"
]
}
],
"policy": [
{
"name": "lan-to-wan",
"action": "accept",
"ingress": [
"lan"
],
"egress": [
"wan"
],
"masquerade": true
}
]
},
"infix-meta:meta": {
"version": "1.7"
},
"infix-services:mdns": {
"enabled": true
},
"infix-services:ssh": {
"enabled": true,
"hostkey": [
"genkey"
],
"listen": [
{
"name": "ipv4",
"address": "0.0.0.0",
"port": 22
},
{
"name": "ipv6",
"address": "::",
"port": 22
}
]
},
"infix-services:web": {
"enabled": true,
"console": {
"enabled": true
},
"netbrowse": {
"enabled": true
},
"restconf": {
"enabled": true
}
}
}
@@ -0,0 +1,2 @@
ACTION=="add", SUBSYSTEM=="net", DEVPATH=="/devices/platform/soc/15100000.ethernet/net/eth1", NAME="sfp2"
ACTION=="add", SUBSYSTEM=="net", DEVPATH=="/devices/platform/soc/15100000.ethernet/net/eth2", NAME="sfp1"
@@ -0,0 +1 @@
CONFIG_DEVICE_TREE_INCLUDES="infix-env.dtsi infix-key.dtsi mt7988-emmc-env.dtsi"
@@ -0,0 +1,40 @@
CONFIG_AUTOBOOT=y
CONFIG_BOOTDELAY=2
# CONFIG_MMC_PCI is not set
CONFIG_ENV_IS_NOWHERE=y
# CONFIG_ENV_IS_IN_MMC is not set
CONFIG_MULTI_DTB_FIT=y
CONFIG_OF_LIST="mt7988a-bananapi-bpi-r4 mt7988a-bananapi-bpi-r4-2g5"
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_MTK=y
CONFIG_USB_MTU3=y
CONFIG_PHY=y
CONFIG_PHY_MTK_TPHY=y
CONFIG_MTK_SPIM=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
CONFIG_SPI_FLASH=y
CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH_MTD=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SPI_FLASH_GIGADEVICE=y
CONFIG_MTD=y
CONFIG_DM_MTD=y
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_SPI_NAND=y
CONFIG_MTK_SPIM=y
CONFIG_MTK_SNOR=y
CONFIG_BUTTON=y
CONFIG_BUTTON_CMD=y
CONFIG_BUTTON_GPIO=y
CONFIG_CMD_SF=y
CONFIG_CMD_USB=y
CONFIG_CMD_MTD=y
CONFIG_CMD_MTDPARTS=y
CONFIG_CMD_DM=y
@@ -0,0 +1,7 @@
#include <mt7988-env.dtsi>
&env {
fdtfile = "mediatek/mt7988a-bananapi-bpi-r4.dtb";
board = "bananapi,bpi-r4-emmc";
ixvariant = "if test \"${BOARD_VARIANT}\" = \"2g5\"; then setenv fdtfile mediatek/mt7988a-bananapi-bpi-r4-2g5.dtb; setenv board bananapi,bpi-r4-2g5-emmc; fi";
};
@@ -0,0 +1,27 @@
/ {
config {
env: environment {
bootcmd = "run ixboot";
boot_targets = "mmc0";
ethprime = "eth0";
fdt_addr_r = "0x43f00000";
kernel_addr_r = "0x44000000";
fdtoverlay_addr_r = "0x47f00000";
scriptaddr = "0x48000000";
ramdisk_addr_r = "0x4A000000";
/*
* Apply BOARD_VARIANT from aux uboot.env.
* Infix writes BOARD_VARIANT=2g5 via fw_setenv on
* BPI-R4-2g5 / BPI-R4P boards to select the correct
* device tree. Unset = standard R4 (2x SFP+).
*/
ixvariant = "if test \"${BOARD_VARIANT}\" = \"2g5\"; then setenv fdtfile mediatek/mt7988a-bananapi-bpi-r4-2g5.dtb; fi";
/* This is a development platform, keep
* developer mode statically enabled.
*/
ixbtn-devmode = "setenv dev_mode yes; echo Enabled";
};
};
};
@@ -0,0 +1,7 @@
#include <mt7988-env.dtsi>
&env {
fdtfile = "mediatek/mt7988a-bananapi-bpi-r4.dtb";
board = "bananapi,bpi-r4-sdmmc";
ixvariant = "if test \"${BOARD_VARIANT}\" = \"2g5\"; then setenv fdtfile mediatek/mt7988a-bananapi-bpi-r4-2g5.dtb; setenv board bananapi,bpi-r4-2g5-sdmmc; fi";
};
@@ -0,0 +1,2 @@
CONFIG_DEVICE_TREE_INCLUDES="infix-env.dtsi infix-key.dtsi mt7988-sd-env.dtsi"
CONFIG_OF_LIST="mt7988a-bananapi-bpi-r4-sd"
+7
View File
@@ -0,0 +1,7 @@
config BR2_PACKAGE_BANANAPI_BPI_R64
bool "Banana Pi R64"
depends on BR2_aarch64
select BR2_PACKAGE_FEATURE_WIFI
select SDCARD_AUX
help
Build Banana PI R64 support
+13
View File
@@ -0,0 +1,13 @@
Copyright (c) 2026 The KernelKit Authors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+148
View File
@@ -0,0 +1,148 @@
# Banana Pi BPI-R64
## Overview
<img align="right" src="banana_pi_bpi-r64_interface.jpg" alt="Board Overview" width=400 padding=10>
The Banana Pi BPI-R64 is a networking board based on the MediaTek MT7622
(dual Cortex-A53, AArch64) SoC.
### Hardware Features
- MediaTek MT7622 ARM Cortex-A53 dual-core processor @ 1.35 GHz
- 1 GB DDR3L RAM
- 8 GB eMMC storage
- microSD card slot
- MT7531 Gigabit Ethernet switch (4x LAN + 1x WAN)
- MT7622 WMAC built-in 2.4 GHz 802.11ac WiFi
- USB 3.0 port
- 2x Mini PCIe slots
### Default Network Configuration
Infix comes preconfigured with:
- **LAN ports** (lan0-lan3): Bridged for internal networking
- **WAN port**: DHCP client enabled for internet connectivity
- **WiFi** (wifi0-ap): Bridged to LAN (MT7622 WMAC, 2.4 GHz; or MT7615 PCIe card if fitted)
## Boot Switch Reference
<img align="right" src="bpi-r64-sw1.png" alt="SW1 Boot Switch" width=90 padding=10>
The BPI-R64 has a 2-position DIP switch (SW1) for selecting the boot device.
The MT7622 Boot ROM always tries SD first if a card is present, so you can
leave SW1 in the OFF (eMMC) position and simply insert or remove an SD card
to control boot device selection.
| SW1 | Boot device |
|-----|-------------|
| OFF | eMMC |
| ON | SD card |
## Getting Started
### Quick Start with SD Card
1. **Flash the image to an SD card** (the filename includes the version, e.g.
`infix-25.01-bpi-r64-sdcard.img`):
<img align="right" src="debug-uart.png" alt="Debug UART" width=100 padding=10>
```sh
dd if=infix-*-bpi-r64-sdcard.img of=/dev/sdX bs=4M status=progress
```
2. **Insert SD card and power on**
3. **Connect console:** 115200 8N1 — use the dedicated Debug UART header
just below the 40-pin GPIO header; pins are labeled GND, RX, TX on the board
4. **Default login:** `admin` / `admin`
## Installing to eMMC
Unlike the BPI-R3 (where SD and eMMC share a bus, requiring a NAND intermediate
step), the BPI-R64 has separate controllers for SD (mmc1/MSDC1) and eMMC
(mmc0/MSDC0). You can write directly to eMMC while booted from SD.
### eMMC Boot ROM Behaviour
> [!IMPORTANT]
> The MT7622 Boot ROM reads BL2 from the eMMC BOOT0 hardware partition (offset
> 0), not from the User Data Area where the main disk image lives. The
> installation procedure below writes BL2 to BOOT0 separately to handle this.
### Procedure
Boot from SD and write the eMMC image from U-Boot using a FAT32-formatted USB
drive.
#### Step 1: Boot from SD card
1. Insert SD card with Infix
2. Power on and break into U-Boot (press Ctrl-C during boot)
#### Step 2: Write the eMMC image from U-Boot
Place `infix-bpi-r64-emmc.img` and `bl2.img` on a FAT32-formatted USB drive,
then from the U-Boot prompt:
```
usb start
fatload usb 0:1 0x44000000 infix-bpi-r64-emmc.img
setexpr blocks ${filesize} / 0x200
mmc dev 0
mmc write 0x44000000 0x0 ${blocks}
```
#### Step 3: Write BL2 to eMMC BOOT0
```
fatload usb 0:1 0x44000000 bl2.img
mmc partconf 0 1 1 1
setexpr blkcnt ${filesize} + 0x1ff
setexpr blkcnt ${blkcnt} / 0x200
mmc write 0x44000000 0x0 ${blkcnt}
mmc partconf 0 1 1 0
```
#### Step 4: Boot from eMMC
1. Power off the board
2. Remove SD card and USB drive
3. Power on
## Platform Notes
### WiFi
The MT7622 SoC includes a built-in WMAC that provides 2.4 GHz 802.11b/g/n/ac
(2×2) — there is no 5 GHz capability from the onboard radio.
For dual-band operation, a PCIe card can be fitted in one of the two Mini PCIe
slots. The [Banana Pi BPI-MT7615][bpi-mt7615] is a purpose-built dual-band
(2.4 + 5 GHz, 802.11ac 4×4) module designed for BPI router boards and is a
natural fit. With it installed, Infix will use it in preference to the onboard
WMAC for the `wifi0-ap` interface.
[bpi-mt7615]: https://docs.banana-pi.org/en/BPI-MT7615/BananaPi_MT7615
### mmc0 = eMMC, mmc1 = SD
On MT7622, MSDC0 (mmc0) is the 8-bit eMMC controller and MSDC1 (mmc1) is the
4-bit SD card controller — the reverse of many other platforms.
## Building
```sh
# Bootloader only (SD)
make O=x-boot-bpir64-sd bpi_r64_sd_boot_defconfig && make O=x-boot-bpir64-sd
# Bootloader only (eMMC)
make O=x-boot-bpir64-emmc bpi_r64_emmc_boot_defconfig && make O=x-boot-bpir64-emmc
# Compose SD image (pass the Infix rootfs output directory)
utils/mkimage.sh -b x-boot-bpir64-sd -r x-aarch64/images bananapi-bpi-r64
# Compose eMMC image
utils/mkimage.sh -b x-boot-bpir64-emmc -r x-aarch64/images -t emmc bananapi-bpi-r64
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

@@ -0,0 +1,2 @@
# Locally calculated
sha256 d48246c717b505cc11df95171f2fd548b389e1a463f1af4c68d0b69fe0d1009b LICENSE
@@ -0,0 +1,35 @@
define BANANAPI_BPI_R64_LINUX_CONFIG_FIXUPS
$(call KCONFIG_ENABLE_OPT,CONFIG_ARCH_MEDIATEK)
$(call KCONFIG_ENABLE_OPT,CONFIG_MACH_MT7622)
$(call KCONFIG_ENABLE_OPT,CONFIG_PINCTRL_MT7622)
$(call KCONFIG_ENABLE_OPT,CONFIG_SERIAL_8250_MT6577)
$(call KCONFIG_ENABLE_OPT,CONFIG_MTK_UART)
$(call KCONFIG_ENABLE_OPT,CONFIG_MEDIATEK_WATCHDOG)
# Ethernet subsystem clock controller — required for the eth MAC,
# MT7531 DSA switch, and HSDMA to get their clocks from &ethsys.
# Without this, eth probe fails and the switch is never detected.
$(call KCONFIG_ENABLE_OPT,CONFIG_COMMON_CLK_MT7622_ETHSYS)
# HIF subsystem clock controller — required for PCIe and USB.
$(call KCONFIG_ENABLE_OPT,CONFIG_COMMON_CLK_MT7622_HIFSYS)
$(call KCONFIG_ENABLE_OPT,CONFIG_MEDIATEK_GE_PHY)
$(call KCONFIG_ENABLE_OPT,CONFIG_REALTEK_PHY)
$(call KCONFIG_ENABLE_OPT,CONFIG_NET_VENDOR_MEDIATEK)
$(call KCONFIG_ENABLE_OPT,CONFIG_NET_MEDIATEK_SOC)
$(call KCONFIG_SET_OPT,CONFIG_NET_DSA_MT7530,m)
$(call KCONFIG_SET_OPT,CONFIG_MT7603E,m)
$(call KCONFIG_SET_OPT,CONFIG_PCIE_MEDIATEK,m)
$(call KCONFIG_ENABLE_OPT,CONFIG_MMC_MTK)
$(call KCONFIG_SET_OPT,CONFIG_USB_XHCI_MTK,m)
$(call KCONFIG_SET_OPT,CONFIG_PHY_MTK_TPHY,m)
$(call KCONFIG_SET_OPT,CONFIG_MTK_THERMAL,m)
$(call KCONFIG_SET_OPT,CONFIG_MTK_SOC_THERMAL,m)
$(call KCONFIG_SET_OPT,CONFIG_I2C_MT65XX,m)
$(call KCONFIG_SET_OPT,CONFIG_PWM_MEDIATEK,m)
$(call KCONFIG_SET_OPT,CONFIG_REGULATOR_MT6380,m)
$(call KCONFIG_SET_OPT,CONFIG_NVMEM_MTK_EFUSE,m)
$(call KCONFIG_SET_OPT,CONFIG_CRYPTO_DEV_SAFEXCEL,m)
$(call KCONFIG_ENABLE_OPT,CONFIG_RTC_DRV_MT7622)
endef
$(eval $(ix-board))
$(eval $(generic-package))
Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

@@ -0,0 +1 @@
dtb-y += mediatek/mt7622-bananapi-bpi-r64.dtb
@@ -0,0 +1,3 @@
#include <arm64/mediatek/mt7622-bananapi-bpi-r64.dts>
#include "mt7622-bananapi-bpi-r64.dtsi"
@@ -0,0 +1,10 @@
/ {
chosen {
infix {
/* Default admin user password: 'admin' */
factory-password-hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A";
usb-ports = <&ssusb>;
usb-port-names = "USB";
};
};
};
@@ -0,0 +1,89 @@
image cfg.ext4 {
empty = true
temporary = true
size = 128M
ext4 {
label = "cfg"
use-mke2fs = true
features = "uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
# The /var partition will be expanded automatically at first boot
# to use the full size of the SD-card or eMMC media.
image var.ext4 {
empty = true
temporary = true
size = 128M
ext4 {
label = "var"
use-mke2fs = true
features = "uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
image #INFIX_ID##VERSION#-bpi-r64-#TARGET#.img {
hdimage {
partition-table-type = "hybrid"
# MT7622 TF-A partition driver detects GPT by checking MBR[0]
# for the 0xEE protective entry. Place it first so that BL2
# (with partition-type = 0x83) lands at MBR slot 1.
gpt-protective-first = true
}
# BL2 bootloader at sector 1024 (0x80000). The MT7622 Boot ROM scans
# the hybrid MBR for a bootable entry and loads BL2 from its offset.
# partition-type makes it visible in the MBR at slot 1 (slot 0 holds
# the 0xEE protective entry required by the TF-A partition driver).
partition bl2 {
partition-type = 0x83
image = "bl2.img"
offset = 1024s
size = 1024s
bootable = true
}
# Factory/calibration data at fixed offset
partition factory {
offset = 4608K
size = 2M
}
# FIP partition - BL31 + U-Boot
partition fip {
image = "fip.bin"
offset = 13312s
size = 4096s
}
partition aux {
partition-uuid = D4EF35A0-0652-45A1-B3DE-D63339C82035
image = "aux.ext4"
}
partition primary {
partition-type-uuid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4
bootable = true
size = 250M
image = "rootfs.squashfs"
}
partition secondary {
partition-type-uuid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4
bootable = true
size = 250M
image = "rootfs.squashfs"
}
partition cfg {
partition-uuid = 7aa497f0-73b5-47e5-b2ab-8752d8a48105
image = "cfg.ext4"
}
partition var {
partition-uuid = 8046A06A-E45A-4A14-A6AD-6684704A393F
image = "var.ext4"
}
}
@@ -0,0 +1,438 @@
{
"ieee802-dot1ab-lldp:lldp": {
"infix-lldp:enabled": true
},
"ietf-hardware:hardware": {
"component": [
{
"name": "USB",
"class": "infix-hardware:usb",
"state": {
"admin-state": "unlocked"
}
},
{
"name": "radio0",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "2.4GHz",
"channel": "auto"
}
}
]
},
"ietf-interfaces:interfaces": {
"interface": [
{
"name": "br0",
"type": "infix-if-type:bridge",
"ietf-ip:ipv4": {
"address": [
{
"ip": "192.168.0.1",
"prefix-length": 24
}
]
}
},
{
"name": "lan0",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "lan1",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "lan2",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "lan3",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
},
{
"name": "lo",
"type": "infix-if-type:loopback",
"ietf-ip:ipv4": {
"address": [
{
"ip": "127.0.0.1",
"prefix-length": 8
}
]
},
"ietf-ip:ipv6": {
"address": [
{
"ip": "::1",
"prefix-length": 128
}
]
}
},
{
"name": "wan",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv4": {
"infix-dhcp-client:dhcp": {
"option": [
{
"id": "ntp-server"
},
{
"id": "broadcast"
},
{
"id": "domain"
},
{
"id": "hostname",
"value": "auto"
},
{
"id": "dns-server"
},
{
"id": "router"
},
{
"id": "netmask"
},
{
"id": "vendor-class",
"value": "Banana Pi BPI-R64"
}
]
}
},
"ietf-ip:ipv6": {
"infix-dhcpv6-client:dhcp": {
"option": [
{
"id": "ntp-server"
},
{
"id": "client-fqdn"
},
{
"id": "domain-search"
},
{
"id": "dns-server"
}
]
}
}
},
{
"name": "wifi0-ap",
"type": "infix-if-type:wifi",
"infix-interfaces:wifi": {
"radio": "radio0",
"access-point": {
"ssid": "Infix",
"security": {
"secret": "wifi"
}
}
},
"infix-interfaces:bridge-port": {
"bridge": "br0"
}
}
]
},
"ietf-keystore:keystore": {
"asymmetric-keys": {
"asymmetric-key": [
{
"name": "genkey",
"public-key-format": "infix-crypto-types:ssh-public-key-format",
"public-key": "",
"private-key-format": "infix-crypto-types:rsa-private-key-format",
"cleartext-private-key": "",
"certificates": {}
}
]
},
"symmetric-keys": {
"symmetric-key": [
{
"name": "wifi",
"cleartext-symmetric-key": "aW5maXhpbmZpeA==",
"key-format": "infix-crypto-types:passphrase-key-format"
}
]
}
},
"ietf-netconf-acm:nacm": {
"enable-nacm": true,
"read-default": "permit",
"write-default": "permit",
"exec-default": "permit",
"groups": {
"group": [
{
"name": "admin",
"user-name": [
"admin"
]
},
{
"name": "operator",
"user-name": []
},
{
"name": "guest",
"user-name": []
}
]
},
"rule-list": [
{
"name": "admin-acl",
"group": [
"admin"
],
"rule": [
{
"name": "permit-all",
"module-name": "*",
"access-operations": "*",
"action": "permit",
"comment": "Allow 'admin' group complete access to all operations and data."
}
]
},
{
"name": "operator-acl",
"group": [
"operator"
],
"rule": [
{
"name": "permit-system-rpcs",
"module-name": "ietf-system",
"rpc-name": "*",
"access-operations": "exec",
"action": "permit",
"comment": "Operators can reboot, shutdown, and set system time."
}
]
},
{
"name": "guest-acl",
"group": [
"guest"
],
"rule": [
{
"name": "deny-all-write+exec",
"module-name": "*",
"access-operations": "create update delete exec",
"action": "deny",
"comment": "Guests cannot change anything or exec rpcs."
}
]
},
{
"name": "default-deny-all",
"group": [
"*"
],
"rule": [
{
"name": "deny-password-access",
"path": "/ietf-system:system/authentication/user/password",
"access-operations": "*",
"action": "deny",
"comment": "No user except admins can access password hashes."
},
{
"name": "deny-keystore-access",
"module-name": "ietf-keystore",
"access-operations": "*",
"action": "deny",
"comment": "No user except admins can access cryptographic keys."
},
{
"name": "deny-truststore-access",
"module-name": "ietf-truststore",
"access-operations": "*",
"action": "deny",
"comment": "No user except admins can access trust store."
}
]
}
]
},
"ietf-netconf-server:netconf-server": {
"listen": {
"endpoints": {
"endpoint": [
{
"name": "default-ssh",
"ssh": {
"tcp-server-parameters": {
"local-bind": [
{
"local-address": "::"
}
]
},
"ssh-server-parameters": {
"server-identity": {
"host-key": [
{
"name": "default-key",
"public-key": {
"central-keystore-reference": "genkey"
}
}
]
}
}
}
}
]
}
}
},
"ietf-system:system": {
"hostname": "bpi-%m",
"ntp": {
"server": [
{
"name": "default",
"udp": {
"address": "pool.ntp.org"
}
}
]
},
"authentication": {
"user": [
{
"name": "admin",
"password": "$factory$",
"infix-system:shell": "bash"
}
]
},
"infix-system:motd-banner": "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCBPUyDigJQgSW1tdXRhYmxlLkZyaWVuZGx5LlNlY3VyZQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQub3JnCictJy0tLSctJwo="
},
"infix-dhcp-server:dhcp-server": {
"option": [
{
"id": "ntp-server",
"address": "auto"
},
{
"id": "dns-server",
"address": "auto"
},
{
"id": "router",
"address": "auto"
}
],
"subnet": [
{
"subnet": "192.168.0.0/24",
"pool": {
"start-address": "192.168.0.100",
"end-address": "192.168.0.250"
}
}
]
},
"infix-firewall:firewall": {
"default": "wan",
"zone": [
{
"name": "lan",
"action": "accept",
"interface": [
"br0"
]
},
{
"name": "wan",
"action": "drop",
"interface": [
"wan"
],
"service": [
"dhcpv6-client"
]
}
],
"policy": [
{
"name": "lan-to-wan",
"action": "accept",
"ingress": [
"lan"
],
"egress": [
"wan"
],
"masquerade": true
}
]
},
"infix-meta:meta": {
"version": "1.7"
},
"infix-services:mdns": {
"enabled": true
},
"infix-services:ssh": {
"enabled": true,
"hostkey": [
"genkey"
],
"listen": [
{
"name": "ipv4",
"address": "0.0.0.0",
"port": 22
},
{
"name": "ipv6",
"address": "::",
"port": 22
}
]
},
"infix-services:web": {
"enabled": true,
"console": {
"enabled": true
},
"netbrowse": {
"enabled": true
},
"restconf": {
"enabled": true
}
}
}
@@ -0,0 +1,14 @@
# Rename MT7531 external switch ports by DT node path.
# The DTS already contains this but it has been observed in the wild
# that we may end up with names like lan118 rather than by DTS label,
# so this set of rules, that run after most other rules, match on the
# OF_FULLNAME which is a stable reference.
#
# MT7622 / BPI-R64 switch topology (switch@1f, ports):
# port@0 = wan, port@1..4 = lan0..lan3, port@5,6 = cpu
ACTION=="add", SUBSYSTEM=="net", ENV{OF_FULLNAME}=="*/switch@1f/ports/port@0", NAME="wan"
ACTION=="add", SUBSYSTEM=="net", ENV{OF_FULLNAME}=="*/switch@1f/ports/port@1", NAME="lan0"
ACTION=="add", SUBSYSTEM=="net", ENV{OF_FULLNAME}=="*/switch@1f/ports/port@2", NAME="lan1"
ACTION=="add", SUBSYSTEM=="net", ENV{OF_FULLNAME}=="*/switch@1f/ports/port@3", NAME="lan2"
ACTION=="add", SUBSYSTEM=="net", ENV{OF_FULLNAME}=="*/switch@1f/ports/port@4", NAME="lan3"
@@ -0,0 +1,3 @@
CONFIG_DEVICE_TREE_INCLUDES="infix-env.dtsi infix-key.dtsi mt7622-emmc-env.dtsi"
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_CMD_MMC_PARTCONF=y
@@ -0,0 +1,19 @@
CONFIG_AUTOBOOT=y
CONFIG_BOOTDELAY=2
# CONFIG_MMC_PCI is not set
CONFIG_ENV_IS_NOWHERE=y
# CONFIG_ENV_IS_IN_MMC is not set
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_MTK=y
CONFIG_PHY=y
CONFIG_PHY_MTK_TPHY=y
CONFIG_DM_MDIO=y
CONFIG_DM_ETH_PHY=y
CONFIG_PHY_ETHERNET_ID=y
CONFIG_CMD_MDIO=y
CONFIG_CMD_USB=y
CONFIG_CMD_DM=y
@@ -0,0 +1,5 @@
#include <mt7622-env.dtsi>
&env {
fdtfile = "mediatek/mt7622-bananapi-bpi-r64.dtb";
};
@@ -0,0 +1,18 @@
/ {
config {
env: environment {
bootcmd = "run ixboot";
boot_targets = "mmc0";
ethprime = "eth0";
fdt_addr_r = "0x43f00000";
kernel_addr_r = "0x44000000";
scriptaddr = "0x48000000";
ramdisk_addr_r = "0x4A000000";
/* This is a development platform, keep
* developer mode statically enabled.
*/
ixbtn-devmode = "setenv dev_mode yes; echo Enabled";
};
};
};
@@ -0,0 +1,6 @@
#include <mt7622-env.dtsi>
&env {
boot_targets = "mmc1"; /* SD = mmc1 on MT7622 */
fdtfile = "mediatek/mt7622-bananapi-bpi-r64.dtb";
};
@@ -0,0 +1,3 @@
CONFIG_DEVICE_TREE_INCLUDES="infix-env.dtsi infix-key.dtsi mt7622-sd-env.dtsi"
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_CMD_MMC_PARTCONF=y
@@ -0,0 +1,2 @@
# Locally calculated
sha256 d2f96418893ac66156d0e691cda189b0d85ae1d814065d1d9aa1845383100f46 LICENSE
@@ -0,0 +1,2 @@
# Locally calculated
sha256 dbe4eae8debbba8135297e15f24aeefef0b4c03781f3f9328db4398d58a728b3 LICENSE
@@ -71,7 +71,8 @@
"id": "domain"
},
{
"id": "hostname"
"id": "hostname",
"value": "auto"
},
{
"id": "dns-server"
@@ -1,3 +0,0 @@
#!/bin/sh
udevadm control --reload-rules
udevadm trigger --subsystem-match=net --action=add
+1
View File
@@ -502,6 +502,7 @@ CONFIG_USB_OTG=y
CONFIG_USB_XHCI_HCD=m
CONFIG_USB_XHCI_MVEBU=m
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_HCD_PLATFORM=m
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_OHCI_HCD_PLATFORM=m
@@ -1,5 +1,6 @@
config BR2_PACKAGE_MARVELL_CN9130_CRB
bool "Marvell CN9130-CRB"
depends on BR2_aarch64
select BR2_PACKAGE_LINUX_FIRMWARE_INSIDE_SECURE_MINIFW
help
Customer Reference Board for CN9130
@@ -0,0 +1,2 @@
# Locally calculated
sha256 d2f96418893ac66156d0e691cda189b0d85ae1d814065d1d9aa1845383100f46 LICENSE
@@ -1,5 +1,6 @@
config BR2_PACKAGE_MARVELL_ESPRESSOBIN
bool "Marvell ESPRESSObin"
depends on BR2_aarch64
select BR2_PACKAGE_LINUX_FIRMWARE_INSIDE_SECURE_MINIFW
help
Marvell ESPRESSObin
+232
View File
@@ -0,0 +1,232 @@
# Marvell ESPRESSObin
<img src="espressobin.png" alt="The board" width=800 padding=10>
The [ESPRESSObin][0] is a single-board computer based on the [Marvell Armada
3720][1] (dual Cortex-A53, AArch64) SoC and the [Marvell 88E6341][2] (Topaz)
switch, oriented toward networking applications.
The board design is old but the switch offers full Linux support, including
advanced TSN features for [IEEE 1588-2019][3] (PTP) and [IEEE 802.1AS-2020][4]
(gPTP).
## Board Variants
The board has gone through several hardware revisions:
| Revision | Storage | Notes |
|------------|---------------------|--------------------------------|
| v1, v3, v5 | SPI NOR only | Obsolete; U-Boot always in SPI |
| v7 | SPI NOR + 4 GB eMMC | Current; SD and eMMC usable |
| Ultra | SPI NOR + 4 GB eMMC | High-end variant |
On **all revisions** the Boot ROM is hardwired to load U-Boot from SPI NOR
flash. There is no strap or jumper to make the Boot ROM load directly from an
SD card. The SD card (or eMMC on v7/Ultra) is used only for the operating
system.
## Building
The ESPRESSObin uses ext4 for its rootfs partitions rather than the default
squashfs, because the stock SPI U-Boot lacks squashfs and `blkmap` support.
The `ext4` configuration snippet enables this. Apply it once after selecting
the defconfig, then build and compose the SD card image:
```sh
make O=x-aarch64 aarch64_defconfig
make O=x-aarch64 apply-ext4
make O=x-aarch64
utils/mkimage.sh -r x-aarch64 marvell-espressobin
```
The resulting image (`x-aarch64/images/infix-espressobin-sdcard.img`) contains
a GPT disk with the standard Infix partition layout, using ext4 instead of the
read-only squashfs:
| Partition | Label | Contents |
|-----------|-----------|------------------------------|
| 1 | aux | RAUC upgrade state (ext4) |
| 2 | primary | Rootfs slot primary (ext4) |
| 3 | secondary | Rootfs slot secondary (ext4) |
| 4 | cfg | Persistent config (ext4) |
| 5 | var | Runtime data (ext4) |
## Writing to SD Card
```sh
dd if=infix-espressobin-sdcard.img of=/dev/sdX bs=4M status=progress conv=fsync
```
## Upgrading
The build produces `x-aarch64/images/infix-aarch64-ext4.pkg`, a RAUC bundle
containing the ext4 rootfs. Once the board is running Infix, upgrade over the
network in the usual way:
```
upgrade ftp://192.168.1.1/infix-aarch64-ext4.pkg
```
RAUC writes the new rootfs to the inactive slot, updates `BOOT_ORDER` in
`/mnt/aux/uboot.env`, and the next boot picks it up automatically.
> [!NOTE]
> Use `infix-aarch64-ext4.pkg`, not the standard `infix-aarch64.pkg`. The
> standard bundle contains a squashfs rootfs which the stock U-Boot cannot
> boot.
## Booting with the Stock SPI U-Boot
The stock Marvell U-Boot has `ext4load` and the standard variables
(`$kernel_addr`, `$fdt_addr`, `$loadaddr`, `$console`, `$image_name`,
`$fdt_name`) already set sensibly. Connect to the board's console port, the
micro USB connector, at 115200 8N1, interrupt autoboot, and paste the commands
below.
### Environment Variable Reference
These variables are pre-set in the stock U-Boot environment. Restore them
with these values if they are ever lost or corrupted:
```
setenv kernel_addr 0x5000000
setenv fdt_addr 0x4f00000
setenv loadaddr 0x5000000
setenv console 'console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000'
setenv image_name boot/Image
setenv extra_params quiet
```
`$fdt_name` selects the device tree for your specific board revision:
| Board revision | `fdt_name` value |
|----------------|-----------------------------------------------------|
| v3 / v5 | `boot/marvell/armada-3720-espressobin.dtb` |
| v7 | `boot/marvell/armada-3720-espressobin-v7.dtb` |
| Ultra | `boot/marvell/armada-3720-espressobin-ultra.dtb` |
| v3/v5 eMMC | `boot/marvell/armada-3720-espressobin-emmc.dtb` |
| v7 eMMC | `boot/marvell/armada-3720-espressobin-v7-emmc.dtb` |
```
setenv fdt_name boot/marvell/armada-3720-espressobin.dtb # adjust for your board
```
### Simple Boot
Fixed boot from the primary slot, useful for initial bring-up:
```
setenv bootcmd 'mmc dev 0; \
ext4load mmc 0:2 $kernel_addr $image_name; \
ext4load mmc 0:2 $fdt_addr $fdt_name; \
setenv bootargs $console root=PARTLABEL=primary rw rootwait $extra_params rauc.slot=primary; \
booti $kernel_addr - $fdt_addr'
saveenv
```
### Automatic Slot Selection (RAUC Integration)
The CLI `upgrade` command writes to the inactive slot and updates `uboot.env`
on the `aux` partition with the new boot order. On the next boot U-Boot reads
`BOOT_ORDER` from the aux partition and selects the appropriate slot. The
setup below also defines `bootcmd_primary`, `bootcmd_secondary`, and
`bootcmd_net` for manual use (see [Manual Slot Selection](#manual-slot-selection)
and [Netbooting](#netbooting)):
```
setenv bootcmd_boot \
'mmc dev 0; \
ext4load mmc 0:$bootpart $kernel_addr $image_name; \
ext4load mmc 0:$bootpart $fdt_addr $fdt_name; \
setenv bootargs $console root=PARTLABEL=$bootslot rw rootwait $extra_params rauc.slot=$bootslot; \
booti $kernel_addr - $fdt_addr'
setenv bootcmd_primary 'setenv bootpart 2; setenv bootslot primary; run bootcmd_boot'
setenv bootcmd_secondary 'setenv bootpart 3; setenv bootslot secondary; run bootcmd_boot'
setenv bootcmd_net \
'dhcp $kernel_addr $image_name; \
tftpboot $fdt_addr $fdt_name; \
setenv bootargs $console root=PARTLABEL=primary rw rootwait $extra_params rauc.slot=primary; \
booti $kernel_addr - $fdt_addr'
setenv bootcmd \
'setenv bootpart 2; setenv bootslot primary; setenv auxpart 1; \
if ext4load mmc 0:$auxpart $loadaddr /uboot.env; then \
env import -c $loadaddr $filesize BOOT_ORDER; \
fi; \
if test "$BOOT_ORDER" = "secondary primary" || \
test "$BOOT_ORDER" = "secondary primary net"; then \
setenv bootpart 3; setenv bootslot secondary; \
fi; \
if test "$BOOT_ORDER" = "net" || \
test "$BOOT_ORDER" = "net primary" || \
test "$BOOT_ORDER" = "net secondary primary"; then \
run bootcmd_net; \
fi; \
echo ">> Booting $bootslot from mmc 0:$bootpart ..."; \
run bootcmd_boot'
saveenv
```
### Manual Slot Selection
To boot a specific slot without waiting for the autoboot countdown, interrupt
the bootloader (press any key) and run one of the convenience commands defined
above:
```
run bootcmd_primary # boot from primary (partition 2)
run bootcmd_secondary # boot from secondary (partition 3)
run bootcmd_net # netboot via DHCP/TFTP
```
You can also force a permanent change to which slot boots next by setting
`BOOT_ORDER` directly from Linux (the change persists across reboots):
```sh
fw_setenv BOOT_ORDER "secondary primary" # next boot: secondary
fw_setenv BOOT_ORDER "primary secondary" # next boot: primary (default)
```
### Netbooting
The stock U-Boot supports TFTP. This is useful for testing a new kernel or
device tree without reflashing the SD card. Set up a TFTP server with the
contents of the Infix `boot/` directory (from the built rootfs at
`x-aarch64/target/boot/`) and configure the variables:
```
setenv serverip 192.168.1.1 # IP of your TFTP server
setenv ipaddr 192.168.1.100 # board IP (omit if using dhcp)
saveenv
```
Then netboot manually:
```
run bootcmd_net
```
`bootcmd_net` uses `dhcp` to obtain an IP address and the `$serverip` from
the DHCP server (option 66), then downloads `$image_name` and `$fdt_name`
via TFTP. The kernel mounts the primary SD card slot as root, so the SD
card must still be present.
To make netbooting the default on next boot (e.g. for iterative kernel
development), set `BOOT_ORDER` from Linux:
```sh
fw_setenv BOOT_ORDER "net primary secondary"
```
This causes `bootcmd` to attempt netboot first; on failure it falls through
to the primary slot on the SD card.
[0]: https://wiki.espressobin.net/
[1]: https://www.marvell.com/content/dam/marvell/en/public-collateral/embedded-processors/marvell-embedded-processors-armada-37xx-hardware-specifications.pdf
[2]: https://www.marvell.com/content/dam/marvell/en/public-collateral/switching/marvell-link-street-88E6341-product-brief.pdf
[3]: https://standards.ieee.org/ieee/1588/6825/
[4]: https://standards.ieee.org/ieee/802.1AS/7121/
Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Some files were not shown because too many files have changed in this diff Show More