Compare commits

..
88 Commits
Author SHA1 Message Date
Tobias Waldekranz ea315bdb10 image-ddi: Mount persistent storage from internal/rw LVM LV 2026-03-08 21:56:45 +00:00
Tobias Waldekranz 3f23aa92be image-itb-rootfs: Assume ownership of legacy filesystem setup
This opens up for DDI images to ship their own implementation.
2026-03-08 21:55:20 +00:00
Tobias Waldekranz 4984d5ac7f image: Allow images to contribute files to the rootfs
This makes it possible to ship differing system files depending on the
images being built. E.g. an ITB image might expect a different
/etc/fstab than a DDI.
2026-03-08 21:55:20 +00:00
Tobias Waldekranz d945bb703b qemu: Support running from DDI images
run.sh has degenerated quite a bit over the years - in no small part
due to the way the qemu-system argv is constructed.

Cut our losses by taking a fresh look at this problem, now that lots
of things need to change anyway. Keep the old script as-is for targets
that still use ITB based images.
2026-03-08 21:55:20 +00:00
Tobias Waldekranz b047bd2a52 x86_64: Switch from GRUB to Barebox 2026-03-08 21:54:35 +00:00
Tobias Waldekranz efc97f6566 initramfs: Build initramfs capable of booting DDI images 2026-03-08 21:54:35 +00:00
Tobias Waldekranz 39f9c1e166 board/common: ddi: Add helper tool to work with DDIs
First user is the initramfs, where it is used to setup the verity
device.

