Compare commits

..
560 changed files with 9561 additions and 21646 deletions
+20 -36
View File
@@ -11,7 +11,7 @@ Talking about code and problems first is often the best way to get started
before submitting a pull request.
When submitting a bug report, patch, or pull request, please start by
stating the version the change is made against, what it does, *and why*.
stating the version the change is made against, what it does, and why.
Please take care to ensure you follow the project coding style and the
commit message format. If you follow these recommendations you help
@@ -21,28 +21,13 @@ the maintainer(s) and make it easier for them to include your code.
Coding Style
------------
Before jumping into code, remember to **document new features** and bug
fixes. Both the manual and ChangeLog are in the `doc/` sub-directory
and it is expected that you provide a human-readable summary for the
release notes (ChangeLog) and at least a configuration example in the
manual for new features.
> **Tip:** Always submit code that follows the style of surrounding code!
> **Tip:** consider ["Readme driven development"][RDD] for new features.
> It is amazing how many flaws in your own bright ideas come to bare
> when you suddenly have to explain them to someone else!
First of all, lines are allowed to be longer than 72 characters these
days. In fact, there exist no enforced maximum, but keeping it around
100 chars is OK.
We expect code contributions for:
- C code in [Linux Coding Style][Linux]
- Python code should follow [PEP-8][]
> **However,** always submit code that follows the style of surrounding
> code! Legacy takes precedence, and remember, we read code a lot more
> than write it, so legibility is important.
As a final note, lines are allowed to be longer than 72 characters these
days. There is no enforced maximum, but the team usually keep it around
100 characters for both C and Python.
The coding style itself is otherwise strictly Linux [KNF][].
Commit Messages
@@ -52,21 +37,22 @@ Commit messages exist to track *why* a change was made. Try to be as
clear and concise as possible in your commit messages, and always, be
proud of your work and set up a proper GIT identity for your commits:
$ git config --global user.name "Jacky Linker"
$ git config --global user.email jacky.linker@example.com
git config --global user.name "Jane Doe"
git config --global user.email jane.doe@example.com
Example commit message from the [Pro Git][gitbook] online book, notice
how `git commit -s` is used to automatically add a `Signed-off-by`:
subsystem: brief, but clear and concise summary of changes
Brief, but clear and concise summary of changes
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as
the subject of an email and the rest of the text as the body. The
empty line separating summary from body is critical. Tools like
rebase can get confused if the empty line is missing.
blank line separating the ummary from the body is critical (unless
you omit the body entirely); tools like rebase can get confused if
you run the two together.
Further paragraphs should be separated with empty lines.
Further paragraphs come after blank lines.
- Bullet points are okay, too
@@ -74,19 +60,17 @@ how `git commit -s` is used to automatically add a `Signed-off-by`:
by a single space, with blank lines in between, but conventions
vary here
Signed-off-by: Jacky Linker <jacky.linker@example.com>
Signed-off-by: Jane Doe <jane.doe@example.com>
Code of Conduct
---------------
It is expected of everyone to respect the [Code of Conduct][conduct].
The *"maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, discussion forum threads, issues, and
other contributions that are not aligned to this Code of Conduct."*
The *"maintainers have the right and responsibility to remove, edit,
or reject comments, commits, code, wiki edits, issues, and other
contributions that are not aligned to this Code of Conduct."*
[Linux]: https://www.kernel.org/doc/html/v6.9/process/coding-style.html
[PEP-8]: https://peps.python.org/pep-0008/
[RDD]: https://tom.preston-werner.com/2010/08/23/readme-driven-development
[gitbook]: https://git-scm.com/book/ch5-2.html
[conduct]: CODE-OF-CONDUCT.md
[KNF]: https://en.wikipedia.org/wiki/Kernel_Normal_Form
[gitbook]: https://git-scm.com/book/ch5-2.html
[conduct]: CODE-OF-CONDUCT.md
-69
View File
@@ -1,69 +0,0 @@
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
name: "\U0001F41E Bug report"
description: Create a bug report
labels:
- "bug"
- "triage"
body:
- type: markdown
attributes:
value: |
**Thank :heart: you for taking the time to fill out this bug report!**
We kindly ask that you search to see if an issue [already exists](https://github.com/kernelkit/infix/issues?q=is%3Aissue+sort%3Acreated-desc+) for the bug you encountered.
- type: textarea
attributes:
label: Current Behavior
description: |
A clear and concise description of the issue you're experiencing.
value: |
For code snippets, logs, commands, etc., please use triple backticks:
```
admin@infix-c0-ff-ee:/> show log
May 15 07:21:02 infix-00-00-00 container[3192]: Failed creating container test from curios-httpd-v24.03.0
- (press h for help or q to quit)
```
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: |
A clear and concise description of what you expected to happen.
value: |
```
admin@infix-c0-ff-ee:/> show log
May 15 07:21:02 infix-c0-ff-ee container[3192]: Successfully created container test from curios-httpd-v24.03.0
- (press h for help or q to quit)
```
validations:
required: true
- type: textarea
attributes:
label: Steps To Reproduce
description: |
Steps to reproduce the issue. For example:
1. Built from source
2. Upgrade to latest release, vYY.MM.P
3. Factory reset
4. Enable feature
5. Check the logs/show command/operational status
validations:
required: false
- type: textarea
attributes:
label: Additional information
description: |
- Relevant parts of `startup-config`
- Output from `show interfaces`, if applicable
- Other observations, screenshots, log files ...
**Tip:** You can attach images or log files by clicking this area to highlight it and then dragging files in.
validations:
required: false
-7
View File
@@ -1,7 +0,0 @@
contact_links:
- name: "🔍 Look for my Issue"
url: https://github.com/kernelkit/infix/issues?q=is%3Aissue+sort%3Acreated-desc+
about: Thank ❤️ you for your time! We kindly ask that you first check if an issue already exists.
- name: "💬 Discussions and Q&A"
url: https://github.com/kernelkit/infix/discussions
about: Discussions are perfect for quick questions, bouncing ideas, and things that may be a bug.
@@ -1,45 +0,0 @@
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
name: "\U0001F6E0 Feature request"
description: Suggest a new feature, idea or improvement of the OS
labels:
- "feature"
- "triage"
body:
- type: markdown
attributes:
value: |
**Thank :heart: you for taking the time to fill out this feature request!**
We kindly ask that you search to see if an issue [already exists](https://github.com/kernelkit/infix/issues?q=is%3Aissue+sort%3Acreated-desc+) for your feature. We are also happy to accept contributions from our users. For details see [CONTRIBUTING](https://github.com/kernelkit/infix/blob/master/.github/CONTRIBUTING.md).
- type: textarea
attributes:
label: Description
description: |
A clear and concise description of the problem or missing feature.
**Example:** *I'm always frustrated when [...]*, or *I'd like to see support for [...]*
validations:
required: true
- type: textarea
attributes:
label: Additional Information
description: |
Any other related information, e.g. existing YANG model(s), or possibly screenshots about the feature request here.
validations:
required: false
- type: textarea
attributes:
label: General Information
description: |
Appended to all feature requests for future readers.
value: |
Anyone can help out by [sponsoring][1] development of new features or [contributing][2] pull requests.
Please use this issue for discussions related to the feature.
[1]: https://github.com/kernelkit/infix/blob/main/.github/SUPPORT.md
[2]: https://github.com/kernelkit/infix/blob/main/.github/CONTRIBUTING.md
validations:
required: true
+7 -1
View File
@@ -1,3 +1,5 @@
<!--- **Summarize** your changes in the title above -->
## Description
<!--
@@ -13,7 +15,7 @@
## Checklist
Tick *relevant* boxes, this PR is-a or has-a:
Tick relevant boxes, this PR is-a or has-a:
- [ ] Bugfix
- [ ] Regression tests
@@ -29,3 +31,7 @@ Tick *relevant* boxes, this PR is-a or has-a:
- [ ] Documentation content changes
- [ ] Other (please describe):
## References
<!-- Please list references to related issue(s) -->
+45 -79
View File
@@ -1,7 +1,6 @@
name: Bob the Builder
on:
pull_request:
push:
branches:
- main
@@ -9,108 +8,83 @@ on:
jobs:
build:
name: Build Infix ${{ matrix.target }}
runs-on: [ self-hosted, latest ]
name: Build ${{ matrix.platform }} ${{ matrix.variant }}
runs-on: ubuntu-latest
strategy:
matrix:
target: [aarch64, x86_64]
platform: [aarch64, x86_64]
variant: [netconf, classic]
fail-fast: false
steps:
- name: Maintenance
run: |
docker image prune -af
docker volume prune -f
docker container prune -f
- uses: actions/checkout@v4
with:
clean: true
submodules: recursive
- name: Set Build Variables
id: vars
run: |
target=${{ matrix.target }}
if [ "${{ matrix.variant }}" = "netconf" ]; then
target=${{ matrix.platform }}
else
target=${{ matrix.platform }}-${{ matrix.variant }}
fi
echo "dir=infix-$target" >> $GITHUB_OUTPUT
echo "tgz=infix-$target.tar.gz" >> $GITHUB_OUTPUT
if [ "$target" = x86_64 ]; then
echo "out=$PWD/output" >> $GITHUB_OUTPUT
else
echo "out=/mnt/x-$target" >> $GITHUB_OUTPUT
fi
- name: Restore Cache of dl/
uses: actions/cache@v4
with:
path: dl/
key: dl-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
key: dl-${{ matrix.variant }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
restore-keys: |
dl-${{ matrix.variant }}-
dl-
- name: Restore Cache of .ccache/
uses: actions/cache@v4
with:
path: .ccache/
key: ccache-${{ matrix.target }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
key: ccache-${{ matrix.platform }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
restore-keys: |
ccache-${{ matrix.target }}-
ccache-${{ matrix.platform }}-
ccache-
- name: Configure ${{ matrix.target }}
- name: Configure & Build
run: |
make ${{ matrix.target }}_defconfig
- name: Unit Test ${{ matrix.target }}
run: |
make test-unit
- name: Build ${{ matrix.target }}
run: |
echo "Building ${{ matrix.target }}_defconfig ..."
if [ "${{ matrix.variant }}" = "netconf" ]; then
target=${{ matrix.platform }}_defconfig
else
target=${{ matrix.platform }}_${{ matrix.variant }}_defconfig
fi
echo "Building $target ..."
sudo mkdir ${{ steps.vars.outputs.out }}
sudo chown $(id -un):$(id -gn) ${{ steps.vars.outputs.out }}
export O=${{ steps.vars.outputs.out }}
make $target
make
- name: Prepare ${{ matrix.target }} Artifact
- name: Prepare Artifact
run: |
cd output/
cd ${{ steps.vars.outputs.out }}
mv images ${{ steps.vars.outputs.dir }}
ln -s ${{ steps.vars.outputs.dir }} images
tar chfz ${{ steps.vars.outputs.tgz }} ${{ steps.vars.outputs.dir }}
- name: Test
if: matrix.platform == 'x86_64' && matrix.variant == 'netconf'
run: |
export O=${{ steps.vars.outputs.out }}
make test-qeneth
- uses: actions/upload-artifact@v4
with:
path: output/${{ steps.vars.outputs.tgz }}
name: artifact-${{ matrix.target }}
test:
name: Regression Test of Infix x86_64
needs: build
runs-on: [ self-hosted, regression ]
steps:
- uses: actions/checkout@v4
with:
clean: true
submodules: recursive
- name: Configure x86_64
run: |
make x86_64_defconfig
- uses: actions/download-artifact@v4
with:
pattern: "artifact-*"
merge-multiple: true
- name: Restore x86-64 output/
run: |
ls -l
mkdir -p output
mv infix-x86_64.tar.gz output/
cd output/
tar xf infix-x86_64.tar.gz
ln -s infix-x86_64 images
- name: Regression Test
run: |
make test
- name: Publish Test Result
# Ensure this runs even if Regression Test fails
if: always()
run: cat test/.log/last/result-gh.md >> $GITHUB_STEP_SUMMARY
path: ${{ steps.vars.outputs.out }}/${{ steps.vars.outputs.tgz }}
name: artifact-${{ matrix.variant }}-${{ matrix.platform }}
release:
if: ${{github.repository_owner == 'kernelkit' && github.ref_name == 'main'}}
name: Upload Latest Build
needs: test
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
@@ -119,13 +93,6 @@ jobs:
with:
pattern: "artifact-*"
merge-multiple: true
- name: Create checksums ...
run: |
for file in *.tar.gz; do
sha256sum $file > $file.sha256
done
- uses: ncipollo/release-action@v1
with:
allowUpdates: true
@@ -135,8 +102,7 @@ jobs:
prerelease: true
tag: "latest"
token: ${{ secrets.GITHUB_TOKEN }}
artifacts: "*.tar.gz*"
artifacts: "*.tar.gz"
- name: Summary
run: |
cat <<EOF >> $GITHUB_STEP_SUMMARY
+1 -8
View File
@@ -24,7 +24,6 @@ jobs:
--post-data "token=$TOKEN&project=${PROJECT_NAME}&md5=1" \
-O coverity-latest.tar.gz.md5
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
- uses: actions/cache@v4
id: cache
with:
@@ -34,7 +33,6 @@ jobs:
${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
${{ runner.os }}-coverity-
${{ runner.os }}-coverity
- name: Download Coverity Scan
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
@@ -49,14 +47,12 @@ jobs:
fi
mkdir coverity
tar xzf coverity-latest.tar.gz --strip 1 -C coverity
- name: Install dependencies
run: |
sudo apt-get -y update
sudo apt-get -y install pkg-config libjansson-dev libev-dev \
libcrypt-dev libglib2.0-dev libpcre2-dev \
libaugeas-dev libglib2.0-dev libpcre2-dev \
libuev-dev libite-dev
- name: Build dependencies
run: |
git clone https://github.com/CESNET/libyang.git
@@ -66,12 +62,10 @@ jobs:
mkdir sysrepo/build
(cd sysrepo/build && cmake .. && make all && sudo make install)
make dep
- name: Check applications
run: |
export PATH=`pwd`/coverity/bin:$PATH
cov-build --dir cov-int make check
- name: Submit results to Coverity Scan
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
@@ -84,7 +78,6 @@ jobs:
--form version=$(git rev-parse HEAD) \
--form description="${PROJECT_NAME} $(git rev-parse HEAD)" \
https://scan.coverity.com/builds?project=${PROJECT_NAME}
- name: Upload build.log
uses: actions/upload-artifact@v4
with:
+74
View File
@@ -0,0 +1,74 @@
name: Reggie Regression
on:
push:
branches:
- '*'
pull_request:
branches:
- '*'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
build:
name: Regression Testing
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
steps:
- uses: actions/checkout@v4
with:
submodules: 'true'
- name: Set Build Variables
id: vars
run: |
target=x86_64
echo "dir=infix-$target" >> $GITHUB_OUTPUT
echo "tgz=infix-$target.tar.gz" >> $GITHUB_OUTPUT
- name: Restore Cache of dl/
uses: actions/cache@v4
with:
path: dl/
key: dl-netconf-${{ hashFiles('.git/modules/buildroot/refs/heads/master', '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/refs/head/master', 'package/*/*.hash') }}
restore-keys: |
ccache-x86_64-
ccache-
- name: Configure NETCONF
run: |
make x86_64_defconfig
- name: Unit Test
run: make test-unit
- name: Build
run: |
make
- name: Prepare Artifact
run: |
cd output
mv images ${{ steps.vars.outputs.dir }}
ln -s ${{ steps.vars.outputs.dir }} images
tar cfz ${{ steps.vars.outputs.tgz }} ${{ steps.vars.outputs.dir }}
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
path: output/${{ steps.vars.outputs.tgz }}
- name: Regression Test
run: make test-qeneth
- name: Publish Test Result
# Ensure this runs even if Regression Test fails
if: always()
run: cat test/.log/last/result-gh.md >> $GITHUB_STEP_SUMMARY
+32 -38
View File
@@ -20,18 +20,20 @@ on:
jobs:
build:
if: github.repository == 'kernelkit/infix' && startsWith(github.ref, 'refs/tags/')
name: Build Infix ${{ github.ref_name }} [${{ matrix.target }}]
runs-on: [ self-hosted, release ]
name: Build Infix ${{ github.ref_name }} [${{ matrix.platform }}-${{ matrix.variant }}]
runs-on: ubuntu-latest
strategy:
matrix:
target: [aarch64, x86_64]
platform: [aarch64, x86_64]
variant: [netconf, classic]
fail-fast: false
steps:
- name: Maintenance
run: |
docker image prune -af
docker volume prune -f
docker container prune -f
- uses: actions/checkout@v4
with:
clean: true
submodules: recursive
- name: Set Release Variables
id: vars
run: |
@@ -42,66 +44,63 @@ jobs:
fi
echo "ver=${ver}" >> $GITHUB_OUTPUT
fver=${ver#v}
target=${{ matrix.target }}-${fver}
if [ "${{ matrix.variant }}" = "netconf" ]; then
target=${{ matrix.platform }}-${fver}
else
target=${{ matrix.platform }}-${{ matrix.variant }}-${fver}
fi
echo "dir=infix-$target" >> $GITHUB_OUTPUT
echo "tgz=infix-$target.tar.gz" >> $GITHUB_OUTPUT
echo "out=/mnt/x-$target" >> $GITHUB_OUTPUT
- name: Restore Cache of dl/
uses: actions/cache@v4
with:
path: dl/
key: dl-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
key: dl-${{ matrix.variant }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
restore-keys: |
dl-${{ matrix.variant }}-
dl-
- name: Restore Cache of .ccache/
uses: actions/cache@v4
with:
path: .ccache/
key: ccache-${{ matrix.target }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
key: ccache-${{ matrix.platform }}-${{ hashFiles('.git/modules/buildroot/HEAD', 'package/*/*.hash') }}
restore-keys: |
ccache-${{ matrix.target }}-
ccache-${{ matrix.platform }}-
ccache-
- name: Configure & Build
env:
INFIX_RELEASE: ${{ steps.vars.outputs.ver }}
run: |
target=${{ matrix.target }}_defconfig
if [ "${{ matrix.variant }}" = "netconf" ]; then
target=${{ matrix.platform }}_defconfig
else
target=${{ matrix.platform }}_${{ matrix.variant }}_defconfig
fi
echo "Building $target ..."
sudo mkdir ${{ steps.vars.outputs.out }}
sudo chown $(id -un):$(id -gn) ${{ steps.vars.outputs.out }}
export O=${{ steps.vars.outputs.out }}
make $target
make
- name: Generate SBOM from Build
- name: Prepare Artifact
run: |
make legal-info
- name: Prepare Artifacts
run: |
cd output/
cd ${{ steps.vars.outputs.out }}
mv images ${{ steps.vars.outputs.dir }}
ln -s ${{ steps.vars.outputs.dir }} images
tar chfz ${{ steps.vars.outputs.tgz }} ${{ steps.vars.outputs.dir }}
mv legal-info legal-info-$target
tar chfz legal-info-$target.tar.gz legal-info-$target
- uses: actions/upload-artifact@v4
with:
name: artifact-${{ matrix.target }}
path: output/*.tar.gz
path: ${{ steps.vars.outputs.out }}/${{ steps.vars.outputs.tgz }}
name: artifact-${{ matrix.variant }}-${{ matrix.platform }}
release:
name: Release Infix ${{ github.ref_name }}
needs: build
runs-on: [ self-hosted, release ]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
submodules: 'true'
- name: Set Release Variables
id: rel
run: |
@@ -123,24 +122,20 @@ jobs:
fi
echo "pre=${{ steps.rel.outputs.pre }}"
echo "latest=${{ steps.rel.outputs.latest }}"
- uses: actions/download-artifact@v4
with:
pattern: "artifact-*"
merge-multiple: true
- name: Create checksums ...
run: |
for file in *.tar.gz; do
sha256sum $file > $file.sha256
done
- name: Extract ChangeLog entry ...
run: |
awk '/^-----*$/{if (x == 1) exit; x=1;next}x' doc/ChangeLog.md \
|head -n -1 > release.md
cat release.md
- uses: ncipollo/release-action@v1
with:
name: Infix ${{ github.ref_name }}
@@ -148,7 +143,6 @@ jobs:
makeLatest: ${{ steps.rel.outputs.latest }}
bodyFile: release.md
artifacts: "*.tar.gz*"
- name: Summary
run: |
cat <<EOF >> $GITHUB_STEP_SUMMARY
+24 -1
View File
@@ -112,6 +112,29 @@ config INFIX_ARCH
default "riscv64" if BR2_riscv
default "x86_64" if BR2_x86_64
# For /etc/os-release, VARIANT & VARIANT_ID used, e.g., in mnt script
choice
prompt "Select variant/flavor"
default INFIX_VARIANT_NETCONF
config INFIX_VARIANT_NETCONF
bool "NETCONF"
help
Managed NETCONF mode, /etc is a ramdisk, all configuration is
generated by sysrepo plugins using NETCONF (xml) or RESTCONF.
config INFIX_VARIANT_CLASSIC
bool "Classic /etc mode"
help
User managed mode, read-write configuration files in /etc that
is saved across reboots.
endchoice
menu "Packages"
source "$BR2_EXTERNAL_INFIX_PATH/package/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/Config.in.host"
endmenu
source "$BR2_EXTERNAL_INFIX_PATH/board/common/Config.in"
+1 -9
View File
@@ -2,12 +2,7 @@ export BR2_EXTERNAL := $(CURDIR)
export PATH := $(CURDIR)/bin:$(PATH)
ARCH ?= $(shell uname -m)
O ?= output
# If a relative output path is specified, we have to translate it to
# an absolute one before handing over control to Buildroot, which will
# otherwise treat it as relative to ./buildroot.
override O := $(if $(filter /%,$O),$O,$(CURDIR)/$O)
O ?= $(CURDIR)/output
config := $(O)/.config
bmake = $(MAKE) -C buildroot O=$(O) $1
@@ -30,9 +25,6 @@ $(config):
%: | buildroot/Makefile
@+$(call bmake,$@)
legal-info: | buildroot/Makefile
$(call bmake,legal-info LINUX_LICENSE_FILES=COPYING)
# Workaround, see board/x86_64/board.mk
test:
@+$(call bmake,$@)
+23 -12
View File
@@ -1,16 +1,29 @@
[![License Badge][]][License] [![GitHub Status][]][GitHub] [![Coverity Status][]][Coverity Scan] [![Discord][discord-badge]][discord-url]
[![License Badge][]][License] [![Coverity Status][]][Coverity Scan] [![Discord][discord-badge]][discord-url]
<img align="right" src="doc/logo.png" alt="Infix - Linux <3 NETCONF" width=480 border=10>
<details><summary><b>Documentation</b></summary>
- **Infix In-Depth**
- [Infix Variants](doc/variant.md)
- [Boot Procedure](doc/boot.md)
- [Containers in Infix](doc/container.md)
- [Developer's Guide](doc/developers-guide.md)
- [Discover Your Device](doc/discovery.md)
- [Virtual Environments](doc/virtual.md)
- [Origin & Licensing](doc/license.md)
- **CLI Topics**
- [Introduction to the CLI](doc/cli/introduction.md)
- [CLI User's Guide](doc/cli/tutorial.md)
- [Quick Overview](doc/cli/quick.md)
</details>
Infix is a free, Linux based, immutable Network Operating System (NOS)
built on [Buildroot][1], and [sysrepo][2]. A powerful mix that ease
porting to different platforms, simplify long-term maintenance, and
provide made-easy management using NETCONF[^1] or the built-in command
line interface (CLI) from a console or SSH login.
> Click the **▶ Example CLI Session** foldout below for an example, or
> head on over to the [Infix Documentation](doc/README.md) for more
> information on how to set up the system.
provide made-easy management using NETCONF[^1] or the built-in [command
line interface (CLI)][3] from a console or SSH login. *Click the
foldout (▶ Example CLI Session) below for an example.*
Although primarily focused on switches and routers, the core values
may be appealing for other use-cases as well:
@@ -100,12 +113,13 @@ and testing, but can also be used for evaluation and demo purposes. For
more information, see: [Infix in Virtual Environments](doc/virtual.md).
> See the [GitHub Releases](https://github.com/kernelkit/infix/releases)
> page for our pre-built images. The *[Latest Build][]* has bleeding
> page for our pre-built images. The *Latest Build* has the bleeding
> edge images, if possible we recommend using a versioned release.
>
> For *customer specific builds* of Infix, see your product repository.
[^1]: NETCONF or RESTCONF, <https://datatracker.ietf.org/doc/html/rfc8040>
[^1]: NETCONF or RESTCONF, <https://datatracker.ietf.org/doc/html/rfc8040>,
for more information, see [Infix Variants](doc/variant.md).
[^2]: An immutable operating system is one with read-only file systems,
atomic updates, rollbacks, declarative configuration, and workload
@@ -116,11 +130,8 @@ more information, see: [Infix in Virtual Environments](doc/virtual.md).
[1]: https://buildroot.org/
[2]: https://www.sysrepo.org/
[3]: doc/cli/introduction.md
[Latest Build]: https://github.com/kernelkit/infix/releases/tag/latest
[License]: https://en.wikipedia.org/wiki/GPL_license
[License Badge]: https://img.shields.io/badge/License-GPL%20v2-blue.svg
[GitHub]: https://github.com/kernelkit/infix/actions/workflows/build.yml/
[GitHub Status]: https://github.com/kernelkit/infix/actions/workflows/build.yml/badge.svg
[Coverity Scan]: https://scan.coverity.com/projects/29393
[Coverity Status]: https://scan.coverity.com/projects/29393/badge.svg
[discord-badge]: https://img.shields.io/discord/1182652155618918411.svg?logo=discord
+64 -4
View File
@@ -1,7 +1,67 @@
aarch64
=======
Board Specific Documentation
----------------------------
- [Marvell CN9130-CRB](cn9130-crb/)
- [Microchip SparX-5i PCB135 (eMMC)](sparx5-pcb135/)
Microchip SparX-5i PCB135 (eMMC)
--------------------------------
At present, only FIT images are supported via the SparX-5i eval
board's U-Boot, which must contain a valid load address. If you are
using this board, after selecting your base configuration, run the
following command to supplement the existing config with the required
FIT options:
make board-enable-sparx-fit
### Unbricking
1. Don't load a corrupt bootloader to begin with
2. Done
If, for some reason, you didn't manage to follow step 1, you can use
the `FLASH_PROG`(`J4`) connector on the board to access the SPI flash
directly.
Using a [Bus Blaster][BB3] in combination with [dangerspi][dangerspi],
you can load a new bootloader. The schematic below details how to
connect the Bus Blaster to the board, but the concept should be
portable to any debugger/device based around an FTDI2232 chip.
```
Bus Blaster: FLASH_PROG (J4):
.---. .---.
VTG >o o| VTG SCK >o o| GND
TRST |o o| GND MISO |o o| #RESET_FLASH
TDI |o o| GND o o| 3V3
TMS |o o| GND #CS |o o| #SYSRESET
TCK o o| GND MOSI |o o| GND
RTCK o o| GND '---'
TDO |o o| GND
TSRST |o o| GND
DBGRQ |o o| GND
DBGACK |o o| GND
'---'
```
| Bus Blaster | FLASH_PROG |
|-------------|----------------|
| `VTG` | `3V3` |
| `GND` | `GND` |
| | |
| `VTG` | `#RESET_FLASH` |
| `GND` | `#SYSRESET` |
| | |
| `TDI` | `MOSI` |
| `TMS` | `#CS` |
| `TCK` | `SCK` |
| `TDO` | `MISO` |
With the cable in place, build U-Boot with the correct configuration:
make fireant_boot_defconfig && make
To flash it to the board, connect the cable to `J4` and run:
make board-sparx-flash-uboot
[BB3]: http://dangerousprototypes.com/docs/Bus_Blaster#Bus_Blaster_v3
[dangerspi]: https://github.com/wkz/dangerspi
-132
View File
@@ -1,132 +0,0 @@
Marvell CN9130-CRB
==================
## Build instructions
### Bootloader
Build the bootloader from the supplied `defconfig`. It might be useful
to build in a separate output directory if you want to build Infix
from the same working tree later:
make O=$(pwd)/x-cn9130-boot cn9130_crb_boot_defconfig
cd x-cn9130-boot
make
The artifact of interest is called `flash-image.bin`, which will be
located in the `images/` directory once the build completes.
### Infix
> If you do not want to build Infix from source, feel free to use a pre-built [release]
The standard `aarch64_defconfig` is compatible with this board:
make O=$(pwd)/x-aarch64 aarch64_defconfig
cd x-aarch64
make
Two artifacts from the `images/` directory of this build are required
to provision a new board:
- `rootfs.itb`: Netbootable image
- `infix-aarch64.pkg`: Standard upgrade bundle
## Provisioning
The overall provisioning flow, in which each step in described in
details in the following sections, is as follows:
- Strap board to boot from SPI FLASH
- Load `flash-image.bin` over UART
- Burn `flash-image.bin` to SPI FLASH
- Netboot `rootfs.itb`
- Run Infix's built-in provisioning script
- Reboot, now booting from the primary partition of the SD-card
#### Strap Board to Boot from SPI FLASH
By default, the board is strapped to boot from eMMC. However, Infix
assumes that the board will boot from SPI FLASH. Therefore we have to
ensure that the DIP switches of `SW2` on the board selects a
`BOOT_MODE` of `0x32`, meaning that the switches on positions 4, 3,
and 1 should be enabled (i.e. these need to be tied to ground):
```
.-----. .-----. .-----.
| | | | | PWR |
| SIM | | uSD | | |
| | | | '-----'
'-----' '-----'
|
v
.-----. .-----.
| SW1 | | SW2 |
'-----' '-----'
.--------------------------.
| |
| |
| CN9130 |
```
#### UART Boot U-Boot
Make sure that:
- [mvebu64boot] is installed and available in your shell's `$PATH`
- No other program is attached to `ttyUSB0`
- No power is applied to the board
1. Start `mvebu64boot`:
mvebu64boot -b /path/to/flash-image.bin /dev/ttyUSB0
2. Apply power
As soon as `mvebu64boot` completes, attach to the serial port,
e.g. using `screen(1)`, or `console(1)` and stop the normal boot
process by hitting any key.
#### Burn U-Boot to SPI FLASH
Make sure that:
- `eth1` is connected to a machine which serves `flash-image.bin` over
TFTP
- U-Boot can reach the TFTP server. If the neighboring machine is also
set up as a DHCP server, simply run the command `dhcp -`
To burn the bootloader to SPI FLASH, run the `bubt` command:
bubt flash-image.bin
Once the command completes, reset the board to verify that it can now
boot unassisted:
reset
#### Boot up `rootfs.itb`
U-Boot will automatically fallback to netboot since the SD-card is
still blank. Make sure that the PC provides the path to `rootfs.itb`
in DHCP option 67 ("bootfile").
#### Install Firmware
Login as `admin`/`admin`, setup networking to the PC, ensure that the date on
the device is reasonably correct, and run the provisioning script:
admin@infix:~$ sudo -i
root@infix:~$ udhcpc -i e28
root@infix:~$ date -us YYYY-MM-DD
root@infix:~$ /libexec/infix/prod/provision tftp://<PC-IP>/infix-aarch64.pkg /dev/mmcblk0
After successful completion, the device is fully provisioned. On the
next boot, the device will boot of its own accord from the primary
SD-card partition.
> If possible, serve `infix-aarch64.pkg` over HTTP instead, as
> libcurl's TFTP implementation is quite slow.
[release]: https://github.com/kernelkit/infix/releases
[mvebu64boot]: https://github.com/addiva-elektronik/mvebu64boot
@@ -17,11 +17,35 @@ run ixboot
boot_targets = "mmc1";
ethprime = "eth1";
/* This is a development platform, keep
* developer mode statically enabled.
/* Uncomment this if you're debugging U-Boot
*
* This will allow you to break out of the
* normal boot flow and into the interactive
* console.
*
* To upgrade U-Boot itself, simply set the
* `bootfile` variable to the path of
* `flash-image.bin` on your TFTP server, then
* issue `run ixupgradeboot`.
*/
ixbtn-devmode = "setenv dev_mode yes; echo Enabled";
ixbtn-factory = "echo \"No button available, use bootmenu\"";
/* bootdelay = "2"; */
/* ixupgradeboot = " */
/* dhcp */
/* setexpr fileblks ${filesize} + 0x1ff */
/* setexpr fileblks ${fileblks} / 0x200 */
/* mmc dev 1 */
/* part start mmc 1 boot bootstart */
/* part size mmc 1 boot bootsize */
/* mmc erase ${bootstart} ${bootsize} */
/* mmc write ${fileaddr} ${bootstart} ${fileblks} */
/* "; */
};
};
};
/* &cp0_eth0 { */
/* phy-mode = "10gbase-r"; */
/* }; */
@@ -1,6 +1,4 @@
CONFIG_DEVICE_TREE_INCLUDES="infix-env.dtsi infix-key.dtsi cn9130-crb-env.dtsi"
CONFIG_SYS_PROMPT="(cn9130-crb) "
CONFIG_ENV_IS_NOWHERE=y
# CONFIG_ENV_IS_IN_MMC is not set
CONFIG_MVEBU_SPI_BOOT=y
-1
View File
@@ -354,7 +354,6 @@
#define XSWP(_n, _label, _mac_offs, _phy) \
port@_n { \
SWP_COMMON(_n, _label, _mac_offs, "usxgmii", _phy); \
managed = "in-band-status"; \
}
#define GSWP(_n, _label, _mac_offs, _phy) \
@@ -1,69 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2020 Marvell International Ltd.
*/
#include "cn9130-crb.dtsi"
/ {
model = "Marvell Armada CN9130-CRB-A";
chosen {
infix {
/* "admin" */
factory-password-hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A";
usb-ports = <&cp0_usb3_1>;
usb-port-names = "USB";
};
};
};
&cp0_pcie0 {
status = "okay";
num-lanes = <4>;
num-viewport = <8>;
/* Generic PHY, providing serdes lanes */
phys = <&cp0_comphy0 0
&cp0_comphy1 0
&cp0_comphy2 0
&cp0_comphy3 0>;
iommu-map =
<0x0 &smmu 0x480 0x20>,
<0x100 &smmu 0x4a0 0x20>,
<0x200 &smmu 0x4c0 0x20>;
iommu-map-mask = <0x031f>;
};
&cp0_usb3_0 {
status = "okay";
usb-phy = <&cp0_usb3_0_phy0>;
phy-names = "usb";
};
&cp0_usb3_1 {
status = "okay";
usb-phy = <&cp0_usb3_0_phy1>;
phy-names = "usb";
};
&cp0_eth2 {
status = "okay";
phy-mode = "2500base-x";
};
&cp0_pinctrl {
cp0_expander0_pins: cp0-expander-pins-0 {
marvell,pins = "mpp39";
marvell,function = "gpio";
};
};
&expander0 {
pinctrl-names = "default";
pinctrl-0 = <&cp0_expander0_pins>;
interrupt-parent = <&cp0_gpio2>;
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells=<2>;
microchip,irq-mirror;
};
+2 -2
View File
@@ -227,10 +227,10 @@
/* ETH1 (Connection to BMC) */
&cp0_eth2 {
&cp0_eth1 {
status = "okay";
phy-mode = "sgmii";
phys = <&cp0_comphy5 2>;
phys = <&cp0_comphy5 0>;
managed = "in-band-status";
nvmem-cells = <&base_mac 0>;
-6
View File
@@ -175,15 +175,9 @@ CONFIG_VLAN_8021Q=y
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_MQPRIO=y
CONFIG_NET_CLS_BASIC=y
CONFIG_NET_CLS_BPF=y
CONFIG_NET_CLS_FLOWER=y
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_GACT=y
CONFIG_NET_ACT_MIRRED=y
CONFIG_NET_ACT_SKBEDIT=y
CONFIG_DCB=y
CONFIG_NETLINK_DIAG=y
CONFIG_MPLS=y
CONFIG_NET_MPLS_GSO=y
-64
View File
@@ -1,64 +0,0 @@
Microchip SparX-5i PCB135 (eMMC)
================================
At present, only FIT images are supported via the SparX-5i eval
board's U-Boot, which must contain a valid load address. If you are
using this board, after selecting your base configuration, run the
following command to supplement the existing config with the required
FIT options:
make board-enable-sparx-fit
## Unbricking
1. Don't load a corrupt bootloader to begin with
2. Done
If, for some reason, you didn't manage to follow step 1, you can use
the `FLASH_PROG`(`J4`) connector on the board to access the SPI flash
directly.
Using a [Bus Blaster][BB3] in combination with [dangerspi][dangerspi],
you can load a new bootloader. The schematic below details how to
connect the Bus Blaster to the board, but the concept should be
portable to any debugger/device based around an FTDI2232 chip.
```
Bus Blaster: FLASH_PROG (J4):
.---. .---.
VTG >o o| VTG SCK >o o| GND
TRST |o o| GND MISO |o o| #RESET_FLASH
TDI |o o| GND o o| 3V3
TMS |o o| GND #CS |o o| #SYSRESET
TCK o o| GND MOSI |o o| GND
RTCK o o| GND '---'
TDO |o o| GND
TSRST |o o| GND
DBGRQ |o o| GND
DBGACK |o o| GND
'---'
```
| Bus Blaster | FLASH_PROG |
|-------------|----------------|
| `VTG` | `3V3` |
| `GND` | `GND` |
| | |
| `VTG` | `#RESET_FLASH` |
| `GND` | `#SYSRESET` |
| | |
| `TDI` | `MOSI` |
| `TMS` | `#CS` |
| `TCK` | `SCK` |
| `TDO` | `MISO` |
With the cable in place, build U-Boot with the correct configuration:
make fireant_boot_defconfig && make
To flash it to the board, connect the cable to `J4` and run:
make board-sparx-flash-uboot
[BB3]: http://dangerousprototypes.com/docs/Bus_Blaster#Bus_Blaster_v3
[dangerspi]: https://github.com/wkz/dangerspi
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
. "$BR2_CONFIG"
# Prevent regen of host key at every boot, /etc is saved across reboots
if [ -L "$TARGET_DIR/etc/dropbear" ]; then
rm "$TARGET_DIR/etc/dropbear"
mkdir "$TARGET_DIR/etc/dropbear"
fi
# Classic builds don't have D-Bus
if [ -f "$TARGET_DIR/etc/dnsmasq.conf" ]; then
sed -i '/enable-dbus/d' "$TARGET_DIR/etc/dnsmasq.conf"
fi
+684
View File
@@ -0,0 +1,684 @@
#!/bin/sh
# COLUMS and ROWS should be set on the console, if not, use fallback
if [ -z "$COLUMNS" ]; then
if command -v tput; then
COLUMNS=$(tput cols)
else
COLUMNS=80
fi
fi
h1()
{
STR="$*"
if [ -n "$plain" ]; then
echo "$STR" | tr '[:lower:]' '[:upper:]'
echo "$STR" | sed 's/./=/g'
else
printf "\033[7m%-${COLUMNS}s\033[0m" "$STR"
fi
}
h2()
{
STR="$*"
if [ -n "$plain" ]; then
echo "$STR"
echo "$STR" | sed 's/./-/g'
else
printf "\033[1m%-${COLUMNS}s\033[0m" "$STR"
fi
}
ul()
{
if [ -n "$plain" ]; then
echo "__${*}__"
else
printf "\033[54%s\033[0m" "$*"
fi
}
em()
{
if [ -n "$plain" ]; then
echo "**${*}**"
else
printf "\033[5m%s\033[0m" "$*"
fi
}
overview()
{
cat <<EOF
$(h1 "Help System Press 'Q' to quit | Arrow keys and PgUp/PgDn to scroll")
$(h2 "See Also")
help edit Tutorial on VI and Mg editors
help net Network set up introduction
setup User friendly setup and diagnostic tool
$(h2 "General Syntax")
cmd [optional arg] E.g., use 'date -h' to get help for date command
$(h2 "File system")
pwd | ls | cd Show directory, contents, or change directory
cat file Show file contents
vi | mg [file] Edit file with the VI or Micro Emacs editor
$(h2 "Services")
initctl list Lists all configurable services (svc's)
initctl enable svc Enable a service 'svc'
initctl reload Reload init process' state, start/stop svc's
initctl start svc Start a stopped service 'svc'
initctl stop svc Stop 'svc'
initctl restart svc Restart a running 'svc'
initctl status [svc] Display running status of all services, or one 'svc'
$(h2 "Tools")
setup User friendly setup and diagnostic tool
date [-h] Display current time, or sets the system date
factory Factory reset the device (on the next boot)
hwclock [-h] Query or set the hardware clock (RTC)
logout | Ctrl-D Log out from TTY
mdio | mvls Low-level MDIO access, also for Marvell switch status
tail -F file Continuously read from a file Useful for monitoring the
health of services, see 'ls /var/log/' for log files
less [file] Pagers provding easily scrollable content (q quits) >
more [file] > e.g., 'cat very-long-file | less'
most [file] > e.g., 'cat very-long-file | most'
passwd Change user password
pwgen Password generator
reboot Restart the device
reset Reset the shell prompt if it gets garbled
$(h2 "Network Tools")
ethtool [-h] Ethernet stats, and low-level MAC/PHY settings
traceroute [-h] Trace the route ip packets follow going to a host
tcpdump [-h] Display network packet headers in real-time
arping [-h] Ping hosts by ARP requests/replies
fping [-h] Send ICMP ECHO_REQUEST packets to multiple hosts
ping [-h] Send ICMP ECHO_REQUEST packets to a network host
lynx URL [-h] The text mode web browser
netcalc [-h] Calculate IP network settings from a IP address
netcat [-h] NetCat - TCP/IP swiss army knife (alias: nc)
socat [-h] Multipurpose socket relay program
ttyd [-h] Sharing a terminal over the web
ifconfig [--help] See/Reconfigure available network interfaces
route [--help] Edit the kernel's routing tables
ifup | ifdown IFACE Bring up/down interfaces in /etc/network/interfaces
ip [link|addr] Manage available network interfaces
ip [rule|route] Manage routing tables
bridge [link|vlan] Manage bridge ports and VLANs
scp Securely copy a file to a remote host file system
tftp Copy a file to/from a remote host
ftpput Store a local file on a remote machine via FTP
ftpget Retrieve a remote file via FTP
wget Get a file using HTTP or FTP from a remote host
$(h2 "Overview Commands")
df -h List disk usage (in human readable format)
free List memory usage
ps List running processes
show [arg] Show system status, see 'show help' for more info
top Displays CPU usage and top list of running tasks
$(h2 "Interesting Files")
/etc/default/svc Command line args for service 'svc' (see above)
/etc/rc.local Local setup, runs after all services have started
/etc/network/ Directory of networking setup, see 'help net'
$(h2 "Example Commands")
cd /tmp; wget ftp://192.168.55.43/file && cat file
cd /var/log; tftp -p -l messages 192.168.55.43
cat /proc/net/arp
edit /etc/network/interfaces
$(h2 "See Also")
help edit Tutorial on VI and Mg editors
help net Network set up introduction
setup User friendly setup and diagnostic tool
EOF
}
vi()
{
cat <<EOF
$(h1 "Visual Editor (vi)")
Vi is the de facto standard editor in UNIX systems. It comes with two modes:
- $(em "Command mode (default):") administrative tasks such as saving files,
executing commands, moving the cursor, cutting and pasting lines or words,
as well as finding and replacing. $(em "Return to command mode with Esc")
- $(em "Insert mode:") Everything that's typed in this mode is interpreted as
input and placed in the file.
$(h2 "Navigation commands")
h - move the cursor one character to the left
j - move the cursor down one character
k - mode the cursor up one character
l - move the cursor right one character
b - move to beginning of word, or previous word
w - move to next word
0 - move to beginning of line
$ - move to end of line
:0 - move to beginning of file
G - move to end of file
$(h2 "Editing commands")
u - undo last operation
x - delete the character the cursor is on
cw - change word, from position of cursor
dw - delete to end of word
dd - delete the line the character is on
p - paste (line, word, or char) after cursor
P - paste (line, word, or char) before cursor
$(h2 "Saving and quit commands")
:w - save the current file
:w filename - save a copy of the file named filename
:w! - try to save the file, even if it is read only
:wq - save and quit vi
ZZ - save and quit vi
:wq! - try to save the file if it is read only, quit if successful
:wq filename - save a copy of the file named filename and quit
:wq! filename - save a copy of the file named filename and quit,
override read only permissions if possible
:q - quit vi
:q! - quit vi even if the file has unsaved changes
$(h2 "Enter insert mode")
a - append new text after the cursor
i - insert text before the cursor
o - open a new line below the cursor
O - open a new line above the cursor
> Return to command mode with Esc
EOF
}
emacs()
{
cat <<EOF
$(h1 "Micro Emacs (mg)")
Mg is a bit more user-friendly than vi. It has the same familiar interface
as Notepad, but with slightly different keybindings.
$(h2 "Introduction")
Most commands involve using the Control ("Ctrl") or the Meta ("Alt") key.
The following conventions are used in the online help:
C-<chr> means hold down the Control key while typing the character <chr>
M-<chr> means hold down the Alt key while typing the character <chr>
If you don't have a Meta/Alt key, you can use Esc instead. Press and release
the Esc key and then type <chr>. This is equivalent to M-<chr>.
$(h2 "Navigation")
Though arrow keys, Home/End, and PgUp/PgDn usually work, using Mg over serial
console can sometimes cause these keys to be mismapped by terminal program.
C-f Move forward one character (can also use right arrow key)
C-b Move backward one character (can also use left arrow key)
C-p Move up one line (can also use up arrow key)
C-n Move down one line (can also use down arrow key)
M-f Move forward one word
M-b Move backward one word
C-a Move to beginning of line (can also use Home key)
C-e Move to end of line (can also use End key)
C-v Move forward one page (can also use PgDn/Page Down key)
M-v Move backward one page (can also use PgUp/Page Up key)
M-< Move to beginning of file
M-> Move to end of file
C-x g Move to line number
$(h2 "Editing")
All edit commands that kill (cut) text is placed in a kill ring (clipboard).
Note: when marking text, there is no visual mark.
C-_ Undo, also C-x u
M-% Replace word/string in file, from cursor position
M-q Reformat paragraph (set fill column with C-x f)
C-s Search forward (type C-s again to find next)
C-r Reversed search
C-Space Set beginning of mark (beginning of selected text)
C-x C-x Jump back and forth between mark and cursor position
C-x h Mark whole buffer
C-w Wipe (cut) region from mark to cursor position
M-w Copy region from mark to cursor position
C-y Yank (paste) text from kill ring
C-k Kill (cut) to end of line
M-Backspace Kill (delete) previous word
M-d Kill (delete) next word
C-d Delete character to the right
C-o Open new line at cursor
$(h2 "General Commands")
C-g Abort current command
C-l Recenter buffer on current line
C-h b List all keybindings
M-! Run shell command, output in new buffer
C-z Suspend Mg, return to shell, use 'fg' to get back
C-x C-f Open file
C-x C-i Insert file at cursor position
C-x C-s Save file
C-x s Save file (interactive)
C-x k Kill (close) file
C-x C-b List open buffers (files)
C-x b Switch to another buffer
C-x C-c Exit
$(h2 "Window Commands")
C-x 0 Unsplit, keep other window
C-x 1 Unsplit, keep this window
C-x 2 Split window in two
C-x o Go to other window
C-x p Go to previous window
C-x n Go to next window
C-x ^ Enlarge this split
EOF
}
editor()
{
case $1 in
vi)
vi
;;
ed* | em* | mg)
emacs
;;
*)
vi
emacs
cat <<EOF
$(h1 "Summary")
Use Mg or GNU Nano if you are a beginner. The system is set up to so you can
use the 'edit' command, which will start GNU Nano:
edit /etc/rc.local # Starts GNU Nano
EOF
;;
esac
}
networking()
{
cat <<EOF
$(h1 "Networking")
This section details how to set up everything from basic to advanced networking.
Topics covered include:
- Static vs Dynamic Addresses
- VLAN Interfaces
- Bridging Interfaces
- Link Aggregation (bonding)
- Persistent Configuration
Please note, the terms 'port' and 'interface' may be used interchangably in
the following text (and elsewher online as well). Usually the term 'port' is
reserved for Ethernet links attached to a switch or bridge, while the term
'interface' more generically refers to the physical interface in a system.
$(h2 "Static vs Dynamic Addresses")
An IPv4 address consists of four "octets" separated by periods. A static IPv4
address can look like this:
192.168.1.42
However, for networking to function properly, a device usually needs a netmask,
default route, NTP server, and at least one DNS address. Setting all these up
statically is a lot of work to maintain, in particular with many devices.
For both IPv4 and IPv6 there is an alternative called DHCP. It is a dynamic
protocol where a server on request from a client device hands out a "lease" of
an IP address, as well as lot of other network parameters, including but not
limited to the ones already mentioned. A client device can give hints to the
server, e.g., its hostname, MAC address (default), or other client identifier.
It is up to the server to honor these hints or not, but it is very common to
set up the server to honor the client's hostname and automatically update the
central name server (DNS) when the client is online.
| There are many other interesting aspects to DHCP not covered here.
| For instance, DHCP relay servers (proxies), that can be used to
| forward DHCP requests from very large networks to a central server.
| Some relay "agents" even support something called Option 82, which
| when running on a simple switch, can attach port and relay info to
| the client's DHCP request -- allowing the server to assign an IP
| address per port, even on remote switches (with a relay agent).
When your interface is setup with DHCP, use the 'ifconfig' or 'ip addr' tools
to see which address you got, if needed (see next section).
In cases when the DHCP client cannot find a DHCP server, and thus not obtain a
lesae, the system falls back to set a link-local address (169.254.*.*). This
can be disabled by editing the file /etc/dhcpcd.conf, adding:
noipv4ll
A link-local address is however very useful, in particular in combination with
mDNS to discover and access a device you do not know, or do not want to know,
the IP address to. See more in the next section.
$(h2 "DNS and mDNS")
Managing a central DNS is both painful and time consuming, most networks, and
in particular industrial, therefore only set up a DNS for static servers and
resources. Leaving end devices, switches, and in many cases even routers,
without a human-friendly name on the network. This have misled many to think
that they need to know the IP address, and often opt for static addresses on
equipment. Meaning many devices out-of-the-box have a static address set that
need to be manually changed before the device is deployed on the network.
A less time consuming, and human-friendly, way is to enable mDNS (multicast
DNS). With this protocol the device notifies all neighbors on the same LAN
of how to reach it:
"Hello everyone, my address is 169.254.47.11, you can call me device.local"
Any other device that also has mDNS enabled can then automaticall update a
local database of name-to-address mappings. Usually the name sent out is
the device's hostname. (It is up to the device manufacturer to set a useful
default hostname, i.e., model-01-02-03, where the suffix is the last octets
of the base MAC address, from the product label on the case.)
As you can see, in combination with a link-local address (previous section)
mDNS is a very attractive combination that greatly simplify device management.
Tools:
avahi-browse -a
ping foo.local
mDNS, or more correctly mDNS-SD, is also used for *Service Discovery*. E.g.,
a printer can publish IPP records with meta data on the printer type and model
or donwload URL for drivers. Switches and routers usually publish how they
can be reached: HTTP/HTTPS and SSH.
mDNS is supported in this product and should be enabled by default. To
verify that it works, in Windows, macOS, or Linux, open your web browser
and point it to <https://hostname-01-02-03.local>. This is the hostname
and three last octets of the device's base MAC address. You can also use
mDNS browsers or command line tools like mdns-scan
$(h2 "VLAN Interfaces")
A VLAN interface in Linux is an "upper" interface, e.g., 'eth0.1'. It is
where you set an IP address and interact with th rest of the world. The
base/raw/lower interface, here 'eth0', is the physical interface on which
Ethernet packets ingress and egress with a VLAN tag. To create 'eth0.1':
ip link add eth0.1 link eth0 vlan id 1
In Linux a VLAN interface is a "stackable" entity. Many VLAN interfaces
can be built on top of each other. When injecting a packet on the top
most interface, the kernel adds the corresponding VLAN "tag" when the
packet goes down the order of stacked interfaces, and then finally hits
the physical interface and proceeds to egress onto the media.
ip link add eth0.1.2 link eth0.1 vlan id 2
Injecting a packet on 'eth0.1.2' creates a double-tagged VLAN frame when
the packet egresses 'eth0'. The outermost tag has VID 1 and the inner
VID is 2.
VLAN interfaces can be used for many things, here we will focus on their
use as upper interface on a bridge.
$(h2 "Bridging Interfaces")
A bridge is the correct name for a switch. In the context of this text,
however, we will use the term to refer to the Linux bridge module in the
kernel, which implements an advanced software switch. The Linux bridge
supports "offloading" many switching functions to an underlying switching
chipset, when available. This greatly simplifies managing that switch since
the same tools one use to manage the bridge will, by extension, also be used
to manage the switch.
To create a bridge in Linux:
ip link add br0 type bridge
To add three ports (interfaces) to the bridge we use:
ip link set eth0 master br0
ip link set eth1 master br0
ip link set eth2 master br0
Bring all ports and the bridge 'up' and you have a working switch! Any frame
injected on eth0 (from the outside) can be switched to either of eth1, eth2,
*or* br0. As soon as the bridge has learned where end devices are connected,
none of the other ports will see the traffic -- like a regular switch.
Note: these ports should not (cannot) have any IP address. Instead, any IP
address is set on 'br0'. To disable IPv6 link-local address, set the
/proc/sys/net/ipv6/conf/eth0/disable_ipv6 sysctl file to '1'.
$(h2 "Bridging and VLANs")
A VLAN-aware bridge works the same way, only with VLAN separation taken into
account. All communication, as well as MAC address learning, is limited to
ports in the same VLAN. The syntax is slightly different and requires a few
more steps:
ip link add br0 type bridge vlan_filtering 1
ip link set eth0 master br0
ip link set eth1 master br0
ip link set eth2 master br0
ip link set eth3 master br0
To assign ports to different VLANs, and make sure they are regular "access"
ports (untagged). We assign eth0 and eth1 to VLAN 1 and the others to VLAN 2:
bridge vlan add vid 1 dev eth0 pvid untagged
bridge vlan add vid 1 dev eth1 pvid untagged
bridge vlan add vid 2 dev eth2 pvid untagged
bridge vlan add vid 2 dev eth3 pvid untagged
Here's the twist, to be able to reach the bridge (switch) itself from each
VLAN, we need to ensure the bridge itself is a tagged member of each VLAN:
bridge vlan add vid 1 dev br0 self
bridge vlan add vid 2 dev br0 self
This way we can add VLAN interfaces on top of br0, which we in turn can set
a static or dynamic IP address on:
ip link add vlan1 link br0 type vlan id 1
ip link add vlan2 link br0 type vlan id 2
The resulting stack of interfaces look like this:
:
vlan1 : vlan2 Layer-3 :: IP Networking
\\ : / _________________________
.-------------.
| br0 | Layer-2 :: Switching
'-------------' _________________________
/ | : | \\
eth0 eth1 : eth2 eth3 Layer-1 :: Link layer
:
$(h2 "Persistent Configuration")
A simple end device can get by with the following in /etc/network/interfaces:
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
This brings up both the loopback (required for UNIX networking to function),
and the (presumed only) Ethernet interface. The loopback gets its standard
address, 127.0.0.1, and eth0 will request its IP address using DHCP.
To set up the bridge example (above), is actually quite a lot easier than
using the command line ip and bridge tools. Create the file 'bridge':
edit /etc/network/interfaces.d/bridge
Paste in the following content:
iface e0
bridge-access 1
iface e1
bridge-access 1
iface e2
bridge-access 2
iface e3
bridge-access 2
auto br0
iface br0
bridge-ports e0 e1 e2 e3
bridge-vlan-aware yes
bridge-stp on
bridge-vids 1 2
auto vlan1
iface vlan1 inet dhcp
vlan-id 1
vlan-raw-device br0
auto vlan2
iface vlan2 inet static
vlan-id 2
vlan-raw-device br0
address 192.168.2.1/24
Notice how 'vlan1' only has a DHCP and 'vlan2' uses a static address. It is
possible to combine the two if needed. Use 'inet dhcp' and add an 'address'
statement to the iface stanza.
$(h2 "Port Classification")
The bundled 'show' script is a very handy tool. It use several tricks to make
information about the system more accessible. On switching capable hardware
products, switch ports are identified early at system bootstrap and placed in
the 'port' group. See 'ip link' output:
...
4: e0: <BROADCAST,MULTICAST> master br0 state UP $(em "group port")
link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
...
When running in Qemu or other hardware it may be useful to manually classify
certain interfaces as ports. This can be achieved in many ways, here we show
two. First /etc/mactab, which is read at boot to rename interfaces according
their matching MAC address, one interface per line:
e0 52:54:00:12:34:56
e1 52:54:00:12:34:57
e2 52:54:00:12:34:58
e3 52:54:00:12:34:59
Another way is to add something like this to /etc/rc.local:
for port in eth0 eth1 eth3 eth4; do
ip link set \$port group port
done
$(h2 "Interesting Files")
- /etc/dhcpcd.conf General DHCP and ZeroConf (LL) settings
- /etc/network/interfaces The original, useful for small setups
- /etc/network/interfaces.d/* Snippets, useful for non-trivial setups
- /etc/mactab Rename interfaces: 'NAME16CHARS WHITESPACE MAC'
- /etc/sysctl.conf Interface and TCP/IP settings, e.g., routing
- /etc/sysctl.d/* Snippets, useful for per-subsystem settings
$(h1 "Summary")
All persistent networking is set up in /etc/network/interfaces using the
program ifupdown-ng. The tools to reconfigure networking at runtime are:
ifup [-a] [IFACES]
ifdown [-a] [IFACES]
When changing the configuration at runtime you usually have to bring the
affected interfaces down (ifdown e0 e1 e2 e3), if they were set up with
/etc/network/interfaces before. Then do the change, and bring it all up
again.
Both tools understand dependencies between interfaces, so when a 'ifup -a'
command is received it brings up all interfaces: adding links to br0 before
adding VLANs, the vlan1 and vlan2 interfaces on top so it of it all. Then
finally it can start the DHCP client on vlan1 and set the static IP address
on vlan2.
$(em ">>> Be careful with these tools when logged in remotely! <<<")
EOF
}
topic()
{
topic=$1
[ -n "$1" ] && shift
case $topic in
ed*)
# shellcheck disable=SC2068
editor $*
;;
net*)
networking
;;
*)
overview
;;
esac
}
if [ "$1" = "-p" ]; then
shift
pager="cat"
plain="yes"
else
if command -v most; then
pager=most
elif command -v less; then
pager="less -R"
elif command -v more; then
pager="more"
else
pager="cat"
fi
fi
if [ -t 1 ] ; then
fn=$(mktemp /tmp/system-help.XXXXXX)
# shellcheck disable=SC2086,SC2068
topic $@ >"$fn"
$pager "$fn"
rm "$fn"
else
topic "$*"
fi
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
# Changes hostname in /etc/hostname and /etc/hosts
current=$(cat /etc/hostname)
newname=$1
[ -n "$newname" ] || exit 1
sed -i "s/$current/$newname/" /etc/hosts
sed -i "s/$current/$newname/" /etc/hostname
hostname $newname
initctl touch sysklogd
initctl touch dnsmasq
initctl reload
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
pdmenu
clear
+327
View File
@@ -0,0 +1,327 @@
#!/bin/sh
# Displays basic information about the system
# shellcheck disable=SC2048,SC2086
. /etc/os-release
bopt="-c"
opt="-br"
all=""
plain=""
TTY=$(resize)
eval "$TTY"
# COLUMS and ROWS should be set on the console, if not, use fallback
if [ -z "$COLUMNS" ]; then
if command -v tput; then
COLUMNS=$(tput cols)
else
COLUMNS=80
fi
fi
h1()
{
STR="$*"
if [ -n "$plain" ]; then
echo "$STR" | tr '[:lower:]' '[:upper:]'
else
printf "\033[7m%-${COLUMNS}s\033[0m\n" "$STR"
fi
}
h2()
{
STR="$*"
if [ -n "$plain" ]; then
echo "$STR"
echo "$STR" | sed 's/./-/g'
else
printf "\033[1m%-${COLUMNS}s\033[0m\n" "$STR"
fi
}
dm()
{
if [ -n "$plain" ]; then
echo "${*}"
else
printf "\033[2m%s\033[0m\n" "$*"
fi
}
ul()
{
if [ -n "$plain" ]; then
printf "__%s__" "$*"
else
printf "\033[4%s\033[0m" "$*"
fi
}
em()
{
if [ -n "$plain" ]; then
printf "**%s**" "$*"
else
printf "\033[5m%s\033[0m" "$*"
fi
}
usage()
{
cat <<EOF
usage:
show [opt] cmd
options:
-a Show all, of something
-f Show full output, not brief port/iface listings
-h Show this help text
-n Show output without any footer
-p Show plain output, no bells or whistles
commands:
port PORT Show port configuration and link information
ports Show ports available for bridging
vlans Show port groups in bridge
ifaces Show interfaces and their addresses
fdb Show forwarding database (unicast)
mdb Show multicast forwarding database
ip route Show routing table
log [FILE] Show latest entries from syslog, or other FILE
rmon PORT Show RMON counters for PORT (when applicable)
system Show OS details
version Show OS verson
EOF
}
# Usage 1: show port eth0
# Usage 2: show port
# Usage 3: show ports
#
# The first show ethtool output for 'eth0' (in this case). The latter
# two are the same, showing a summary of all interfaces classified as
# access ports.
ports()
{
if [ $# -gt 0 ] && [ -e "/sys/class/net/$1" ]; then
for port in $*; do
ethtool "$port"
done
return
fi
h1 "PORT STATE MAC ADDRESS FLAGS"
if grep -q port /etc/iproute2/group && [ -z "$all" ]; then
ip $opt link show group port
else
ip $opt link show
fi
if [ -z "$plain" ] && [ -z "$nofoot" ]; then
dm "______________________________________________________________________________"
dm "Use: '[ip|bridge] --help' and '[ip|bridge] link help' for more details."
fi
}
vlans()
{
h1 "INTERFACE VLAN FLAGS"
bridge $bopt vlan show |tail +2 | awk 'NF { iface=$1; vid=$2; printf("%-16s %4d ", iface, vid); for (i=3; i <= NF; i++) printf("%s ", $i); printf("\n"); }'
if [ -z "$plain" ] && [ -z "$nofoot" ]; then
dm "______________________________________________________________________________"
dm "See: 'bridge --help' and 'bridge vlan help' for more details."
fi
}
ifaces()
{
h1 "INTERFACE STATE ADDRESS"
if [ -n "$all" ]; then
ip $opt addr show
elif grep -q iface /etc/iproute2/group; then
ip $opt addr show group iface
else
ip $opt addr show |awk '{ if ($1 !~ /eth[0-9]*/ && $1 !~ /.*@NONE/) { print }}'
fi
if [ -z "$plain" ] && [ -z "$nofoot" ]; then
dm "______________________________________________________________________________"
dm "See: 'ip --help' and 'ip address help' for more details."
fi
}
log()
{
if [ -n "$1" ] && [ -r "/var/log/$1" ]; then
fn="/var/log/$1"
else
fn="/var/log/syslog"
fi
if [ -n "$all" ]; then
cat $fn
else
tail -$LINES $fn
fi
if [ -z "$plain" ] && [ -z "$nofoot" ]; then
dm "______________________________________________________________________________"
dm "See: 'tail -25 /log/FILE', 'tail -F /log/FILE' to continuously monitor files."
fi
}
rmon()
{
if [ -z "$*" ]; then
echo "Missing argument, see 'show port' for available interfaces"
exit 1
fi
for port in $*; do
ethtool -S "$port"
done
if [ -z "$plain" ] && [ -z "$nofoot" ]; then
dm "______________________________________________________________________________"
dm "See: 'ethtool --help' for more details."
fi
}
rstp()
{
mstpctl showbridge
echo "br0 port info"
mstpctl showport br0
}
fdb()
{
bridge $bopt fdb show
}
mdb()
{
bridge $bopt mdb show
}
routes()
{
ip $opt route show
}
igmp()
{
querierctl $@
}
system()
{
h1 "SYSTEM INFORMATION"
echo "System Name : $(uname -n)"
echo "System Variant : $VARIANT"
echo "System Description : $PRETTY_NAME"
echo "System Contact : $HOME_URL"
echo "System Timezone : $(cat /etc/timezone)"
echo "System Type : $NAME"
echo "System Version : $(cat /etc/version)"
echo "System Arch : $(uname -m)"
echo "Kernel Version : $(uname -sr)"
}
version()
{
cat /etc/version
}
while [ "$1" != "" ]; do
case $1 in
-a)
all=1
;;
-f)
opt=""
if [ -n "$plain" ]; then
opt="-color=never"
bopt="-color=never"
fi
;;
-n)
nofoot="yes"
;;
-p)
plain="yes"
opt="$opt -color=never"
bopt="$bopt -color=never"
;;
-h)
usage
exit 0
;;
*)
break
esac
shift
done
cmd=$1
if [ -n "$cmd" ]; then
shift
fi
case $cmd in
help)
usage
;;
port*)
ports $*
;;
vlan*)
vlans
;;
fdb)
fdb
;;
mdb)
mdb
;;
if*)
ifaces
;;
ip)
cmd=$1
shift
case $cmd in
addr*)
ifaces
;;
route*)
routes
;;
igmp*)
igmp $*
;;
*)
usage
;;
esac
;;
log)
log $1
;;
rmon)
rmon $*
;;
route*)
routes
;;
span*)
rstp
;;
sys*)
system
;;
ver*)
version
;;
*)
usage
exit 1
;;
esac
+55
View File
@@ -0,0 +1,55 @@
#!/bin/sh
#set -x
usage()
{
cat <<EOF
usage:
yorn [-h] ["Do you want to run command?" command]
options:
-h Show this help text
-p Show plain output, no bells or whistles
Displays the yes-or-no question and runs command on yes.
EOF
}
if [ -z "$1" ]; then
usage
exit 1
fi
case $1 in
-h)
usage
exit 0
;;
-p)
plain=1
shift
;;
*)
;;
esac
question=$1
shift
command=$*
if [ -z "$command" ]; then
usage
exit 1
fi
if [ -z "$plain" ]; then
if dialog --erase-on-exit --colors --defaultno --yesno "\Zb$question\ZB" 0 0; then
yorn=y
fi
else
# shellcheck disable=SC2162,SC3045
read -n 1 -p "$question (y/N): " yorn
fi
if [ "$yorn" = "y" ] || [ "$yorn" = "Y" ]; then
$command
fi
+18
View File
@@ -0,0 +1,18 @@
# System-wide .bashrc file for interactive bash(1) shells.
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
# Reevaluate for each line, in case hostname changes
function prompt_command
{
PS1="\u@$(hostname):\w\$ "
}
export PROMPT_COMMAND=prompt_command
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# Disble built-ins
enable -n help
+51
View File
@@ -0,0 +1,51 @@
# Infix's configuration for dhcpcd.
# See dhcpcd.conf(5) for details.
# Allow users of this group to interact with dhcpcd via the control socket.
#controlgroup wheel
# Inform the DHCP server of our hostname for DDNS.
#hostname
# Use the hardware address of the interface for the Client ID.
#clientid
# or
# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
# Some non-RFC compliant DHCP servers do not reply with this set.
# In this case, comment out duid and enable clientid above.
duid
# Persist interface configuration when dhcpcd exits.
persistent
# vendorclassid is set to blank to avoid sending the default of
# dhcpcd-<version>:<os>:<machine>:<platform>
vendorclassid
# A list of options to request from the DHCP server.
option domain_name_servers, domain_name, domain_search
option classless_static_routes
# Respect the network MTU. This is applied to DHCP routes.
option interface_mtu
# Request a hostname from the network
option host_name
# Most distributions have NTP support.
#option ntp_servers
# Rapid commit support.
# Safe to enable by default because it requires the equivalent option set
# on the server to actually work.
option rapid_commit
# A ServerID is required by RFC2131.
require dhcp_server_identifier
# Generate SLAAC address using the Hardware Address of the interface
#slaac hwaddr
# OR generate Stable Private IPv6 Addresses based from the DUID
slaac private
# Background immediately, do not wait for DHCP lease (speed up boot process)
background
+144
View File
@@ -0,0 +1,144 @@
#
# Run-time configuration file for dialog
#
# Automatically generated by "dialog --create-rc <file>"
#
#
# Types of values:
#
# Number - <number>
# String - "string"
# Boolean - <ON|OFF>
# Attribute - (foreground,background,highlight?,underline?,reverse?)
# Set aspect-ration.
aspect = 0
# Set separator (for multiple widgets output).
separate_widget = ""
# Set tab-length (for textbox tab-conversion).
tab_len = 0
# Make tab-traversal for checklist, etc., include the list.
visit_items = OFF
# Shadow dialog boxes? This also turns on color.
use_shadow = ON
# Turn color support ON or OFF
use_colors = ON
# Screen color
screen_color = (WHITE,BLUE,OFF)
# Shadow color
shadow_color = (BLACK,BLACK,OFF)
# Dialog box color
dialog_color = (BLACK,CYAN,OFF)
# Dialog box title color
title_color = (BLACK,CYAN,ON)
# Dialog box border color
border_color = dialog_color
# Active button color
button_active_color = (CYAN,BLACK,ON)
# Inactive button color
button_inactive_color = dialog_color
# Active button key color
button_key_active_color = (WHITE,BLACK,ON)
# Inactive button key color
button_key_inactive_color = (WHITE,CYAN,ON)
# Active button label color
button_label_active_color = button_active_color
# Inactive button label color
button_label_inactive_color = dialog_color
# Input box color
inputbox_color = (BLACK,CYAN,OFF)
# Input box border color
inputbox_border_color = inputbox_color
# Search box color
searchbox_color = inputbox_color
# Search box title color
searchbox_title_color = (BLUE,WHITE,ON)
# Search box border color
searchbox_border_color = (WHITE,WHITE,ON)
# File position indicator color
position_indicator_color = searchbox_title_color
# Menu box color
menubox_color = dialog_color
# Menu box border color
menubox_border_color = dialog_color
# Item color
item_color = inputbox_color
# Selected item color
item_selected_color = button_key_active_color
# Tag color
tag_color = button_inactive_color
# Selected tag color
tag_selected_color = (CYAN,BLACK,OFF)
# Tag key color
tag_key_color = button_key_inactive_color
# Selected tag key color
tag_key_selected_color = (WHITE,BLACK,ON)
# Check box color
check_color = inputbox_color
# Selected check box color
check_selected_color = button_key_active_color
# Up arrow color
uarrow_color = (GREEN,WHITE,ON)
# Down arrow color
darrow_color = uarrow_color
# Item help-text color
itemhelp_color = (WHITE,BLACK,OFF)
# Active form text color
form_active_text_color = button_key_active_color
# Form text color
form_text_color = (WHITE,CYAN,ON)
# Readonly form item color
form_item_readonly_color = (CYAN,WHITE,ON)
# Dialog box gauge color
gauge_color = searchbox_title_color
# Dialog box border2 color
border2_color = dialog_color
# Input box border2 color
inputbox_border2_color = inputbox_color
# Search box border2 color
searchbox_border2_color = inputbox_color
# Menu box border2 color
menubox_border2_color = dialog_color
@@ -0,0 +1 @@
run [S] /libexec/infix/swup --
+112
View File
@@ -0,0 +1,112 @@
# NetBox mdev.conf based on https://github.com/slashbeast/mdev-like-a-boss/
# Syntax:
# [-]devicename_regex user:group mode [=path]|[>path]|[!] [@|$|*cmd args...]
# [-]$ENVVAR=regex user:group mode [=path]|[>path]|[!] [@|$|*cmd args...]
# [-]@maj,min[-min2] user:group mode [=path]|[>path]|[!] [@|$|*cmd args...]
#
# [-]: do not stop on this match, continue reading mdev.conf
# =: move, >: move and create a symlink
# !: do not create device node
# @|$|*: run cmd if $ACTION=remove, @cmd if $ACTION=add, *cmd in all cases
# support module loading on hotplug
$MODALIAS=.* root:root 660 @modprobe -b "$MODALIAS"
# null may already exist; therefore ownership has to be changed with command
null root:root 666 @chmod 666 $MDEV
zero root:root 666
full root:root 666
random root:root 444
urandom root:root 444
hwrandom root:root 444
grsec root:root 660
# Kernel-based Virtual Machine.
#kvm root:kvm 660
# vhost-net, to be used with kvm.
#vhost-net root:kvm 660
kmem root:root 640
mem root:root 640
port root:root 640
# console may already exist; therefore ownership has to be changed with command
console root:tty 600 @chmod 600 $MDEV
ptmx root:tty 666
pty.* root:tty 660
# Typical devices
tty root:tty 666
tty[0-9]* root:tty 660
vcsa*[0-9]* root:tty 660
ttyS[0-9]* root:dialout 660
# block devices
ram([0-9]*) root:disk 660 >rd/%1
loop([0-9]+) root:disk 660 >loop/%1
sr[0-9]* root:cdrom 660 @ln -sf $MDEV cdrom
fd[0-9]* root:floppy 660
#SUBSYSTEM=block;.* root:disk 660 */libexec/infix/storage-device
# Run settle-nics every time new NIC appear.
# If you don't want to auto-populate /etc/mactab with NICs,
# run 'settle-nis' without '--write-mactab' param.
#-SUBSYSTEM=net;DEVPATH=.*/net/.*;.* root:root 600 @/libexec/infix/settle-nics --write-mactab
net/tun[0-9]* root:netdev 660
net/tap[0-9]* root:root 600
# alsa sound devices and audio stuff
#SUBSYSTEM=sound;.* root:audio 660 @/libexec/infix/sound-control
adsp root:audio 660 >sound/
audio root:audio 660 >sound/
dsp root:audio 660 >sound/
mixer root:audio 660 >sound/
sequencer.* root:audio 660 >sound/
# raid controllers
cciss!(.*) root:disk 660 =cciss/%1
ida!(.*) root:disk 660 =ida/%1
rd!(.*) root:disk 660 =rd/%1
fuse root:root 666
card[0-9] root:video 660 =dri/
agpgart root:root 660 >misc/
psaux root:root 660 >misc/
rtc root:root 664 >misc/
# input stuff
SUBSYSTEM=input;.* root:plugdev 660
# v4l stuff
vbi[0-9] root:video 660 >v4l/
video[0-9] root:video 660 >v4l/
# dvb stuff
dvb.* root:video 660
# drm etc
dri/.* root:video 660
# Don't create old usbdev* devices.
usbdev[0-9].[0-9]* root:root 660 !
# Stop creating x:x:x:x which looks like /dev/dm-*
[0-9]+\:[0-9]+\:[0-9]+\:[0-9]+ root:root 660 !
# /dev/cpu support.
microcode root:root 600 =cpu/
cpu([0-9]+) root:root 600 =cpu/%1/cpuid
msr([0-9]+) root:root 600 =cpu/%1/msr
# Populate /dev/bus/usb.
#SUBSYSTEM=usb;DEVTYPE=usb_device;.* root:root 660 */libexec/infix/dev-bus-usb
# Catch-all other devices, Right now useful only for debuging.
#.* root:root 660 */libexec/infix/catch-all
+1
View File
@@ -0,0 +1 @@
Note: use help, show, and setup commands to set up and diagnose the system.
@@ -0,0 +1,6 @@
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback
source-directory /etc/network/interfaces.d
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/pdmenu
title:Setup & Diagnostics
color:desktop:blue:blue
color:title:blue:white
color:base:blue:white
menu:main:Main Menu:Use arrow keys, Enter, Escape, and Q to navigate
show:_System Settings..::system
show:_Network Settings..::network
show:_Tools..::tools
nop
exec:Show _fdb:truncate:show -p fdb
exec:Show _mdb:truncate:show -p mdb
exec:Show _ports:truncate:show -p ports
exec:Show _vlans:truncate:show -p vlans
exec:Show _interfaces:truncate:show -p iface
exec:Show _routes:truncate:show -p route
nop
exec:Show _online users:truncate:w
exec:Show _CPU Load::top
nop
show:_Help..::help
exit:_Quit
menu:help:Help:Help Menu
exec:Introduction:truncate:/bin/help -p
exec:Editors:truncate:/bin/help -p edit
exec:Networking:truncate:/bin/help -p net
nop
exit:_Main menu..
menu:network:Network:Network Settings
exec:Show all _links:truncated:ip -br link
exec:Show all _addresses:truncated:ip -br address
exec:Show managed _interfaces:truncated:ifparse --all
nop
exec:Take _interface down:edit:ifdown ~Enter name of interface to take down:~
exec:Take _interface up:edit:ifup ~Enter name of interface to take up:~
nop
exec:Edit _dhcpcd.conf::edit /etc/dhcpcd.conf
exec:Edit _dnsmasq.conf::edit /etc/dnsmasq.conf
exec:Edit _interfaces::edit /etc/network/interfaces
exec:Edit _mactab::edit /etc/mactab
exec:Edit _sysctl.conf::edit /etc/sysctl.conf
nop
exit:_Main menu..
menu:system:System:System Settings
exec:List _log files:truncate:ls -l /var/log
exec:Show _log file:edit,truncate:show -p -a log ~Show logfile, Enter for syslog:syslog~
exec:Change _hostname:edit:hostnm ~Enter new hostname \[-a-zA-Z0-9\]:~
exec:Change your _password::passwd
exec:Edit _rc.local::edit /etc/rc.local
nop
exec:_Show State of Services:truncate:initctl -p
exec:_Reload services:truncate:initctl reload;sleep 2;initctl -p
exec:Show _available services:truncate:initctl -p ls
exec:_Enable service:edit:initctl enable ~Enter name of service (filename) to enable:~
exec:_Disable service:edit:initctl disable ~Enter name of service (filename) to disable:~
nop
exec:_Factory Reset::yorn "Factory reset device (reboots), are you sure?" factory -y
nop
exit:_Main menu..
menu:tools:Tools:Tools
exec:_Ping:edit,pause:ping ~Enter address (IP or name) to ping:~
exec:_Shell Prompt::/bin/bash --login
exec:_SSH:edit,pause:ssh ~Enter [username@]address (IP or name) to SSH to:~
exec:_Telnet:edit,pause:telnet ~Enter address (IP or name) to telnet to:~
exec:_Traceroute:edit,pause:mtr ~Enter address (IP or name) to traceroute to:~
exec:Browse _WWW:edit,pause:lynx ~Enter URL to browse:~
nop
exit:_Main menu..
+19
View File
@@ -0,0 +1,19 @@
#!/bin/sh
# This file is run at the very end of runlevel S (bootstrap)
#
# Note: 1) not all initctl commands are allowed here
# 2) to enable IP forwarding, use /etc/sysctl.conf, or /etc/sysctl.d/
# 3) ensure the script calls `exit 0` at the end
#
# Uncomment to classify all interfaces starting with 'eth' as ports.
#for port in $(ip -br link |awk '/eth/{print $1}'); do
# ip link set $port group port
#done
# Uncomment to enable IP masquerading (NAT) of all traffic egressing
# the WAN interface, here eth0. E.g., if you are a router for your
# LAN on eth1.
#iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
exit 0
+62
View File
@@ -0,0 +1,62 @@
#!/bin/sh
# Factory default:
# 1) all switch ports in VLAN 1 of br0
# 2) no switch ports => DHCP on eth0
# 3) no eth0
create_bridge()
{
nm=$1
shift
ports=$@
touch "/etc/network/interfaces.d/$nm"
for port in $ports; do
cat <<-EOF >>"/etc/network/interfaces.d/$nm"
iface $port
bridge-access 1
post-up ip link set $port group port
EOF
done
cat <<-EOF >> "/etc/network/interfaces.d/$nm"
auto $nm
iface $nm
bridge-ports $ports
bridge-vlan-aware yes
bridge-stp on
bridge-vids 1
auto vlan1
iface vlan1 inet dhcp
vlan-id 1
vlan-raw-device $nm
post-up ip link set vlan1 group iface
EOF
ip link set vlan1 group iface
}
# Check if already set up
[ -z "$(ls -A /etc/network/interfaces.d/)" ] || exit 0
# Check for custom hostname from Qemu/Qeneth
nm=$(cat /sys/firmware/qemu_fw_cfg/by_name/opt/hostname/raw)
if [ -n "$nm" ]; then
hostnm "$nm"
fi
# need to check for 'length > 0' because ip command
# outputs empty json objects for non-port group ifs
ports=$(ip -json link show group port | jq -r '.[].ifname | select(length > 0)' | tr "\n" " ")
if [ -n "$ports" ]; then
create_bridge br0 $ports
else
ifaces=$(ip -json addr show |jq -r '.[] | select(.link_type=="ether").ifname')
for iface in $ifaces; do
cat <<-EOF > "/etc/network/interfaces.d/$iface"
auto $iface
iface $iface inet dhcp
pre-up ip link set $iface group iface
EOF
done
fi
+6
View File
@@ -0,0 +1,6 @@
#!/bin/sh
# Probe for various types of harware features
if dmesg |grep -q QEMU || test -d /sys/module/qemu_fw_cfg; then
initctl -nbq cond set qemu
fi
+2 -21
View File
@@ -18,27 +18,7 @@ endchoice
config SIGN_KEY
string "Signing key"
depends on SIGN_ENABLED
default "${BR2_EXTERNAL_INFIX_PATH}/board/common/signing-keys/development" if SIGN_SRC_DIR
menuconfig TRUSTED_KEYS
bool "Trusted keys for image"
depends on SIGN_ENABLED
help
Keys that will be accepted for this image
config TRUSTED_KEYS_DEVELOPMENT
bool "Development key"
depends on TRUSTED_KEYS
config TRUSTED_KEYS_DEVELOPMENT_PATH
string
depends on TRUSTED_KEYS_DEVELOPMENT
default "${BR2_EXTERNAL_INFIX_PATH}/board/common/signing-keys/development/infix.crt"
config TRUSTED_KEYS_EXTRA_PATH
string "Path to extra keys to include in image"
depends on TRUSTED_KEYS
default "${BR2_EXTERNAL_INFIX_PATH}/board/common/dev-key" if SIGN_SRC_DIR
menuconfig DISK_IMAGE
bool "Disk image"
@@ -160,3 +140,4 @@ config FIT_ARCH
config FIT_KERNEL_LOAD_ADDR
string "Kernel load address"
depends on FIT_IMAGE
+1 -3
View File
@@ -1,13 +1,11 @@
ifeq ($(SIGN_ENABLED),y)
include $(BR2_EXTERNAL_INFIX_PATH)/board/common/uboot/uboot.mk
TRUSTED_KEYS=$(TRUSTED_KEYS_DEVELOPMENT_PATH) $(TRUSTED_KEYS_EXTRA_PATH)
define RAUC_POST_BUILD_INSTALL_CERT
@$(call IXMSG,"Installing signing cert for RAUC")
mkdir -p $(TARGET_DIR)/etc/rauc/keys
$(foreach crt,$(shell ls $(TRUSTED_KEYS)), \
$(foreach crt,$(shell ls $(SIGN_KEY)/*.crt), \
cp $(crt) $(TARGET_DIR)/etc/rauc/keys/$(shell openssl x509 -hash -noout <$(crt)).0;)
endef
RAUC_POST_BUILD_HOOKS += RAUC_POST_BUILD_INSTALL_CERT
endif
-3
View File
@@ -44,19 +44,16 @@ image @DISKIMG@ {
partition aux {
offset = @AUXOFFS@
image = "aux.ext4"
partition-uuid = @AUXUUID@
}
partition primary {
image = "rootfs.squashfs"
size = @IMGSIZE@
partition-uuid = @PRIMARYUUID@
}
partition secondary {
image = "rootfs.squashfs"
size = @IMGSIZE@
partition-uuid = @SECONDARYUUID@
}
partition cfg {
+1 -9
View File
@@ -1,7 +1,6 @@
#!/bin/sh
set -e
. $BR2_EXTERNAL_INFIX_PATH/board/common/rootfs/etc/partition-uuid
set -e
K=10
M=20
@@ -158,9 +157,6 @@ genboot
# Use awk over sed because replacement text may contain newlines,
# which sed does not approve of.
awk \
-vauxuuid=$AUX_UUID \
-vprimaryuuid=$PRIMARY_UUID \
-vsecondaryuuid=$SECONDARY_UUID \
-vtotal=$total \
-vauxsize=$auxsize -vauxoffs=$auxoffs \
-vimgsize=$imgsize \
@@ -178,10 +174,6 @@ awk \
sub(/@DISKIMG@/, diskimg);
sub(/@BOOTIMG@/, bootimg);
sub(/@BOOTPART@/, bootpart);
sub(/@AUXUUID@/, auxuuid);
sub(/@PRIMARYUUID@/, primaryuuid);
sub(/@SECONDARYUUID@/, secondaryuuid);
}1' \
< $common/genimage.cfg.in >$root/genimage.cfg
+1 -1
View File
@@ -60,7 +60,7 @@ cat <<EOF >"$BINARIES_DIR/${NM}.gns3a"
"status": "stable",
"maintainer": "$VENDOR_NAME",
"maintainer_email": "${SUPPORT_URL#mailto:}",
"usage": "Default login, user/pass: admin/admin\n\nType 'cli' (and Enter) followed by 'help' for an overview of commands and relevant configuration files.",
"usage": "Default login, user/pass: admin/admin\n\nType 'help' for an overview of commands and relevant configuration files.\n\nFor Classic builds the following applies: the /etc directory is writable, use the passwd tool after login as part of your set up.\nFor networking, classify interfaces as switchports with /etc/mactab, syntax: 'MAC-address eN', where N is the port number (1-MAX).\nTo set up bridging and management interfaces, use /etc/network/interfaces, and /etc/network/interfaces.d/",
"port_name_format": "eth{0}",
"linked_clone": true,
"qemu": {
+7 -48
View File
@@ -1,40 +1,8 @@
#!/bin/sh
# shellcheck disable=SC1090,SC1091
common=$(dirname "$(readlink -f "$0")")
. "$BR2_CONFIG" 2>/dev/null
. "$TARGET_DIR/usr/lib/os-release"
# Extract list of loaded YANG modules and their features for yangdoc.html
mkyangdoc()
{
cmd="yangdoc -o $1 -p $TARGET_DIR/usr/share/yang"
# shellcheck disable=SC2155
export SYSREPO_SHM_PREFIX="yangdoc"
while IFS= read -r line; do
if echo "$line" | grep -q '^[a-z]'; then
module=$(echo "$line" | awk '{print $1}')
cmd="$cmd -m $module"
feature=$(echo "$line" | awk -F'|' '{print $8}' | sed 's/^ *//;s/ *$//')
if [ -n "$feature" ]; then
feature_list=$(echo "$feature" | tr ' ' '\n')
for feat in $feature_list; do
cmd="$cmd -e $feat"
done
fi
fi
done <<EOF
$(sysrepoctl -l; rm -f /dev/shm/${SYSREPO_SHM_PREFIX}*)
EOF
# Ignore a few top-level oddballs not used by core Infix
cmd="$cmd -x supported-algorithms"
# Execute the command
echo "Calling: $cmd"
$cmd
}
if [ -n "${ID_LIKE}" ]; then
ID="${ID} ${ID_LIKE}"
fi
@@ -63,7 +31,6 @@ rm -f "$TARGET_DIR/etc/os-release"
echo "ID=$INFIX_ID"
echo "PRETTY_NAME=\"$INFIX_TAGLINE $VERSION\""
echo "ID_LIKE=\"${ID}\""
echo "DEFAULT_HOSTNAME=$BR2_TARGET_GENERIC_HOSTNAME"
echo "VERSION=\"${VERSION}\""
echo "VERSION_ID=${VERSION}"
echo "BUILD_ID=\"${GIT_VERSION}\""
@@ -73,6 +40,13 @@ rm -f "$TARGET_DIR/etc/os-release"
if [ -n "$INFIX_RELEASE" ]; then
echo "IMAGE_VERSION=\"$INFIX_RELEASE\""
fi
if [ "$INFIX_VARIANT_NETCONF" = "y" ]; then
echo "VARIANT=\"Managed NETCONF\""
echo "VARIANT_ID=netconf"
else
echo "VARIANT=\"Classic, writable /etc\""
echo "VARIANT_ID=classic"
fi
echo "ARCHITECTURE=\"${INFIX_ARCH}\""
echo "HOME_URL=$INFIX_HOME"
if [ -n "$INFIX_VENDOR" ]; then
@@ -94,12 +68,6 @@ rm -f "$TARGET_DIR/etc/os-release"
echo "$INFIX_TAGLINE $VERSION -- $(date +"%b %e %H:%M %Z %Y")" > "$TARGET_DIR/etc/version"
# Drop Buildroot default symlink to /tmp
if [ -L "$TARGET_DIR/var/lib/avahi-autoipd" ]; then
rm "$TARGET_DIR/var/lib/avahi-autoipd"
mkdir "$TARGET_DIR/var/lib/avahi-autoipd"
fi
# Allow pdmenu (setup) and bash to be login shells, bash is added
# automatically when selected in menuyconfig, but not when BusyBox
# provides a symlink (for ash). The /bin/{true,false} are old UNIX
@@ -112,12 +80,3 @@ grep -qsE '^/bin/true$$' "$TARGET_DIR/etc/shells" \
|| echo "/bin/true" >> "$TARGET_DIR/etc/shells"
grep -qsE '^/bin/false$$' "$TARGET_DIR/etc/shells" \
|| echo "/bin/false" >> "$TARGET_DIR/etc/shells"
# Allow clish (symlink to /usr/bin/klish) to be a login shell
grep -qsE '^/bin/clish$$' "$TARGET_DIR/etc/shells" \
|| echo "/bin/clish" >> "$TARGET_DIR/etc/shells"
# Create YANG documentation
if [ "$BR2_PACKAGE_HOST_PYTHON_YANGDOC" = "y" ]; then
mkyangdoc "$BINARIES_DIR/yangdoc.html"
fi
+9 -10
View File
@@ -54,16 +54,17 @@ choice
config QEMU_CONSOLE_VIRTIO
bool "Virtio (hvc0)"
depends on QEMU_LOADER_KERNEL
config QEMU_CONSOLE_SERIAL
bool "Serial (ttyS0/ttyAMA0)"
depends on !QEMU_LOADER_OVMF
endchoice
config QEMU_MACHINE
string "Select emulated machine"
default "qemu-system-aarch64 -M virt,accel=kvm:tcg -cpu max" if QEMU_aarch64
default "qemu-system-x86_64 -M pc,accel=kvm:tcg -cpu max" if QEMU_x86_64
default "qemu-system-aarch64 -M virt -cpu cortex-a72" if QEMU_aarch64
default "qemu-system-x86_64 -M q35,accel=kvm -cpu host" if QEMU_x86_64
help
You should not have to change this setting, although you may
want to tweak it, or change the acceleration.
@@ -76,9 +77,9 @@ config QEMU_MACHINE_RAM
string "RAM size (k/M/G)"
default "384M"
help
The default, 384 MiB, works for most configurations. However,
if you get kernel panic with: "System is deadlocked on memory",
try increasing this one.
The default, 384 MiB, works for most configurations, even less for
the Infix Classic builds. However, if you get kernel panic with:
"System is deadlocked on memory", try increasing this one.
config QEMU_KERNEL
string
@@ -108,12 +109,10 @@ config QEMU_RW
default "cfg.ext4"
config QEMU_RW_VAR_OPT
bool "Separate writable /var"
bool "Separate writable /var (256MB)"
if QEMU_RW_VAR_OPT
config QEMU_RW_VAR_SIZE
string "Size of /var"
default "256M"
config QEMU_RW_VAR
string "Writable /var layer"
default "var.ext4"
+13 -29
View File
@@ -117,7 +117,7 @@ rootfs_args()
echo -n "-device sd-card,drive=mmc "
echo -n "-drive id=mmc,file=$CONFIG_QEMU_ROOTFS,if=none,format=raw "
elif [ "$CONFIG_QEMU_ROOTFS_VSCSI" = "y" ]; then
echo -n "-drive file=$CONFIG_QEMU_ROOTFS.qcow2,if=virtio,format=qcow2,bus=0,unit=0 "
echo -n "-drive file=$CONFIG_QEMU_ROOTFS,if=virtio,format=raw,bus=0,unit=0 "
fi
}
@@ -148,20 +148,14 @@ usb_args()
dd if=/dev/zero of=${USBSTICK} bs=8M count=1 >/dev/null 2>&1
mkfs.vfat $USBSTICK >/dev/null 2>&1
fi
echo -n "-drive if=none,id=usbstick,format=raw,file=$USBSTICK "
echo -n "-drive if=none,id=usbstick,format=raw,file=${USBSTICK} "
echo -n "-usb "
echo -n "-device usb-ehci,id=ehci "
echo -n "-device usb-storage,bus=ehci.0,drive=usbstick "
}
rw_args()
{
[ "$CONFIG_QEMU_RW" ] || return
if ! [ -f "aux.ext4" ]; then
dd if=/dev/zero of="aux.ext4" bs=1M count=1 >/dev/null 2>&1
mkfs.ext4 -L aux "aux.ext4" >/dev/null 2>&1
fi
echo -n "-drive file=aux.ext4,if=virtio,format=raw,bus=0,unit=3 "
[ "$CONFIG_QEMU_RW" ] || return
if ! [ -f "$CONFIG_QEMU_RW" ]; then
dd if=/dev/zero of="$CONFIG_QEMU_RW" bs=16M count=1 >/dev/null 2>&1
@@ -172,7 +166,7 @@ rw_args()
if [ "$CONFIG_QEMU_RW_VAR_OPT" ]; then
if ! [ -f "$CONFIG_QEMU_RW_VAR" ]; then
dd if=/dev/zero of="$CONFIG_QEMU_RW_VAR" bs=$CONFIG_QEMU_RW_VAR_SIZE count=1 >/dev/null 2>&1
dd if=/dev/zero of="$CONFIG_QEMU_RW_VAR" bs=256M count=1 >/dev/null 2>&1
mkfs.ext4 -L var "$CONFIG_QEMU_RW_VAR" >/dev/null 2>&1
fi
@@ -204,10 +198,10 @@ net_args()
echo -n "-fw_cfg name=opt/mactab,file=$mactab "
if [ "$CONFIG_QEMU_NET_BRIDGE" = "y" ]; then
echo -n "-netdev bridge,id=e1,br=$CONFIG_QEMU_NET_BRIDGE_DEV "
net_dev_args 1
echo -n "-netdev bridge,id=e0,br=$CONFIG_QEMU_NET_BRIDGE_DEV "
net_dev_args 0
elif [ "$CONFIG_QEMU_NET_TAP" = "y" ]; then
for i in $(seq 1 $(($CONFIG_QEMU_NET_TAP_N))); do
for i in $(seq 0 $(($CONFIG_QEMU_NET_TAP_N - 1))); do
echo -n "-netdev tap,id=e$i,ifname=qtap$i "
net_dev_args $i
done
@@ -215,8 +209,8 @@ net_args()
local useropts=
[ "$CONFIG_QEMU_NET_USER_OPTS" ] && useropts=",$CONFIG_QEMU_NET_USER_OPTS"
echo -n "-netdev user,id=e1${useropts} "
net_dev_args 1
echo -n "-netdev user,id=e0${useropts} "
net_dev_args 0
else
echo -n "-nic none"
fi
@@ -255,17 +249,8 @@ wdt_args()
echo -n "-device i6300esb -rtc clock=host"
}
gdb_args()
{
echo -n "-chardev socket,id=gdbqemu,path=gdbqemu.sock,server=on,wait=off "
echo -n "-gdb chardev:gdbqemu"
}
run_qemu()
{
if [ "$CONFIG_QEMU_ROOTFS_VSCSI" = "y" ]; then
qemu-img create -f qcow2 -o backing_file=$CONFIG_QEMU_ROOTFS -F raw $CONFIG_QEMU_ROOTFS.qcow2 > /dev/null
fi
local qemu
read qemu <<EOF
$CONFIG_QEMU_MACHINE -m $CONFIG_QEMU_MACHINE_RAM \
@@ -278,7 +263,6 @@ run_qemu()
$(net_args) \
$(wdt_args) \
$(vpd_args) \
$(gdb_args) \
$CONFIG_QEMU_EXTRA
EOF
@@ -319,10 +303,10 @@ generate_dot()
{
[ "$CONFIG_QEMU_NET_TAP" = "y" ] || return
hostports="<qtap1> qtap1"
targetports="<e1> e1"
edges="host:qtap1 -- target:e1 [kind=mgmt];"
for tap in $(seq 2 $(($CONFIG_QEMU_NET_TAP_N - 1))); do
hostports="<qtap0> qtap0"
targetports="<e0> e0"
edges="host:qtap0 -- target:e0 [kind=mgmt];"
for tap in $(seq 1 $(($CONFIG_QEMU_NET_TAP_N - 1))); do
hostports="$hostports | <qtap$tap> qtap$tap "
targetports="$targetports | <e$tap> e$tap "
edges="$edges host:qtap$tap -- target:e$tap;"
@@ -43,7 +43,7 @@ if [ -x /bin/ip -o -x /sbin/ip ] ; then
BIND)
ip addr flush dev "$2" label "$2:avahi"
ip addr add "$3"/16 brd 169.254.255.255 label "$2:avahi" scope link dev "$2" proto 6
ip route add default dev "$2" metric "$METRIC" scope link proto zeroconf ||:
ip route add default dev "$2" metric "$METRIC" scope link ||:
;;
CONFLICT|UNBIND|STOP)
+2 -6
View File
@@ -2,12 +2,8 @@
# managed by openresolv. DHCP lease, VPN tunnel establishment,
# and similar events feed servers and configuration to dnsmasq.
domain-needed
# Only listen to loopback (local system)
interface=lo
bind-dynamic
#listen-address=127.0.0.1,::1
#interface=lo
listen-address=127.0.0.1
enable-dbus
# Generated by openresolv
-1
View File
@@ -1,2 +1 @@
set COLORTERM=yes
rlimit soft core infinity
@@ -1 +1,3 @@
task name:ixinit log:tag:ixinit [S] <pid/syslogd> /libexec/finit/runparts -bp /libexec/infix/init.d -- Probing system
run [S] log:console /libexec/infix/probe -- Probing system information
run [S] <pid/syslogd> /libexec/infix/sysctl-sync-ip-conf --
run [S] <pid/syslogd> /libexec/infix/nameif -- Probing network interfaces
@@ -1,4 +1,4 @@
service :%i pid:!/run/k8s-logger-%i.pid <usr/container:%i> \
[2345] k8s-logger -cni %i -f local1 /run/containers/%i.fifo -- Logger for container %i
sysv :%i pid:!/run/container:%i.pid <pid/k8s-logger:%i> log kill:10 \
sysv :%i pid:!/run/container:%i.pid <pid/k8s-logger:%i> kill:10 \
[2345] container -n %i -- container %i
@@ -1 +0,0 @@
task [S] <service/confd/ready> /libexec/infix/mkcert -- Verifying self-signed https certificate
@@ -1,3 +0,0 @@
service name:rousette notify:none log <pid/confd> \
[12345] rousette --syslog -t 60 \
-- RESTCONF server
@@ -1 +0,0 @@
service [2345] <!> ttyd -i lo -p 8001 login -- Web terminal daemon (ttyd)
@@ -1 +0,0 @@
../available/mkcert.conf
+1 -1
View File
@@ -19,4 +19,4 @@ LABEL=aux /mnt/aux auto noatime,nodiratime,noauto 0 0
LABEL=var /mnt/var auto noatime,nodiratime,noauto 0 0
LABEL=cfg /mnt/cfg auto noatime,nodiratime,noauto 0 0
hostfs /mnt/host 9p cache=none,msize=16384,noauto 0 0
/libexec/infix/mnt# /cfg helper none 0 0
/libexec/infix/mnt# /cfg helper none 0 0
@@ -1,7 +1,3 @@
0 unspec
1 kernel_lo
2 kernel_ra
3 kernel_ll
4 static
5 dhcp
6 random
@@ -1 +0,0 @@
configure ports dsa0 lldp status disabled
-6
View File
@@ -1,6 +0,0 @@
# Sourced by mkcert at boot
country=SE
state=Vastmanland
city=Vasteras
org=KernelKit
unit=Infix
@@ -1,29 +0,0 @@
server {
listen 80;
listen [::]:80;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name _;
include ssl.conf;
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location / {
root html;
index index.html index.htm;
}
include /etc/nginx/app/*.conf;
}
@@ -1,10 +0,0 @@
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name network.local;
include ssl.conf;
location / {
include /etc/nginx/netbrowse.conf;
}
}
@@ -1,19 +0,0 @@
server {
listen 7681 ssl;
listen [::]:7681 ssl;
server_name _;
include ssl.conf;
location / {
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://127.0.0.1:8001;
proxy_redirect off;
}
}
@@ -1 +0,0 @@
../available/default.conf
@@ -1,6 +0,0 @@
location /netbrowse/ {
return 301 /netbrowse;
}
location /netbrowse {
include /etc/nginx/netbrowse.conf;
}
@@ -1,9 +0,0 @@
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
-24
View File
@@ -1,24 +0,0 @@
user www-data www-data;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/enabled/*.conf;
access_log syslog:server=unix:/dev/log,nohostname,facility=local7,severity=info;
error_log syslog:server=unix:/dev/log,nohostname,facility=local7 info;
}
@@ -1,8 +0,0 @@
# /telemetry/optics is for streaming (not used atm)
location ~ ^/(restconf|yang|.well-known)/ {
grpc_pass grpc://[::1]:10080;
grpc_set_header Host $host;
grpc_set_header X-Real-IP $remote_addr;
grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
grpc_set_header X-Forwarded-Proto $scheme;
}
-9
View File
@@ -1,9 +0,0 @@
ssl_certificate /etc/ssl/certs/self-signed.crt;
ssl_certificate_key /etc/ssl/private/self-signed.key;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
@@ -1,20 +0,0 @@
#%PAM-1.0
auth requisite pam_nologin.so
auth [success=1 default=ignore] pam_unix.so nullok
auth requisite pam_deny.so
auth required pam_permit.so
account requisite pam_nologin.so
account [success=1 default=ignore] pam_unix.so
account requisite pam_deny.so
account required pam_permit.so
password [success=1 default=ignore] pam_unix.so
password requisite pam_deny.so
password required pam_permit.so
session required pam_loginuid.so
session include common-session
session optional pam_keyinit.so force revoke
session optional pam_lastlog.so showfailed
session optional pam_motd.so
-20
View File
@@ -1,20 +0,0 @@
#%PAM-1.0
auth requisite pam_nologin.so
auth [success=1 default=ignore] pam_unix.so nullok
auth requisite pam_deny.so
auth required pam_permit.so
account requisite pam_nologin.so
account [success=1 default=ignore] pam_unix.so
account requisite pam_deny.so
account required pam_permit.so
password [success=1 default=ignore] pam_unix.so
password requisite pam_deny.so
password required pam_permit.so
session required pam_loginuid.so
session include common-session
session optional pam_keyinit.so force revoke
session optional pam_lastlog.so showfailed
session optional pam_motd.so
-3
View File
@@ -1,3 +0,0 @@
AUX_UUID="78460f84-de84-4fe7-89bd-4c1f433b2230"
PRIMARY_UUID="107ae911-a97b-4380-975c-7ce1a2dde1e0"
SECONDARY_UUID="352bd9b2-2ca9-44e2-bdc7-edbc87ba1e02"
@@ -1 +0,0 @@
UsePAM yes
@@ -1 +0,0 @@
kernel.core_pattern=/var/crash/core-%e
@@ -1,3 +1,2 @@
net.ipv4.ip_forward=1
net.ipv4.ip_forward_update_priority=0
net.ipv6.conf.all.forwarding=1
@@ -1,10 +0,0 @@
Reserved facilities for logging in various subsystems:
- local0: rauc
- local1: containers
- local2:
- local3:
- local5:
- local6: reserved
- local7: nginx
@@ -1,22 +0,0 @@
#!/bin/sh
# Find and install any product specific files in /etc before bootstrap
ident=$(basename "$0")
PREFIXD=/usr/share/product
PRODUCT=$(jq -r '."product-name" | ascii_downcase' /run/system.json)
note()
{
logger -k -p user.notice -t "$ident" "$1"
}
DIR="$PREFIXD/$PRODUCT"
if [ -z "$PRODUCT" ] || [ ! -d "$DIR" ]; then
note "No vendor/product specific directory found, using built-in defaults."
exit 0
fi
note "Using vendor/product specific defaults."
for dir in "$DIR"/*; do
[ -d "$dir" ] && cp -a "$dir" /
done
@@ -1,52 +0,0 @@
#!/bin/sh
# Opportunistically look for interfaces with multiple transmit queues
# and hardware support for the mqprio queuing discipline. For every
# matching interface, set up mappings from kernel-internal packet
# priorities, via traffic classes, to transmit queues such that as
# many high priorities as possible are scheduled on separate queues.
set -e
map()
{
case "$1" in
2)
echo "map 0 0 0 0 0 0 1 1";;
3)
echo "map 0 0 0 0 1 1 2 2";;
4)
echo "map 0 0 1 1 2 2 3 3";;
5)
echo "map 0 0 1 1 2 2 3 4";;
6)
echo "map 0 0 1 1 2 3 4 5";;
7)
echo "map 0 0 1 2 3 4 5 6";;
8)
echo "map 0 1 2 3 4 5 6 7";;
esac
}
queues()
{
out="queues "
for tc in $(seq 0 $(($1 - 1))); do
out="$out 1@$tc"
done
echo "$out"
}
set $(ip -j -d link show | jq -r '.[] | .ifname, .num_tx_queues')
while [ "$1" ]; do
iface="$1"
txqs="$2"
shift 2
[ $txqs -lt 2 ] && continue
[ $txqs -gt 8 ] && txqs=8
tc qdisc add dev $iface root mqprio hw 1 \
num_tc $txqs $(map $txqs) $(queues $txqs) || true
done
@@ -1,102 +0,0 @@
#!/bin/sh
# Run .cfg migration jq scripts to backup and transform older .cfg files
ident=$(basename "$0")
MIGRATIONS_DIR="/usr/share/confd/migrate"
CONFIG_FILE="/cfg/startup-config.cfg"
BACKUP_DIR="/cfg/backup"
note()
{
logger -k -p user.notice -t "$ident" "$1"
}
err()
{
logger -k -p user.err -t "$ident" "$1"
}
file_version()
{
jq -r '
if .["infix-meta:meta"] | has("version") then
.["infix-meta:meta"]["version"]
else
"0.0"
end
' "$1"
}
atoi()
{
echo "$1" | awk -F. '{print $1 * 1000 + $2}'
}
if [ ! -f "$CONFIG_FILE" ]; then
# Nothing to migrate
note "No $(basename "$CONFIG_FILE" .cfg) yet, likely factory reset."
exit 0
fi
cfg_version=$(file_version "$CONFIG_FILE")
current_version=$(atoi "$cfg_version")
# Find the latest version by examining the highest numbered directory
sys_version=$(find "$MIGRATIONS_DIR" -mindepth 1 -maxdepth 1 -type d | sort -V | tail -n1 | xargs -n1 basename)
latest_version=$(atoi "$sys_version")
# Check for downgrade
if [ "$current_version" -gt "$latest_version" ]; then
err "Configuration file $CONFIG_FILE version ($cfg_version) is newer than the latest supported version ($sys_version). Exiting."
exit 1
fi
# If the current version is already the latest, exit the script
if [ "$current_version" -eq "$latest_version" ]; then
note "Configuration is already at the latest version ($sys_version). No migration needed."
exit 0
fi
note "Configuration file $CONFIG_FILE is of version $cfg_version, migrating ..."
# Create the backup directory if it doesn't exist
mkdir -p "$BACKUP_DIR"
# Create a backup of the current configuration file
nm=$(basename "$CONFIG_FILE" .cfg)
BACKUP_FILE="$BACKUP_DIR/${nm}-${cfg_version}.cfg"
if cp "$CONFIG_FILE" "$BACKUP_FILE"; then
note "Backup created: $BACKUP_FILE"
else
err "Failed creating backup: $BACKUP_FILE"
exit 1
fi
# Apply the scripts for each version directory in sequence
for version_dir in $(find "$MIGRATIONS_DIR" -mindepth 1 -maxdepth 1 -type d | sort -V); do
dir=$(basename "$version_dir")
version=$(atoi "$dir")
# Step by step upgrade file to latest version
if [ "$current_version" -lt "$version" ]; then
note "Applying migrations for version $dir ..."
# Apply all scripts in the version directory in order
for script in $(find "$version_dir" -type f -name '*.sh' | sort -V); do
note "Calling $script for $CONFIG_FILE ..."
sh "$script" "$CONFIG_FILE"
done
# File now at $version ...
current_version="$version"
fi
done
# Update the JSON file to the latest version
if jq --arg version "$sys_version" '.["infix-meta:meta"]["infix-meta:version"] = $version' "$CONFIG_FILE" \
> "${CONFIG_FILE}.tmp" && mv "${CONFIG_FILE}.tmp" "$CONFIG_FILE"; then
note "Configuration updated to version $sys_version."
else
err "Failed updating configuration to version $sys_version!"
exit 1
fi
@@ -1,2 +0,0 @@
#!/bin/sh
exec initctl -bq cond set ixinit-done
-42
View File
@@ -1,42 +0,0 @@
#!/bin/sh
KEY=/cfg/ssl/private/self-signed.key
CRT=/cfg/ssl/certs/self-signed.crt
country=US
state=California
city=Berkeley
org="Acme, Inc."
unit=Second
if [ -f /etc/mkcert.conf ]; then
. /etc/mkcert.conf
fi
if [ -z "$cn" ]; then
cn=$1
if [ -z "$cn" ]; then
cn=$(hostname).local
fi
fi
generate()
{
mkdir -p /cfg/ssl/private /cfg/ssl/certs
chmod 700 /cfg/ssl/private
gencert --country "$country" --state "$state" --city "$city" --organisation "$org" \
--organisation-unit "$unit" --common-name "$cn" \
--out-certificate $CRT --out-key $KEY
}
CN=$(openssl x509 -noout -subject -in "${CRT}" 2>/dev/null |sed 's/.*CN=//')
if [ -z "$CN" ] || [ "$CN" != "$cn" ]; then
generate "$cn"
fi
cp "${KEY}" "/etc/ssl/private/"
cp "${CRT}" "/etc/ssl/certs/"
initctl cond set mkcert
exit 0
-14
View File
@@ -1,14 +0,0 @@
#!/bin/sh
# Generate NETCONF SSH host key pair
set -e
BIT=2048
KEY=$1
PUB=$2
mkdir -p "$(dirname "$KEY")" "$(dirname "$PUB")"
openssl genpkey -quiet -algorithm RSA -pkeyopt rsa_keygen_bits:$BIT -outform PEM > "$KEY"
openssl rsa -RSAPublicKey_out < "$KEY" > "$PUB"
exit 0
+5
View File
@@ -126,6 +126,11 @@ if ! mount_rw cfg >/dev/null 2>&1; then
# Even if /mnt/var isn't available, if /mnt/cfg isn't either, then
# there's no point in overlaying one ramdisk on top of another.
vlibsrc=
else
# Classic Infix has read-write /etc across boots
if [ "$VARIANT_ID" != "netconf" ]; then
etcsrc=/mnt/cfg
fi
fi
if check_factory; then
@@ -10,7 +10,8 @@ sysctl net.ipv4.conf.default >$tmp
sysctl net.ipv6.conf.default >>$tmp
for iface in $(ip -j link show | jq -r .[].ifname); do
sed -e "s/.default./.${iface}./g" $tmp | sysctl -q -p -
sed -e "s/.default./.${iface}./g" $tmp | sysctl -p -
done
rm $tmp
@@ -2,11 +2,6 @@
set -e
# We can't use bash's time, as it prints the timing information of the
# entire pipeline, meaning we can't redirect it to the log file.
TIME=$(which time)
TIMEFMT="\"time\": { \"real\": %e, \"user\": %U, \"sys\": %S },"
inform()
{
local level="$1"
@@ -40,7 +35,6 @@ action_exec()
local actdir="$2/action/$1"
local orderfile="$actdir/order"
local code=0
local meta=
generate_order "$2"
@@ -56,29 +50,9 @@ action_exec()
for node in $order; do
for work in $(find "$actdir/$node" -type f -executable 2>/dev/null | sort); do
meta=$work-meta.json
$work >>"$work.log" 2>&1 || code=$?
echo "[exit:$code]" >>"$work.log"
cat >$meta <<EOF
{
"generation": $(basename $2),
"action": "$1",
"node": "$node",
"work": "$(basename $work)",
EOF
$TIME -f "$TIMEFMT" -o $meta.time $work >>"$work.log" 2>&1 || code=$?
echo -ne "\t" >>$meta
# busybox's time(1) will happily write "Command exited
# with non-zero status" and similar messages to the
# output, even when -f is used. Work around that by only
# grabbing the last line, which holds the requested
# output.
tail -n1 $meta.time >>$meta
cat >>$meta <<EOF
"exitcode": $code
}
EOF
[ $code -eq 0 ] || abort "$work failed with exitcode $code"
done
done
+8 -60
View File
@@ -58,7 +58,6 @@ unpack_archive()
[ -n "$quiet" ] || log "Extracting OCI archive $file ..."
tar xf "$file" || (log "Error: failed unpacking $file in $(pwd)"; exit 1)
remove=true
fi
dir=$(dirname "$index")
@@ -73,10 +72,6 @@ unpack_archive()
name=$dir
fi
if [ "$remove" = "true" ]; then
rm -rf "$file"
fi
echo "$name"
}
@@ -108,8 +103,8 @@ create()
logging="--log-driver k8s-file --log-opt path=/run/containers/$name.fifo"
fi
args="$args --replace --quiet --cgroup-parent=containers $caps"
args="$args --restart=$restart --systemd=false --tz=local $privileged"
args="$args --cgroup-parent=containers"
args="$args --restart=$restart --systemd=false --tz=local $privileged --replace --quiet"
args="$args $ro $vol $mount $hostname $entrypoint $env $port $logging"
pidfn=/run/container:${name}.pid
@@ -130,11 +125,10 @@ create()
args="$args --dns-search=$domain"
done
else
args="$args --network=none"
network="--net none"
fi
# shellcheck disable=SC2048
log "Calling podman create --name $name --conmon-pidfile=$pidfn $args $image $*"
if podman create --name "$name" --conmon-pidfile="$pidfn" $args "$image" $*; then
[ -n "$quiet" ] || log "Successfully created container $name from $image"
rm -f "/run/containers/env/${name}.env"
@@ -222,20 +216,6 @@ netwrm()
done
}
# Schedule restart of (any) container using network $1 to activate network changes
netrestart()
{
net=$1
for c in $(podman ps $all --format "{{.Names}}"); do
for n in $(podman inspect "$c" |jq -r '.[].NetworkSettings.Networks | keys[]'); do
if [ "$n" = "$net" ]; then
initctl -nbq touch "container@$c"
fi
done
done
}
usage()
{
cat <<EOF
@@ -246,8 +226,6 @@ options:
-a, --all Show all, of something
--dns NAMESERVER Set nameserver(s) when creating a container
--dns-search LIST Set host lookup search list when creating container
--cap-add CAP Add capability to unprivileged container
--cap-drop CAP Drop capability, for privileged containter
-c, --creds USR[:PWD] Credentials to pass to curl -u for remote ops
-d, --detach Detach a container started with 'run IMG [CMD]'
-e, --env FILE Environment variables when creating container
@@ -281,7 +259,7 @@ commands:
list [image | oci] List names (only) of containers, images, or OCI archives
load [NAME | URL] NM Load OCI tarball fileNAME or URL to image NM
remove IMAGE Remove an (unused) container image
restart [network] NAME Restart a (crashed) container or container(s) using network
restart [NAME] Restart a crashed container
run NAME [CMD] Run a container interactively, with an optional command
save IMAGE FILE Save a container image to an OCI tarball FILE[.tar.gz]
shell Start a shell inside a container
@@ -298,14 +276,6 @@ while [ "$1" != "" ]; do
-a | --all)
all="-a"
;;
--cap-add)
shift
caps="$caps --cap-add=$1"
;;
--cap-drop)
shift
caps="$caps --cap-drop=$1"
;;
-c | --creds)
shift
creds="-u $1"
@@ -571,24 +541,8 @@ case $cmd in
if [ -n "$name" ]; then
wrap "$name" restart
elif [ -n "$1" ]; then
cmd=$1
name=$2
if [ "$cmd" = "network" ] && [ -n "$name" ]; then
netrestart "$name"
else
name=$1
stop "$name"
timeout=20
while running "$name"; do
_=$((timeout -= 1))
if [ $timeout -le 0 ]; then
log "Timeout waiting for container $1 to stop before restarting it."
exit 1
fi
sleep 1
done
start "$name"
fi
stop "$1"
start "$1"
else
usage
exit 1
@@ -613,14 +567,8 @@ case $cmd in
echo "No such container ($1), or invalid ImageName. Cannot upgrade."
exit 1;
fi
if echo "$img" | grep -Eq '^localhost/'; then
# Likely an OCI archive, or local directory, assume user has updated image.
file=$(awk '{s=$NF} END{print s}' "/var/lib/containers/active/${1}.sh")
echo "Upgrading container ${1} with local archive: $file ..."
else
podman stop "$1"
podman pull "$img" || (echo "Failed fetching $img, check your network (settings)."; exit 1)
fi
podman stop "$1"
podman pull "$img" || (echo "Failed fetching $img, check your network (settings)."; exit 1)
"/var/lib/containers/active/${1}.sh" || (echo "Failed recreating container $1"; exit 1)
;;
volume)
@@ -119,7 +119,7 @@ case "$ACTION" in
if [ -n "$hostname" ]; then
log "setting new hostname: $hostname"
hostname "$hostname"
sed -i -E "s/^(127\.0\.1\.1\s+).*/\1$hostname/" /etc/hosts
augtool -s "set /files/etc/hosts/*[ipaddr='127.0.1.1']/canonical $hostname"
fi
# drop info from this interface
+6 -9
View File
@@ -7,19 +7,16 @@
&env {
vendor = "infix";
preboot = "run ixpreboot";
ixbootdelay = "0.5";
bootdelay = "-2";
bootmenu_delay = "10";
bootcmd = "run ixbtn";
boot_targets = "virtio mmc";
bootcmd = "run ixboot";
ixpreboot = /incbin/("scripts/ixpreboot.sh");
ixbtn-devmode = /incbin/("scripts/ixbtn-devmode.sh");
ixbtn-factory = /incbin/("scripts/ixbtn-factory.sh");
ixfactory = /incbin/("scripts/ixfactory.sh");
ixbtn = /incbin/("scripts/ixbtn.sh");
ixdevmode = /incbin/("scripts/ixdevmode.sh");
ixfactory = /incbin/("scripts/ixfactory.sh");
ixbtn = /incbin/("scripts/ixbtn.sh");
ixboot = /incbin/("scripts/ixboot.sh");
ixbootmedia = /incbin/("scripts/ixbootmedia.sh");
ixbootslot = /incbin/("scripts/ixbootslot.sh");
ixprepblk = /incbin/("scripts/ixprepblk.sh");
ixprepdhcp = /incbin/("scripts/ixprepdhcp.sh");
-10
View File
@@ -1,6 +1,5 @@
# CONFIG_OF_OMIT_DTB is not set
CONFIG_DEVICE_TREE_INCLUDES="infix-env.dtsi infix-key.dtsi"
CONFIG_SYS_PROMPT="(ixboot) "
CONFIG_ENV_IMPORT_FDT=y
@@ -17,7 +16,6 @@ CONFIG_DISTRO_DEFAULTS=y
CONFIG_CMD_SETEXPR=y
CONFIG_CMD_SETEXPR_FMT=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_PCI=y
@@ -26,11 +24,3 @@ CONFIG_CMD_MMC=y
CONFIG_FS_SQUASHFS=y
CONFIG_CMD_SQUASHFS=y
CONFIG_PROT_TCP=y
CONFIG_PROT_TCP_SACK=y
CONFIG_CMD_WGET=y
CONFIG_USE_PREBOOT=y
CONFIG_CMD_BOOTMENU=y
CONFIG_CMD_PAUSE=y
# CONFIG_CMD_BOOTEFI_BOOTMGR is not set
@@ -0,0 +1,32 @@
From 4aef55d1b8cc24187f12f83a2f4d9bfc41ba12ee Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Mon, 30 Jan 2023 15:54:56 +0100
Subject: [PATCH v2 1/9] image: Fix script execution from FIT images with
external data
Update the script loading code to recognize when script data is stored
externally from the FIT metadata (i.e., built with `mkimage -E`).
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
boot/image-board.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/boot/image-board.c b/boot/image-board.c
index 25b60ec30b..af693c9c08 100644
--- a/boot/image-board.c
+++ b/boot/image-board.c
@@ -1111,7 +1111,8 @@ fallback:
}
/* get script subimage data address and length */
- if (fit_image_get_data(fit_hdr, noffset, &fit_data, &fit_len)) {
+ if (fit_image_get_data_and_size(fit_hdr, noffset,
+ &fit_data, &fit_len)) {
puts("Could not find script subimage data\n");
return 1;
}
--
2.34.1
@@ -0,0 +1,73 @@
From 74f121de98a1614a4068960445b8355cb3e5fa04 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 24 Jan 2023 14:00:04 +0100
Subject: [PATCH v2 2/9] cmd: blk: Allow generic read/write operations to work
in sandbox
Ensure that the memory destination/source addresses of block
read/write operations are mapped in before access. Currently, this is
only needed on sandbox builds.
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
cmd/blk_common.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/cmd/blk_common.c b/cmd/blk_common.c
index 75a072caf5..9f9d4327a9 100644
--- a/cmd/blk_common.c
+++ b/cmd/blk_common.c
@@ -11,6 +11,7 @@
#include <common.h>
#include <blk.h>
#include <command.h>
+#include <mapmem.h>
int blk_common_cmd(int argc, char *const argv[], enum uclass_id uclass_id,
int *cur_devnump)
@@ -63,31 +64,37 @@ int blk_common_cmd(int argc, char *const argv[], enum uclass_id uclass_id,
default: /* at least 4 args */
if (strcmp(argv[1], "read") == 0) {
- ulong addr = hextoul(argv[2], NULL);
+ phys_addr_t paddr = hextoul(argv[2], NULL);
lbaint_t blk = hextoul(argv[3], NULL);
ulong cnt = hextoul(argv[4], NULL);
+ void *vaddr;
ulong n;
printf("\n%s read: device %d block # "LBAFU", count %lu ... ",
if_name, *cur_devnump, blk, cnt);
+ vaddr = map_sysmem(paddr, 512 * cnt);
n = blk_read_devnum(uclass_id, *cur_devnump, blk, cnt,
- (ulong *)addr);
+ vaddr);
+ unmap_sysmem(vaddr);
printf("%ld blocks read: %s\n", n,
n == cnt ? "OK" : "ERROR");
return n == cnt ? 0 : 1;
} else if (strcmp(argv[1], "write") == 0) {
- ulong addr = hextoul(argv[2], NULL);
+ phys_addr_t paddr = hextoul(argv[2], NULL);
lbaint_t blk = hextoul(argv[3], NULL);
ulong cnt = hextoul(argv[4], NULL);
+ void *vaddr;
ulong n;
printf("\n%s write: device %d block # "LBAFU", count %lu ... ",
if_name, *cur_devnump, blk, cnt);
+ vaddr = map_sysmem(paddr, 512 * cnt);
n = blk_write_devnum(uclass_id, *cur_devnump, blk, cnt,
- (ulong *)addr);
+ vaddr);
+ unmap_sysmem(vaddr);
printf("%ld blocks written: %s\n", n,
n == cnt ? "OK" : "ERROR");
--
2.34.1
@@ -0,0 +1,501 @@
From 104a2ab39ac72c402d7463bec05aae4a6d09cfbf Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Feb 2023 15:06:12 +0100
Subject: [PATCH v2 3/9] blk: blkmap: Add basic infrastructure
blkmaps are loosely modeled on Linux's device mapper subsystem. The
basic idea is that you can create virtual block devices whose blocks
can be backed by a plethora of sources that are user configurable.
This change just adds the basic infrastructure for creating and
removing blkmap devices. Subsequent changes will extend this to add
support for actual mappings.
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
MAINTAINERS | 6 +
drivers/block/Kconfig | 18 ++
drivers/block/Makefile | 1 +
drivers/block/blk-uclass.c | 1 +
drivers/block/blkmap.c | 343 +++++++++++++++++++++++++++++++++++++
include/blkmap.h | 35 ++++
include/dm/uclass-id.h | 1 +
7 files changed, 405 insertions(+)
create mode 100644 drivers/block/blkmap.c
create mode 100644 include/blkmap.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 6f53f9c2f6..3e47c9b34c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -793,6 +793,12 @@ M: Alper Nebi Yasak <alpernebiyasak@gmail.com>
S: Maintained
F: tools/binman/
+BLKMAP
+M: Tobias Waldekranz <tobias@waldekranz.com>
+S: Maintained
+F: drivers/block/blkmap.c
+F: include/blkmap.h
+
BOOTDEVICE
M: Simon Glass <sjg@chromium.org>
S: Maintained
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index e95da48bdc..5a1aeb3d2b 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -67,6 +67,24 @@ config BLOCK_CACHE
it will prevent repeated reads from directory structures and other
filesystem data structures.
+config BLKMAP
+ bool "Composable virtual block devices (blkmap)"
+ depends on BLK
+ help
+ Create virtual block devices that are backed by various sources,
+ e.g. RAM, or parts of an existing block device. Though much more
+ rudimentary, it borrows a lot of ideas from Linux's device mapper
+ subsystem.
+
+ Example use-cases:
+ - Treat a region of RAM as a block device, i.e. a RAM disk. This let's
+ you extract files from filesystem images stored in RAM (perhaps as a
+ result of a TFTP transfer).
+ - Create a virtual partition on an existing device. This let's you
+ access filesystems that aren't stored at an exact partition
+ boundary. A common example is a filesystem image embedded in an FIT
+ image.
+
config SPL_BLOCK_CACHE
bool "Use block device cache in SPL"
depends on SPL_BLK
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index f12447d78d..a161d145fd 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_IDE) += ide.o
endif
obj-$(CONFIG_SANDBOX) += sandbox.o host-uclass.o host_dev.o
obj-$(CONFIG_$(SPL_TPL_)BLOCK_CACHE) += blkcache.o
+obj-$(CONFIG_BLKMAP) += blkmap.o
obj-$(CONFIG_EFI_MEDIA) += efi-media-uclass.o
obj-$(CONFIG_EFI_MEDIA_SANDBOX) += sb_efi_media.o
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index c69fc4d518..cb73faaeda 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -32,6 +32,7 @@ static struct {
{ UCLASS_EFI_LOADER, "efiloader" },
{ UCLASS_VIRTIO, "virtio" },
{ UCLASS_PVBLOCK, "pvblock" },
+ { UCLASS_BLKMAP, "blkmap" },
};
static enum uclass_id uclass_name_to_iftype(const char *uclass_idname)
diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c
new file mode 100644
index 0000000000..acfc002ceb
--- /dev/null
+++ b/drivers/block/blkmap.c
@@ -0,0 +1,343 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 Addiva Elektronik
+ * Author: Tobias Waldekranz <tobias@waldekranz.com>
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <blkmap.h>
+#include <dm.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <part.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+
+struct blkmap;
+
+/**
+ * struct blkmap_slice - Region mapped to a blkmap
+ *
+ * Common data for a region mapped to a blkmap, specialized by each
+ * map type.
+ *
+ * @node: List node used to associate this slice with a blkmap
+ * @blknr: Start block number of the mapping
+ * @blkcnt: Number of blocks covered by this mapping
+ */
+struct blkmap_slice {
+ struct list_head node;
+
+ lbaint_t blknr;
+ lbaint_t blkcnt;
+
+ /**
+ * @read: - Read from slice
+ *
+ * @read.bm: Blkmap to which this slice belongs
+ * @read.bms: This slice
+ * @read.blknr: Start block number to read from
+ * @read.blkcnt: Number of blocks to read
+ * @read.buffer: Buffer to store read data to
+ */
+ ulong (*read)(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt, void *buffer);
+
+ /**
+ * @write: - Write to slice
+ *
+ * @write.bm: Blkmap to which this slice belongs
+ * @write.bms: This slice
+ * @write.blknr: Start block number to write to
+ * @write.blkcnt: Number of blocks to write
+ * @write.buffer: Data to be written
+ */
+ ulong (*write)(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt, const void *buffer);
+
+ /**
+ * @destroy: - Tear down slice
+ *
+ * @read.bm: Blkmap to which this slice belongs
+ * @read.bms: This slice
+ */
+ void (*destroy)(struct blkmap *bm, struct blkmap_slice *bms);
+};
+
+/**
+ * struct blkmap - Block map
+ *
+ * Data associated with a blkmap.
+ *
+ * @label: Human readable name of this blkmap
+ * @blk: Underlying block device
+ * @slices: List of slices associated with this blkmap
+ */
+struct blkmap {
+ char *label;
+ struct udevice *blk;
+ struct list_head slices;
+};
+
+static bool blkmap_slice_contains(struct blkmap_slice *bms, lbaint_t blknr)
+{
+ return (blknr >= bms->blknr) && (blknr < (bms->blknr + bms->blkcnt));
+}
+
+static bool blkmap_slice_available(struct blkmap *bm, struct blkmap_slice *new)
+{
+ struct blkmap_slice *bms;
+ lbaint_t first, last;
+
+ first = new->blknr;
+ last = new->blknr + new->blkcnt - 1;
+
+ list_for_each_entry(bms, &bm->slices, node) {
+ if (blkmap_slice_contains(bms, first) ||
+ blkmap_slice_contains(bms, last) ||
+ blkmap_slice_contains(new, bms->blknr) ||
+ blkmap_slice_contains(new, bms->blknr + bms->blkcnt - 1))
+ return false;
+ }
+
+ return true;
+}
+
+static int blkmap_slice_add(struct blkmap *bm, struct blkmap_slice *new)
+{
+ struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
+ struct list_head *insert = &bm->slices;
+ struct blkmap_slice *bms;
+
+ if (!blkmap_slice_available(bm, new))
+ return -EBUSY;
+
+ list_for_each_entry(bms, &bm->slices, node) {
+ if (bms->blknr < new->blknr)
+ continue;
+
+ insert = &bms->node;
+ break;
+ }
+
+ list_add_tail(&new->node, insert);
+
+ /* Disk might have grown, update the size */
+ bms = list_last_entry(&bm->slices, struct blkmap_slice, node);
+ bd->lba = bms->blknr + bms->blkcnt;
+ return 0;
+}
+
+static ulong blkmap_blk_read_slice(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt,
+ void *buffer)
+{
+ lbaint_t nr, cnt;
+
+ nr = blknr - bms->blknr;
+ cnt = (blkcnt < bms->blkcnt) ? blkcnt : bms->blkcnt;
+ return bms->read(bm, bms, nr, cnt, buffer);
+}
+
+static ulong blkmap_blk_read(struct udevice *dev, lbaint_t blknr,
+ lbaint_t blkcnt, void *buffer)
+{
+ struct blk_desc *bd = dev_get_uclass_plat(dev);
+ struct blkmap *bm = dev_get_plat(dev->parent);
+ struct blkmap_slice *bms;
+ lbaint_t cnt, total = 0;
+
+ list_for_each_entry(bms, &bm->slices, node) {
+ if (!blkmap_slice_contains(bms, blknr))
+ continue;
+
+ cnt = blkmap_blk_read_slice(bm, bms, blknr, blkcnt, buffer);
+ blknr += cnt;
+ blkcnt -= cnt;
+ buffer += cnt << bd->log2blksz;
+ total += cnt;
+ }
+
+ return total;
+}
+
+static ulong blkmap_blk_write_slice(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer)
+{
+ lbaint_t nr, cnt;
+
+ nr = blknr - bms->blknr;
+ cnt = (blkcnt < bms->blkcnt) ? blkcnt : bms->blkcnt;
+ return bms->write(bm, bms, nr, cnt, buffer);
+}
+
+static ulong blkmap_blk_write(struct udevice *dev, lbaint_t blknr,
+ lbaint_t blkcnt, const void *buffer)
+{
+ struct blk_desc *bd = dev_get_uclass_plat(dev);
+ struct blkmap *bm = dev_get_plat(dev->parent);
+ struct blkmap_slice *bms;
+ lbaint_t cnt, total = 0;
+
+ list_for_each_entry(bms, &bm->slices, node) {
+ if (!blkmap_slice_contains(bms, blknr))
+ continue;
+
+ cnt = blkmap_blk_write_slice(bm, bms, blknr, blkcnt, buffer);
+ blknr += cnt;
+ blkcnt -= cnt;
+ buffer += cnt << bd->log2blksz;
+ total += cnt;
+ }
+
+ return total;
+}
+
+static const struct blk_ops blkmap_blk_ops = {
+ .read = blkmap_blk_read,
+ .write = blkmap_blk_write,
+};
+
+U_BOOT_DRIVER(blkmap_blk) = {
+ .name = "blkmap_blk",
+ .id = UCLASS_BLK,
+ .ops = &blkmap_blk_ops,
+};
+
+int blkmap_dev_bind(struct udevice *dev)
+{
+ struct blkmap *bm = dev_get_plat(dev);
+ struct blk_desc *bd;
+ int err;
+
+ err = blk_create_devicef(dev, "blkmap_blk", "blk", UCLASS_BLKMAP,
+ dev_seq(dev), 512, 0, &bm->blk);
+ if (err)
+ return log_msg_ret("blk", err);
+
+ INIT_LIST_HEAD(&bm->slices);
+
+ bd = dev_get_uclass_plat(bm->blk);
+ snprintf(bd->vendor, BLK_VEN_SIZE, "U-Boot");
+ snprintf(bd->product, BLK_PRD_SIZE, "blkmap");
+ snprintf(bd->revision, BLK_REV_SIZE, "1.0");
+
+ /* EFI core isn't keen on zero-sized disks, so we lie. This is
+ * updated with the correct size once the user adds a
+ * mapping.
+ */
+ bd->lba = 1;
+
+ return 0;
+}
+
+int blkmap_dev_unbind(struct udevice *dev)
+{
+ struct blkmap *bm = dev_get_plat(dev);
+ struct blkmap_slice *bms, *tmp;
+ int err;
+
+ list_for_each_entry_safe(bms, tmp, &bm->slices, node) {
+ list_del(&bms->node);
+ free(bms);
+ }
+
+ err = device_remove(bm->blk, DM_REMOVE_NORMAL);
+ if (err)
+ return err;
+
+ return device_unbind(bm->blk);
+}
+
+U_BOOT_DRIVER(blkmap_root) = {
+ .name = "blkmap_dev",
+ .id = UCLASS_BLKMAP,
+ .bind = blkmap_dev_bind,
+ .unbind = blkmap_dev_unbind,
+ .plat_auto = sizeof(struct blkmap),
+};
+
+struct udevice *blkmap_from_label(const char *label)
+{
+ struct udevice *dev;
+ struct uclass *uc;
+ struct blkmap *bm;
+
+ uclass_id_foreach_dev(UCLASS_BLKMAP, dev, uc) {
+ bm = dev_get_plat(dev);
+ if (bm->label && !strcmp(label, bm->label))
+ return dev;
+ }
+
+ return NULL;
+}
+
+int blkmap_create(const char *label, struct udevice **devp)
+{
+ char *hname, *hlabel;
+ struct udevice *dev;
+ struct blkmap *bm;
+ size_t namelen;
+ int err;
+
+ dev = blkmap_from_label(label);
+ if (dev) {
+ err = -EBUSY;
+ goto err;
+ }
+
+ hlabel = strdup(label);
+ if (!hlabel) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ namelen = strlen("blkmap-") + strlen(label) + 1;
+ hname = malloc(namelen);
+ if (!hname) {
+ err = -ENOMEM;
+ goto err_free_hlabel;
+ }
+
+ strlcpy(hname, "blkmap-", namelen);
+ strlcat(hname, label, namelen);
+
+ err = device_bind_driver(dm_root(), "blkmap_dev", hname, &dev);
+ if (err)
+ goto err_free_hname;
+
+ device_set_name_alloced(dev);
+ bm = dev_get_plat(dev);
+ bm->label = hlabel;
+
+ if (devp)
+ *devp = dev;
+
+ return 0;
+
+err_free_hname:
+ free(hname);
+err_free_hlabel:
+ free(hlabel);
+err:
+ return err;
+}
+
+int blkmap_destroy(struct udevice *dev)
+{
+ int err;
+
+ err = device_remove(dev, DM_REMOVE_NORMAL);
+ if (err)
+ return err;
+
+ return device_unbind(dev);
+}
+
+UCLASS_DRIVER(blkmap) = {
+ .id = UCLASS_BLKMAP,
+ .name = "blkmap",
+};
diff --git a/include/blkmap.h b/include/blkmap.h
new file mode 100644
index 0000000000..3c7e36efab
--- /dev/null
+++ b/include/blkmap.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2023 Addiva Elektronik
+ * Author: Tobias Waldekranz <tobias@waldekranz.com>
+ */
+
+#ifndef _BLKMAP_H
+#define _BLKMAP_H
+
+/**
+ * blkmap_from_label() - Find blkmap from label
+ *
+ * @label: Label of the requested blkmap
+ * Returns: A pointer to the blkmap on success, NULL on failure
+ */
+struct udevice *blkmap_from_label(const char *label);
+
+/**
+ * blkmap_create() - Create new blkmap
+ *
+ * @label: Label of the new blkmap
+ * @devp: If not NULL, updated with the address of the resulting device
+ * Returns: 0 on success, negative error code on failure
+ */
+int blkmap_create(const char *label, struct udevice **devp);
+
+/**
+ * blkmap_destroy() - Destroy blkmap
+ *
+ * @dev: The blkmap to be destroyed
+ * Returns: 0 on success, negative error code on failure
+ */
+int blkmap_destroy(struct udevice *dev);
+
+#endif /* _BLKMAP_H */
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 33e43c20db..576237b954 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -37,6 +37,7 @@ enum uclass_id {
UCLASS_AUDIO_CODEC, /* Audio codec with control and data path */
UCLASS_AXI, /* AXI bus */
UCLASS_BLK, /* Block device */
+ UCLASS_BLKMAP, /* Composable virtual block device */
UCLASS_BOOTCOUNT, /* Bootcount backing store */
UCLASS_BOOTDEV, /* Boot device for locating an OS to boot */
UCLASS_BOOTMETH, /* Bootmethod for booting an OS */
--
2.34.1
@@ -0,0 +1,174 @@
From 77fd2a74a5f7a14f42b5c7acd175a9c1519c4f16 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Feb 2023 15:08:00 +0100
Subject: [PATCH v2 4/9] blk: blkmap: Add memory mapping support
Allow a slice of RAM to be mapped to a blkmap. This means that RAM can
now be accessed as if it was a block device, meaning that existing
filesystem drivers can now be used to access ramdisks.
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
drivers/block/blkmap.c | 105 +++++++++++++++++++++++++++++++++++++++++
include/blkmap.h | 29 ++++++++++++
2 files changed, 134 insertions(+)
diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c
index acfc002ceb..6d6eed889e 100644
--- a/drivers/block/blkmap.c
+++ b/drivers/block/blkmap.c
@@ -130,6 +130,111 @@ static int blkmap_slice_add(struct blkmap *bm, struct blkmap_slice *new)
return 0;
}
+/**
+ * struct blkmap_mem - Memory mapping
+ *
+ * @slice: Common map data
+ * @addr: Target memory region of this mapping
+ * @remapped: True if @addr is backed by a physical to virtual memory
+ * mapping that must be torn down at the end of this mapping's
+ * lifetime.
+ */
+struct blkmap_mem {
+ struct blkmap_slice slice;
+ void *addr;
+ bool remapped;
+};
+
+static ulong blkmap_mem_read(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt, void *buffer)
+{
+ struct blkmap_mem *bmm = container_of(bms, struct blkmap_mem, slice);
+ struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
+ char *src;
+
+ src = bmm->addr + (blknr << bd->log2blksz);
+ memcpy(buffer, src, blkcnt << bd->log2blksz);
+ return blkcnt;
+}
+
+static ulong blkmap_mem_write(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer)
+{
+ struct blkmap_mem *bmm = container_of(bms, struct blkmap_mem, slice);
+ struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
+ char *dst;
+
+ dst = bmm->addr + (blknr << bd->log2blksz);
+ memcpy(dst, buffer, blkcnt << bd->log2blksz);
+ return blkcnt;
+}
+
+static void blkmap_mem_destroy(struct blkmap *bm, struct blkmap_slice *bms)
+{
+ struct blkmap_mem *bmm = container_of(bms, struct blkmap_mem, slice);
+
+ if (bmm->remapped)
+ unmap_sysmem(bmm->addr);
+}
+
+int __blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *addr, bool remapped)
+{
+ struct blkmap *bm = dev_get_plat(dev);
+ struct blkmap_mem *bmm;
+ int err;
+
+ bmm = malloc(sizeof(*bmm));
+ if (!bmm)
+ return -ENOMEM;
+
+ *bmm = (struct blkmap_mem) {
+ .slice = {
+ .blknr = blknr,
+ .blkcnt = blkcnt,
+
+ .read = blkmap_mem_read,
+ .write = blkmap_mem_write,
+ .destroy = blkmap_mem_destroy,
+ },
+
+ .addr = addr,
+ .remapped = remapped,
+ };
+
+ err = blkmap_slice_add(bm, &bmm->slice);
+ if (err)
+ free(bmm);
+
+ return err;
+}
+
+int blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *addr)
+{
+ return __blkmap_map_mem(dev, blknr, blkcnt, addr, false);
+}
+
+int blkmap_map_pmem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ phys_addr_t paddr)
+{
+ struct blkmap *bm = dev_get_plat(dev);
+ struct blk_desc *bd = dev_get_uclass_plat(bm->blk);
+ void *addr;
+ int err;
+
+ addr = map_sysmem(paddr, blkcnt << bd->log2blksz);
+ if (!addr)
+ return -ENOMEM;
+
+ err = __blkmap_map_mem(dev, blknr, blkcnt, addr, true);
+ if (err)
+ unmap_sysmem(addr);
+
+ return err;
+}
+
static ulong blkmap_blk_read_slice(struct blkmap *bm, struct blkmap_slice *bms,
lbaint_t blknr, lbaint_t blkcnt,
void *buffer)
diff --git a/include/blkmap.h b/include/blkmap.h
index 3c7e36efab..74baeb19f8 100644
--- a/include/blkmap.h
+++ b/include/blkmap.h
@@ -7,6 +7,35 @@
#ifndef _BLKMAP_H
#define _BLKMAP_H
+/**
+ * blkmap_map_mem() - Map region of memory
+ *
+ * @dev: Blkmap to create the mapping on
+ * @blknr: Start block number of the mapping
+ * @blkcnt: Number of blocks to map
+ * @addr: The target memory address of the mapping
+ * Returns: 0 on success, negative error code on failure
+ */
+int blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ void *addr);
+
+/**
+ * blkmap_map_pmem() - Map region of physical memory
+ *
+ * Ensures that a valid physical to virtual memory mapping for the
+ * requested region is valid for the lifetime of the mapping, on
+ * architectures that require it (sandbox).
+ *
+ * @dev: Blkmap to create the mapping on
+ * @blknr: Start block number of the mapping
+ * @blkcnt: Number of blocks to map
+ * @paddr: The target physical memory address of the mapping
+ * Returns: 0 on success, negative error code on failure
+ */
+int blkmap_map_pmem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ phys_addr_t paddr);
+
+
/**
* blkmap_from_label() - Find blkmap from label
*
--
2.34.1
@@ -0,0 +1,125 @@
From 29ed14e1a427c4e308413bccdc75084c1c1ec75a Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Feb 2023 15:09:21 +0100
Subject: [PATCH v2 5/9] blk: blkmap: Add linear device mapping support
Allow a slice of an existing block device to be mapped to a
blkmap. This means that filesystems that are not stored at exact
partition boundaries can be accessed by remapping a slice of the
existing device to a blkmap device.
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
drivers/block/blkmap.c | 71 ++++++++++++++++++++++++++++++++++++++++++
include/blkmap.h | 13 ++++++++
2 files changed, 84 insertions(+)
diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c
index 6d6eed889e..2bb0acc20f 100644
--- a/drivers/block/blkmap.c
+++ b/drivers/block/blkmap.c
@@ -130,6 +130,77 @@ static int blkmap_slice_add(struct blkmap *bm, struct blkmap_slice *new)
return 0;
}
+/**
+ * struct blkmap_linear - Linear mapping to other block device
+ *
+ * @slice: Common map data
+ * @blk: Target block device of this mapping
+ * @blknr: Start block number of the target device
+ */
+struct blkmap_linear {
+ struct blkmap_slice slice;
+
+ struct udevice *blk;
+ lbaint_t blknr;
+};
+
+static ulong blkmap_linear_read(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt, void *buffer)
+{
+ struct blkmap_linear *bml = container_of(bms, struct blkmap_linear, slice);
+
+ return blk_read(bml->blk, bml->blknr + blknr, blkcnt, buffer);
+}
+
+static ulong blkmap_linear_write(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer)
+{
+ struct blkmap_linear *bml = container_of(bms, struct blkmap_linear, slice);
+
+ return blk_write(bml->blk, bml->blknr + blknr, blkcnt, buffer);
+}
+
+int blkmap_map_linear(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ struct udevice *lblk, lbaint_t lblknr)
+{
+ struct blkmap *bm = dev_get_plat(dev);
+ struct blkmap_linear *linear;
+ struct blk_desc *bd, *lbd;
+ int err;
+
+ bd = dev_get_uclass_plat(bm->blk);
+ lbd = dev_get_uclass_plat(lblk);
+ if (lbd->blksz != bd->blksz)
+ /* We could support block size translation, but we
+ * don't yet.
+ */
+ return -EINVAL;
+
+ linear = malloc(sizeof(*linear));
+ if (!linear)
+ return -ENOMEM;
+
+ *linear = (struct blkmap_linear) {
+ .slice = {
+ .blknr = blknr,
+ .blkcnt = blkcnt,
+
+ .read = blkmap_linear_read,
+ .write = blkmap_linear_write,
+ },
+
+ .blk = lblk,
+ .blknr = lblknr,
+ };
+
+ err = blkmap_slice_add(bm, &linear->slice);
+ if (err)
+ free(linear);
+
+ return err;
+}
+
/**
* struct blkmap_mem - Memory mapping
*
diff --git a/include/blkmap.h b/include/blkmap.h
index 74baeb19f8..af54583c7d 100644
--- a/include/blkmap.h
+++ b/include/blkmap.h
@@ -7,6 +7,19 @@
#ifndef _BLKMAP_H
#define _BLKMAP_H
+/**
+ * blkmap_map_linear() - Map region of other block device
+ *
+ * @dev: Blkmap to create the mapping on
+ * @blknr: Start block number of the mapping
+ * @blkcnt: Number of blocks to map
+ * @lblk: The target block device of the mapping
+ * @lblknr: The start block number of the target device
+ * Returns: 0 on success, negative error code on failure
+ */
+int blkmap_map_linear(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ struct udevice *lblk, lbaint_t lblknr);
+
/**
* blkmap_map_mem() - Map region of memory
*
--
2.34.1

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