Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,24 @@ include("//bazel_common:score_modules_target_sw.MODULE.bazel")
# Score test images
include("//bazel_common:score_images.MODULE.bazel")

# The release tag includes the KAS/Isar sources; no delivery images are needed.
new_git_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository")

new_git_repository(
name = "eb_corbos_toolkit",
build_file_content = """
exports_files(["BUILD.bazel"])

filegroup(
name = "sources",
srcs = glob(["kas/**", "layers/**", ".devcontainer/**"]),
visibility = ["//visibility:public"],
)
""",
commit = "2b0a6c88dd12f892de830ffdabc5dabda275838c", # v2.0.0-beta2
remote = "https://github.com/Elektrobit/eb_corbos_toolkit.git",
)

# Single-version locks for the deps Stage 2 collects test artifacts from (GTest, the Rust
# test rules, the ferrocene coverage tooling). Read after the includes above so it pins the
# versions they bring in transitively.
Expand Down
3 changes: 3 additions & 0 deletions images/ebclfsa_aarch64/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ This is an `aarch64`-based, pre-built image, capable of demonstraing the executi
The example can be executed using QEMU.
In the [related CI workflow](../.github/workflows/build_and_test_ebclfsa.yml), all these steps are performed, and the resulting log files are stored and made available for download.

For a new image assembled from Debian packages with KAS, instead of deploying
onto this prebuilt image, see the [from-scratch build](../ebclfsa_aarch64_from_scratch/README.md).

> [!TIP]
> **Quick Start**
>
Expand Down
73 changes: 73 additions & 0 deletions images/ebclfsa_aarch64_from_scratch/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# *******************************************************************************
# Copyright (c) 2026 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************

load("@rules_shell//shell:sh_binary.bzl", "sh_binary")
load("@rules_shell//shell:sh_test.bzl", "sh_test")

genrule(
name = "image",
srcs = [
"kas.yml",
"@eb_corbos_toolkit//:BUILD.bazel",
"@eb_corbos_toolkit//:sources",
"//showcases:showcases_deb",
"//images/ebclfsa_aarch64/build/config-overlay:etc/crinit/crinit.d/getty-console.crinit",
"//images/ebclfsa_aarch64/build/config-overlay:usr/bin/delayed-start.sh",
] + glob(["meta-score/**"]),
outs = [
"fastdev-trixie-ebclfsa-ebcl-qemuarm64-vmlinux",
"fastdev-trixie-ebclfsa-ebcl-qemuarm64.wic",
],
cmd = "bash $(location build_image.sh) " +
"$$(dirname $(location @eb_corbos_toolkit//:BUILD.bazel)) " +
"$(location //showcases:showcases_deb) " +
"$(location kas.yml) " +
"$(location //images/ebclfsa_aarch64/build/config-overlay:etc/crinit/crinit.d/getty-console.crinit) " +
"$(location //images/ebclfsa_aarch64/build/config-overlay:usr/bin/delayed-start.sh) " +
"$(RULEDIR)",
local = True,
tags = ["manual"],
tools = ["build_image.sh"],
visibility = ["//visibility:public"],
)

sh_binary(
name = "run",
srcs = ["//runners/qemu_aarch64/scripts:run_qemu.sh"],
args = [
"$(location :fastdev-trixie-ebclfsa-ebcl-qemuarm64-vmlinux)",
"$(location :fastdev-trixie-ebclfsa-ebcl-qemuarm64.wic)",
"-append",
"'root=/dev/vda1 sdk_enable lisa_syscall_whitelist=2026 rw sharedmem.enable_sharedmem=0 init=/usr/bin/ebclfsa-cflinit'",
"-snapshot",
],
data = [
":fastdev-trixie-ebclfsa-ebcl-qemuarm64.wic",
":fastdev-trixie-ebclfsa-ebcl-qemuarm64-vmlinux",
],
tags = ["manual"],
use_bash_launcher = True,
visibility = ["//visibility:public"],
)