Later on, it will be extended for use by RAUC during upgrades, to
fetch image info in statd, etc.
2026-03-08 21:54:35 +00:00
Tobias Waldekranz f81de1d3ec image-lvm-stub: Base image for use with 'make run' 2026-03-08 21:54:35 +00:00
Tobias Waldekranz e7fabfc37d image-ddi-disk: Full system image 2026-03-08 21:54:35 +00:00
Tobias Waldekranz 956e604dcb image-ddi: Add Discoverable Disk Image (DDI) 2026-03-03 07:35:35 +00:00
Tobias Waldekranz 9d3669b647 image-barebox-esp: EFI System Partition with Barebox 2026-03-03 07:35:31 +00:00
Tobias Waldekranz 17a3ca58a0 qemu: Only allow custom kernel options with QEMU's native loader
This is the only mode that supports the `-append` option. It has
nothing to do with "not MMC".
2026-02-27 23:28:05 +00:00
Tobias Waldekranz 7e2d0cf2f8 buildroot: linux: Allow kernel installation to target with dracut 2026-02-27 23:27:53 +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
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
265 changed files with 12284 additions and 1384 deletions
+41
View File
@@ -0,0 +1,41 @@
name: 'Restore Build Caches'
description: 'Restore dl/ and .ccache/ caches for Buildroot builds'
inputs:
target:
description: 'Build target for cache key differentiation'
required: true
dl-prefix:
description: 'Prefix for dl/ cache key (e.g., "dl", "dl-boot")'
required: false
default: 'dl'
ccache-prefix:
description: 'Prefix for .ccache/ cache key (e.g., "ccache", "ccache-boot")'
required: false
default: 'ccache'
enabled:
description: 'Set to false to skip cache restoration'
required: false
default: 'true'
runs:
using: 'composite'
steps:
- name: Restore Cache of dl/
if: ${{ inputs.enabled == 'true' }}
uses: actions/cache@v4
with:
path: dl/
key: ${{ inputs.dl-prefix }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
restore-keys: |
${{ inputs.dl-prefix }}-
dl-
- name: Restore Cache of .ccache/
if: ${{ inputs.enabled == 'true' }}
uses: actions/cache@v4
with:
path: .ccache/
key: ${{ inputs.ccache-prefix }}-${{ inputs.target }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
restore-keys: |
${{ inputs.ccache-prefix }}-${{ inputs.target }}-
${{ inputs.ccache-prefix }}-
ccache-
+15
View File
@@ -0,0 +1,15 @@
name: 'Podman Cleanup'
description: 'Clean up stale podman state from previous runs'
runs:
using: 'composite'
steps:
- name: Cleanup podman state
shell: bash
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
+7 -17
View File
@@ -22,7 +22,10 @@ jobs:
- cn9130_crb_boot
- fireant_boot
- nanopi_r2s_boot
- rpi2_boot
- rpi64_boot
- sama7g54_ek_emmc_boot
- sama7g54_ek_sd_boot
env:
MAKEFLAGS: -j5
steps:
@@ -63,24 +66,11 @@ jobs:
echo "Building ${defconfig}_defconfig, version ${version}-${rev}, artifact ${archive} ..."
- name: Restore Cache of dl/
uses: actions/cache@v4
- uses: ./.github/actions/cache-restore
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: |
+13
View File
@@ -8,9 +8,11 @@ on:
type: choice
required: true
options:
- raspberrypi-rpi2
- raspberrypi-rpi64
- bananapi-bpi-r3
- friendlyarm-nanopi-r2s
- microchip-sama7g54-ek
default: 'raspberrypi-rpi64'
jobs:
@@ -49,6 +51,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
@@ -65,6 +72,12 @@ jobs:
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
+6 -28
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
with:
clean: true
submodules: recursive
- uses: ./.github/actions/podman-cleanup
- 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: ./.github/actions/cache-restore
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:
+4 -28
View File
@@ -78,15 +78,6 @@ 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
@@ -98,6 +89,8 @@ jobs:
submodules: recursive
token: ${{ secrets.CHECKOUT_TOKEN || github.token }}
- uses: ./.github/actions/podman-cleanup
- 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: ./.github/actions/cache-restore
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: |
+3 -15
View File
@@ -45,22 +45,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Restore Cache of dl/
uses: actions/cache@v4
- uses: ./.github/actions/cache-restore
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 ========================================================================="
+2 -10
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
with:
submodules: 'true'
- uses: ./.github/actions/podman-cleanup
- name: Set Release Variables
id: rel
run: |
+2 -10
View File
@@ -60,16 +60,6 @@ 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
with:
@@ -80,6 +70,8 @@ jobs:
submodules: recursive
token: ${{ secrets.CHECKOUT_TOKEN || github.token }}
- uses: ./.github/actions/podman-cleanup
- name: Run pre-test script
if: ${{ inputs.pre_test_script != '' }}
run: |
+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@v4
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: ./.github/actions/podman-cleanup
- 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: ./.github/actions/cache-restore
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
@@ -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
+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
+78 -44
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,6 +58,12 @@ 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:
@@ -62,60 +77,44 @@ The BPI-R3 has a 4-position DIP switch that controls boot media:
| 1010 | SPI NAND | Boot from SPI NAND (advanced users) |
> [!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
@@ -177,13 +176,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 +229,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.
@@ -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 {
@@ -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

@@ -1,3 +0,0 @@
#!/bin/sh
udevadm control --reload-rules
udevadm trigger --subsystem-match=net --action=add
@@ -0,0 +1,445 @@
{
"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"
},
{
"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.
*/
@@ -1,3 +0,0 @@
#!/bin/sh
udevadm control --reload-rules
udevadm trigger --subsystem-match=net --action=add
@@ -1,4 +0,0 @@
#!/bin/sh
# Workaround for: https://github.com/kernelkit/infix/issues/1357
udevadm control --reload-rules
udevadm trigger --subsystem-match=net --action=add
@@ -1,4 +0,0 @@
#!/bin/sh
# Workaround for: https://github.com/kernelkit/infix/issues/1357
udevadm control --reload-rules
udevadm trigger --subsystem-match=net --action=add
+1
View File
@@ -1,5 +1,6 @@
if BR2_arm
source "$BR2_EXTERNAL_INFIX_PATH/board/arm/microchip-sama7g54-ek/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/arm/raspberrypi-rpi2/Config.in"
endif
@@ -0,0 +1,7 @@
config BR2_PACKAGE_MICROCHIP_SAMA7G54_EK
bool "Microchip SAMA7G54-EK Evaluation Kit"
depends on BR2_arm
select SDCARD_AUX
help
Support for the Microchip SAMA7G54 Evaluation Kit featuring
a Cortex-A7 processor with MACB Gigabit Ethernet and MMC storage.
+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.
+116
View File
@@ -0,0 +1,116 @@
Microchip SAMA7G54-EK
=====================
The [SAMA7G54-EK][1] is an evaluation kit for the Microchip SAMA7G5 series,
featuring an ARM Cortex-A7 processor @ 800 MHz with 512 MB DDR3L RAM.
The board features:
- 2x MACB Gigabit Ethernet ports
- 8 GB eMMC (SDMMC0) + microSD card slot (SDMMC1)
- QSPI NOR flash
- USB 2.0 host ports
- CAN bus interfaces
- Flexcom serial ports (UART, SPI, I2C)
How to Build
------------
Since there are no pre-built images for ARM 32-bit, you need to build
both Infix and the bootloader from source.
### SD Card
1. Build the bootloader
make O=x-boot-sama7g54 sama7g54_ek_sd_boot_defconfig
make O=x-boot-sama7g54
2. Build Infix
make O=x-arm arm_defconfig
make O=x-arm
3. Create the SD card image
./utils/mkimage.sh -b x-boot-sama7g54 -r x-arm microchip-sama7g54-ek
### eMMC
1. Build the bootloader
make O=x-boot-sama7g54-emmc sama7g54_ek_emmc_boot_defconfig
make O=x-boot-sama7g54-emmc
2. Build Infix (same as above, skip if already built)
make O=x-arm arm_defconfig
make O=x-arm
3. Create the eMMC image
./utils/mkimage.sh -b x-boot-sama7g54-emmc -r x-arm -t emmc microchip-sama7g54-ek
Flashing to SD Card
-------------------
[Flash the image][0] to a microSD card (at least 2 GB):
```bash
sudo dd if=x-boot-sama7g54/images/infix-arm-sdcard.img of=/dev/sdX \
bs=1M status=progress oflag=direct
```
You can also use `bmaptool` for faster writes:
```bash
sudo bmaptool copy x-boot-sama7g54/images/infix-arm-sdcard.img /dev/sdX
```
> [!WARNING]
> Ensure `/dev/sdX` is the correct device for your SD card and not used
> by the host system! Use `lsblk` to verify.
Flashing to eMMC
-----------------
The SAMA7G5EK has an on-board 8 GB eMMC (SDMMC0/mmc0). Jumper J22
controls if booting from onboard storage is allowed or not; open means
allowed. When open, the SW4 button can also prevent booting from eMMC
if held at power on.
The easiest method is to flash from a running SD card system:
1. Boot the board from SD card
2. Transfer the eMMC image to the board (USB drive, network, etc.)
3. Flash the eMMC:
sudo bmaptool copy emmc.img /dev/mmcblk0
4. Power off, remove SD card, and boot from eMMC
Booting the Board
-----------------
1. Insert the flashed SD card (or ensure eMMC is flashed)
2. Connect an Ethernet cable
3. Power up the board
4. Find the assigned IP and SSH in, default login: `admin` / `admin`
Console Port
------------
The debug console is on Flexcom3 (active by default):
- Baud rate: 115200
- Data bits: 8
- Parity: None
- Stop bits: 1
Connect a USB-to-serial adapter to the board's debug UART header.
> [!WARNING]
> Use only 3.3V serial adapters.
[0]: https://kernelkit.org/posts/flashing-sdcard/
[1]: https://www.microchip.com/en-us/development-tool/EV21H18A
@@ -0,0 +1 @@
dtb-y += microchip/at91-sama7g5ek.dtb
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Infix OS device tree for Microchip SAMA7G5 Evaluation Kit
*/
#include <arm/microchip/at91-sama7g5ek.dts>
#include "infix.dtsi"
/ {
chosen {
stdout-path = "serial0:115200n8";
};
};
/* Thermal sensor disabled until OTP is calibrated */
&thermal_sensor {
status = "disabled";
};
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Common Infix OS defaults
*/
/ {
chosen {
infix {
/* Default admin user password: 'admin' */
factory-password-hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A";
};
};
};
@@ -0,0 +1,85 @@
# Disk image for Microchip SAMA7G5EK (sama7g5 evaluation kit)
image boot.vfat {
vfat {
files = {
"boot.bin",
"u-boot.bin"
}
}
size = 16M
}
image cfg.ext4 {
empty = true
temporary = true
size = 16M
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#-sama7g54-ek-#TARGET#.img {
hdimage {
partition-table-type = "hybrid"
}
partition boot {
partition-type = 0xC
bootable = "true"
image = "boot.vfat"
offset = 1M
}
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"
}
}
# Silence genimage warnings
config {}
@@ -0,0 +1,69 @@
# Microchip SAMA7G54-EK kernel configuration fixups
define MICROCHIP_SAMA7G54_EK_LINUX_CONFIG_FIXUPS
# AT91/Microchip SoC
$(call KCONFIG_ENABLE_OPT,CONFIG_ARCH_AT91)
$(call KCONFIG_ENABLE_OPT,CONFIG_SOC_SAMA7G5)
$(call KCONFIG_ENABLE_OPT,CONFIG_ATMEL_CLOCKSOURCE_TCB)
# Serial console (FLEXCOM)
# Use ttyAT naming to avoid major/minor conflict with the
# 8250 driver (needed by Raspberry Pi 2 in the shared ARM config)
$(call KCONFIG_ENABLE_OPT,CONFIG_SERIAL_ATMEL)
$(call KCONFIG_ENABLE_OPT,CONFIG_SERIAL_ATMEL_CONSOLE)
$(call KCONFIG_ENABLE_OPT,CONFIG_SERIAL_ATMEL_TTYAT)
$(call KCONFIG_ENABLE_OPT,CONFIG_MFD_ATMEL_FLEXCOM)
# Network: MACB Ethernet
$(call KCONFIG_ENABLE_OPT,CONFIG_NET_VENDOR_MICROCHIP)
$(call KCONFIG_ENABLE_OPT,CONFIG_MACB)
$(call KCONFIG_ENABLE_OPT,CONFIG_MICREL_PHY)
# MMC/SD
$(call KCONFIG_ENABLE_OPT,CONFIG_MMC_SDHCI)
$(call KCONFIG_ENABLE_OPT,CONFIG_MMC_SDHCI_PLTFM)
$(call KCONFIG_ENABLE_OPT,CONFIG_MMC_SDHCI_OF_AT91)
# Pin control and GPIO
$(call KCONFIG_ENABLE_OPT,CONFIG_PINCTRL_AT91)
$(call KCONFIG_ENABLE_OPT,CONFIG_PINCTRL_AT91PIO4)
$(call KCONFIG_ENABLE_OPT,CONFIG_GPIO_SYSFS)
# I2C and SPI
$(call KCONFIG_ENABLE_OPT,CONFIG_I2C_AT91)
$(call KCONFIG_ENABLE_OPT,CONFIG_SPI_ATMEL)
$(call KCONFIG_ENABLE_OPT,CONFIG_SPI_ATMEL_QUADSPI)
# Power management and reset
$(call KCONFIG_ENABLE_OPT,CONFIG_POWER_RESET)
$(call KCONFIG_ENABLE_OPT,CONFIG_POWER_RESET_AT91_RESET)
$(call KCONFIG_ENABLE_OPT,CONFIG_POWER_RESET_AT91_SAMA5D2_SHDWC)
# Watchdog
$(call KCONFIG_ENABLE_OPT,CONFIG_WATCHDOG)
$(call KCONFIG_ENABLE_OPT,CONFIG_SAMA5D4_WATCHDOG)
# DMA and RTC
$(call KCONFIG_ENABLE_OPT,CONFIG_AT_XDMAC)
$(call KCONFIG_ENABLE_OPT,CONFIG_RTC_CLASS)
$(call KCONFIG_ENABLE_OPT,CONFIG_RTC_DRV_AT91SAM9)
# Crypto hardware acceleration
$(call KCONFIG_ENABLE_OPT,CONFIG_CRYPTO_DEV_ATMEL_AES)
$(call KCONFIG_ENABLE_OPT,CONFIG_CRYPTO_DEV_ATMEL_TDES)
$(call KCONFIG_ENABLE_OPT,CONFIG_CRYPTO_DEV_ATMEL_SHA)
# USB Host
$(call KCONFIG_ENABLE_OPT,CONFIG_USB_EHCI_HCD)
$(call KCONFIG_ENABLE_OPT,CONFIG_USB_OHCI_HCD)
# Regulators
$(call KCONFIG_ENABLE_OPT,CONFIG_REGULATOR)
$(call KCONFIG_ENABLE_OPT,CONFIG_REGULATOR_FIXED_VOLTAGE)
$(call KCONFIG_ENABLE_OPT,CONFIG_REGULATOR_MCP16502)
# NVMEM for OTP
$(call KCONFIG_ENABLE_OPT,CONFIG_NVMEM_MICROCHIP_OTPC)
endef
$(eval $(ix-board))
$(eval $(generic-package))
@@ -0,0 +1,12 @@
[system]
compatible=infix-sama7g54-ek
bootloader=uboot
statusfile=/mnt/aux/rauc.status
[slot.rootfs.0]
device=/dev/disk/by-partlabel/primary
bootname=primary
[slot.rootfs.1]
device=/dev/disk/by-partlabel/secondary
bootname=secondary
@@ -0,0 +1,5 @@
{
"@ethtool:driver=macb": {
"broken-flow-control": true
}
}
@@ -0,0 +1 @@
CONFIG_DEVICE_TREE_INCLUDES="infix-env.dtsi infix-key.dtsi sama7g54-ek-env-emmc.dtsi"
@@ -0,0 +1,13 @@
# Common U-Boot extras for SAMA7G54-EK
CONFIG_EFI_PARTITION=y
CONFIG_ENV_IMPORT_FDT=y
CONFIG_FIT=y
CONFIG_FIT_SIGNATURE=y
CONFIG_RSA=y
CONFIG_RSA_VERIFY=y
CONFIG_BLKMAP=y
CONFIG_LZ4=y
CONFIG_LZMA=y
CONFIG_CMD_UNLZ4=y
CONFIG_CMD_UNZIP=y
CONFIG_CMD_IMI=y
@@ -0,0 +1,19 @@
/ {
config {
environment {
vendor = "Microchip";
bootcmd = "run ixboot";
boot_targets = "mmc0";
fdtfile = "microchip/at91-sama7g5ek.dtb";
fdt_addr_r = "0x62000000";
kernel_addr_r = "0x63000000";
scriptaddr = "0x68000000";
ramdisk_addr_r = "0x69000000";
ixbootdelay = "0.5";
bootdelay = "-2";
bootmenu_delay = "10";
ixbtn-devmode = "setenv dev_mode yes; echo Enabled";
ixbtn-factory = "echo \"No button, use bootmenu\"";
};
};
};
@@ -0,0 +1,19 @@
/ {
config {
environment {
vendor = "Microchip";
bootcmd = "run ixboot";
boot_targets = "mmc1";
fdtfile = "microchip/at91-sama7g5ek.dtb";
fdt_addr_r = "0x62000000";
kernel_addr_r = "0x63000000";
scriptaddr = "0x68000000";
ramdisk_addr_r = "0x69000000";
ixbootdelay = "0.5";
bootdelay = "-2";
bootmenu_delay = "10";
ixbtn-devmode = "setenv dev_mode yes; echo Enabled";
ixbtn-factory = "echo \"No button, use bootmenu\"";
};
};
};
@@ -0,0 +1 @@
CONFIG_DEVICE_TREE_INCLUDES="infix-env.dtsi infix-key.dtsi sama7g54-ek-env-sd.dtsi"
@@ -0,0 +1,4 @@
label Infix (arm)
kernel /boot/zImage
fdtdir /boot
append ${bootargs_root} ${bootargs_log} usbcore.authorized_default=2 -- ${bootargs_user}
+10
View File
@@ -1,11 +1,21 @@
menu "Images"
comment "DDI Based"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-ddi/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-ddi-disk/Config.in"
comment "ITB Based"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-itb-rootfs/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-itb-aux/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-itb-qcow/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-itb-gns3a/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-itb-rauc/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-itb-dl-release/Config.in"
comment "General"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-barebox-esp/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-lvm-stub/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-readme/Config.in"
endmenu
+102
View File
@@ -0,0 +1,102 @@
#Simple dracut config for a system without systemd
#Dracut configuration
show_modules=yes
i18n_install_all=no
lvmconf=no
mdadmconf=no
early_microcode=no
hostonly=no
hostonly_cmdline=no
use_fstab=no
kernel_cmdline="rd.break=initqueue"
do_strip=no
# Dracut modules needed
add_dracutmodules+=" \
busybox \
"
# Modules to ignore
omit_dracutmodules+=" \
base \
bash \
biosdevname \
btrfs \
bluetooth \
caps \
cifs \
connman \
crypt \
crypt-gpg \
dash \
dbus-broker \
dbus-daemon \
dm \
dmraid \
dmsquash-live-ntfs \
dracut-systemd \
fcoe \
fcoe-uefi \
fs-lib \
iscsi \
i18n \
kernel-modules \
kernel-modules-extra \
lvmmerge \
lvm \
lunmask \
mdraid \
memstrack \
mksh \
modsign \
mount-root \
multipath \
nbd \
network-legacy \
network-wicked \
nfs \
nvdimm \
nvmf \
parse-lunmask \
pcsc \
qemu \
qemu-net \
resume \
rootfs-block \
rngd \
shutdown \
systemd \
systemd-udevd \
systemd-coredump \
systemd-ask-password \
systemd-timedated \
systemd-rfkill \
systemd-resolved \
systemd-hostnamed \
systemd-initrd \
systemd-integritysetup \
systemd-journald \
systemd-ldconfig \
systemd-networkd \
systemd-timesyncd \
systemd-veritysetup \
systemd-modules-load \
systemd-pcrphase \
systemd-portabled \
systemd-pstore \
systemd-sysctl \
systemd-repart \
systemd-sysext \
systemd-sysusers \
systemd-tmpfiles \
squash \
ssh-client \
stratis \
tpm2-tss \
udev-rules \
url-lib \
usrmount \
virtiofs \
"
@@ -0,0 +1,6 @@
config IMAGE_BAREBOX_ESP
bool "Barebox EFI System Partition"
depends on BR2_TARGET_BAREBOX
default y if IMAGE_DDI
help
An EFI System Partition (ESP) with Barebox installed.
+38
View File
@@ -0,0 +1,38 @@
#!/bin/sh
set -e
case "$BR2_ARCH" in
x86_64)
BOOT_EFI=BOOTX64.EFI
;;
*)
echo "Unknown EFI boot path for $BR2_ARCH" >&2
exit 1
;;
esac
mkdir -p "${WORKDIR}"/root
rm -rf "${WORKDIR}"/tmp
mkdir -p "${WORKDIR}"/tmp
cat <<EOF >"${WORKDIR}"/genimage.cfg
image barebox-esp.vfat {
size = "16M"
vfat {
file EFI/BOOT/$BOOT_EFI {
image = $BINARIES_DIR/barebox.efi
}
}
}
# Silence genimage warnings
config {}
EOF
genimage \
--tmppath "${WORKDIR}"/tmp \
--rootpath "${WORKDIR}"/root \
--inputpath "${WORKDIR}" \
--outputpath "${BINARIES_DIR}" \
--config "${WORKDIR}"/genimage.cfg
@@ -0,0 +1,7 @@
################################################################################
#
# image-barebox-esp
#
################################################################################
$(eval $(ix-image))
@@ -0,0 +1,8 @@
menuconfig IMAGE_DDI_DISK
bool "LVM2 based provisioning disk (DDI)"
depends on IMAGE_BAREBOX_ESP
depends on IMAGE_DDI
help
Compose a full disk image consisting of an EFI System
Partition (ESP) containing Barebox, and an LVM PV in which
Infix is installed as an LV.
+46
View File
@@ -0,0 +1,46 @@
#!/bin/sh
set -e
mkdir -p "${WORKDIR}"/root
rm -rf "${WORKDIR}"/tmp
mkdir -p "${WORKDIR}"/tmp
"${BR2_EXTERNAL_INFIX_PATH}"/utils/lvm-mkinternal \
"${BINARIES_DIR}"/"${ARTIFACT}".raw >"${WORKDIR}"/internal.lvm
cat <<EOF >"${WORKDIR}"/genimage.cfg
image ${ARTIFACT}.disk {
hdimage {
partition-table-type = "gpt"
}
partition esp {
partition-type-uuid = "esp"
image = "$BINARIES_DIR/barebox-esp.vfat"
}
partition esp-backup {
partition-type-uuid = "esp"
image = "$BINARIES_DIR/barebox-esp.vfat"
}
partition internal {
growfs = "true"
partition-type-uuid = "lvm"
image = "internal.lvm"
}
}
# Silence genimage warnings
config {}
EOF
genimage \
--tmppath "${WORKDIR}"/tmp \
--rootpath "${WORKDIR}"/root \
--inputpath "${WORKDIR}" \
--outputpath "${BINARIES_DIR}" \
--config "${WORKDIR}"/genimage.cfg
@@ -0,0 +1,9 @@
################################################################################
#
# image-ddi-disk
#
################################################################################
IMAGE_DDI_DISK_DEPENDENCIES := image-barebox-esp image-ddi
$(eval $(ix-image))
+33
View File
@@ -0,0 +1,33 @@
menuconfig IMAGE_DDI
bool "Discoverable Disk Image (DDI)"
select BR2_TARGET_ROOTFS_SQUASHFS
select BR2_PACKAGE_HOST_GENIMAGE
help
Create a Discoverable Disk Image containing:
- SquashFS of the root filesystem
- dm-verity hash tree of the root filesystem
- DDI compliant JSON signature object of the hash tree
https://uapi-group.org/specifications/specs/discoverable_disk_image/
config IMAGE_DDI_KEY
string "signing key"
depends on IMAGE_DDI
default "${BR2_EXTERNAL_INFIX_PATH}/board/common/signing-keys/development/infix.key"
help
Path to the private RSA key, in PKCS#8 format, used to sign
the dm-verity hash tree.
config IMAGE_DDI_CERT
string "signing cert"
depends on IMAGE_DDI
default "${BR2_EXTERNAL_INFIX_PATH}/board/common/signing-keys/development/infix.crt"
help
Path to the X509 certificate whose associated public key can
validate the authenticity of the generated signature.
The SHA256 fingerprint of this certificate is recorded
alongside the standard PKCS#7 signature in the JSON object,
which can be useful to locate corresponding key on systems
that lack full X509 parsing capabilities.
+81
View File
@@ -0,0 +1,81 @@
#!/bin/sh
# Generate the DDI in two phases. First we create the verity hash tree
# and signature, then we collect them together with the rootfs in the
# ddi. The reason for this is that genimage (at least up to v19) can
# not infer the size of a partition if the image to be placed in it is
# created by the same genimage instance. With the two-phase approach,
# we work around that problem and can create a DDI without any wasted
# space.
set -e
rm -rf "${WORKDIR}"/tmp
mkdir -p "${WORKDIR}"/tmp "${WORKDIR}"/verity
cat <<EOF >"${WORKDIR}"/genimage-verity.cfg
image rootfs.verity {
verity {
image = "rootfs.squashfs"
}
}
image rootfs.verity-sig {
verity-sig {
image = "rootfs.verity"
cert = "${CERT}"
key = "${KEY}"
}
}
config {}
EOF
genimage \
--loglevel 1 \
--tmppath "${WORKDIR}"/tmp \
--rootpath "${WORKDIR}" \
--inputpath "${BINARIES_DIR}" \
--outputpath "${WORKDIR}"/verity \
--config "${WORKDIR}"/genimage-verity.cfg
case "${BR2_ARCH}" in
"x86_64")
arch=x86-64
;;
*)
echo "ERROR: missing mapping from ${BR2_ARCH} to genimage arch" >&2
exit 1
;;
esac
cat <<EOF >"${WORKDIR}"/genimage-ddi.cfg
image ${ARTIFACT}.raw {
hdimage {
partition-table-type = "gpt"
}
partition root {
partition-type-uuid = "root-${arch}"
image = "rootfs.squashfs"
}
partition root-verity {
partition-type-uuid = "root-${arch}-verity"
image = "${WORKDIR}/verity/rootfs.verity"
}
partition root-verity-sig {
partition-type-uuid = "root-${arch}-verity-sig"
image = "${WORKDIR}/verity/rootfs.verity-sig"
}
}
config {}
EOF
genimage \
--loglevel 1 \
--tmppath "${WORKDIR}"/tmp \
--rootpath "${WORKDIR}" \
--inputpath "${BINARIES_DIR}" \
--outputpath "${BINARIES_DIR}" \
--config "${WORKDIR}"/genimage-ddi.cfg
+32
View File
@@ -0,0 +1,32 @@
image rootfs.verity {
verity {
image = "rootfs.squashfs"
}
}
image rootfs.verity-sig {
verity-sig {
image = "rootfs.verity"
cert = "@CERT@"
key = "@KEY@"
}
}
image @ARTIFACT@.raw {
hdimage {
partition-table-type = "gpt"
}
partition root {
partition-type-uuid = "root-@ARCH@"
image = "rootfs.squashfs"
}
partition root-verity {
partition-type-uuid = "root-@ARCH@-verity"
image = "rootfs.verity"
}
partition root-verity-sig {
partition-type-uuid = "root-@ARCH@-verity-sig"
image = "rootfs.verity-sig"
}
}
+10
View File
@@ -0,0 +1,10 @@
################################################################################
#
# image-ddi
#
################################################################################
IMAGE_DDI_DEPENDENCIES := host-genimage rootfs-squashfs
IMAGE_DDI_CONFIG_VARS := KEY CERT
$(eval $(ix-image))
@@ -0,0 +1,15 @@
tmpfs /tmp tmpfs mode=0755,nosuid,nodev 0 0
tmpfs /run tmpfs mode=0755,nosuid,nodev 0 0
tmpfs /media tmpfs mode=1755,nosuid,nodev 0 0
tmpfs /mnt/tmp tmpfs defaults 0 0
# Locate and mount /cfg, /home, /root and /var from the internal
# volume, wherever that is located - or, as a last resort, setup tmpfs
# mounts at these points. Setup an ephemeral writable overlay on /etc.
/usr/libexec/infix/mnt# /mnt/rw helper none 0 0
# Optional, nice-to-have mounts
debugfs /sys/kernel/debug debugfs nofail 0 0
tracefs /sys/kernel/tracing tracefs nofail 0 0
cfgfs /config configfs nofail,noauto 0 0
host /mnt/host 9p nofail,noauto,cache=none,msize=16384 0 0
+211
View File
@@ -0,0 +1,211 @@
#!/bin/sh
# Called from /etc/fstab to ensure we have something writable mounted
# at /cfg, /home, /root, and /var.
#
# In the normal case, the "rw" LV from the "internal" LVM VG is used
# to back all persistant storage. In the event that "internal" is
# present, but the "rw" LV is missing, one will be provisioned, along
# with the required BTRFS subvolumes.
#
# In all other scenarios where the subvolumes are not available, the
# system will fall back to temporary storage for all mount points.
#
# For /etc, a writable, tmpfs backed, layer is always overlayed on top
# of the read-only contents from the OS image.
set -e
nm=$(basename "$0")
need_restore=
code=0
logmsg()
{
logger -k -t "$nm" -p user.crit "$@"
}
status()
{
GREEN="$(printf '\033[1;32m')"
RED="$(printf '\033[1;31m')"
YELLOW="$(printf '\033[1;33m')"
BOLD="$(printf '\033[1m')"
RESET="$(printf '\033[0m')"
case $1 in
0) color=$GREEN; text=' OK ' ;;
1) color=$RED; text='FAIL' ;;
2) color=$YELLOW;text='WARN' ;;
*) color=$YELLOW;text=' ⋯ ' ;;
esac
printf '%s[%s%s%s%s]%s ' "$BOLD" "$color" "$text" "$RESET" "$BOLD" "$RESET"
}
print_start()
{
printf '\r\033[K%s%s' "$(status 3)" "$*" > /dev/console
need_restore=YES
}
print_end()
{
rc=$1; shift
if [ $# -gt 0 ]; then
printf '\r\033[K%s%s\n' "$(status "$rc")" "$*" > /dev/console
else
printf '\r%s\n' "$(status "$rc")" > /dev/console
fi
}
# Restore Finit's original progress message so its [ OK ] appears correctly
print_restore()
{
[ "$need_restore" ] || return 0
print_start "Mounting filesystems from /etc/fstab"
}
# # External button or bootloader changed kernel command line
# check_factory()
# {
# if [ -f /mnt/cfg/infix/.reset ]; then
# return 0;
# fi
# if grep -q 'finit.cond=factory-reset' /proc/cmdline; then
# return 0;
# fi
# # Add to your br2-external to extend factory-reset check
# if [ ! -x /usr/libexec/infix/check-factory ]; then
# return 1;
# fi
# /usr/libexec/infix/check-factory
# }
# factory_reset()
# {
# find /sys/class/leds/ -type l -exec sh -c 'echo 100 > $0/brightness' {} \;
# print_start "Resetting to factory defaults."
# logger $opt -p user.notice -t "$nm" "Resetting to factory defaults."
# rm -rf /mnt/cfg/* /mnt/var/*
# sync
# logger $opt -p user.notice -t "$nm" "Factory reset complete."
# print_end 0 "Factory reset complete."
# print_restore
# }
subvols="cfg var root home"
internal_rw_provision()
{
print_start "Provisioning persistent storage on internal volume"
lvm lvcreate --name rw --extents 50%FREE internal || {
logmsg "No rw LV available, nor could it be created"
print_end 1
return 1
}
mkfs.btrfs -L rw /dev/internal/rw || {
logmsg "Could not create BTRFS on rw LV"
print_end 1
return 1
}
mount -t btrfs /dev/internal/rw /mnt/rw || {
logmsg "Failed to mount rw"
print_end 1
return 1
}
for subvol in $subvols; do
btrfs subvolume create /mnt/rw/@"$subvol" || {
logmsg "Failed to create @$subvol on rw"
print_end 1
return 1
}
done
umount /mnt/rw || {
logmsg "Failed to unmount rw"
print_end 1
return 1
}
print_end 0
}
internal_rw_activate()
{
lvm vgs internal || {
logmsg "No internal volume available"
return 1
}
lvm vgchange -ay internal || {
logmsg "Unable to bring internal volume online"
return 1
}
# The only condition under which we do BTRFS provisioning is when
# the LV is absent. In all other failure scenarios: fall back to
# tmpfs and let the user sort it out. This way we do not risk any
# loss of data.
[ -b /dev/internal/rw ] && return 0
internal_rw_provision
}
internal_rw_mount()
{
internal_rw_activate || return 1
for subvol in $subvols; do
mount -t btrfs /dev/internal/rw /"$subvol" -o subvol=@"$subvol" || {
logmsg "Failed to mount /$subvol"
return 1
}
done
}
tmpfs_rw_mount()
{
for subvol in $subvols; do
mkdir -p -m 0755 /mnt/tmp/"$subvol"
mount /mnt/tmp/"$subvol" /"$subvol" -o bind || {
logmsg "Failed to mount temporary /$subvol"
return 1
}
done
}
tmpfs_etc_mount()
{
mkdir -p -m 0755 /mnt/tmp/etc/
tar c -C /etc . | tar x -C /mnt/tmp/etc
mount /mnt/tmp/etc /etc -o bind
}
exec >/mnt/tmp/mnt.log 2>&1
tmpfs_etc_mount || {
code=1
logmsg "Failed to make /etc writable"
}
if ! internal_rw_mount; then
code=1
print_end 1 "Mounting persistent storage from internal volume"
logmsg "Internal volume not found, falling back to tmpfs"
print_start "Falling back to ephemeral tmpfs storage!"
tmpfs_rw_mount
print_end $?
fi
print_restore
exit $code
@@ -0,0 +1,8 @@
config IMAGE_LVM_STUB
bool "LVM2 stub image"
default y if IMAGE_DDI
help
An empty LVM2 physical volume attached to the internal
volume group. This is useful as a base image for persistent
storage in QEMU emulation scenarios where the OS is supplied
in a separate image.
+34
View File
@@ -0,0 +1,34 @@
#!/bin/sh
set -e
mkdir -p "${WORKDIR}"/root
rm -rf "${WORKDIR}"/tmp
mkdir -p "${WORKDIR}"/tmp
"${BR2_EXTERNAL_INFIX_PATH}"/utils/lvm-mkinternal >"${WORKDIR}"/stub.lvm
cat <<EOF >"${WORKDIR}"/genimage.cfg
image lvm-stub.disk {
hdimage {
partition-table-type = "gpt"
}
partition internal {
growfs = "true"
image = "stub.lvm"
partition-type-uuid = "lvm"
}
}
# Silence genimage warnings
config {}
EOF
genimage \
--tmppath "${WORKDIR}"/tmp \
--rootpath "${WORKDIR}"/root \
--inputpath "${WORKDIR}" \
--outputpath "${BINARIES_DIR}" \
--config "${WORKDIR}"/genimage.cfg
@@ -0,0 +1,7 @@
################################################################################
#
# image-lvm-stub
#
################################################################################
$(eval $(ix-image))
+2
View File
@@ -10,6 +10,7 @@ $(1): $$($(2)_DEPENDENCIES)
PKGDIR=$$($(2)_DIR) \
WORKDIR=$$(BUILD_DIR)/$(1) \
BINARIES_DIR=$$(BINARIES_DIR) \
BR2_ARCH=$$(BR2_ARCH) \
BR2_EXTERNAL_INFIX_PATH=$$(BR2_EXTERNAL_INFIX_PATH) \
ARTIFACT=$$(INFIX_ARTIFACT) \
COMPATIBLE=$$(INFIX_COMPATIBLE) \
@@ -19,6 +20,7 @@ $(1): $$($(2)_DEPENDENCIES)
ifeq ($$($(2)),y)
TARGETS_ROOTFS += $(1)
BR2_ROOTFS_OVERLAY := "$$(realpath $$(pkgdir)/rootfs) $$(call qstrip,$$(BR2_ROOTFS_OVERLAY))"
endif
endef
+15
View File
@@ -0,0 +1,15 @@
#!/bin/bash
check() {
return 0
}
depends() {
return 0
}
install() {
# Not sure if this should be handled by buildroot's merged-usr
# module. Fix it here for now.
ln -s "lib" "${initdir?}/lib64"
}
+279
View File
@@ -0,0 +1,279 @@
#!/bin/sh
echo -ne "\e[31m●\e[0m \e[33m●\e[0m \e[32m●\e[0m Infix Initramfs — " >/dev/console
source /etc/os-release >/dev/console
echo "$VERSION"
set -e
getkopt()
{
grep -q -E "(^| )$1( |$)" /proc/cmdline
}
getkparam()
{
sed -n "s/.*\<$1=\([^ ]*\).*/\1/p" /proc/cmdline
}
debug_shell()
{
[ "$(getkparam rd.shell)" = "$1" ] || return 0
exec </dev/console &>/dev/console
echo "Starting debug shell at $1"
exec sh -i
}
die()
{
step="${*:-$step}"
echo -e "\r\e[0K[\e[31mFAIL\e[0m] $step" >/dev/console
echo "<0>ix-initramfs: ERROR: $step" >/dev/kmsg
debug_shell error
exit 1
}
warn()
{
step="${*:-$step}"
echo -e "\r\e[0K[\e[33mWARN\e[0m] $step" >/dev/console
echo "<5>ix-initramfs: WARNING: $step" >/dev/kmsg
debug_shell warning
}
ok()
{
step="${*:-$step}"
echo -e "\r\e[0K[\e[32m OK \e[0m] $step" >/dev/console
echo "<5>ix-initramfs: $step" >/dev/kmsg
}
begin()
{
step="$*"
echo -ne "[\e[33m ⋯ \e[0m] $step" >/dev/console
}
debug()
{
echo "<7>ix-initramfs: $*" >/dev/kmsg
}
mountcore()
{
mount -t proc proc /proc
mount -t sysfs sys /sys
mount -t devtmpfs dev /dev
}
mountroot()
{
mkdir /newroot
mount "$1" /newroot || \
die "Unable to mount rootfs on $1"
ok "Mounting root filesystem on $(basename $1)"
}
switchroot()
{
local innerinit=$(getkparam init)
ok "Switching to root filesystem"
exec switch_root /newroot ${innerinit:-/sbin/init}
}
internal_get_part()
{
local _i _pv
for _i in $(seq 50); do
_pv=$(lvm pvs --reportformat json \
| jq -r '.report[].pv[] | select(.vg_name == "internal") | .pv_name')
if [ "$_pv" ]; then
[ $_i -gt 5 ] && ok
echo "$_pv"
return 0
fi
[ $_i -eq 5 ] && begin "Waiting for the internal volume to come online"
sleep .2
done
warn "Proceeding without the internal volume"
return 0
}
internal_inflate()
{
local _dev _growfs _index _part
getkopt rd.nointernal && return 0
GPT_PART_GROWFS_BIT=59
_part=$(internal_get_part)
[ "$_part" ] || return 0
_index=$(cat /sys/class/block/$(basename "$_part")/partition)
[ "$_index" ] || return 1
_dev=/dev/$(basename $(realpath /sys/class/block/$(basename "$_part")/../))
[ -b "$_dev" ] || return 1
sgdisk "$_dev" -A "$_index":get:$GPT_PART_GROWFS_BIT \
| grep -q "$_index:$GPT_PART_GROWFS_BIT:1" \
|| return 0
begin "Inflating internal VG in $_part"
# First, expand the GPT to cover the entire disk and expand the
# LVM partition as much as possible.
if ! sgdisk "$_dev" \
--disk-guid=random \
--set-alignment=1 \
--move-second-header \
--delete="$_index" \
--largest-new="$_index" --typecode="$_index":8e00 \
>/tmp/internal-inflate.log 2>&1; then
warn "Failed to inflate GPT on $_dev"
return 0
fi
if ! lvm pvresize "$_part" >>/tmp/internal-inflate.log 2>&1; then
warn "Failed to resize PV $_part"
return 0
fi
ok "Inflated internal VG in $_part"
}
addparts()
{
local _disk="$1"
local _partscan="/sys/class/block/"$(basename "$_disk")/partscan
[ -f "$_partscan" ] && [ $(cat "$_partscan") -eq 1 ] && return
kpartx -a "$_disk" 2>/dev/null || die "addparts: Unable to add partitions from $_disk"
}
gptuuid_probe()
{
local _uuid=$(echo "$1" | sed -e 's/^GPTUUID=//' | tr ABCDEF abcdef)
local _cand _disk _initrd
[ -f /initrd.image ] && _initrd=/initrd.image
for _disk in $_initrd $(find /dev/ -type b); do
_cand=$(ddi "$_disk" inspect uuid | tr ABCDEF abcdef)
[ $? -eq 0 ] || continue
if [ "$_cand" = "$_uuid" ]; then
ok "Located $_uuid in $_disk"
echo "$_disk"
return
fi
done
die "gptuuid_probe: Unable to find disk $_uuid"
}
ddi_probe()
{
local _disk="$1"
local _dm="$(basename $_disk).root"
local _hash=$(getkparam rd.ddi.roothash)
local _v _trust
if [ -n "$_hash" ]; then
ok "Trusting pre-authenticated root hash"
_v="-V $_hash"
else
_v="-v"
fi
_trust=$(ddi "$_disk" part root open $_v "$_dm" 2>&1 \
|| die "ddi_probe: veritysetup of $_disk failed")
ok "$_trust"
ok "Opened verity protected root from $(basename $_disk)"
echo /dev/mapper/"$_dm"
}
lvm_probe()
{
local _vg=$(dirname "$1") _lv=$(basename "$1")
lvm vgchange -ay "$_vg" &>/dev/null || \
die "lvm_probe: Failed to activate the $_vg VG"
[ -b /dev/"$1" ] || die "lvm_probe: Unable to locate the $_lv LV in $_vg"
echo /dev/"$1"
}
lo_probe()
{
local _lo=$(losetup -f || die "probe_lo: found no free loop device for $1")
losetup -P "$_lo" "$1" || die "probe_lo: losetup of $1 to $_lo failed"
debug "lo_probe: setup $_lo backed by $1"
echo "$_lo"
}
probe()
{
local _real _kind
case "$1" in
/*)
_real=$(realpath "$1")
_kind=$(stat -c %F "$_real" 2>/dev/null || true)
case "$_kind" in
"block special file")
addparts "$_real"
echo "$_real"
;;
"regular file")
lo_probe "$_real"
;;
"")
die "Unknown root \"$1\""
;;
*)
die "Unsupported root \"$1\": $_kind"
;;
esac
;;
lvm)
shift
probe $(lvm_probe "$@")
;;
ddi)
shift
ddi_probe $(probe "$@")
;;
GPTUUID=*)
gptuuid_probe "$@"
;;
esac
}
mountcore
debug_shell internal
internal_inflate
debug_shell probe
rootdev=$(probe $(getkparam root | sed -e 's/:/ /g'))
debug_shell mount
mountroot "$rootdev"
debug_shell switchroot
switchroot
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash
progs="blkid ddi dmsetup kpartx jq lvm openssl sgdisk veritysetup"
check() {
require_binaries $progs || return 1
return 0
}
depends() {
return 0
}
install() {
inst_multiple $progs
inst '/etc/os-release'
inst '/etc/rauc/keys/*'
cp "$moddir/init" "${initdir?}/init"
}
+279
View File
@@ -0,0 +1,279 @@
mainmenu "QEMU @ARCH@ Virtualization"
config QEMU_@ARCH@
bool
default y
config QEMU_ARCH
string
default "@ARCH@"
config QEMU_VIRTIO_BUS
string
default "device" if QEMU_arm
default "pci"
config QEMU_BIN_DDI
string
default "@IMAGE@"
config QEMU_BIN_DISK
string
default "@DISK@"
config QEMU_BIN_ESP
string
default "@ESP@"
config QEMU_BIN_KERNEL
string
depends on QEMU_LOADER_QEMU
default "../zImage" if QEMU_arm
default "../Image" if QEMU_aarch64
default "../bzImage" if QEMU_x86_64
config QEMU_BIN_LVM_STUB
string
default "../lvm-stub.disk"
choice
prompt "Loader"
default QEMU_LOADER_QEMU
config QEMU_LOADER_QEMU
bool "QEMU"
config QEMU_LOADER_OVMF
bool "OVMF (UEFI)"
endchoice
config QEMU_BIN_BIOS
string
depends on !QEMU_LOADER_KERNEL
default "OVMF.fd" if QEMU_LOADER_OVMF
menu "Machine"
config QEMU_MACHINE
string "Machine"
default "pc" if QEMU_x86_64
default "virt"
config QEMU_CPU
string "CPU"
default "host" if QEMU_x86_64
default "cortex-a53" if QEMU_aarch64
default "max"
config QEMU_RAM
string "RAM size (k/M/G)"
default "384M"
choice
prompt "Console"
default QEMU_CONSOLE_VIRTIO
config QEMU_CONSOLE_VIRTIO
bool "Virtio (hvc0)"
config QEMU_CONSOLE_SERIAL
bool "Serial (ttyS0/ttyAMA0)"
endchoice
config QEMU_CONSOLE
string
default "hvc0" if QEMU_CONSOLE_VIRTIO
default "ttyAMA0" if QEMU_arm
default "ttyAMA0" if QEMU_aarch64
default "ttyS0"
endmenu
menu "Disks & Filesystems"
config QEMU_DISK_INITRD
bool "Use the DDI as initrd"
depends on QEMU_LOADER_QEMU
help
Pass, and boot from, the DDI as the initial RAM disk.
This is useful to test netbooting scenarios, e.g., in
combination with an empty system disk to simulate an initial
deployment.
comment "System disk"
choice
prompt "Interface"
default QEMU_DISK_SYS_IF_VIRTIO
config QEMU_DISK_SYS_IF_VIRTIO
bool "virtio"
help
Attach system disks using virtio block devices.
endchoice
choice
prompt "Contents"
default QEMU_DISK_SYS_SPLIT
config QEMU_DISK_SYS_EMPTY
bool "Empty disk"
help
Attach an empty disk.
This is useful for testing things like installing Infix from a
USB mass storage device (see "USB Mass Storage" below).
config QEMU_DISK_SYS_FULL
bool "Full system disk"
help
Use the full system disk containing:
- EFI partition (and backup) with Barebox
- LVM PV with Infix installed
This is useful when testing system upgrades, fallback
mechanisms related to corrupt disks etc.
WARNING: Usage of this option is fraught with peril as
incremental builds of Infix are likely to cause corruption in
the QCoW2 layer. If you do not understand the meaning of this
you most likely to NOT want to make use of this feature.
config QEMU_DISK_SYS_NONE
bool "None"
help
Do not attach any system disk.
This is useful for testing how Infix behaves when no persistent
storage is available - a common scenario during bringup of a
new board.
config QEMU_DISK_SYS_SPLIT
bool "Split ESP/DDI/LVM"
help
Attach the EFI System partition, containing Barebox; the raw
DDI image; and an (initially empty) LVM stub for persistent
storage - each as a separate disk.
This is the simplest way of testing out incremental builds of
Infix. Since the DDI is attached as a raw read-only disk, there
is no risk of CoW corruption like with a full system disk.
NOTE: In this setup, the size below refers to the size of the
LVM stub.
endchoice
config QEMU_DISK_SYS_SIZE
string "Size (k/M/G)"
default "8G"
comment "USB mass storage"
choice
prompt "Contents"
default QEMU_DISK_USB_NONE
config QEMU_DISK_USB_DISK
bool "Full system disk"
help
Attach the full system disk containing:
- EFI partition (and backup) with Barebox
- LVM PV with Infix installed
config QEMU_DISK_USB_NONE
bool "None"
help
Do not attach any disk over USB.
endchoice
config QEMU_DISK_USB_SIZE
string "Size (k/M/G)"
depends on !QEMU_DISK_USB_NONE
default "4G"
comment "Host filesystem passthrough (9P)"
config QEMU_DISK_HOST
string "Path"
default "/tmp"
endmenu
menu "Networking"
choice
prompt "Mode"
default QEMU_NET_USER
config QEMU_NET_BRIDGE
bool "Bridged"
config QEMU_NET_NONE
bool "None"
config QEMU_NET_ROCKER
bool "Rocker"
config QEMU_NET_TAP
bool "TAP"
config QEMU_NET_USER
bool "User"
endchoice
config QEMU_NET_MODE
string
default "bridge" if QEMU_NET_BRIDGE
default "none" if QEMU_NET_NONE
default "rocker" if QEMU_NET_ROCKER
default "tap" if QEMU_NET_TAP
default "user" if QEMU_NET_USER
config QEMU_NET_MODEL
string "Interface model"
default "virtio-net-device" if QEMU_arm
default "virtio-net-pci"
help
The default virtio NIC works for most use-cases, but if you
want to play with low-level stuff like ethtool, you might
want to test the Intel 82545EM driver, e1000.
Note: ARM 32-bit uses virtio-net-device (MMIO) by default.
config QEMU_NET_BRIDGE_DEV
string "Bridge device"
depends on QEMU_NET_BRIDGE
default "virbr0"
config QEMU_NET_USER_OPTS
string "User mode options"
depends on QEMU_NET_USER
help
Extra -nic user,<OPTIONS>
config QEMU_NET_TAP_N
int "Number of TAPs"
depends on QEMU_NET_TAP
default 1
config QEMU_NET_PORTS
int "Number of Rocker switch ports"
depends on QEMU_NET_ROCKER
default 10
endmenu
config QEMU_EXTRA
string "Extra QEMU options"
config QEMU_APPEND
string "Extra kernel options"
depends on QEMU_LOADER_QEMU
+480
View File
@@ -0,0 +1,480 @@
#!/bin/sh
# This script can be used to start an Infix OS image in Qemu. It reads
# either a .config, generated from Config.in, or qemu.cfg from a release
# tarball, for the required configuration data.
#
# Debian/Ubuntu users can change the configuration post-release, install
# the kconfig-frontends package:
#
# sudo apt install kconfig-frontends
#
# and then call this script with:
#
# ./run.sh -c
#
# To bring up a menuconfig dialog. Select `Exit` and save the changes.
# For more help, see:_
#
# ./run.sh -h
#
# shellcheck disable=SC3037
# Add /sbin to PATH for mkfs.ext4 and such (not default in debian)
export PATH="/sbin:/usr/sbin:$PATH"
qdir=$(dirname "$(readlink -f "$0")")
imgdir=$(readlink -f "${qdir}/..")
prognm=$(basename "$0")
usage()
{
cat <<EOF
usage: $prognm [OPTIONS] [-- KERNEL-ARGS]
Start Infix in a VM.
Any arguments after -- are passed to the kernel, provided that QEMU's
native loader is being used (i.e., not UEFI, for example). This
includes a second --, which the kernel uses to delimit between kernel
arguments and those passed to the init process.
Options:
-0
Clear any copy-on-write layers, resetting all disks to their
initial states, and exit.
-c
Run menuconfig to change Qemu settings. This requires the
'kconfig-frontends' package (Debian/Ubuntu).
-G
Skip config generation. This is useful if you are testing out new
QEMU features by manually modifying qemu.cfg.
-h
Show this help message
Example:
$prognm -- loglevel=4 -- finit.debug
Will set the kernel's loglevel to 4, and pass finit.debug as an
argument to PID 1.
EOF
}
die()
{
echo "$prognm: $*" >&2
exit 1
}
binpath()
{
case "$1" in
./*|../*)
# Relative paths are relative to the location of .config
printf "$qdir/$1"
;;
*)
printf "$1"
;;
esac
}
q()
{
local _cmd="$1"
shift
case "$_cmd" in
sect)
printf ' \\\n\t' >>"$qdir"/qemu.sh
case $# in
1)
printf -- "-$1" >>"$qdir"/qemu.sh
_delim=" "
;;
2)
printf -- "-$1 $2" >>"$qdir"/qemu.sh
_delim=","
;;
*)
die "q sect: Invalid arguments"
;;
esac
;;
param)
[ $# -eq 2 ] || die "q param: Takes exactly two arguments"
printf -- "$_delim$1=$2" >>"$qdir"/qemu.sh
_delim=","
;;
option)
[ $# -eq 1 ] || die "q option: Takes exactly one argument"
printf -- "$_delim$1" >>"$qdir"/qemu.sh
_delim=","
;;
*)
die "q: Unknown command: $_cmd"
;;
esac
}
q_sect_device_virtio()
{
q sect device virtio-$1-$QEMU_VIRTIO_BUS
}
q_add_disk()
{
if [ "$QEMU_DISK_SYS_IF_VIRTIO" ]; then
q_sect_device_virtio blk
q param drive "$1"
else
die "Unknown system disk interface"
fi
}
q_sect_device_usb()
{
if [ -z "$usb_bus_added" ]; then
q sect usb
q sect device usb-ehci
q param id ehci
usb_bus_added=YES
fi
q sect device "$1"
q param bus ehci.0
}
qcowed()
{
local _qcow="$qdir"/"$1".qcow2
local _base _size
if [ -f "$_qcow" ] && qemu-img check -q "$_qcow"; then
echo "$_qcow"
return
fi
rm -f "$_qcow"
case $# in
2)
_size="$2"
qemu-img create -q -f qcow2 "$_qcow" "$_size" \
|| die "Unable to create $1"
;;
3)
_base="$2"
_size="$3"
[ "$_size" = "auto" ] && _size=
qemu-img create -q -f qcow2 -F raw \
-o backing_file="$_base" "$_qcow" $_size \
|| die "Unable to create CoW layer for $_base"
;;
*)
die "qcowed: usage: qcowed <name> [<backing-file>] <size>"
;;
esac
echo "$_qcow"
}
append()
{
echo -n " $*" >>"$qdir"/append
}
gen_machine()
{
q sect machine
q param type "$QEMU_MACHINE"
q param accel kvm:tcg
q sect cpu "$QEMU_CPU"
q sect m
q param size "$QEMU_RAM"
}
gen_loader()
{
if [ "$QEMU_LOADER_QEMU" ]; then
q sect kernel $(binpath "$QEMU_BIN_KERNEL")
elif [ "$QEMU_LOADER_OVMF" ]; then
q sect bios $(binpath "$QEMU_BIN_BIOS")
fi
}
gen_serial()
{
q sect display none
q_sect_device_virtio serial
q sect chardev stdio
q param id console0
q param mux on
q sect mon
q param chardev console0
case "$QEMU_CONSOLE" in
hvc0)
q sect device virtconsole
q param nr 0
q param name console
q param chardev console0
;;
ttyS0|ttyAMA0)
q sect serial chardev:console0
;;
*)
die "Unsupported console: $QEMU_CONSOLE"
;;
esac
append console="$QEMU_CONSOLE"
[ "$V" ] && append debug || append loglevel=4
}
gpt_uuid()
{
sgdisk "$1" -p | awk '
BEGIN { err = 1; } END { exit(err); }
/^Creating new GPT/ { exit; }
/^Disk identifier \(GUID\): / {
print($4); err = 0; exit;
}' || die "Unable to determine GPT UUID of $1"
}
gen_disk_sys_empty()
{
q sect drive
q param id disk-sys
q param format qcow2
q param if none
q param file $(qcowed disk-sys "$QEMU_DISK_SYS_SIZE")
q_add_disk disk-sys
}
gen_disk_sys_full()
{
q sect drive
q param id disk-sys
q param format qcow2
q param if none
q param file $(qcowed disk-sys $(binpath "$QEMU_BIN_DISK") \
"$QEMU_DISK_SYS_SIZE")
q_add_disk disk-sys
append root=ddi:lvm:internal/$(basename "$QEMU_BIN_DDI")
}
gen_disk_sys_split()
{
# EFI System Partition
q sect drive
q param id disk-esp
q param format qcow2
q param if none
q param file $(qcowed disk-esp $(binpath "$QEMU_BIN_ESP") auto)
q_add_disk disk-esp
# LVM stub
q sect drive
q param id disk-sys
q param format qcow2
q param if none
q param file $(qcowed disk-sys $(binpath "$QEMU_BIN_LVM_STUB") \
"$QEMU_DISK_SYS_SIZE")
q_add_disk disk-sys
# DDI (ro)
q sect drive
q param id disk-ddi
q param format raw
q param file $(binpath "$QEMU_BIN_DDI")
q param if none
q param read-only on
q_add_disk disk-ddi
append root=ddi:GPTUUID=$(gpt_uuid $(binpath "$QEMU_BIN_DDI"))
}
gen_disk_sys()
{
[ "$QEMU_DISK_SYS_NONE" ] && return
if [ "$QEMU_DISK_SYS_EMPTY" ]; then
gen_disk_sys_empty
elif [ "$QEMU_DISK_SYS_FULL" ]; then
gen_disk_sys_full
elif [ "$QEMU_DISK_SYS_SPLIT" ]; then
gen_disk_sys_split
else
die "Unknown system disk mode"
fi
}
gen_disk_usb()
{
[ "$QEMU_DISK_USB_NONE" ] && return
if [ "$QEMU_DISK_USB_DISK" ]; then
q sect drive
q param id disk-usb
q param format qcow2
q param file $(qcowed disk-usb \
$(binpath "$QEMU_BIN_DISK") \
"$QEMU_DISK_USB_SIZE")
q param if none
q_sect_device_usb usb-storage
q param drive disk-usb
else
die "Unknown USB attachment"
fi
}
gen_disk_initrd()
{
[ "$QEMU_DISK_INITRD" ] || return
q sect initrd $(binpath "$QEMU_BIN_DDI")
append root=ddi:/initrd.image
}
internal_is_available()
{
[ "$QEMU_DISK_SYS_FULL" ] || [ "$QEMU_DISK_SYS_SPLIT" ] \
|| [ "$QEMU_DISK_USB_DISK" ]
}
gen_disks()
{
gen_disk_sys
gen_disk_usb
gen_disk_initrd
internal_is_available || append rd.nointernal
}
gen_gdb()
{
# Create a UNIX socket on the host that is connected to a virtio
# console in the guest, which gdbserver can attach to for
# userspace debugging.
q sect chardev socket
q param id gdbserver
q param path "$qdir"/gdbserver.sock
q param server on
q param wait off
q sect device virtconsole
q param nr 1
q param name gdbserver
q param chardev gdbserver
# Create a UNIX socket on the host that is connected to QEMU's GDB
# stub, for bootloader/kernel debugging.
q sect chardev socket
q param id gdbqemu
q param path "$qdir"/gdbqemu.sock
q param server on
q param wait off
q sect gdb chardev:gdbqemu
}
gen_all()
{
local _append
: >"$qdir"/append
cat <<EOF >"$qdir"/qemu.sh
#!/bin/sh
echo "Starting Qemu :: Ctrl-a x -- exit | Ctrl-a c -- toggle console/monitor"
line=\$(stty -g)
stty raw
trap 'stty "\$line"' EXIT INT TERM
qemu-system-$QEMU_ARCH -nodefaults \\
EOF
chmod +x "$qdir"/qemu.sh
gen_machine
gen_loader
gen_serial
gen_disks
gen_gdb
if [ "$QEMU_LOADER_QEMU" ]; then
_append=$(cat "$qdir"/append)
q sect append "\"$_append $QEMU_APPEND $*\""
fi
echo >>"$qdir"/qemu.sh
}
menuconfig()
{
command -v kconfig-mconf >/dev/null \
|| die "cannot find kconfig-mconf for menuconfig"
CONFIG_= KCONFIG_CONFIG="$qdir"/.config \
kconfig-mconf "$qdir"/Config.in
}
_generate=YES
while getopts "0cGh-" opt; do
case ${opt} in
0)
echo "Clearing all copy-on-write layers" >&2
rm -f "$qdir"/*.qcow2
exit 0
;;
c)
menuconfig
;;
G)
_generate=
;;
h)
usage && exit 0
;;
-)
break
;;
*)
usage && exit 1
;;
esac
done
shift $((OPTIND - 1))
# shellcheck disable=SC1090
. "$qdir"/.config
[ "$_generate" ] && gen_all "$*"
exec "$qdir"/qemu.sh
@@ -149,7 +149,7 @@ config QEMU_HOST
config QEMU_APPEND
string "Extra kernel options"
depends on !QEMU_ROOTFS_MMC
depends on QEMU_LOADER_KERNEL
config QEMU_EXTRA
string "Extra QEMU options"
+15 -7
View File
@@ -4,9 +4,15 @@
#
################################################################################
QEMU_SCRIPTS_DIR := $(pkgdir)
qemu-scripts-dir := $(pkgdir)/$(if $(IMAGE_DDI),ddi,itb)
qemu-image := ../$(INFIX_ARTIFACT).$(if $(IMAGE_DDI),raw,qcow2)
qemu-disk := $(if $(IMAGE_DDI_DISK),../$(INFIX_ARTIFACT).disk)
qemu-esp := $(if $(IMAGE_BAREBOX_ESP),../barebox-esp.vfat)
qemu-kconfig-prefix := $(if $(IMAGE_DDI),,CONFIG_)
qemu-kconfig = \
CONFIG_="CONFIG_" \
CONFIG_="$(qemu-kconfig-prefix)" \
BR2_CONFIG="$(BINARIES_DIR)/qemu/.config" \
$(BUILD_DIR)/buildroot-config/$(1) $(2) "$(BINARIES_DIR)/qemu/Config.in"
@@ -25,17 +31,19 @@ qemu-scripts: \
$(BINARIES_DIR)/qemu/Config.in \
$(BINARIES_DIR)/qemu/.config
$(BINARIES_DIR)/qemu/run.sh: $(QEMU_SCRIPTS_DIR)/run.sh
$(BINARIES_DIR)/qemu/run.sh: $(qemu-scripts-dir)/run.sh
@$(call IXMSG,"Installing QEMU scripts")
@mkdir -p $(dir $@)
@cp $< $@
$(BINARIES_DIR)/qemu/Config.in: $(QEMU_SCRIPTS_DIR)/Config.in.in
$(BINARIES_DIR)/qemu/Config.in: $(qemu-scripts-dir)/Config.in.in
@mkdir -p $(dir $@)
@sed \
-e "s:@ARCH@:QEMU_$(BR2_ARCH):" \
-e "s:@DISK_IMG@:../$(INFIX_ARTIFACT).qcow2:" \
< $< >$@
-e "s:@ARCH@:$(BR2_ARCH):g" \
-e "s:@IMAGE@:$(qemu-image):g" \
-e "s:@DISK@:$(qemu-disk):g" \
-e "s:@ESP@:$(qemu-esp):g" \
<$< >$@
$(BINARIES_DIR)/qemu/.config: $(BINARIES_DIR)/qemu/Config.in
@$(call qemu-kconfig,conf,--olddefconfig)
@@ -0,0 +1,2 @@
#set DEBUG=1
service [2345] <pid/confd,pid/staticd> name:netd netd -- Network route daemon
+1
View File
@@ -0,0 +1 @@
../available/netd.conf
+28
View File
@@ -0,0 +1,28 @@
# Default FRR daemons file for Infix - confd overwrites on routing changes.
# watchfrr, zebra, mgmtd, and staticd are always started by frrinit.sh.
ospfd=no
ripd=no
bfdd=no
bgpd=no
ospf6d=no
ripngd=no
isisd=no
pimd=no
pim6d=no
ldpd=no
eigrpd=no
babeld=no
vrrpd=no
pathd=no
vtysh_enable=yes
watchfrr_options="-l 4"
zebra_options=" -A 127.0.0.1 -s 90000000"
mgmtd_options=" -A 127.0.0.1"
ospfd_options=" -A 127.0.0.1"
ripd_options=" -A 127.0.0.1"
staticd_options="-A 127.0.0.1"
bfdd_options=" -A 127.0.0.1"
frr_profile="traditional"
+2
View File
@@ -0,0 +1,2 @@
# Replaces default frr.conf file
log syslog warnings
@@ -1,9 +0,0 @@
! Default settings for staticd, used for both
! confd generated routes, udhcpc and zeroconf
frr defaults traditional
hostname Router
password zebra
enable password zebra
no log unique-id
log syslog informational
log facility local2
+343
View File
@@ -0,0 +1,343 @@
#!/bin/sh
set -e
capath=/etc/rauc/keys
usage()
{
local _ddi="$(basename $0)"
cat <<EOF
usage: $_ddi [<options>] <image> <command> [<args>]
Discoverable Disk Image manipulation
Options:
-A <arch>
Override the system architecture.
-C <path>
Source trusted signing keys from the supplied directory.
Default: $capath
-h
Show this message and exit.
Commands:
inspect <property>
uuid
Print GPT disk identifier
part <partition> <command> [<args]
Where <partition> is one of:
root The first root partition
open [<options>] <name>
Create a device mapping for the specified partition, called
<name>.
Options:
-v
Use the associated dm-verity hash tree, whose root hash is
available in the associated signature partition.
-V <root-hash>
Use the associated dm-verity hash tree, along with an
externally validated root hash.
verify [<options>]
Verify that the specified partition exists and, optionally,
is accompanied by a trusted dm-verity hash tree.
Options:
-v
Require the presence of an associated dm-verity hash tree,
whose root hash is available in the associated signature
partition.
-V <root-hash>
Require the presence of an associated dm-verity hash tree
whose root hash matches the provided one.
Examples:
Map and mount the verity protected SquashFS root partition from an
image:
$_ddi infix-x86_64.raw part root open -v infix
mount -t squashfs /dev/mapper/infix /opt
EOF
}
X86_64_CODE_ROOT=0x8304
X86_64_CODE_ROOT_VERITY=0x830c
X86_64_CODE_ROOT_VERITY_SIG=0x8370
die()
{
echo "ERROR: $*" >&2
exit 1
}
ok()
{
echo "$*" >&2
}
setup_arch()
{
case "$1" in
x86_64)
CODE_ROOT=$X86_64_CODE_ROOT
CODE_ROOT_VERITY=$X86_64_CODE_ROOT_VERITY
CODE_ROOT_VERITY_SIG=$X86_64_CODE_ROOT_VERITY_SIG
;;
*)
die "Unsupported architecture"
esac
}
setup_work()
{
local _umask
_umask=$(umask)
umask 077
workdir=$(mktemp -d)
umask $_umask
trap 'rm -rf "$workdir"' EXIT INT TERM
}
ddi_to_block()
{
local _kind _lo
_kind=$(stat -Lc %F "$1")
case "$_kind" in
"block special file")
echo "$1"
return
;;
"regular file")
_lo=$(losetup -f || die "Found no free loop device for $1")
losetup -P "$_lo" "$1" || die "Failed to setup loop device of $1"
echo "$_lo"
return
;;
esac
die "$1 is a $_kind, only regular and block devices are supported"
}
ddi_get_part_info()
{
local _code _item
case "$2" in
root) _code="$CODE_ROOT";;
root-verity) _code="$CODE_ROOT_VERITY";;
root-verity-sig) _code="$CODE_ROOT_VERITY_SIG";;
*) die "Unknown partition type \"$1\"" ;;
esac
_code=$(printf "%04X" "$_code")
_item=${3:-exists}
sgdisk "$1" -p | awk -v code="$_code" -v item="$_item" '
/^[ ]*[0-9]+/ {
if ($6 != code)
next;
if (item == "exists") exit(0);
if (item == "index") { print($1); exit(0); }
exit(1);
}
'
}
ddi_get_part_dev()
{
local _dev _index _lvuuid _subsys
_index=$(ddi_get_part_info "$1" "$2" index \
|| die "No $2 partition found on $1")
_subsys=$(dmsetup info -c --noheadings -o subsystem "$1" 2>/dev/null || true)
if [ "$_subsys" = "LVM" ]; then
_lvuuid=$(dmsetup info -c --noheadings -o uuid "$1")
_dev=/dev/mapper/$(dmsetup info -c --noheadings -o name -u "part${_index}-$_lvuuid")
else
_dev=$(basename "$1")
_dev=$(find /sys/block/"$_dev"/ -mindepth 1 -maxdepth 1 -type d \
-name "${_dev}$_index" -o -name "${_dev}p$_index")
_dev=/dev/$(basename "$_dev")
fi
[ -b "$_dev" ] || die "Failed to locate $2 partition in $1"
echo "$_dev"
}
ddi_get_root_hash()
{
local _subj
command -v openssl >/dev/null || die "Missing dependency: openssl"
command -v jq >/dev/null || die "Missing dependency: jq"
jq -r .rootHash "$1" | tr -d '\n' >"$workdir"/hash \
|| die "Invalid signature: rootHash is missing"
jq -r .signature "$1" | base64 -d >"$workdir"/sig \
|| die "Invalid signature: signature data is missing"
openssl cms -verify -verify_retcode -CApath "$capath" \
-content "$workdir"/hash \
-in "$workdir"/sig -inform DER \
-certsout "$workdir"/certs >/dev/null 2>&1 \
|| die "Signature verification failed"
_subj=$(openssl x509 -noout -subject <"$workdir"/certs | sed -e 's/^subject=//')
ok "Trusting root hash signature from $_subj"
cat "$workdir"/hash
}
ddipart_get_verity()
{
local _hash
while getopts "vV:" opt; do
case "$opt" in
V)
vkind="${kind}-verity"
vhash="$OPTARG"
;;
v)
vkind="${kind}-verity"
;;
esac
done
[ "$vkind" ] || return
vpart=$(ddi_get_part_dev "$img" "$vkind")
[ "$vhash" ] && return
vskind="${vkind}-sig"
vspart=$(ddi_get_part_dev "$img" "$vskind")
vhash=$(ddi_get_root_hash "$vspart")
}
ddipart_open()
{
[ "$vpart" ] || die "$kind partition is already accessible at $part"
shift $((OPTIND - 1))
veritysetup open "$part" "$1" "$vpart" "$vhash"
}
ddipart_verify()
{
[ "$vpart" ] || return
veritysetup verify "$part" "$vpart" "$vhash"
ok "Image in $img has $kind partition with valid dm-verity hash tree"
}
ddipart()
{
local _cmd
kind="$1"
shift
ddi_get_part_info "$img" "$kind" \
|| die "No $kind partition found on $img"
_cmd="$1"
shift
case "$_cmd" in
open|verify)
img=$(ddi_to_block $img)
part=$(ddi_get_part_dev "$img" "$kind")
ddipart_get_verity "$@"
ddipart_$_cmd "$@"
;;
*)
die "Unknown partition command \"$_cmd\""
;;
esac
}
ddiinspect()
{
case "$1" in
uuid)
sgdisk "$img" -p | awk '
BEGIN { err = 1; } END { exit(err); }
/^Creating new GPT/ { exit; }
/^Disk identifier \(GUID\): / {
print($4); err = 0; exit;
}'
;;
*)
die "Unknown property: $1"
;;
esac
}
_arch=$(uname -m)
while getopts "A:C:h" opt; do
case ${opt} in
A)
_arch="$OPTARG"
;;
C)
capath="$OPTARG"
;;
h)
usage && exit 0
;;
esac
done
shift $((OPTIND - 1))
if [ $# -lt 2 ]; then
usage && exit 1
fi
img="$1"
cmd="$2"
shift 2
setup_arch "$_arch"
setup_work
case "$cmd" in
inspect)
ddiinspect "$@"
;;
part)
ddipart "$@"
;;
*)
echo "Unknown command \"$cmd\"" >2
exit 1
;;
esac
@@ -0,0 +1,18 @@
# Copy product-specific files (udev rules, factory config, etc.) to /
# based on DT compatible strings, before udevd processes any events.
#
# <hook/mount/all> fires after all filesystems are mounted but before
# finit enters runlevel S and starts any service, so the run task is
# guaranteed to start ahead of udevd. The <run/preudev/success>
# condition below then blocks udevd until pre-udev has finished.
#
# Systems without a matching product directory exit immediately.
run name:preudev cgroup.init [S] <hook/mount/all> log \
/usr/libexec/infix/pre-udev -- Probing platform
# Hold udevd back until pre-udev has had a chance to install any
# product-specific udev rules so that they are applied on first pass.
service nowarn cgroup.system name:udevd notify:none env:-/etc/default/udevd pid:udevd log \
[S12345789] <run/preudev/success> /lib/systemd/systemd-udevd $UDEVD_ARGS -- Device event daemon (udev)
service nowarn cgroup.system name:udevd notify:none env:-/etc/default/udevd pid:udevd log \
[S12345789] <run/preudev/success> udevd $UDEVD_ARGS -- Device event daemon (udev)
@@ -5,5 +5,5 @@ run nowarn if:udevd cgroup.init <service/udevd/ready> log \
# Now that everything should be probed, do a final pass over the
# uevent queue before starting syslogd and everything else
run nowarn if:udevd cgroup.init :post <service/udevd/ready> log \
run nowarn if:udevd cgroup.init :post <run/preudev/success,service/udevd/ready> log \
[S] udevadm settle -t 30 --
@@ -1,40 +1,22 @@
#!/bin/sh
# Find, install, and run product specific files and script in /etc
# before resuming bootstrap.
# Run product specific init scripts and set bootstrap conditions.
#
# Product-specific files (udev rules, factory config, etc.) are already
# copied to / by the pre-udev run task before udevd starts. This
# script handles the remaining product init: running custom scripts
# from /etc/product/init.d/ and setting finit conditions.
#
# Use /etc/product/init.d/S01-myscript for scripts, may be a symlink, it
# will be called with `start` as its only argument.
#
# The compatible array is listed in the same order as the device tree,
# most significant to least. Hence the reverse.[], to ensure overrides
# are applied in order of significance.
ident=$(basename "$0")
PRODUCT_INIT=/etc/product/init.d
PREFIXD=/usr/share/product
COMPATIBLES=$(jq -r '.compatible | reverse.[] | ascii_downcase' /run/system.json)
note()
{
logger -I $$ -k -p user.notice -t "$ident" "$1"
}
found=false
for PRODUCT in $COMPATIBLES; do
DIR="$PREFIXD/$PRODUCT"
if [ -d "$DIR" ]; then
note "Using vendor/product-specific defaults for $PRODUCT."
for dir in "$DIR"/*; do
[ -d "$dir" ] && cp -a "$dir" /
done
found=true
fi
done
if [ "$found" = false ]; then
note "No vendor/product-specific directory found, using built-in defaults."
fi
# Conditions for bootstrap services, this enables product specific
# init scripts to prevent select services from starting.
initctl -nbq cond set led
@@ -290,6 +290,14 @@ def parse_interface_info(ifname):
if power_match:
result['txpower'] = float(power_match.group(1))
# wiphy index -> phy/radio name
elif stripped.startswith('wiphy '):
try:
wiphy_idx = int(stripped.split()[1])
result['phy'] = normalize_phy_name(f'phy{wiphy_idx}')
except (ValueError, IndexError):
pass
return result
+48
View File
@@ -0,0 +1,48 @@
#!/bin/sh
# Copy product-specific files to / based on DT compatible strings.
# Designed to run before udevd, so that udev rules are in place when
# the kernel starts enumerating devices. No Python, no jq, no syslogd.
#
# Mirrors the platform detection from 00-probe and the copy logic from
# 05-product, but reads the DT directly instead of /run/system.json.
PREFIXD=/usr/share/product
COMPAT=/sys/firmware/devicetree/base/compatible
IDENT=$(basename "$0")
note()
{
logger -I $$ -k -p user.notice -t "$IDENT" "$*"
}
# Only DT-based systems have product-specific data keyed by compatible.
# QEMU and x86/DMI systems have no product dirs to copy.
[ -f "$COMPAT" ] || exit 0
# The DT compatible property is a null-separated list of strings,
# ordered most-specific first (e.g. "bananapi,bpi-r3\0mediatek,mt7986a").
# Reverse the list so least-specific is applied first and more-specific
# overrides it, matching the behaviour of 05-product.
reversed=""
while IFS= read -r c; do
[ -n "$c" ] || continue
reversed="$c${reversed:+ $reversed}"
done <<EOF
$(tr '\0' '\n' < "$COMPAT" | tr '[:upper:]' '[:lower:]')
EOF
found=false
for compat in $reversed; do
dir="$PREFIXD/$compat"
[ -d "$dir" ] || continue
note "Using product-specific defaults for $compat."
for subdir in "$dir"/*; do
[ -d "$subdir" ] && cp -a "$subdir" /
done
found=true
done
$found || note "No product-specific directory found, using built-in defaults."
exit 0
@@ -1,15 +0,0 @@
#!/bin/sh
# Sort and collate all /etc/frr/static.d/*.conf files managed by confd,
# udhcpc, and avahi-autoipd before starting staticd.
DIRD=/etc/frr/static.d
NAME=/etc/frr/staticd.conf
NEXT=${NAME}+
rm -f "$NEXT"
find "$DIRD" -type f -name '*.conf' ! -name '*~' | sort | while read -r file; do
cat "$file" >> "$NEXT"
done
cmp -s "$NAME" "$NEXT" && exit 0
mv "$NEXT" "$NAME"
@@ -7,7 +7,7 @@ ACTION="$1"
IP_CACHE="/var/lib/misc/${interface}.cache"
RESOLV_CONF="/run/resolvconf/interfaces/${interface}.conf"
NTPFILE="/run/chrony/dhcp-sources.d/${interface}.sources"
NAME="/etc/frr/static.d/${interface}-dhcp.conf"
NAME="/etc/netd/conf.d/${interface}-dhcp.conf"
NEXT="${NAME}+"
[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
@@ -75,14 +75,23 @@ was_option_requested()
# client MUST ignore the Router option.
set_dhcp_routes()
{
echo "! Generated by udhcpc" > "$NEXT"
echo "# Generated by udhcpc" > "$NEXT"
echo "" >> "$NEXT"
if [ -n "$staticroutes" ]; then
if was_option_requested 121; then
# format: dest1/mask gw1 ... destn/mask gwn
set -- $staticroutes
while [ -n "$1" -a -n "$2" ]; do
dbg "adding route $1 via $2 metric $metric tag 100"
echo "ip route $1 $2 $metric tag 100" >> "$NEXT"
cat >> "$NEXT" <<-EOF
route {
prefix = "$1"
nexthop = "$2"
distance = $metric
tag = 100
}
EOF
shift 2
done
else
@@ -91,7 +100,15 @@ set_dhcp_routes()
elif [ -n "$router" ] ; then
if was_option_requested 3; then
for i in $router ; do
echo "ip route 0.0.0.0/0 $i $metric tag 100" >> "$NEXT"
cat >> "$NEXT" <<-EOF
route {
prefix = "0.0.0.0/0"
nexthop = "$i"
distance = $metric
tag = 100
}
EOF
done
else
log "ignoring unrequested router (option 3)"
@@ -102,7 +119,7 @@ set_dhcp_routes()
cmp -s "$NAME" "$NEXT" && return
mv "$NEXT" "$NAME"
initctl -nbq restart staticd
initctl reload netd
}
clr_dhcp_routes()
@@ -111,7 +128,7 @@ clr_dhcp_routes()
[ -f "$NAME" ] || return
rm "$NAME"
initctl -nbq restart staticd
initctl reload netd
}
clr_dhcp_addresses()
@@ -0,0 +1,3 @@
CODE_ROOT=0x8304
CODE_ROOT_VERITY=0x830c
CODE_ROOT_VERITY_SIG=0x8370
+6 -2
View File
@@ -27,7 +27,7 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA
BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.8"
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.14"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig"
BR2_LINUX_KERNEL_INSTALL_TARGET=y
@@ -39,9 +39,11 @@ BR2_PACKAGE_E2FSPROGS=y
BR2_PACKAGE_E2FSPROGS_RESIZE2FS=y
BR2_PACKAGE_DBUS_CXX=y
BR2_PACKAGE_DBUS_GLIB=y
BR2_PACKAGE_DBUS_TRIGGERD=y
BR2_PACKAGE_EUDEV_RULES_GEN=y
# BR2_PACKAGE_EUDEV_ENABLE_HWDB is not set
BR2_PACKAGE_GPSD_DEVICES="/dev/gps0"
BR2_PACKAGE_GPSD_MAX_CLIENT_VALUE=2
BR2_PACKAGE_GPSD_MAX_DEV_VALUE=1
BR2_PACKAGE_GPTFDISK=y
BR2_PACKAGE_GPTFDISK_SGDISK=y
BR2_PACKAGE_MDIO_TOOLS=y
@@ -146,9 +148,11 @@ INFIX_DESC="Infix is an immutable, friendly, and secure operating system that tu
INFIX_HOME="https://github.com/kernelkit/infix/"
INFIX_DOC="https://kernelkit.org/infix/"
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
BR2_PACKAGE_FEATURE_GPS=y
BR2_PACKAGE_FEATURE_WIFI_MEDIATEK=y
BR2_PACKAGE_FEATURE_WIFI_REALTEK=y
BR2_PACKAGE_CONFD=y
BR2_PACKAGE_NETD=y
BR2_PACKAGE_CONFD_TEST_MODE=y
BR2_PACKAGE_CURIOS_HTTPD=y
BR2_PACKAGE_CURIOS_NFTABLES=y
+6 -2
View File
@@ -27,7 +27,7 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA
BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.8"
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.14"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig"
BR2_LINUX_KERNEL_INSTALL_TARGET=y
@@ -39,9 +39,11 @@ BR2_PACKAGE_E2FSPROGS=y
BR2_PACKAGE_E2FSPROGS_RESIZE2FS=y
BR2_PACKAGE_DBUS_CXX=y
BR2_PACKAGE_DBUS_GLIB=y
BR2_PACKAGE_DBUS_TRIGGERD=y
BR2_PACKAGE_EUDEV_RULES_GEN=y
# BR2_PACKAGE_EUDEV_ENABLE_HWDB is not set
BR2_PACKAGE_GPSD_DEVICES="/dev/gps0"
BR2_PACKAGE_GPSD_MAX_CLIENT_VALUE=2
BR2_PACKAGE_GPSD_MAX_DEV_VALUE=1
BR2_PACKAGE_GPTFDISK=y
BR2_PACKAGE_GPTFDISK_SGDISK=y
BR2_PACKAGE_MDIO_TOOLS=y
@@ -124,7 +126,9 @@ INFIX_DESC="Infix is an immutable, friendly, and secure operating system that tu
INFIX_HOME="https://github.com/kernelkit/infix/"
INFIX_DOC="https://kernelkit.org/infix/"
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
BR2_PACKAGE_FEATURE_GPS=y
BR2_PACKAGE_CONFD=y
BR2_PACKAGE_NETD=y
BR2_PACKAGE_CONFD_TEST_MODE=y
BR2_PACKAGE_GENCERT=y
BR2_PACKAGE_STATD=y
+1
View File
@@ -24,5 +24,6 @@ BR2_TARGET_UBOOT_FORMAT_DTB=y
BR2_PACKAGE_HOST_UBOOT_TOOLS=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FDT_ADD_PUBKEY=y
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
+7 -2
View File
@@ -28,7 +28,7 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA
BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.8"
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.14"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/arm/linux_defconfig"
BR2_LINUX_KERNEL_INSTALL_TARGET=y
@@ -41,9 +41,11 @@ BR2_PACKAGE_E2FSPROGS=y
BR2_PACKAGE_E2FSPROGS_RESIZE2FS=y
BR2_PACKAGE_DBUS_CXX=y
BR2_PACKAGE_DBUS_GLIB=y
BR2_PACKAGE_DBUS_TRIGGERD=y
BR2_PACKAGE_EUDEV_RULES_GEN=y
# BR2_PACKAGE_EUDEV_ENABLE_HWDB is not set
BR2_PACKAGE_GPSD_DEVICES="/dev/gps0"
BR2_PACKAGE_GPSD_MAX_CLIENT_VALUE=2
BR2_PACKAGE_GPSD_MAX_DEV_VALUE=1
BR2_PACKAGE_GPTFDISK=y
BR2_PACKAGE_GPTFDISK_SGDISK=y
BR2_PACKAGE_MDIO_TOOLS=y
@@ -135,15 +137,18 @@ BR2_PACKAGE_HOST_MTOOLS=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FDT_ADD_PUBKEY=y
BR2_PACKAGE_MICROCHIP_SAMA7G54_EK=y
BR2_PACKAGE_RASPBERRYPI_RPI2=y
INFIX_VENDOR_HOME="https://kernelkit.org"
INFIX_DESC="Infix is an immutable, friendly, and secure operating system that turns any ARM or x86 device into a powerful, manageable network appliance. Deploy on anything from $35 Raspberry Pi boards to enterprise switches as routers, IoT gateways, or edge devices. Infix models Linux networking features using YANG so you can manage your devices using NETCONF/RESTCONF APIs and focus on your business logic running in isolated containers."
INFIX_HOME="https://github.com/kernelkit/infix/"
INFIX_DOC="https://kernelkit.org/infix/"
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
BR2_PACKAGE_FEATURE_GPS=y
BR2_PACKAGE_FEATURE_WIFI_MEDIATEK=y
BR2_PACKAGE_FEATURE_WIFI_REALTEK=y
BR2_PACKAGE_CONFD=y
BR2_PACKAGE_NETD=y
BR2_PACKAGE_CONFD_TEST_MODE=y
BR2_PACKAGE_GENCERT=y
BR2_PACKAGE_STATD=y
+7 -2
View File
@@ -28,7 +28,7 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA
BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.8"
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.14"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/arm/linux_defconfig"
BR2_LINUX_KERNEL_INSTALL_TARGET=y
@@ -41,9 +41,11 @@ BR2_PACKAGE_E2FSPROGS=y
BR2_PACKAGE_E2FSPROGS_RESIZE2FS=y
BR2_PACKAGE_DBUS_CXX=y
BR2_PACKAGE_DBUS_GLIB=y
BR2_PACKAGE_DBUS_TRIGGERD=y
BR2_PACKAGE_EUDEV_RULES_GEN=y
# BR2_PACKAGE_EUDEV_ENABLE_HWDB is not set
BR2_PACKAGE_GPSD_DEVICES="/dev/gps0"
BR2_PACKAGE_GPSD_MAX_CLIENT_VALUE=2
BR2_PACKAGE_GPSD_MAX_DEV_VALUE=1
BR2_PACKAGE_GPTFDISK=y
BR2_PACKAGE_GPTFDISK_SGDISK=y
BR2_PACKAGE_MDIO_TOOLS=y
@@ -117,13 +119,16 @@ BR2_PACKAGE_HOST_MTOOLS=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FDT_ADD_PUBKEY=y
BR2_PACKAGE_MICROCHIP_SAMA7G54_EK=y
BR2_PACKAGE_RASPBERRYPI_RPI2=y
INFIX_VENDOR_HOME="https://kernelkit.org"
INFIX_DESC="Infix is an immutable, friendly, and secure operating system that turns any ARM or x86 device into a powerful, manageable network appliance. Deploy on anything from $35 Raspberry Pi boards to enterprise switches as routers, IoT gateways, or edge devices. Infix models Linux networking features using YANG so you can manage your devices using NETCONF/RESTCONF APIs and focus on your business logic running in isolated containers."
INFIX_HOME="https://github.com/kernelkit/infix/"
INFIX_DOC="https://kernelkit.org/infix/"
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
BR2_PACKAGE_FEATURE_GPS=y
BR2_PACKAGE_CONFD=y
BR2_PACKAGE_NETD=y
BR2_PACKAGE_CONFD_TEST_MODE=y
BR2_PACKAGE_GENCERT=y
BR2_PACKAGE_STATD=y

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