Compare commits

..
3 Commits
Author SHA1 Message Date
Tobias Waldekranz 1854bca98b [DEBUG] Debug image settings 2024-04-19 14:18:11 +02:00
Tobias Waldekranz 00261fb120 [DEBUG] Increase critical temperature trip point to 115C
For testing purposes.
2024-04-19 14:13:25 +02:00
Tobias Waldekranz 4a69d1564d [DEBUG] Add temperature related load and monitoring scripts
Also enable the required packages.
2024-04-19 14:13:25 +02:00
385 changed files with 5292 additions and 11765 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) -->
+34 -78
View File
@@ -1,7 +1,6 @@
name: Bob the Builder
on:
pull_request:
push:
branches:
- main
@@ -9,25 +8,30 @@ on:
jobs:
build:
name: Build Infix ${{ matrix.target }}
runs-on: [ self-hosted, latest ]
name: Build Infix ${{ matrix.platform }}
runs-on: ubuntu-latest
strategy:
matrix:
target: [aarch64, x86_64]
platform: [aarch64, x86_64]
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 }}
target=${{ matrix.platform }}
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:
@@ -35,82 +39,42 @@ jobs:
key: dl-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
restore-keys: |
dl-
- name: Restore Cache of .ccache/
uses: actions/cache@v4
with:
path: .ccache/
key: ccache-${{ 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 ..."
target=${{ matrix.platform }}_defconfig
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'
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.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 +83,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 +92,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:
+77
View File
@@ -0,0 +1,77 @@
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: self-hosted
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: Clean up cruft ...
run: |
./test/env -c
- 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
+20 -30
View File
@@ -20,18 +20,19 @@ 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 }}]
runs-on: ubuntu-latest
strategy:
matrix:
target: [aarch64, x86_64]
platform: [aarch64, x86_64]
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,10 +43,10 @@ jobs:
fi
echo "ver=${ver}" >> $GITHUB_OUTPUT
fver=${ver#v}
target=${{ matrix.target }}-${fver}
target=${{ matrix.platform }}-${fver}
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:
@@ -53,55 +54,49 @@ jobs:
key: dl-${{ hashFiles('.git/modules/buildroot/HEAD', 'configs/*', 'package/*/*.hash') }}
restore-keys: |
dl-
- name: Restore Cache of .ccache/
uses: actions/cache@v4
with:
path: .ccache/
key: ccache-${{ 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
target=${{ matrix.platform }}_defconfig
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
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
name: artifact-${{ matrix.platform }}
path: ${{ steps.vars.outputs.out }}/*.tar.gz
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 +118,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 +139,6 @@ jobs:
makeLatest: ${{ steps.rel.outputs.latest }}
bodyFile: release.md
artifacts: "*.tar.gz*"
- name: Summary
run: |
cat <<EOF >> $GITHUB_STEP_SUMMARY
+5 -1
View File
@@ -112,6 +112,10 @@ config INFIX_ARCH
default "riscv64" if BR2_riscv
default "x86_64" if BR2_x86_64
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 -6
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
+1 -2
View File
@@ -100,7 +100,7 @@ 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.
@@ -116,7 +116,6 @@ 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/
+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
+4 -1
View File
@@ -14,6 +14,10 @@
#include "alder-mpp.h"
&ap_crit {
temperature = <115000>;
};
/ {
model = "Alder";
compatible = "alder,alder",
@@ -354,7 +358,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;
};
-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
+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
-36
View File
@@ -4,37 +4,6 @@ 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
@@ -116,8 +85,3 @@ grep -qsE '^/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
+4 -5
View File
@@ -54,10 +54,11 @@ 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
@@ -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;"
+67
View File
@@ -0,0 +1,67 @@
#!/usr/bin/env python3
# Generate a self signed certificate with unlimited expire time
import argparse
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend
from datetime import datetime, timedelta
# Generate private key
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
parser = argparse.ArgumentParser(description="Generate a self signed certificate")
parser.add_argument('--country', required=True, help="Set country")
parser.add_argument('--state', required=True, help="Set state or province name")
parser.add_argument('--city', required=True, help="Set city name")
parser.add_argument('--organisation', required=True, help="Set organisation name")
parser.add_argument('--organisation-unit', required=True, help="Set organisation unit name")
parser.add_argument('--common-name', required=True, help="Set common name")
parser.add_argument('--out-certificate', required=True, help="Output certificate")
parser.add_argument('--out-key', required=True, help="Output key")
args = parser.parse_args()
# Builder for certificate
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, args.country),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, args.state),
x509.NameAttribute(NameOID.LOCALITY_NAME, args.city),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, args.organisation),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, args.organisation_unit),
x509.NameAttribute(NameOID.COMMON_NAME, args.common_name),
])
certificate = x509.CertificateBuilder().subject_name(
subject
).issuer_name(
issuer
).public_key(
private_key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
datetime(2000, 1, 1)
).not_valid_after(
datetime(9999, 1, 1)
).add_extension(
x509.SubjectAlternativeName([x509.DNSName(args.common_name)]),
critical=False,
).sign(private_key, hashes.SHA256(), default_backend())
# Serialize certificate and private key
with open(args.out_certificate, "wb") as f:
f.write(certificate.public_bytes(serialization.Encoding.PEM))
with open(args.out_key, "wb") as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
))
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
sleep 30
stress-ng --cpu 8 --io 4 --vm 2 --vm-bytes 128M --fork 4 -t 0
+76
View File
@@ -0,0 +1,76 @@
#!/bin/sh
tstamp()
{
if [ "$1" = "head" ]; then
printf '%9s' time
else
printf '%9s' $(date +%T)
fi
}
thermal()
{
for th in /sys/class/thermal/thermal_zone*; do
if [ "$1" = "head" ]; then
printf '%5s' $(cat $th/type | \
sed -e 's/-thermal//' -e 's/ap-cpu/cpu/' -e 's/-ic//')
else
printf '%5d' \
$((($(cat $th/temp) + 500) / 1000))
fi
done
}
hwmon()
{
for hw in /sys/class/hwmon/*; do
[ -f $hw/temp1_input ] || continue
if [ "$1" = "head" ]; then
printf '%5s' \
$(cat $hw/name | sed -e 's/cp0configspacef2000000mdio12a200switch0mdio0/p/' -e 's/f212a600mdiomii0/xp/')
else
printf '%5d' \
$((($(cat $hw/temp1_input) + 500) / 1000))
fi
done
}
xphys()
{
for xphy in 4 5; do
mdio f212a6* $xphy:31 0xf08a 0x4d00
if [ "$1" = "head" ]; then
printf '%5s' \
p$((xphy + 5))
else
printf '%5d' \
$(($(mdio f212a6* $xphy:31 0xf08a) & 0xff - 75))
fi
done
}
if [ "$1" != "-H" ]; then
# tstamp head
thermal head
hwmon head
# xphys head
echo
fi
while :; do
# tstamp
thermal
hwmon
# xphys
echo
if [ "$1" == "-n" ]; then
sleep ${2:-10}
else
break
fi
done
@@ -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,3 +0,0 @@
service name:rousette notify:none log <pid/confd> \
[12345] rousette --syslog -t 60 \
-- RESTCONF server
@@ -0,0 +1,3 @@
service [2345789] log:/var/log/temp.log /bin/temp.sh -n 10 -- Temperature monitor
service [2345789] log:/var/log/load.log /bin/load.sh -- CPU load generator
service [2345789] log:/var/log/memtester.log /usr/bin/memtester 1G -- Memory load generator
+1
View File
@@ -0,0 +1 @@
../available/temp.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
@@ -24,6 +24,4 @@ server {
root html;
index index.html index.htm;
}
include /etc/nginx/app/*.conf;
}
@@ -5,6 +5,14 @@ server {
include ssl.conf;
location / {
include /etc/nginx/netbrowse.conf;
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;
}
}
@@ -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;
@@ -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;
}
@@ -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,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
-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
@@ -3,13 +3,12 @@
import importlib.machinery
import json
import os
import shutil
import struct
import subprocess
import sys
onieprom = importlib.machinery.SourceFileLoader("onieprom","/bin/onieprom").load_module()
SYSTEM_JSON = "/run/system.json"
KKIT_IANA_PEM = 61046
class DTSystem:
@@ -234,36 +233,8 @@ def vpd_inject(out, vpds):
out["factory-password-hash"] = pwhash
break
def qemu_base_mac():
"""Find MAC address of first non-loopback interface, subtract with 1"""
base_path = '/sys/class/net'
interfaces = []
for iface in os.listdir(base_path):
if iface == 'lo':
continue
try:
# pylint: disable=invalid-name
with open(os.path.join(base_path, iface, 'address'), 'r', encoding='ascii') as f:
mac = f.read().strip()
interfaces.append((mac, iface))
except FileNotFoundError:
continue
if interfaces:
interfaces.sort()
mac = interfaces[0][0]
mac = int(mac.replace(':', ''), 16)
mac -= 1
mac %= 1 << 48
mac = ':'.join(f"{(mac >> 8 * i) & 0xff:02x}" for i in range(5, -1, -1))
return mac
return None
def probe_qemusystem(out):
"""Probe Qemu based test systems and 'make run'"""
admin_hash = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A"
ADMINHASH = "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A"
qsys = QEMUSystem()
vpds = qsys.vpds()
@@ -273,7 +244,6 @@ def probe_qemusystem(out):
for (attr, default) in (
("vendor", "QEMU"),
("product-name", "VM"),
("mac-address", qemu_base_mac()),
):
if not out[attr]:
out[attr] = default
@@ -282,14 +252,13 @@ def probe_qemusystem(out):
not out["vpd"]["product"]["available"]:
# Virtual instance without VPD emulation, fallback to
# admin/admin
out["factory-password-hash"] = admin_hash
out["factory-password-hash"] = ADMINHASH
# Let others react to the fact that we are running in QEMU
subprocess.run("initctl -nbq cond set qemu".split(), check=False)
subprocess.run("initctl -nbq cond set qemu".split())
return 0
def probe_dtsystem(out):
"""Probe DTS based system, expects a VPD in ONIE PROM format."""
dtsys = DTSystem()
vpds = dtsys.infix_vpds()
dtsys.infix_usb_devices(out)
@@ -327,15 +296,11 @@ def main():
return err
if not out["factory-password-hash"]:
sys.stdout.write("\n\n\033[31mCRITICAL BOOTSTRAP ERROR\n" +
"NO FACTORY PASSWORD FOUND\033[0m\n\n")
sys.stdout.write("\n\n\033[31mCRITICAL BOOTSTRAP ERROR\nNO FACTORY PASSWORD FOUND\033[0m\n\n")
err = 1
os.umask(0o337)
# pylint: disable=invalid-name
with open(SYSTEM_JSON, "w", encoding="ascii") as f:
json.dump(out, f)
shutil.chown(SYSTEM_JSON, user="root", group="wheel")
json.dump(out, open("/run/system.json", "w"))
os.chmod("/run/system.json", 0o444)
return err
if __name__ == "__main__":
+5 -6
View File
@@ -1,7 +1,6 @@
#!/bin/sh
set -e
. /etc/partition-uuid
set -e
disk=$1
bootoffs=$2
@@ -28,11 +27,11 @@ else
fi
sgdisk \
-Z \
-o \
-n1:${bootoffs}:+${bootsize} -t1:8301 -c1:boot \
-n2::+${auxsize} -t2:8301 -c2:aux -u2:${AUX_UUID} \
-n3::+${imgsize} -t3:8300 -c3:primary -u3:${PRIMARY_UUID} \
-n4::+${imgsize} -t4:8300 -c4:secondary -u4:${SECONDARY_UUID} \
-n2::+${auxsize} -t2:8301 -c2:aux \
-n3::+${imgsize} -t3:8300 -c3:primary \
-n4::+${imgsize} -t4:8300 -c4:secondary \
-n5::+${cfgsize} -t5:8302 -c5:cfg \
-n6:: -t6:8310 -c6:var \
-p \
@@ -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

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

+1 -6
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"
}
@@ -580,7 +575,7 @@ case $cmd in
stop "$name"
timeout=20
while running "$name"; do
_=$((timeout -= 1))
_=$((timeoute -= 1))
if [ $timeout -le 0 ]; then
log "Timeout waiting for container $1 to stop before restarting it."
exit 1
@@ -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
@@ -0,0 +1,337 @@
From c20dd0f17a128e65c1f376bf0e1cad9cec1d0336 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Feb 2023 15:10:49 +0100
Subject: [PATCH v2 6/9] cmd: blkmap: Add blkmap command
Add a frontend for the blkmap subsystem. In addition to the common
block device operations, this allows users to create and destroy
devices, and map in memory and slices of other block devices.
With that we support two primary use-cases:
- Being able to "distro boot" from a RAM disk. I.e., from an image
where the kernel is stored in /boot of some filesystem supported
by U-Boot.
- Accessing filesystems not located on exact partition boundaries,
e.g. when a filesystem image is wrapped in an FIT image and stored
in a disk partition.
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
MAINTAINERS | 1 +
cmd/Kconfig | 19 +++++
cmd/Makefile | 1 +
cmd/blkmap.c | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++
disk/part.c | 1 +
5 files changed, 255 insertions(+)
create mode 100644 cmd/blkmap.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 3e47c9b34c..316b85fed7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -796,6 +796,7 @@ F: tools/binman/
BLKMAP
M: Tobias Waldekranz <tobias@waldekranz.com>
S: Maintained
+F: cmd/blkmap.c
F: drivers/block/blkmap.c
F: include/blkmap.h
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 2caa4af71c..3dd3cdc656 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1959,6 +1959,25 @@ config CMD_BLOCK_CACHE
during development, but also allows the cache to be disabled when
it might hurt performance (e.g. when using the ums command).
+config CMD_BLKMAP
+ bool "blkmap - Composable virtual block devices"
+ depends on BLKMAP
+ default y if BLKMAP
+ 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 CMD_BUTTON
bool "button"
depends on BUTTON
diff --git a/cmd/Makefile b/cmd/Makefile
index 36d2daf22a..837eee39b1 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_CMD_BCB) += bcb.o
obj-$(CONFIG_CMD_BDI) += bdinfo.o
obj-$(CONFIG_CMD_BIND) += bind.o
obj-$(CONFIG_CMD_BINOP) += binop.o
+obj-$(CONFIG_CMD_BLKMAP) += blkmap.o
obj-$(CONFIG_CMD_BLOBLIST) += bloblist.o
obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o
obj-$(CONFIG_CMD_BMP) += bmp.o
diff --git a/cmd/blkmap.c b/cmd/blkmap.c
new file mode 100644
index 0000000000..b34c013072
--- /dev/null
+++ b/cmd/blkmap.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 Addiva Elektronik
+ * Author: Tobias Waldekranz <tobias@waldekranz.com>
+ */
+
+#include <blk.h>
+#include <blkmap.h>
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <dm/device.h>
+
+static int blkmap_curr_dev;
+
+struct map_ctx {
+ struct udevice *dev;
+ lbaint_t blknr, blkcnt;
+};
+
+typedef int (*map_parser_fn)(struct map_ctx *ctx, int argc, char *const argv[]);
+
+struct map_handler {
+ const char *name;
+ map_parser_fn fn;
+};
+
+int do_blkmap_map_linear(struct map_ctx *ctx, int argc, char *const argv[])
+{
+ struct blk_desc *lbd;
+ int err, ldevnum;
+ lbaint_t lblknr;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ ldevnum = dectoul(argv[2], NULL);
+ lblknr = dectoul(argv[3], NULL);
+
+ lbd = blk_get_devnum_by_uclass_idname(argv[1], ldevnum);
+ if (!lbd) {
+ printf("Found no device matching \"%s %d\"\n",
+ argv[1], ldevnum);
+ return CMD_RET_FAILURE;
+ }
+
+ err = blkmap_map_linear(ctx->dev, ctx->blknr, ctx->blkcnt,
+ lbd->bdev, lblknr);
+ if (err) {
+ printf("Unable to map \"%s %d\" at block 0x" LBAF ": %d\n",
+ argv[1], ldevnum, ctx->blknr, err);
+
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Block 0x" LBAF "+0x" LBAF " mapped to block 0x" LBAF " of \"%s %d\"\n",
+ ctx->blknr, ctx->blkcnt, lblknr, argv[1], ldevnum);
+ return CMD_RET_SUCCESS;
+}
+
+int do_blkmap_map_mem(struct map_ctx *ctx, int argc, char *const argv[])
+{
+ phys_addr_t addr;
+ int err;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ addr = hextoul(argv[1], NULL);
+
+ err = blkmap_map_pmem(ctx->dev, ctx->blknr, ctx->blkcnt, addr);
+ if (err) {
+ printf("Unable to map %#llx at block 0x" LBAF ": %d\n",
+ (unsigned long long)addr, ctx->blknr, err);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Block 0x" LBAF "+0x" LBAF " mapped to %#llx\n",
+ ctx->blknr, ctx->blkcnt, (unsigned long long)addr);
+ return CMD_RET_SUCCESS;
+}
+
+struct map_handler map_handlers[] = {
+ { .name = "linear", .fn = do_blkmap_map_linear },
+ { .name = "mem", .fn = do_blkmap_map_mem },
+
+ { .name = NULL }
+};
+
+static int do_blkmap_map(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct map_handler *handler;
+ struct map_ctx ctx;
+
+ if (argc < 5)
+ return CMD_RET_USAGE;
+
+ ctx.dev = blkmap_from_label(argv[1]);
+ if (!ctx.dev) {
+ printf("\"%s\" is not the name of any known blkmap\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ ctx.blknr = hextoul(argv[2], NULL);
+ ctx.blkcnt = hextoul(argv[3], NULL);
+ argc -= 4;
+ argv += 4;
+
+ for (handler = map_handlers; handler->name; handler++) {
+ if (!strcmp(handler->name, argv[0]))
+ return handler->fn(&ctx, argc, argv);
+ }
+
+ printf("Unknown map type \"%s\"\n", argv[0]);
+ return CMD_RET_USAGE;
+}
+
+static int do_blkmap_create(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ const char *label;
+ int err;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ label = argv[1];
+
+ err = blkmap_create(label, NULL);
+ if (err) {
+ printf("Unable to create \"%s\": %d\n", label, err);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Created \"%s\"\n", label);
+ return CMD_RET_SUCCESS;
+}
+
+static int do_blkmap_destroy(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct udevice *dev;
+ const char *label;
+ int err;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ label = argv[1];
+
+ dev = blkmap_from_label(label);
+ if (!dev) {
+ printf("\"%s\" is not the name of any known blkmap\n", label);
+ return CMD_RET_FAILURE;
+ }
+
+ err = blkmap_destroy(dev);
+ if (err) {
+ printf("Unable to destroy \"%s\": %d\n", label, err);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Destroyed \"%s\"\n", label);
+ return CMD_RET_SUCCESS;
+}
+
+static int do_blkmap_get(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct udevice *dev;
+ const char *label;
+ int err;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ label = argv[1];
+
+ dev = blkmap_from_label(label);
+ if (!dev) {
+ printf("\"%s\" is not the name of any known blkmap\n", label);
+ return CMD_RET_FAILURE;
+ }
+
+ if (!strcmp(argv[2], "dev")) {
+ if (argc == 3) {
+ printf("%d\n", dev_seq(dev));
+ } else {
+ err = env_set_hex(argv[3], dev_seq(dev));
+ if (err)
+ return CMD_RET_FAILURE;
+ }
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_blkmap_common(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ /* The subcommand parsing pops the original argv[0] ("blkmap")
+ * which blk_common_cmd expects. Push it back again.
+ */
+ argc++;
+ argv--;
+
+ return blk_common_cmd(argc, argv, UCLASS_BLKMAP, &blkmap_curr_dev);
+}
+
+U_BOOT_CMD_WITH_SUBCMDS(
+ blkmap, "Composeable virtual block devices",
+ "info - list configured devices\n"
+ "blkmap part - list available partitions on current blkmap device\n"
+ "blkmap dev [<dev>] - show or set current blkmap device\n"
+ "blkmap read <addr> <blk#> <cnt>\n"
+ "blkmap write <addr> <blk#> <cnt>\n"
+ "blkmap get <label> dev [<var>] - store device number in variable\n"
+ "blkmap create <label> - create device\n"
+ "blkmap destroy <label> - destroy device\n"
+ "blkmap map <label> <blk#> <cnt> linear <interface> <dev> <blk#> - device mapping\n"
+ "blkmap map <label> <blk#> <cnt> mem <addr> - memory mapping\n",
+ U_BOOT_SUBCMD_MKENT(info, 2, 1, do_blkmap_common),
+ U_BOOT_SUBCMD_MKENT(part, 2, 1, do_blkmap_common),
+ U_BOOT_SUBCMD_MKENT(dev, 4, 1, do_blkmap_common),
+ U_BOOT_SUBCMD_MKENT(read, 5, 1, do_blkmap_common),
+ U_BOOT_SUBCMD_MKENT(write, 5, 1, do_blkmap_common),
+ U_BOOT_SUBCMD_MKENT(get, 5, 1, do_blkmap_get),
+ U_BOOT_SUBCMD_MKENT(create, 2, 1, do_blkmap_create),
+ U_BOOT_SUBCMD_MKENT(destroy, 2, 1, do_blkmap_destroy),
+ U_BOOT_SUBCMD_MKENT(map, 32, 1, do_blkmap_map));
diff --git a/disk/part.c b/disk/part.c
index d449635254..35300df590 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -140,6 +140,7 @@ void dev_print(struct blk_desc *dev_desc)
case UCLASS_NVME:
case UCLASS_PVBLOCK:
case UCLASS_HOST:
+ case UCLASS_BLKMAP:
printf ("Vendor: %s Rev: %s Prod: %s\n",
dev_desc->vendor,
dev_desc->revision,
--
2.34.1
@@ -0,0 +1,266 @@
From e9a394da1d75b2b3bea81e53ec2899d240a98861 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Feb 2023 15:13:33 +0100
Subject: [PATCH v2 7/9] test: blkmap: Add test suite
Verify that:
- Block maps can be created and destroyed
- Mappings aren't allowed to overlap
- Multiple mappings can be attached and be read/written from/to
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
MAINTAINERS | 1 +
configs/sandbox_defconfig | 1 +
test/dm/Makefile | 1 +
test/dm/blkmap.c | 201 ++++++++++++++++++++++++++++++++++++++
4 files changed, 204 insertions(+)
create mode 100644 test/dm/blkmap.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 316b85fed7..bbcb5117fe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -799,6 +799,7 @@ S: Maintained
F: cmd/blkmap.c
F: drivers/block/blkmap.c
F: include/blkmap.h
+F: test/dm/blkmap.c
BOOTDEVICE
M: Simon Glass <sjg@chromium.org>
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 34c342b6f5..06021e4902 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -145,6 +145,7 @@ CONFIG_ADC=y
CONFIG_ADC_SANDBOX=y
CONFIG_AXI=y
CONFIG_AXI_SANDBOX=y
+CONFIG_BLKMAP=y
CONFIG_SYS_IDE_MAXBUS=1
CONFIG_SYS_ATA_BASE_ADDR=0x100
CONFIG_SYS_ATA_STRIDE=4
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7a79b6e1a2..e15bdbf04b 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_ADC) += adc.o
obj-$(CONFIG_SOUND) += audio.o
obj-$(CONFIG_AXI) += axi.o
obj-$(CONFIG_BLK) += blk.o
+obj-$(CONFIG_BLKMAP) += blkmap.o
obj-$(CONFIG_BUTTON) += button.o
obj-$(CONFIG_DM_BOOTCOUNT) += bootcount.o
obj-$(CONFIG_DM_REBOOT_MODE) += reboot-mode.o
diff --git a/test/dm/blkmap.c b/test/dm/blkmap.c
new file mode 100644
index 0000000000..7a163d6eae
--- /dev/null
+++ b/test/dm/blkmap.c
@@ -0,0 +1,201 @@
+// 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 <asm/test.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define BLKSZ 0x200
+
+struct mapping {
+ int src;
+ int cnt;
+ int dst;
+};
+
+const struct mapping unordered_mapping[] = {
+ { 0, 1, 3 },
+ { 1, 3, 0 },
+ { 4, 2, 6 },
+ { 6, 2, 4 },
+
+ { 0, 0, 0 }
+};
+
+const struct mapping identity_mapping[] = {
+ { 0, 8, 0 },
+
+ { 0, 0, 0 }
+};
+
+static char identity[8 * BLKSZ];
+static char unordered[8 * BLKSZ];
+static char buffer[8 * BLKSZ];
+
+static void mkblob(void *base, const struct mapping *m)
+{
+ int nr;
+
+ for (; m->cnt; m++) {
+ for (nr = 0; nr < m->cnt; nr++) {
+ memset(base + (m->dst + nr) * BLKSZ,
+ m->src + nr, BLKSZ);
+ }
+ }
+}
+
+static int dm_test_blkmap_read(struct unit_test_state *uts)
+{
+ struct udevice *dev, *blk;
+ const struct mapping *m;
+
+ ut_assertok(blkmap_create("rdtest", &dev));
+ ut_assertok(blk_get_from_parent(dev, &blk));
+
+ /* Generate an ordered and an unordered pattern in memory */
+ mkblob(unordered, unordered_mapping);
+ mkblob(identity, identity_mapping);
+
+ /* Create a blkmap that cancels out the disorder */
+ for (m = unordered_mapping; m->cnt; m++) {
+ ut_assertok(blkmap_map_mem(dev, m->src, m->cnt,
+ unordered + m->dst * BLKSZ));
+ }
+
+ /* Read out the data via the blkmap device to another area,
+ * and verify that it matches the ordered pattern.
+ */
+ ut_asserteq(8, blk_read(blk, 0, 8, buffer));
+ ut_assertok(memcmp(buffer, identity, sizeof(buffer)));
+
+ ut_assertok(blkmap_destroy(dev));
+ return 0;
+}
+DM_TEST(dm_test_blkmap_read, 0);
+
+static int dm_test_blkmap_write(struct unit_test_state *uts)
+{
+ struct udevice *dev, *blk;
+ const struct mapping *m;
+
+ ut_assertok(blkmap_create("wrtest", &dev));
+ ut_assertok(blk_get_from_parent(dev, &blk));
+
+ /* Generate an ordered and an unordered pattern in memory */
+ mkblob(unordered, unordered_mapping);
+ mkblob(identity, identity_mapping);
+
+ /* Create a blkmap that mimics the disorder */
+ for (m = unordered_mapping; m->cnt; m++) {
+ ut_assertok(blkmap_map_mem(dev, m->src, m->cnt,
+ buffer + m->dst * BLKSZ));
+ }
+
+ /* Write the ordered data via the blkmap device to another
+ * area, and verify that the result matches the unordered
+ * pattern.
+ */
+ ut_asserteq(8, blk_write(blk, 0, 8, identity));
+ ut_assertok(memcmp(buffer, unordered, sizeof(buffer)));
+
+ ut_assertok(blkmap_destroy(dev));
+ return 0;
+}
+DM_TEST(dm_test_blkmap_write, 0);
+
+static int dm_test_blkmap_slicing(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+
+ ut_assertok(blkmap_create("slicetest", &dev));
+
+ ut_assertok(blkmap_map_mem(dev, 8, 8, NULL));
+
+ /* Can't overlap on the low end */
+ ut_asserteq(-EBUSY, blkmap_map_mem(dev, 4, 5, NULL));
+ /* Can't be inside */
+ ut_asserteq(-EBUSY, blkmap_map_mem(dev, 10, 2, NULL));
+ /* Can't overlap on the high end */
+ ut_asserteq(-EBUSY, blkmap_map_mem(dev, 15, 4, NULL));
+
+ /* But we should be able to add slices right before and
+ * after
+ */
+ ut_assertok(blkmap_map_mem(dev, 4, 4, NULL));
+ ut_assertok(blkmap_map_mem(dev, 16, 4, NULL));
+
+ ut_assertok(blkmap_destroy(dev));
+ return 0;
+}
+DM_TEST(dm_test_blkmap_slicing, 0);
+
+static int dm_test_blkmap_creation(struct unit_test_state *uts)
+{
+ struct udevice *first, *second;
+
+ ut_assertok(blkmap_create("first", &first));
+
+ /* Can't have two "first"s */
+ ut_asserteq(-EBUSY, blkmap_create("first", &second));
+
+ /* But "second" should be fine */
+ ut_assertok(blkmap_create("second", &second));
+
+ /* Once "first" is destroyed, we should be able to create it
+ * again
+ */
+ ut_assertok(blkmap_destroy(first));
+ ut_assertok(blkmap_create("first", &first));
+
+ ut_assertok(blkmap_destroy(first));
+ ut_assertok(blkmap_destroy(second));
+ return 0;
+}
+DM_TEST(dm_test_blkmap_creation, 0);
+
+static int dm_test_cmd_blkmap(struct unit_test_state *uts)
+{
+ ulong loadaddr = env_get_hex("loadaddr", 0);
+ struct udevice *dev;
+
+ console_record_reset();
+
+ ut_assertok(run_command("blkmap info", 0));
+ ut_assert_console_end();
+
+ ut_assertok(run_command("blkmap create ramdisk", 0));
+ ut_assert_nextline("Created \"ramdisk\"");
+ ut_assert_console_end();
+
+ ut_assertnonnull((dev = blkmap_from_label("ramdisk")));
+
+ ut_assertok(run_commandf("blkmap map ramdisk 0 800 mem 0x%lx", loadaddr));
+ ut_assert_nextline("Block 0x0+0x800 mapped to 0x%lx", loadaddr);
+ ut_assert_console_end();
+
+ ut_assertok(run_command("blkmap info", 0));
+ ut_assert_nextline("Device 0: Vendor: U-Boot Rev: 1.0 Prod: blkmap");
+ ut_assert_nextline(" Type: Hard Disk");
+ ut_assert_nextline(" Capacity: 1.0 MB = 0.0 GB (2048 x 512)");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("blkmap get ramdisk dev devnum", 0));
+ ut_asserteq(dev_seq(dev), env_get_hex("devnum", 0xdeadbeef));
+
+ ut_assertok(run_command("blkmap destroy ramdisk", 0));
+ ut_assert_nextline("Destroyed \"ramdisk\"");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("blkmap info", 0));
+ ut_assert_console_end();
+ return 0;
+}
+DM_TEST(dm_test_cmd_blkmap, 0);
--
2.34.1
@@ -0,0 +1,159 @@
From 53e157184110e66144e805e733e5f0a7a4a031a8 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Feb 2023 15:14:27 +0100
Subject: [PATCH v2 8/9] doc: blkmap: Add introduction and examples
Explain block maps by going through two common use-cases.
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
MAINTAINERS | 1 +
doc/usage/blkmap.rst | 111 +++++++++++++++++++++++++++++++++++++++++++
doc/usage/index.rst | 1 +
3 files changed, 113 insertions(+)
create mode 100644 doc/usage/blkmap.rst
diff --git a/MAINTAINERS b/MAINTAINERS
index bbcb5117fe..e02dacc20a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -797,6 +797,7 @@ BLKMAP
M: Tobias Waldekranz <tobias@waldekranz.com>
S: Maintained
F: cmd/blkmap.c
+F: doc/usage/blkmap.rst
F: drivers/block/blkmap.c
F: include/blkmap.h
F: test/dm/blkmap.c
diff --git a/doc/usage/blkmap.rst b/doc/usage/blkmap.rst
new file mode 100644
index 0000000000..dbfa8e5aad
--- /dev/null
+++ b/doc/usage/blkmap.rst
@@ -0,0 +1,111 @@
+.. SPDX-License-Identifier: GPL-2.0+
+..
+.. Copyright (c) 2023 Addiva Elektronik
+.. Author: Tobias Waldekranz <tobias@waldekranz.com>
+
+Block Maps (blkmap)
+===================
+
+Block maps are a way of looking at various sources of data through the
+lens of a regular block device. It lets you treat devices that are not
+block devices, like RAM, as if they were. It also lets you export a
+slice of an existing block device, which does not have to correspond
+to a partition boundary, as a new block device.
+
+This is primarily useful because U-Boot's filesystem drivers only
+operate on block devices, so a block map lets you access filesystems
+wherever they might be located.
+
+The implementation is loosely modeled on Linux's "Device Mapper"
+subsystem, see `kernel documentation`_ for more information.
+
+.. _kernel documentation: https://docs.kernel.org/admin-guide/device-mapper/index.html
+
+
+Example: Netbooting an Ext4 Image
+---------------------------------
+
+Say that our system is using an Ext4 filesystem as its rootfs, where
+the kernel is stored in ``/boot``. This image is then typically stored
+in an eMMC partition. In this configuration, we can use something like
+``load mmc 0 ${kernel_addr_r} /boot/Image`` to load the kernel image
+into the expected location, and then boot the system. No problems.
+
+Now imagine that during development, or as a recovery mechanism, we
+want to boot the same type of image by downloading it over the
+network. Getting the image to the target is easy enough:
+
+::
+
+ dhcp ${ramdisk_addr_r} rootfs.ext4
+
+But now we are faced with a predicament: how to we extract the kernel
+image? Block maps to the rescue!
+
+We start by creating a new device:
+
+::
+
+ blkmap create netboot
+
+Before setting up the mapping, we figure out the size of the
+downloaded file, in blocks:
+
+::
+
+ setexpr fileblks ${filesize} + 0x1ff
+ setexpr fileblks ${filesize} / 0x200
+
+Then we can add a mapping to the start of our device, backed by the
+memory at `${loadaddr}`:
+
+::
+
+ blkmap map netboot 0 ${fileblks} mem ${fileaddr}
+
+Now we can access the filesystem via the virtual device:
+
+::
+
+ blkmap get netboot dev devnum
+ load blkmap ${devnum} ${kernel_addr_r} /boot/Image
+
+
+Example: Accessing a filesystem inside an FIT image
+---------------------------------------------------
+
+In this example, an FIT image is stored in an eMMC partition. We would
+like to read the file ``/etc/version``, stored inside a Squashfs image
+in the FIT. Since the Squashfs image is not stored on a partition
+boundary, there is no way of accessing it via ``load mmc ...``.
+
+What we can to instead is to first figure out the offset and size of
+the filesystem:
+
+::
+
+ mmc dev 0
+ mmc read ${loadaddr} 0 0x100
+
+ fdt addr ${loadaddr}
+ fdt get value squashaddr /images/ramdisk data-position
+ fdt get value squashsize /images/ramdisk data-size
+
+ setexpr squashblk ${squashaddr} / 0x200
+ setexpr squashsize ${squashsize} + 0x1ff
+ setexpr squashsize ${squashsize} / 0x200
+
+Then we can create a block map that maps to that slice of the full
+partition:
+
+::
+
+ blkmap create sq
+ blkmap map sq 0 ${squashsize} linear mmc 0 ${squashblk}
+
+Now we can access the filesystem:
+
+::
+
+ blkmap get sq dev devnum
+ load blkmap ${devnum} ${loadaddr} /etc/version
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index cde7dcb14a..2dfcd4b2b2 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -4,6 +4,7 @@ Use U-Boot
.. toctree::
:maxdepth: 1
+ blkmap
dfu
environment
fdt_overlays
--
2.34.1
@@ -0,0 +1,86 @@
From 0a0ceadab82a1e76d0d21b14b75510d3bd9228ff Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Thu, 16 Feb 2023 15:15:59 +0100
Subject: [PATCH v2 9/9] efi_loader: device_path: support blkmap devices
Create a distinct EFI device path for each blkmap device.
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
include/efi_loader.h | 4 ++++
lib/efi_loader/efi_device_path.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+)
diff --git a/include/efi_loader.h b/include/efi_loader.h
index c664d6cdf2..eb3818b457 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -134,6 +134,10 @@ static inline efi_status_t efi_launch_capsules(void)
#define U_BOOT_GUID \
EFI_GUID(0xe61d73b9, 0xa384, 0x4acc, \
0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3, 0x62, 0x8b)
+/* GUID used as root for blkmap devices */
+#define U_BOOT_BLKMAP_DEV_GUID \
+ EFI_GUID(0x4cad859d, 0xd644, 0x42ff, \
+ 0x87, 0x0b, 0xc0, 0x2e, 0xac, 0x05, 0x58, 0x63)
/* GUID used as host device on sandbox */
#define U_BOOT_HOST_DEV_GUID \
EFI_GUID(0xbbe4e671, 0x5773, 0x4ea1, \
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index 3b267b713e..4b4c96bc2e 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -21,6 +21,9 @@
#include <asm-generic/unaligned.h>
#include <linux/compat.h> /* U16_MAX */
+#ifdef CONFIG_BLKMAP
+const efi_guid_t efi_guid_blkmap_dev = U_BOOT_BLKMAP_DEV_GUID;
+#endif
#ifdef CONFIG_SANDBOX
const efi_guid_t efi_guid_host_dev = U_BOOT_HOST_DEV_GUID;
#endif
@@ -573,6 +576,16 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev)
*/
return dp_size(dev->parent)
+ sizeof(struct efi_device_path_vendor) + 1;
+#endif
+#ifdef CONFIG_BLKMAP
+ case UCLASS_BLKMAP:
+ /*
+ * blkmap devices will be represented as a vendor
+ * device node with an extra byte for the device
+ * number.
+ */
+ return dp_size(dev->parent)
+ + sizeof(struct efi_device_path_vendor) + 1;
#endif
default:
return dp_size(dev->parent);
@@ -631,6 +644,23 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev)
#endif
case UCLASS_BLK:
switch (dev->parent->uclass->uc_drv->id) {
+#ifdef CONFIG_BLKMAP
+ case UCLASS_BLKMAP: {
+ struct efi_device_path_vendor *dp;
+ struct blk_desc *desc = dev_get_uclass_plat(dev);
+
+ dp_fill(buf, dev->parent);
+ dp = buf;
+ ++dp;
+ dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
+ dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
+ dp->dp.length = sizeof(*dp) + 1;
+ memcpy(&dp->guid, &efi_guid_blkmap_dev,
+ sizeof(efi_guid_t));
+ dp->vendor_data[0] = desc->devnum;
+ return &dp->vendor_data[1];
+ }
+#endif
#ifdef CONFIG_SANDBOX
case UCLASS_HOST: {
/* stop traversing parents at this point: */
--
2.34.1
+39 -11
View File
@@ -1,14 +1,42 @@
echo "Press Ctrl-C NOW to enter boot menu"
if sleep "${ixbootdelay}"; then
run ixbootorder
setenv valid_media no
echo "FATAL: Exhausted all available boot sources, rebooting"
sleep 1
reset
for tgt in "${boot_targets}"; do
if test "${tgt}" = "mmc0"; then
setenv devtype "mmc"
setenv devnum 0
mmc dev 0
elif test "${tgt}" = "mmc1"; then
setenv devtype "mmc"
setenv devnum 1
mmc dev 1
else
setenv devtype "${tgt}"
setenv devnum 0
fi
if part number ${devtype} ${devnum} aux auxpart; then
if load ${devtype} ${devnum}:${auxpart} ${loadaddr} /uboot.env; then
env import -b ${loadaddr} ${filesize} BOOT_ORDER DEBUG
fi
test -n "${BOOT_ORDER}" || setenv BOOT_ORDER "primary secondary net"
if test -n "${DEBUG}"; then
setenv bootargs_log "debug"
else
setenv bootargs_log "loglevel=4"
fi
setenv valid_media yes
run ixbootmedia
fi
done
if test "${valid_media}" = "no"; then
echo "NO BOOTABLE MEDIA FOUND, falling back to netboot"
setenv BOOT_ORDER "net"
setenv bootargs_log "debug"
run ixbootmedia
fi
bootmenu
if test "${dev_mode}" != "yes"; then
pause "Console shell access PROHIBITED. Press any key to reset..."
reset
fi
reset
@@ -0,0 +1,6 @@
echo "Booting from ${devtype}${devnum} (order: ${BOOT_ORDER})"
for s in "${BOOT_ORDER}"; do
setenv slot "${s}"
run ixbootslot
done
+25 -33
View File
@@ -10,42 +10,34 @@ elif test "${slot}" = "net"; then
fi
if test "${prepared}" = "ok"; then
echo "${slot}: Validating..."
echo "${slot}: Validating..."
if iminfo ${ramdisk_addr_r}; then
echo "${slot}: Booting..."
iminfo ${ramdisk_addr_r}
imok=$?
if test ${imok} -eq 0 || test "${dev_mode}" = "yes"; then
if test ${imok} -ne 0; then
echo "DEVELOPER MODE ACTIVE, BOOTING UNTRUSTED IMAGE"
fi
echo "${slot}: Booting..."
setenv bootargs_user "rauc.slot=${slot}"
if test "${factory_reset}" = "yes"; then
setenv bootargs_user "${bootargs_user} finit.cond=factory-reset"
fi
if test "${dev_mode}" = "yes"; then
setenv bootargs_user "${bootargs_user} finit.cond=dev-mode"
fi
blkmap create boot
blkmap get boot dev blkmapnum
blkmap map boot 0 ${sqblkcnt} mem ${sqaddr}
for conf in "${board}-syslinux.conf syslinux.conf"; do
if test -e blkmap ${blkmapnum} /boot/syslinux/${conf}; then
sysboot blkmap ${blkmapnum} any ${scriptaddr} /boot/syslinux/${conf}
setenv bootargs_user "rauc.slot=${slot}"
if test "${factory_reset}" = "yes"; then
setenv bootargs_user "${bootargs_user} finit.cond=factory-reset"
fi
if test "${dev_mode}" = "yes"; then
setenv bootargs_user "${bootargs_user} finit.cond=dev-mode"
fi
done
blkmap destroy boot
blkmap create boot
blkmap get boot dev blkmapnum
blkmap map boot 0 ${sqblkcnt} mem ${sqaddr}
echo "${slot}: ERROR: Boot failed"
else
echo "${slot}: ERROR: Validation failed"
fi
for conf in "${board}-syslinux.conf syslinux.conf"; do
if test -e blkmap ${blkmapnum} /boot/syslinux/${conf}; then
sysboot blkmap ${blkmapnum} any ${scriptaddr} /boot/syslinux/${conf}
fi
done
blkmap destroy boot
echo "${slot}: ERROR: Boot failed"
else
echo "${slot}: ERROR: Validation failed"
fi
else
echo "${slot}: ERROR: Unable to use slot"
echo "${slot}: ERROR: Unable to use slot"
fi
@@ -1,6 +0,0 @@
if button factory-reset; then
echo "Keep button pressed for 10 seconds to engage factory reset"
if sleep 10 && button factory-reset; then
run ixfactory
fi
fi
+13
View File
@@ -0,0 +1,13 @@
setenv dev_mode no
setenv factory_reset no
echo -n "dev-mode: "
run ixdevmode
echo -n "factory-reset: "
run ixfactory
if test "${dev_mode}" = "yes"; then
sleep 1 && run ixboot
else
run ixboot
fi
+7 -4
View File
@@ -1,4 +1,7 @@
setenv factory_reset yes
echo "FACTORY RESET ENGAGED"
echo "ALL user data will be deleted on system boot."
echo "To ABORT, power off device NOW."
if button factory-reset; then
echo "Keep button pressed for 10 seconds to engage reset"
if sleep 10 && button factory-reset; then
setenv factory_reset yes
echo "FACTORY RESET ENGAGED"
fi
fi
+14
View File
@@ -0,0 +1,14 @@
${devtype} dev ${devnum}
${devtype} read ${ramdisk_addr_r} ${devoffs} 0x10
fdt addr ${ramdisk_addr_r}
fdt get value squashaddr /images/ramdisk data-position
fdt get value squashsize /images/ramdisk data-size
setexpr blkcnt ${squashaddr} + ${squashsize}
setexpr blkcnt ${blkcnt} + 0x1ff
setexpr blkcnt ${blkcnt} / 0x200
${devtype} read ${ramdisk_addr_r} ${devoffs} ${blkcnt}
-73
View File
@@ -1,73 +0,0 @@
setenv dev_mode no
setenv factory_reset no
echo -n "dev-mode: "
run ixbtn-devmode
echo -n "factory-reset: "
run ixbtn-factory
setenv valid_media no
setenv ixmenu_n 0
for tgt in "${boot_targets}"; do
if test "${tgt}" = "mmc0"; then
setenv devtype "mmc"
setenv devnum 0
mmc dev 0
elif test "${tgt}" = "mmc1"; then
setenv devtype "mmc"
setenv devnum 1
mmc dev 1
else
setenv devtype "${tgt}"
setenv devnum 0
fi
if part number ${devtype} ${devnum} aux auxpart; then
setenv "boot_${tgt}_primary" "setenv devtype ${devtype}; setenv devnum ${devnum}; setenv slot primary; run ixbootslot"
setenv "bootmenu_${ixmenu_n}" "Boot primary ${tgt} partition=run boot_${tgt}_primary"
setexpr ixmenu_n ${ixmenu_n} + 1
setenv "boot_${tgt}_secondary" "setenv devtype ${devtype}; setenv devnum ${devnum}; setenv slot secondary; run ixbootslot"
setenv "bootmenu_${ixmenu_n}" "Boot secondary ${tgt} partition=run boot_${tgt}_secondary"
setexpr ixmenu_n ${ixmenu_n} + 1
if load ${devtype} ${devnum}:${auxpart} ${loadaddr} /uboot.env; then
env import -b ${loadaddr} ${filesize} BOOT_ORDER DEBUG
fi
if test -n "${DEBUG}"; then
setenv bootargs_log "debug"
else
setenv bootargs_log "loglevel=4"
fi
test -n "${BOOT_ORDER}" || setenv BOOT_ORDER "primary secondary net"
echo "Valid boot device found on ${tgt} (order: ${BOOT_ORDER})"
for slot in "${BOOT_ORDER}"; do
if test "${slot}" = "primary"; then
setenv ixbootorder "${ixbootorder}run boot_${tgt}_primary; "
elif test "${slot}" = "secondary"; then
setenv ixbootorder "${ixbootorder}run boot_${tgt}_secondary; "
elif test "${slot}" = "net"; then
setenv ixbootorder "${ixbootorder}run boot_net; "
fi
done
setenv valid_media yes
fi
done
setenv "boot_net" "setenv slot net; run ixbootslot"
setenv "bootmenu_${ixmenu_n}" "Boot over network=run boot_net"
setexpr ixmenu_n ${ixmenu_n} + 1
setenv "bootmenu_${ixmenu_n}" "Factory reset=run ixfactory; echo; pause; bootmenu"
setexpr ixmenu_n ${ixmenu_n} + 1
if test "${valid_media}" = "no"; then
echo "NO BOOTABLE MEDIA FOUND, falling back to netboot"
setenv bootargs_log "debug"
setenv ixbootorder "run boot_net"
fi
+11 -23
View File
@@ -1,28 +1,16 @@
setenv autoload no
if dhcp ${ramdisk_addr_r}; then
if dhcp; then
setenv proto tftp
setenv dltool tftpboot
setenv old_fdt_addr ${fdt_addr}
if fdt addr ${ramdisk_addr_r}; then
fdt get value sqoffs /images/rootfs data-position
fdt get value sqsize /images/rootfs data-size
fdt addr ${old_fdt_addr}
if setexpr proto sub "^(http|tftp)://.*" "\\1" "${bootfile}" && setexpr bootfile sub "^(http|tftp)://([^/]+?)/(.*)" "\2:\3"; then
if test "${proto}" = "http"; then
setenv dltool wget
fi
fi
setexpr sqaddr ${ramdisk_addr_r} + ${sqoffs}
setexpr sqblkcnt ${sqsize} / 0x200
setexpr sqkbsize ${sqsize} / 0x400
if ${dltool} ${ramdisk_addr_r} "${bootfile}"; then
setenv old_fdt_addr ${fdt_addr}
if fdt addr ${ramdisk_addr_r}; then
fdt get value sqoffs /images/rootfs data-position
fdt get value sqsize /images/rootfs data-size
fdt addr ${old_fdt_addr}
setexpr sqaddr ${ramdisk_addr_r} + ${sqoffs}
setexpr sqblkcnt ${sqsize} / 0x200
setexpr sqkbsize ${sqsize} / 0x400
setenv bootargs_root "root=/dev/ram0 ramdisk_size=0x${sqkbsize} initrd=0x${sqaddr},${sqsize}"
setenv prepared ok
fi
setenv bootargs_root "root=/dev/ram0 ramdisk_size=0x${sqkbsize} initrd=0x${sqaddr},${sqsize}"
setenv prepared ok
fi
fi
@@ -0,0 +1,5 @@
if part number mmc 0 aux auxpart; then
if load mmc 0:${auxpart} ${loadaddr} /uboot.env; then
env import -b ${loadaddr} ${filesize} BOOT_ORDER DEBUG
fi
fi
+28
View File
@@ -0,0 +1,28 @@
setenv devtype mmc
setenv devnum 0
part start ${devtype} ${devnum} ${slot} devoffs
${devtype} dev ${devnum}
${devtype} read ${ramdisk_addr_r} ${devoffs} 0x10
setenv bootargs_root "root=/dev/dm-0 dm-mod.create=\"rootfs,,0,ro,0"
setenv old_fdt_addr ${fdt_addr}
if fdt addr ${ramdisk_addr_r}; then
fdt get value sqoffs /images/rootfs data-position
fdt get value sqsize /images/rootfs data-size
fdt addr ${old_fdt_addr}
setexpr sqaddr ${ramdisk_addr_r} + ${sqoffs}
setexpr sqblknr ${sqoffs} / 0x200
setexpr sqblkcnt ${sqsize} / 0x200
setexpr fitblkcnt ${sqblknr} + ${sqblkcnt}
if ${devtype} read ${ramdisk_addr_r} ${devoffs} ${fitblkcnt}; then
setexpr decsqblkcnt fmt %u ${sqblkcnt}
setexpr decsqblknr fmt %u ${sqblknr}
setenv bootargs_root "${bootargs_root} ${decsqblkcnt} linear PARTLABEL=${slot} ${decsqblknr}\""
setenv ramdisk "-"
setenv prepared ok
fi
fi
+21 -22
View File
@@ -1,27 +1,26 @@
define uboot-add-pubkey
$(call IXMSG,"Installing trusted key $1")
$(HOST_DIR)/bin/fdt_add_pubkey \
-a sha256,rsa$(shell \
openssl x509 -text -noout -in $1 | \
grep 'Public-Key: ' | \
sed -e 's/.*(\(.*\) bit)/\1/') \
-k $(dir $1) \
-n $(notdir $(basename $1)) \
-r image \
$2
endef
# U-Boot has its own public key format which has to be stored in its
# control DT. So we collect all of the trusted keys, convert them to
# the required format, and write the result to infix-key.dtb in the
# U-Boot build tree. This will then be built in to the final U-Boot
# image's control DT via the CONFIG_DEVICE_TREE_INCLUDES option (see
# extras.config).
# This is a bit awkward. If you know about a more straight forward way
# of doing this, please simplify.
#
# U-Boot needs the public part of the signing key to be preprocessed
# and then inserted into its control DT. mkimage(1) can perform this
# conversion, but only as a side-effect of building/signing an FIT
# image. Since we might not always be doing that, e.g. when only
# building a hardware specific bootloader, we build a dummy FIT just
# to get the key information into a DTB, which we then convert back to
# a .dtsi and install in the U-Boot build tree. This will then be
# built in to the final U-Boot image's control DT via the
# CONFIG_DEVICE_TREE_INCLUDES option (see extras.config).
define UBOOT_PRE_BUILD_INSTALL_KEY
@$(call IXMSG,"Installing Infix signing key ($(SIGN_KEY))")
$(HOST_DIR)/bin/dtc <(echo '/dts-v1/; / { signature {}; };') >$(@D)/infix-key.dtb
$(foreach key, \
$(call qstrip,$(TRUSTED_KEYS_DEVELOPMENT_PATH)) $(call qstrip,$(TRUSTED_KEYS_EXTRA_PATH)),\
$(call uboot-add-pubkey,$(key),$(@D)/infix-key.dtb))
$(HOST_DIR)/bin/mkimage \
-k $(SIGN_KEY) \
-f $(BR2_EXTERNAL_INFIX_PATH)/board/common/uboot/key-dummy.its \
-K $(@D)/infix-key.dtb \
$(if $(SIGN_SRC_PKCS11),-N pkcs11) \
-r \
$(@D)/key-dummy.itb
rm $(@D)/key-dummy.itb
$(HOST_DIR)/bin/dtc -I dtb -O dts \
<$(@D)/infix-key.dtb \
| sed -e 's:/dts-v[0-9]\+/;::' >$(@D)/arch/$(UBOOT_ARCH)/dts/infix-key.dtsi
+32
View File
@@ -0,0 +1,32 @@
test-dir := $(BR2_EXTERNAL_INFIX_PATH)/test
INFIX_TESTS ?= $(test-dir)/case/all.yaml
test-env = $(test-dir)/env \
-f $(BINARIES_DIR)/infix-x86_64.img \
-p $(BINARIES_DIR)/infix-x86_64.pkg \
$(1) $(2)
test-env-qeneth = $(call test-env,-q $(test-dir)/virt/quad,$(1))
test-env-run = $(call test-env,-C -t $(BINARIES_DIR)/qemu.dot,$(1))
test test-qeneth:
$(call test-env-qeneth,\
$(BR2_EXTERNAL_INFIX_PATH)/test/9pm/9pm.py \
$(INFIX_TESTS))
test-sh test-qeneth-sh:
$(call test-env-qeneth,-i /bin/sh)
test-run: | ~/.infix-test-venv
$(call test-env-run,\
$(BR2_EXTERNAL_INFIX_PATH)/test/9pm/9pm.py \
$(INFIX_TESTS))
test-run-sh: | ~/.infix-test-venv
$(call test-env-run,/bin/sh)
test-run-play: | ~/.infix-test-venv
$(call test-env-run,$(test-dir)/case/meta/play.py)
~/.infix-test-venv:
$(test-dir)/docker/init-venv.sh $(test-dir)/docker/pip-requirements.txt
.PHONY: test test-sh test-qeneth test-qeneth-sh test-run test-run-sh test-run-play
+1 -6
View File
@@ -1,6 +1 @@
search -l aux --set=aux
search -l primary --set=primary
search -l secondary --set=secondary
set prefix=($aux)/grub
configfile ($aux)/grub/grub.cfg
set prefix=(hd0,gpt2)/grub
+5 -12
View File
@@ -33,24 +33,17 @@ else
set log="loglevel=4"
fi
# From board/common/rootfs/etc/partition-uuid
search -p 107ae911-a97b-4380-975c-7ce1a2dde1e0 --set primary
search -p 352bd9b2-2ca9-44e2-bdc7-edbc87ba1e02 --set secondary
export primary
export secondary
submenu "primary" "$log" {
set slot="$1"
set append="console=ttyS0 console=hvc0 root=PARTLABEL=$slot $2"
set root="($primary)"
set append="console=ttyS0 root=PARTLABEL=$slot $2"
set root=(hd0,gpt3)
source /boot/grub/grub.cfg
}
submenu "secondary" "$log" {
set slot="$1"
set append="console=ttyS0 console=hvc0 root=PARTLABEL=$slot $2"
set root="($secondary)"
set append="console=ttyS0 root=PARTLABEL=$slot $2"
set root=(hd0,gpt4)
source /boot/grub/grub.cfg
}
@@ -63,7 +56,7 @@ submenu "net" "$log" {
set root=(initrd)
set slot="$1"
set append="console=ttyS0 console=hvc0 qroot=/dev/ram0 ramdisk_size=65536 $2"
set append="console=ttyS0 root=/dev/ram0 ramdisk_size=65536 $2"
source /boot/grub/grub.cfg
else
if [ -z "$net_efinet0_dhcp_next_server" ]; then
+6 -15
View File
@@ -13,20 +13,18 @@ BR2_TARGET_GENERIC_ISSUE="Infix by KernelKit"
BR2_INIT_FINIT=y
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs"
# BR2_TARGET_ENABLE_ROOT_LOGIN is not set
BR2_SYSTEM_BIN_SH_BASH=y
BR2_TARGET_GENERIC_GETTY_PORT="@console"
BR2_TARGET_GENERIC_GETTY_TERM="xterm"
BR2_SYSTEM_DHCP="eth0"
BR2_ENABLE_LOCALE_WHITELIST="C en_US en_CA C.UTF-8"
BR2_GENERATE_LOCALE="en_US en_CA C.UTF-8"
BR2_ENABLE_LOCALE_WHITELIST="C en_US en_CA"
BR2_GENERATE_LOCALE="en_US en_CA"
BR2_TARGET_TZ_INFO=y
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/rootfs"
BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.34"
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.22"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig"
BR2_LINUX_KERNEL_DTS_SUPPORT=y
@@ -47,6 +45,7 @@ BR2_PACKAGE_EUDEV_RULES_GEN=y
BR2_PACKAGE_GPTFDISK=y
BR2_PACKAGE_GPTFDISK_SGDISK=y
BR2_PACKAGE_MDIO_TOOLS=y
BR2_PACKAGE_MEMTESTER=y
BR2_PACKAGE_RNG_TOOLS=y
BR2_PACKAGE_UBOOT_TOOLS=y
BR2_PACKAGE_UBOOT_TOOLS_FIT_SUPPORT=y
@@ -54,18 +53,17 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y
BR2_PACKAGE_UBOOT_TOOLS_MKENVIMAGE=y
BR2_PACKAGE_PYTHON3=y
BR2_PACKAGE_PYTHON_CRYPTOGRAPHY=y
BR2_PACKAGE_PYTHON_GUNICORN=y
BR2_PACKAGE_LIBSSH_OPENSSL=y
BR2_PACKAGE_LIBSSH2=y
BR2_PACKAGE_LIBSSH2_OPENSSL=y
BR2_PACKAGE_LIBXCRYPT=y
BR2_PACKAGE_LIBOPENSSL_BIN=y
BR2_PACKAGE_LIBCURL_CURL=y
BR2_PACKAGE_NETOPEER2_CLI=y
BR2_PACKAGE_NSS_MDNS=y
BR2_PACKAGE_LINUX_PAM=y
BR2_PACKAGE_LIBPAM_RADIUS_AUTH=y
BR2_PACKAGE_ONIGURUMA=y
BR2_PACKAGE_AVAHI=y
BR2_PACKAGE_AVAHI_DAEMON=y
BR2_PACKAGE_AVAHI_DEFAULT_SERVICES=y
BR2_PACKAGE_CHRONY=y
@@ -96,7 +94,6 @@ BR2_PACKAGE_SOCAT=y
BR2_PACKAGE_TCPDUMP=y
BR2_PACKAGE_TRACEROUTE=y
BR2_PACKAGE_ULOGD=y
BR2_PACKAGE_WHOIS=y
BR2_PACKAGE_BASH_COMPLETION=y
BR2_PACKAGE_SUDO=y
BR2_PACKAGE_TTYD=y
@@ -132,7 +129,6 @@ INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
BR2_PACKAGE_CONFD=y
BR2_PACKAGE_CURIOS_HTTPD=y
BR2_PACKAGE_EXECD=y
BR2_PACKAGE_GENCERT=y
BR2_PACKAGE_STATD=y
BR2_PACKAGE_FACTORY=y
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
@@ -145,7 +141,6 @@ BR2_PACKAGE_IITO=y
BR2_PACKAGE_K8S_LOGGER=y
BR2_PACKAGE_KEYACK=y
BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
BR2_PACKAGE_LANDING=y
BR2_PACKAGE_LOWDOWN=y
BR2_PACKAGE_MCD=y
BR2_PACKAGE_MDNS_ALIAS=y
@@ -155,11 +150,7 @@ BR2_PACKAGE_PODMAN_DRIVER_BTRFS=y
BR2_PACKAGE_PODMAN_DRIVER_DEVICEMAPPER=y
BR2_PACKAGE_PODMAN_DRIVER_VFS=y
BR2_PACKAGE_TETRIS=y
BR2_PACKAGE_ROUSETTE=y
BR2_PACKAGE_LIBINPUT=y
BR2_PACKAGE_HOST_PYTHON_YANGDOC=y
DISK_IMAGE_BOOT_BIN=y
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
GNS3_APPLIANCE_RAM=512
GNS3_APPLIANCE_IFNUM=10

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