sh_test(
name = "build_image_test",
size = "small",
srcs = ["build_image_test.sh"],
data = [
"build_image.sh",
"kas.yml",
"//images/ebclfsa_aarch64/build/config-overlay:etc/crinit/crinit.d/getty-console.crinit",
"//images/ebclfsa_aarch64/build/config-overlay:usr/bin/delayed-start.sh",
] + glob(["meta-score/**"]),
)
68 changes: 68 additions & 0 deletions images/ebclfsa_aarch64_from_scratch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# EB corbos Linux for Safety Applications: image from scratch

```bash
bazel run --config=eb-aarch64 //images/ebclfsa_aarch64_from_scratch:run
```

This cross-compiles the showcases with the EB aarch64 toolchains, packages
[`//showcases:showcases_pkg_tar`](../../showcases/BUILD) as the `score-showcases`
arm64 Debian package, and builds a new `fastdev` disk image with KAS/Isar.
The image is assembled from Debian packages using a Git checkout of the
[EB corbos Toolkit v2.0.0-beta2 tag](https://github.com/Elektrobit/eb_corbos_toolkit/tree/v2.0.0-beta2),
pinned to its commit in `MODULE.bazel`. Only the KAS configuration, bundled Isar
layers and development-container setup are copied into the build workspace.
The large delivery archive, including its prebuilt container and disk images,
is not downloaded. The build container is pulled separately from GHCR.
It does **not** boot or modify the toolkit's prebuilt disk image.
The toolkit still supplies precompiled system packages, including the kernel;
this is an image build from packages, not a source rebuild of the entire OS.

## Requirements

- An x86_64 Linux host with Docker and permission to run privileged containers.
The Docker daemon must see the Bazel output directory at the same absolute
path as the build process (not a remote Docker daemon).
- Network access to GitHub, GHCR, and the package repositories referenced by the
toolkit; substantial free disk space for the Isar build.
- `qemu-system-aarch64` and passwordless `sudo`, as required by the existing
[QEMU runner](../../runners/qemu_aarch64/scripts/run_qemu.sh).

The local image-building action runs the toolkit's digest-pinned v18 development
container. It registers its aarch64 binfmt interpreter if none is registered;
this requires privileged access and affects the host kernel's binfmt registry.
Existing aarch64 registrations are left untouched. KAS/Isar needs privileges
for chroots and mounts, so this action cannot run in a Bazel sandbox or on a
remote executor.

## Outputs and boot

To build without starting QEMU:

```bash
bazel build --config=eb-aarch64 //images/ebclfsa_aarch64_from_scratch:image
```

The kernel and `.wic` disk image are written to
`bazel-bin/images/ebclfsa_aarch64_from_scratch/`. The temporary KAS workspace
is removed after the build. The showcases are installed at `/showcases`.
The existing console configuration starts the showcase CLI automatically.
QEMU uses a temporary disk snapshot so running it does not modify Bazel's
image output. Exit QEMU with `Ctrl-a x`.

The Debian package can also be built separately:

```bash
bazel build --config=eb-aarch64 //showcases:showcases_deb
```

The original [prebuilt-image integration](../ebclfsa_aarch64/README.md) remains
available unchanged.

## Tests

The staging test checks package and console configuration placement, excludes
prebuilt images, and verifies cleanup and failure propagation without Docker:

```bash
bazel test --config=eb-aarch64 //images/ebclfsa_aarch64_from_scratch:build_image_test
```
84 changes: 84 additions & 0 deletions images/ebclfsa_aarch64_from_scratch/build_image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/bin/bash
# *******************************************************************************
# Copyright (c) 2026 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************

set -euo pipefail

if [[ $# != 6 ]]; then
echo "Usage: $0 TOOLKIT_SOURCE_DIR DEB KAS_CONFIG GETTY_CONFIG START_SCRIPT OUTPUT_DIR" >&2
exit 1
fi

for tool in docker realpath; do
if ! command -v "$tool" >/dev/null; then
echo "Error: required image build tool is missing: $tool" >&2
exit 1
fi
done
docker info >/dev/null

toolkit=$(realpath "$1")
deb=$(realpath "$2")
config=$(realpath "$3")
getty=$(realpath "$4")
start=$(realpath "$5")
output=$(realpath "$6")
sources=$(dirname "$config")
# Keep the workspace on the same filesystem visible to the Docker daemon.
work=$(mktemp -d "$output/kas-work.XXXXXXXX")
trap 'rm -rf -- "$work"' EXIT

cp -R "$toolkit/kas" "$toolkit/layers" "$toolkit/.devcontainer" "$work/"
cp -R "$sources/meta-score" "$work/meta-score"
cp "$config" "$work/kas/score.yml"
packages="$work/meta-score/recipes-score/score-showcases/files"
console="$work/meta-score/recipes-crinit/fastdev/files"
mkdir -p "$packages" "$console"
cp "$deb" "$packages/score-showcases_1.0_arm64.deb"
cp "$getty" "$console/getty-console.crinit"
cp "$start" "$console/delayed-start.sh"

# Match the toolkit's v18 container, pinned independently of its mutable tag.
container=ghcr.io/elektrobit/eb-corbos-toolkit-devcontainer-amd64@sha256:10f487469c03fb2b5be1c804ec0b0c911d3903a9dd9a8fcbb8b8f401d43b158c
docker run --rm --init --privileged --user root \
--mount "type=bind,src=$work,dst=/workspace" \
--workdir /workspace "$container" \
bash -euo pipefail -c '
uid=$1
gid=$2
if ! getent group "$gid" >/dev/null; then
groupmod -g "$gid" developer
fi
usermod -u "$uid" -g "$gid" developer
trap '\''chown -R "$uid:$gid" /workspace'\'' EXIT
if [[ ! -e /proc/sys/fs/binfmt_misc/qemu-aarch64 ]]; then
mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
update-binfmts --import /workspace/.devcontainer/binfmt-config/qemu-aarch64
fi
# KAS resolves includes relative to the enclosing Git repository.
runuser -u developer -- git init --quiet /workspace
# The release checkout already includes the patched Isar tree; its internal
# patch sources are not shipped.
runuser -u developer -- kas build \
--skip repos_checkout --skip repos_apply_patches \
kas/public.yml:kas/score.yml
' bash "$(id -u)" "$(id -g)"

deploy="$work/build/tmp/deploy/images/ebcl-qemuarm64"
for artifact in fastdev-trixie-ebclfsa-ebcl-qemuarm64{.wic,-vmlinux}; do
if [[ ! -f "$deploy/$artifact" ]]; then
echo "Error: KAS did not produce the expected artifact: $deploy/$artifact" >&2
exit 1
fi
cp --sparse=always -L "$deploy/$artifact" "$output/$artifact"
done
93 changes: 93 additions & 0 deletions images/ebclfsa_aarch64_from_scratch/build_image_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/bin/bash
# *******************************************************************************
# Copyright (c) 2026 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************

set -euo pipefail

sources="$TEST_SRCDIR/_main/images/ebclfsa_aarch64_from_scratch"
overlay="$TEST_SRCDIR/_main/images/ebclfsa_aarch64/build/config-overlay"
fixture="$TEST_TMPDIR/fixture"
output="$TEST_TMPDIR/output"
mkdir -p "$fixture/"{kas,layers/isar,.devcontainer,prebuilt} "$output"
echo "must not use a prebuilt image" > "$fixture/prebuilt/image.wic"
echo "KAS configuration" > "$fixture/kas/public.yml"
echo "bundled Isar" > "$fixture/layers/isar/isar-init-build-env"
echo "container configuration" > "$fixture/.devcontainer/devcontainer.json"
echo "Debian package fixture" > "$TEST_TMPDIR/showcases.deb"

# Exercise staging, artifact export and error propagation without a privileged
# container or network access.
docker() {
if [[ $1 == info ]]; then
return 0
fi
local mount work deploy
while [[ $# -gt 0 ]]; do
if [[ $1 == --mount ]]; then
mount=$2
break
fi
shift
done
work=${mount#type=bind,src=}
work=${work%,dst=/workspace}
[[ ! -e "$work/prebuilt" ]]
cmp "$TEST_TMPDIR/fixture/kas/public.yml" "$work/kas/public.yml"
cmp "$TEST_TMPDIR/fixture/layers/isar/isar-init-build-env" "$work/layers/isar/isar-init-build-env"
cmp "$TEST_TMPDIR/fixture/.devcontainer/devcontainer.json" "$work/.devcontainer/devcontainer.json"
cmp "$TEST_TMPDIR/showcases.deb" \
"$work/meta-score/recipes-score/score-showcases/files/score-showcases_1.0_arm64.deb"
cmp "$TEST_SRCDIR/_main/images/ebclfsa_aarch64_from_scratch/kas.yml" "$work/kas/score.yml"
cmp "$TEST_SRCDIR/_main/images/ebclfsa_aarch64/build/config-overlay/etc/crinit/crinit.d/getty-console.crinit" \
"$work/meta-score/recipes-crinit/fastdev/files/getty-console.crinit"
cmp "$TEST_SRCDIR/_main/images/ebclfsa_aarch64/build/config-overlay/usr/bin/delayed-start.sh" \
"$work/meta-score/recipes-crinit/fastdev/files/delayed-start.sh"
if [[ ${MOCK_DOCKER_FAIL:-0} == 1 ]]; then
return 17
fi
deploy="$work/build/tmp/deploy/images/ebcl-qemuarm64"
mkdir -p "$deploy"
echo kernel > "$deploy/fastdev-trixie-ebclfsa-ebcl-qemuarm64-vmlinux"
if [[ ${MOCK_MISSING_IMAGE:-0} != 1 ]]; then
echo disk > "$deploy/fastdev-trixie-ebclfsa-ebcl-qemuarm64.wic"
fi
}
export -f docker

build_image() {
bash "$sources/build_image.sh" "$fixture" \
"$TEST_TMPDIR/showcases.deb" "$sources/kas.yml" \
"$overlay/etc/crinit/crinit.d/getty-console.crinit" \
"$overlay/usr/bin/delayed-start.sh" "$output"
}

build_image
[[ ! -e "$fixture/kas/score.yml" ]]
[[ ! -e "$fixture/meta-score" ]]
[[ $(cat "$output/fastdev-trixie-ebclfsa-ebcl-qemuarm64-vmlinux") == kernel ]]
[[ $(cat "$output/fastdev-trixie-ebclfsa-ebcl-qemuarm64.wic") == disk ]]

export MOCK_DOCKER_FAIL=1
if build_image; then
echo "Error: container failure was not propagated" >&2
exit 1
fi
export MOCK_DOCKER_FAIL=0 MOCK_MISSING_IMAGE=1
if build_image; then
echo "Error: missing image artifact was not rejected" >&2
exit 1
fi
if find "$output" -maxdepth 1 -name 'kas-work.*' | grep -q .; then
echo "Error: temporary KAS workspace was not cleaned up" >&2
exit 1
fi
25 changes: 25 additions & 0 deletions images/ebclfsa_aarch64_from_scratch/kas.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# *******************************************************************************
# Copyright (c) 2026 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************

header:
version: 18

repos:
meta-score:
path: meta-score
layers:
.:

local_conf_header:
score_showcases: |
IMAGE_INSTALL:append = " score-showcases"
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2026 Contributors to the Eclipse Foundation
# SPDX-License-Identifier: Apache-2.0

BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "score"
BBFILE_PATTERN_score = "^${LAYERDIR}/"
BBFILE_PRIORITY_score = "10"
LAYERSERIES_COMPAT_score = "next"
Loading
Loading