diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000000..d848a7d1fd
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,5 @@
+{
+ "name": "eclipse-s-core",
+ "image": "ghcr.io/eclipse-score/devcontainer:0.1.0",
+ "postStartCommand": "ssh-keygen -f '/home/vscode/.ssh/known_hosts' -R '[localhost]:2222' || true"
+}
diff --git a/.github/workflows/build_and_test_ebclfsa.yml b/.github/workflows/build_and_test_ebclfsa.yml
new file mode 100644
index 0000000000..4dcab88585
--- /dev/null
+++ b/.github/workflows/build_and_test_ebclfsa.yml
@@ -0,0 +1,41 @@
+# *******************************************************************************
+# Copyright (c) 2025 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
+# *******************************************************************************
+
+name: Build for and Test on EB corbos Linux for Safety Applications
+
+on:
+ pull_request:
+ paths:
+ - 'ebclfsa/**'
+ workflow_dispatch:
+
+jobs:
+ build:
+ name: build-and-test-ebclfsa
+ runs-on: ubuntu-latest
+ container:
+ image: ghcr.io/eclipse-score/devcontainer:0.1.0
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Build for EB corbos Linux for Safety Applications and run tests
+ run: bazel build --config=aarch64 --spawn_strategy=local //example/ipc_bridge_hi_wrapper:run_example
+ working-directory: ./ebclfsa
+
+ - name: Upload test logs
+ uses: actions/upload-artifact@v5
+ with:
+ name: test-logs
+ path: ebclfsa/bazel-bin/example/ipc_bridge_hi_wrapper/*.log
diff --git a/ebclfsa/.bazelrc b/ebclfsa/.bazelrc
new file mode 100644
index 0000000000..4cde06a656
--- /dev/null
+++ b/ebclfsa/.bazelrc
@@ -0,0 +1,10 @@
+common --@score_baselibs//score/mw/log/detail/flags:KUse_Stub_Implementation_Only=False
+common --@score_baselibs//score/mw/log/flags:KRemote_Logging=False
+common --@score_baselibs//score/json:base_library=nlohmann
+common --@score_communication//score/mw/com/flags:tracing_library=stub
+
+common --registry=https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/
+common --registry=https://bcr.bazel.build
+
+common --extra_toolchains=@gcc_toolchain//:aarch64_gcc_13
+build:aarch64 --platforms=@score_toolchains_gcc//platforms:aarch64-linux
diff --git a/ebclfsa/BUILD b/ebclfsa/BUILD
new file mode 100644
index 0000000000..df35a19965
--- /dev/null
+++ b/ebclfsa/BUILD
@@ -0,0 +1,13 @@
+# *******************************************************************************
+# Copyright (c) 2025 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
+
+# *******************************************************************************
diff --git a/ebclfsa/MODULE.bazel b/ebclfsa/MODULE.bazel
new file mode 100644
index 0000000000..4fdc46c3f5
--- /dev/null
+++ b/ebclfsa/MODULE.bazel
@@ -0,0 +1,82 @@
+# *******************************************************************************
+# Copyright (c) 2025 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
+# *******************************************************************************
+
+"EB corbos Linux for Safety Applications - S-CORE Reference Integration"
+
+module(
+ name = "reference_integration_ebclfsa",
+ version = "0.1.0",
+ compatibility_level = 0,
+)
+
+bazel_dep(name = "rules_cc", version = "0.2.0")
+
+bazel_dep(name = "score_toolchains_gcc", version = "0.0.0", dev_dependency=True)
+git_override(
+ module_name = "score_toolchains_gcc",
+ remote = "https://github.com/Elektrobit/eclipse-score_toolchains_gcc.git",
+ commit = "fb009e490b9b8f28805d587f50d0bf6d885f3414",
+)
+gcc = use_extension("@score_toolchains_gcc//extentions:gcc.bzl", "gcc", dev_dependency=True)
+gcc.toolchain(
+ url = "https://linux.elektrobit.com/tmp/score/fastdev-sdk-ubuntu-ebcl-deb-qemu-arm64.tar.xz",
+ sha256 = "cf8d277a2b95bbdad3e177c488fa77d01723510690a911218ef33747574d78fe",
+ strip_prefix = "fastdev-sdk-ubuntu-ebcl-deb-qemuarm64",
+)
+
+# TODO to be moved to toolchain. https://github.com/eclipse-score/toolchains_gcc/issues/11
+gcc.extra_features(
+ features = [
+ "minimal_warnings",
+ "treat_warnings_as_errors",
+ ],
+)
+gcc.warning_flags(
+ minimal_warnings = ["-Wall", "-Wno-error=deprecated-declarations"],
+ strict_warnings = ["-Wextra", "-Wpedantic"],
+ treat_warnings_as_errors = ["-Werror"],
+)
+
+use_repo(gcc, "gcc_toolchain", "gcc_toolchain_gcc")
+
+
+bazel_dep(name = "rules_boost", repo_name = "com_github_nelhage_rules_boost")
+archive_override(
+ module_name = "rules_boost",
+ urls = ["https://github.com/nelhage/rules_boost/archive/refs/heads/master.tar.gz"],
+ strip_prefix = "rules_boost-master",
+)
+
+bazel_dep(name = "boost.program_options", version = "1.87.0")
+
+bazel_dep(name = "score_baselibs")
+single_version_override(
+ module_name = "score_baselibs",
+ version = "0.1.3",
+ patch_strip = 1,
+ patches = [
+ "//patches:fix_hard_coded_amd64.patch",
+ ],
+)
+bazel_dep(name = "score_communication")
+single_version_override(
+ module_name = "score_communication",
+ version = "0.1.1",
+)
+
+# git_override are not forwarded by bazel_dep, so we need to redefine it here
+git_override(
+ module_name = "trlc",
+ remote = "https://github.com/bmw-software-engineering/trlc.git",
+ commit = "650b51a47264a4f232b3341f473527710fc32669", # trlc-2.0.2 release
+)
diff --git a/ebclfsa/README.md b/ebclfsa/README.md
new file mode 100644
index 0000000000..57b9e91cb5
--- /dev/null
+++ b/ebclfsa/README.md
@@ -0,0 +1,386 @@
+# Eclipse S-CORE on Elektrobit corbos Linux for Safety Applications
+
+This directory shows the integration of Eclipse S-CORE on Elektrobit corbos Linux for Safety Applications.
+It builds an [example](example/) based on the Eclipse S-CORE communication framework as demo/test application.
+This application is then integrated into the so-called "fast-dev" variant of EB corbos Linux for Safety Applications (EBcLfSA).
+This is an `aarch64`-based, pre-built image, capable of demonstraing the execution of high integrity applications in regular Linux user-space.
+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.
+
+
+> [!TIP]
+> **Quick Start**
+>
+> The fastest way to run the integration interactively is to use [GitHub Codespaces](https://github.com/features/codespaces), a cloud based development environment.
+> You need a GitHub.com account for this to work.
+There is a free tier of this commercial service, which is sufficient.
+However, please understand that we cannot advise you about possible costs in your specific case.
+> - Click on the following badge: [](https://codespaces.new/eclipse-score/reference_integration)
+> - In the following dialog, make sure to select "Machine type" as "4-core".
+> Click "Create codespace."
+> It will take some time (2-3 minutes) for the machine to start.
+> There will be a log message "Finished configuring codespace."
+> - Hit "Ctrl-Shift-C" to open a new terminal.
+> - Copy and paste the following command into the terminal and hit "Enter":
+>
+> ```bash
+> cd ./ebclfsa && bazel build --config=aarch64 --spawn_strategy=local //example/ipc_bridge_hi_wrapper:run_example
+> ```
+>
+> This will build and run the example.
+> There may be a warning about "High codespace CPU (100%) utilization detected.", which you can ignore.
+> The complete process will take around 6 minutes to complete on the 4-core machine.
+>
+> The expected output looks like this:
+>
+> ```console
+> [...]
+> Target //example/ipc_bridge_hi_wrapper:run_example up-to-date:
+> bazel-bin/example/ipc_bridge_hi_wrapper/qemu_run.log
+> bazel-bin/example/ipc_bridge_hi_wrapper/ssh_run.log
+>INFO: Elapsed time: 361.273s, Critical Path: 91.92s
+>INFO: 836 processes: 10 internal, 826 local.
+>INFO: Build completed successfully, 836 total actions
+> ```
+>
+> The two log files mentioned in this output are the main results of the test execution.
+> You can open them by Ctrl-clicking on the output entry.
+>
+> The remainder of this document describes in detail what you have just accomplished.
+>
+> In order to close the Codespace again, first take note of the name of the Codespace.
+> It is a random combination of and adjective and a noun, mentioned in the bottom left of the browser window.
+> Go to your [GitHub Codespaces Dashboard](https://github.com/codespaces), find the Codespace in your list, click on the "..." in that row and select "Delete".
+>
+> Note that the demo can, of course, als run locally on your computer.
+> Clone the repository, open it in Visual Studio Code, start the supplied Development Container, and run the demo as described above.
+> This requires a setup that can run [Development Containers](https://containers.dev/) using [Visual Studio Code](https://code.visualstudio.com/).
+> The [Visual Studio Code documentation](https://code.visualstudio.com/docs/devcontainers/containers) can be a good starting point; however, an in-depth explanation of this is beyond the goals of this Quick Start.
+
+## Prebuilt Binary Assets
+
+The whole setup is open source.
+To simplify the deployment and focus on the integration itself, this demo uses pre-built binary assets.
+These consist of a pre-built image and a cross-compilation toolchain.
+Both assets are referenced in the corresponding Bazel targets and are automatically downloaded on demand.
+
+The pre-built image provides a so called "fast-dev" integration for EBcLfSA,
+which makes development and debugging of high integrity applications easy.
+The fast-dev image itself is based on a single aarch64 Linux VM with a specially patched Linux kernel and user-space.
+It checks at runtime, whether high integrity applications adhere to certain assumptions of use (AoU) of EBcLfSA.
+
+Note that this image represents a development image but not a production image of Linux for Safety Application.
+It is aimed at demonstrating development with focus on key features and AoUs.
+
+## Main constraints for high-integrity applications
+
+For non-safety ("low integrity") applications, Linux for Safety Applications _is_ a standard Linux system.
+For applications with safety requirements, also referred to as _high integrity (HI) applications_,
+Linux for Safety Applications expects few constraints, especially:
+
+1. An HI application must be flagged with an additional checksum in its ELF-header to be detected as an high integrity application.
+2. An HI application must check its registration status with the supervisor.
+3. At least one HI application (e.g. a health manager) must cyclically trigger
+ the watchdog of Linux for Safety Applications.
+4. Few kernel system calls are not allowed to be invoked by an HI application.
+ - The patches of the "fast-dev" kernel will create a log which helps you to identify them.
+ - Recommendation:
+ Build your HI applications and associated libraries on top of the C standard's library definition.
+ Elektrobit will provide an appropriately qualified version for production projects.
+5. Ask for advice when you want to modify/extend kernel functionality or invoke device-specific I/O operations.
+
+The example application disregards the items 2-5.
+They are mandatory for production systems but can be violated during development in the fast-dev environment.
+For example, the items 3 and 4 only make sense in a complete system.
+
+Current restrictions:
+
+- HI applications must be statically linked.
+- PID1 needs to be an HI process.
+- HI processes can only be started by another HI process.
+
+## Application- and Integration-Specific Violation of System Call Restrictions
+
+The current integration setup is based on a non-safety-certified set of a toolchain and standard libraries.
+As a result, an application compiled and linked with the provided example toolchain will generate system call violations.
+For the used communication example app this happens during application startup/teardown and is indicated by the occurrence of `ioctl`,`clone3` and `madvice` system calls.
+
+The full product version intended for production implements process and memory management for high integrity applications according to the C Standard Library.
+When using other standard library implementations, `clone3` and `madvice` might be called.
+This is ok during development and will not affect you when switching to the safety compliant C Standard Library.
+Avoid calling such system calls directly from HI applications, though.
+The following table gives an overview why the occurred system calls are not supported and what would be the proposed alternative solution.
+Keep in mind, this is only relevant if the system calls are explicitly called by the application code, or libraries other than the provided standard libraries.
+
+| System Call | Reason | Suggested Alternative or Workaround |
+|---------|--------|-------------------------------------|
+| `ioctl` | Very flexible function signature, which is hard to "make safe" in a generic way. | Try to avoid direct `ioctl` calls. If direct driver interaction is needed, use alternative kernel standard interfaces like `netlink` or device file IO. A customer specific implementation of a certain function signature might be possible. |
+| `clone3` | No part of C standard library. Not needed to create HI processes. | Use C standard library functions to create processes and threads (or system call `clone`). The full product version intended for production will implement them in a way that ensures safe execution. |
+| `madvise` | No part of C standard library. All memory of HI Apps is pre-faulted and fully committed at allocation time, hence most kernel optimizations/hints have limited effect. | Use C standard library functions for memory management. The full product version intended for production will implement them in a way that ensures safe execution. |
+
+## User-Space
+
+The user-space of the pre-built image consists of three main components:
+
+- The _trampoline application_, a simplified HI init process
+- EBcLfSA example HI and LI applications
+- Low integrity system init and user-space
+
+
+
+The system itself is able to run without any Eclipse S-CORE demo applications.
+Nevertheless, the trampoline application already provides an entry point for a subsequently deployed application binary.
+This entry point is used by the [Eclipse S-CORE Example](#eclipse-s-core-example) application.
+
+### Trampoline App (cflinit)
+
+The trampoline application `cflinit` acts as a simplified HI init process which starts the applications as listed above.
+This includes the HI application of the EBcLfSA example, as well as a wrapper for the Eclipse S-CORE application binary.
+Besides the HI applications, it starts [crinit](https://gitext.elektrobitautomotive.com/EB-Linux/crinit) as a secondary low integrity init daemon,
+which brings up the regular (low integrity) Linux user-land.
+Once all apps are started, it sleeps forever.
+
+Below you can see the output generated by `cflinit`.
+
+```console
+cflinit: INFO: Hello from EBcLfSA HI init application
+cflinit: INFO: Mounted tmpfs to /dev/shm
+cflinit: INFO: Starting application crinit
+cflinit: INFO: Starting application HI App
+cflinit: ERROR: Could not read /usr/bin/hi_app (2)
+cflinit: INFO: Starting application EBcLfSA HI demo
+cflinit: INFO: Starting application EBcLfSA HI upper
+cflinit: INFO: Finished starting child applications; going to sleep
+```
+
+As long as the Eclipse S-CORE example is not yet deployed (detected by a missing `/usr/bin/hi_app` binary) the above `ERROR` occurs and `cflinit` skips starting it.
+
+### EBcLfSA HI Demo
+
+For technical reasons, the image contains also a secondary demo, with the executables `ebclfsa-hi-demo`, `ebclfsa-hi-upper`, and `ebclfsa-li-demo`.
+They demonstrate message passing via a shared memory interface, which does not use Eclipse S-CORE.
+Hence, they are not relevant for the demonstration and should be ignored.
+
+### Low Integrity System Init and User-Space
+
+As mentioned above, `crinit` is used to set up a low integrity user-land beside the high integrity applications.
+This is used primarily for development and user experience by providing components like an SSH server, a login daemon, or `gdbserver`.
+
+## Eclipse S-CORE Example
+
+> [!IMPORTANT]
+> This guide assumes that you use the SDK's [dev-container](https://github.com/eclipse-score/devcontainer).
+> If you are using the Codespace as described in the Quick Start, this is the case.
+> The dev-container contains all required dependencies, like `qemu-system-aarch64` and `sshpass`.
+
+This section shows how you can use the above described SDK with the [example application](example/).
+You will see how you can create a low integrity and a high integrity application, build them with the S-CORE toolchain and run them finally on Linux for Safety Applications.
+
+The first three subsections explain the build and runtime setup.
+They help you to understand the integration.
+You can apply the approach on other S-CORE apps, too.
+
+- Application Setup:
+ The two application setup of the `ipc_bridge` example and how to make one of them an HI application.
+- S-CORE Toolchain in Linux for Safety Applications:
+ The general integration of the required tools into S-CORE's Bazel toolchain.
+ This should work for other applications, too.
+- Bazel Rules for the Example Applications: The specific Bazel ruleset for the `ipc_bridge` example
+
+The next three sections guide you through the concrete steps of applying these rules
+to build and deploy the example.
+
+- Full Run of the Example Application
+- Building the application
+- Using the fast-dev image
+
+And please also look at the shortcuts we implemented in the Visual Studio Code workspace to speed up the usage of the application example.
+You find them at the end of this section.
+
+### Application Setup
+
+The application setup is constructed of two instances of the `ipc_bridge` application, a high integrity (HI) instance acting as receiver and a low integrity (LI) instance acting as sender.
+The HI instance is started automatically by `cflinit` and listens in background.
+You start the LI instance manually in a terminal to run the demo.
+Even though both instances rely on the same source code, they do not use the same application binary.
+The HI application instance uses a binary located at `/usr/bin/ipc_bridge_cpp_sil` with a marked ELF-header, while the unmodified binary for the LI application is located at `/usr/bin/ipc_bridge_cpp`.
+
+The application instances are called with the following arguments:
+
+| HI | LI |
+| -------- | ------- |
+| `-n 10 -m recv -t 200 -s /etc/mw_com_config.json` | `-n 10 -m send -t 200 -s /etc/mw_com_config.json` |
+
+Feel free to adjust them as needed.
+
+In order to have those arguments changeable, the HI arguments are not hardcoded into `cflinit`.
+Instead, `cflinit` calls a small wrapper binary `/usr/bin/hi_app` which is based on the implementation in `example/ipc_bridge_hi_wrapper/main.cc`.
+When `hi_app` is executed by `cflinit`, it simply calls `execve` on `/usr/bin/ipc_bridge_cpp_sil` with the correct set of arguments.
+This way `cflinit` keeps its static entrypoint for the Eclipse S-CORE example app, while the user is still able to specify the used arguments for the HI `ipc_bridge` instance.
+
+### S-CORE Toolchain in Linux for Safety Applications
+
+The demo SDK integrates the [S-CORE toolchain with two extensions](https://github.com/Elektrobit/eclipse-score_toolchains_gcc/tree/ebclfsa_integration_demo):
+
+- Additional tooling for AArch64 cross-building.
+- Additional tool `lisa-elf-enabler`: It marks an ELF header of an application in a way that Linux for Safety Applications detects it as an HI application.
+ The tool is available to Bazel via `@gcc_toolchain_gcc//:elf-enabler`.
+
+### Bazel Rules for the Example Applications
+
+The [example](example/) extends the original `ipc_brige` example of the [communication module](https://github.com/eclipse-score/communication) with the application setup and the toolchain extensions described above.
+With those changes, the toolchain can be used via `bazel build --config=aarch64 --spawn_strategy=local `.
+
+> [!IMPORTANT]
+> Building inside a sandbox is currently not possible.
+
+For building and running the example setup, the following Bazel rules have been created in `example/ipc_bridge_hi_wrapper/BUILD`:
+
+| Target | Dependencies | Description |
+| ------ | ------------ | ----------- |
+| `ipc_bridge_cpp_sil` | `//example/ipc_bridge:ipc_bridge_cpp` | Create copy of `ipc_bridge_cpp` at `ipc_bridge_cpp_sil` and add CRC checksum to ELF-header |
+| `ipc_bridge_hi_wrapper` | | Build intermediate `ipc_bridge_hi_wrapper` |
+| `hi_app` | `:ipc_bridge_hi_wrapper` `:ipc_bridge_cpp_sil` | Create copy of `ipc_bridge_hi_wrapper` at `hi_app` and add CRC checksum to ELF-header. |
+| `fetch-fastdev-archive` | | Download fast-dev image archive |
+| `fastdev-image` | `:fetch-fastdev-archive` | Extract fast-dev image archive |
+| `upload` | `:hi_app` `:fastdev-image` | Upload application binaries to fast-dev image |
+| `run_example` | `:upload`| Run Eclipse S-CORE example application |
+
+The following sections introduce some of the rules mentioned above.
+
+### Full Run of the Example Application
+
+The `run_example` target provides an easy entry point, to build, post-process, deploy, run and stop the example:
+
+```bash
+bazel build --config=aarch64 --spawn_strategy=local //example/ipc_bridge_hi_wrapper:run_example
+```
+
+This command will take a while to finish, since it performs some downloads and starts the fast-dev image.
+After successful execution LI application instance can be seen in the `ssh_run.log`:
+
+```console
+Starting to send data
+Sending sample: 0
+Sending sample: 1
+Sending sample: 2
+Sending sample: 3
+Sending sample: 4
+Sending sample: 5
+Sending sample: 6
+Sending sample: 7
+Sending sample: 8
+Sending sample: 9
+Stop offering service...and terminating, bye bye
+```
+
+`qemu_run.log` provides the serial console output of the started fast-dev image, including the following noteworthy parts:
+
+1. `cflinit` starting `hi_app` as HI application:
+
+```console
+cflinit: INFO: Starting application HI App
+```
+
+2. `hi_app` starting `ipc_bridge_cpp_sil` as HI application:
+
+```console
+HI_App: Starting ipc_bridge_cpp_sil
+```
+
+3. The logs from `ipc_bridge_cpp_sil` as receiver itself
+
+```console
+1970/01/01 00:00:02.2898 29129 000 ECU1 IPBR lola log debug verbose 2 LoLa SD: find service for /tmp/mw_com_lola/service_discovery/6432/1
+...
+1970/01/01 00:00:11.11349 113498 000 ECU1 IPBR lola log debug verbose 3 LoLa SD: Synchronous call to handler for FindServiceHandle 0 finished
+xpad/cp60/MapApiLanesStamped: Subscribing to service
+xpad/cp60/MapApiLanesStamped: Received sample: 2
+xpad/cp60/MapApiLanesStamped: Received sample: 3
+...
+xpad/cp60/MapApiLanesStamped: Cycle duration 204ms
+1970/01/01 00:00:12.12851 128518 000 ECU1 IPBR lola log debug verbose 3 LoLa SD: Asynchronous call to handler for FindServiceHandle 0 finished
+...
+```
+
+4. Kernel logs indicating that some performed system calls would not be allowed on a production system.
+For more information on this, check the [previous section](#application--and-integration-specific-violation-of-system-call-restrictions) on application- and integration-specific syscall violations.
+
+```console
+SDK:handler_do_el0_svc_pre: syscall __NR_clone3 (435) is not allowed
+```
+
+### Building the Application
+
+Building all components of the example application can be performed with the `hi_app` rule.
+
+```bash
+bazel build --config=aarch64 --spawn_strategy=local //example/ipc_bridge_hi_wrapper:hi_app
+```
+
+Due the dependencies towards `:ipc_bridge_cpp_sil` and `:ipc_bridge_hi_wrapper` this will build all required binaries.
+Including the LI `ipc_bridge_cpp` binary, a temporary `ipc_bridge_hi_wrapper` binary as well as the post-processed `ipc_bridge_cpp_sil` and `hi_app` binaries.
+
+### Using the fast-dev Image
+
+The easiest way to setup the fast-dev image, is to use the `fastdev-image` rule.
+
+```bash
+bazel build --config=aarch64 --spawn_strategy=local //example/ipc_bridge_hi_wrapper:fastdev-image
+```
+
+This will first download the image via the `fetch-fastdev-archive` rule and cache the archive.
+Afterwards, the `fastdev-image` rule extracts the archive (containing a disk image and a kernel) to `bazel-bin/example/ipc_bridge_hi_wrapper/deb-qemuarm64/`.
+
+To start the unmodified base image (without the Eclipse S-CORE example application) manually, the included `run_qemu.sh` script can be used.
+
+```bash
+./run_qemu.sh bazel-bin/example/ipc_bridge_hi_wrapper/deb-qemuarm64/
+```
+
+This is of course optional, and only needed if a deeper manual look into the image is wished.
+After the image has started up, the password `linux` can be used for the `root` user for login.
+The ssh port of the qemu instance is forwarded to `localhost:2222`.
+Therefore `ssh` and `scp` can be used with the same credentials from inside the development container.
+
+```bash
+ssh -p 2222 root@localhost
+```
+
+> [!NOTE]
+> Be aware, that running the image via qemu, will change the stored disk image.
+> Bazel will detect this change and overwrite the disk image with the original one from the downloaded archive.
+> If it is planned to have persistent changes on the image, copy the content of `bazel-bin/example/ipc_bridge_hi_wrapper/deb-qemuarm64/` to a location outside of `bazel-bin` and adapt the command line argument in the above `./run_qemu.sh` call accordingly.
+
+For deploying the example application to the image, the `upload` rule is available, which will start the image based on the content of `bazel-bin/example/ipc_bridge_hi_wrapper/deb-qemuarm64/` and deploy all needed files via `scp`.
+
+```bash
+bazel build --config=aarch64 --spawn_strategy=local //example/ipc_bridge_hi_wrapper:upload
+```
+
+Since the deployment step will change the stored disk image, the `upload` rule stores its output in `bazel-bin/example/ipc_bridge_hi_wrapper/deb-qemuarm64-modified/`.
+Running the image with the deployed example applications works the same way as before, just with a different folder for the used image and kernel:
+
+```bash
+./run_qemu.sh bazel-bin/example/ipc_bridge_hi_wrapper/deb-qemuarm64-modified/
+```
+
+Like before you can interact with the image via the serial console or ssh.
+To trigger the LI Eclipse S-CORE example app, simply call:
+
+```bash
+ipc_bridge_cpp -n 10 -m send -t 200 -s /etc/mw_com_config.json
+```
+
+To reboot or power-off the running image, `crinit-ctl` with the command line argument `reboot` or `poweroff` can be used.
+
+```bash
+# Reboot
+crinit-ctl reboot
+# Poweroff
+crinit-ctl poweroff
+```
+
+## Further notes
+
+The toolchain and librares are provided for demonstration and prototyping purposes without further qualification.
diff --git a/ebclfsa/docs/system_setup.drawio.png b/ebclfsa/docs/system_setup.drawio.png
new file mode 100644
index 0000000000..f6f4fea62d
Binary files /dev/null and b/ebclfsa/docs/system_setup.drawio.png differ
diff --git a/ebclfsa/example/ipc_bridge/BUILD b/ebclfsa/example/ipc_bridge/BUILD
new file mode 100644
index 0000000000..79b84cc3bc
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge/BUILD
@@ -0,0 +1,65 @@
+# *******************************************************************************
+# Copyright (c) 2025 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("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER_WARNING_FEATURES")
+
+cc_binary(
+ name = "ipc_bridge_cpp",
+ srcs = [
+ "assert_handler.cpp",
+ "assert_handler.h",
+ "main.cpp",
+ ],
+ data = ["etc/mw_com_config.json"],
+ features = COMPILER_WARNING_FEATURES,
+ deps = [
+ ":sample_sender_receiver",
+ "@score_communication//score/mw/com",
+ "@score_baselibs//score/mw/log",
+ "@score_baselibs//score/language/futurecpp",
+ "@boost.program_options",
+ ],
+ visibility = [
+ "//visibility:public", # platform_only
+ ],
+)
+
+cc_library(
+ name = "sample_sender_receiver",
+ srcs = [
+ "sample_sender_receiver.cpp",
+ ],
+ hdrs = [
+ "sample_sender_receiver.h",
+ ],
+ features = COMPILER_WARNING_FEATURES,
+ deps = [
+ ":datatype",
+ "@score_communication//score/mw/com",
+ "@score_baselibs//score/mw/log",
+ ],
+)
+
+cc_library(
+ name = "datatype",
+ srcs = [
+ "datatype.cpp",
+ ],
+ hdrs = [
+ "datatype.h",
+ ],
+ features = COMPILER_WARNING_FEATURES,
+ deps = [
+ "@score_communication//score/mw/com",
+ "@score_baselibs//score/language/futurecpp",
+ ],
+)
diff --git a/ebclfsa/example/ipc_bridge/assert_handler.cpp b/ebclfsa/example/ipc_bridge/assert_handler.cpp
new file mode 100644
index 0000000000..9a46bdae1f
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge/assert_handler.cpp
@@ -0,0 +1,69 @@
+/********************************************************************************
+ * Copyright (c) 2025 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
+ ********************************************************************************/
+#include "assert_handler.h"
+
+#include "score/mw/log/logging.h"
+
+#include
+#include
+#include
+#include
+#include
+
+namespace score::mw::com
+{
+
+namespace
+{
+
+void assert_handler(const score::cpp::handler_parameters& params)
+{
+ std::cerr << "Assertion \"" << params.condition << "\" failed";
+ if (params.message != nullptr)
+ {
+ std::cerr << ": " << params.message;
+ }
+ std::cerr << " (" << params.file << ':' << params.line << ")" << std::endl;
+ std::cerr.flush();
+
+ score::mw::log::LogFatal("AsHa") << params.condition << params.message << params.file << params.line;
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+ const char* const no_abort = std::getenv("ASSERT_NO_CORE");
+ if (no_abort != nullptr)
+ {
+ std::cerr << "Would not coredump on \"" << no_abort << "\"" << std::endl;
+ if (std::strcmp(no_abort, params.condition) == 0)
+ {
+ std::cerr << "... matched." << std::endl;
+ std::cerr.flush();
+ std::quick_exit(1);
+ }
+ std::cerr << "... not matched." << std::endl;
+ }
+ std::cerr.flush();
+}
+
+} // namespace
+
+void SetupAssertHandler()
+{
+ score::cpp::set_assertion_handler(assert_handler);
+ // in addition, delay the calls to std::terminate() till the datarouter is able to read the logs
+ std::set_terminate([]() {
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+ std::abort();
+ });
+}
+
+} // namespace score::mw::com
diff --git a/ebclfsa/example/ipc_bridge/assert_handler.h b/ebclfsa/example/ipc_bridge/assert_handler.h
new file mode 100644
index 0000000000..b163843cd2
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge/assert_handler.h
@@ -0,0 +1,23 @@
+/********************************************************************************
+ * Copyright (c) 2025 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
+ ********************************************************************************/
+#ifndef SCORE_MW_IPC_BRIDGE_ASSERTHANDLER_H
+#define SCORE_MW_IPC_BRIDGE_ASSERTHANDLER_H
+
+namespace score::mw::com
+{
+
+void SetupAssertHandler();
+
+} // namespace score::mw::com
+
+#endif // SCORE_MW_IPC_BRIDGE_ASSERTHANDLER_H
diff --git a/ebclfsa/example/ipc_bridge/datatype.cpp b/ebclfsa/example/ipc_bridge/datatype.cpp
new file mode 100644
index 0000000000..83dcd7d427
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge/datatype.cpp
@@ -0,0 +1,13 @@
+/********************************************************************************
+ * Copyright (c) 2025 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
+ ********************************************************************************/
+#include "datatype.h"
diff --git a/ebclfsa/example/ipc_bridge/datatype.h b/ebclfsa/example/ipc_bridge/datatype.h
new file mode 100644
index 0000000000..8f2b6c321d
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge/datatype.h
@@ -0,0 +1,305 @@
+/********************************************************************************
+ * Copyright (c) 2025 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
+ ********************************************************************************/
+#ifndef SCORE_IPC_BRIDGE_DATATYPE_H
+#define SCORE_IPC_BRIDGE_DATATYPE_H
+
+#include "score/mw/com/types.h"
+
+namespace score::mw::com
+{
+
+constexpr std::size_t MAX_SUCCESSORS = 16U;
+constexpr std::size_t MAX_LANES = 16U;
+
+enum class StdTimestampSyncState : std::uint32_t
+{
+ /// @brief Timestamp is in sync with the global master, MAX_DIFF property is guaranteed.
+ kStdTimestampSyncState_InSync = 0U,
+ /// @brief Timestamp is not in sync with the global master, no property guarantees can be given, use at your own
+ /// risk.
+ kStdTimestampSyncState_NotInSync = 1U,
+ /// @brief No timestamp is available due to infrastructure reasons (e.g. initial value, or no StbM integrated, or
+ /// prediction target timestamp cannot be calculated, ...).
+ kStdTimestampSyncState_Invalid = 255U
+};
+
+struct StdTimestamp
+{
+ /// @brief The sub-seconds part of the timestamp
+ ///
+ //// unit: [ns]
+ std::uint32_t fractional_seconds;
+ /// @brief The seconds part of the timestamp.
+ ///
+ /// unit: [s]
+ std::uint32_t seconds;
+ /// @brief Status whether the timestamp is in sync with the global master or not.
+ StdTimestampSyncState sync_status;
+};
+
+enum class EventDataQualifier : std::uint32_t
+{
+ /// @brief Event data available, normal operation.
+ ///
+ /// The event is valid and all data elements in the scope of the qualifier should be evaluated. Parts of the service
+ /// may still be in degradation (i.e.contained qualifiers or quality of service attributes (e.g. standard deviation)
+ /// must be evaluated).
+ kEventDataQualifier_EventDataAvailable = 0U,
+ /// @brief Event data available, but a degradation condition applies (e.g. calibration). The reason of the
+ /// degradation is stored in the parameter extendedQualifier.
+ ///
+ /// Parts of the data may still be in degradation. Therefore, the receiver must decide (based on contained
+ /// qualifiers or quality of service attributes) whether the data can be still used.
+ kEventDataQualifier_EventDataAvailableReduced = 1U,
+ /// @brief Data for this event is currently not available. The extendedQualifier (if present) contains information
+ /// on the reason for non-availability.
+ ///
+ /// The remaining information in the scope of the event (except extendedQualifier) must not be evaluated.
+ kEventDataQualifier_EventDataNotAvailable = 2U,
+ /// @brief Data for this event is currently unknown.
+ ///
+ /// The remaining information in the scope of the event (except extendedQualifier) must not be evaluated.
+ // kEventDataQualifier_EventDataUnknown = 14U,
+ /// @brief There is no event data available, due to the event data being invalid (e.g. CRC error) or due to a
+ /// timeout.
+ ///
+ /// The remaining information in the scope of the event (except extendedQualifier) must not be evaluated.
+ kEventDataQualifier_EventDataInvalid = 255U
+};
+
+struct MapApiLaneBoundaryData
+{
+};
+
+using LaneIdType = std::size_t;
+using LaneWidth = std::size_t;
+using LaneBoundaryId = std::size_t;
+
+namespace map_api
+{
+
+using LinkId = std::size_t;
+using LengthM = std::double_t;
+
+struct LaneConnectionInfo
+{
+};
+
+using LaneConnectionInfoList = std::array;
+
+struct LaneRestrictionInfo
+{
+};
+
+using LaneRestrictionInfoList = std::array;
+
+struct ShoulderLaneInfo
+{
+};
+
+using ShoulderLaneInfoList = std::array;
+
+struct LaneToLinkAssociation
+{
+};
+
+using LaneUsedInBothDirections = bool;
+
+} // namespace map_api
+
+namespace adp
+{
+
+struct MapApiPointData
+{
+};
+
+enum class LaneType : std::size_t
+{
+ UNKNOWN,
+};
+
+enum class LaneTypeNew : std::size_t
+{
+ Unknown,
+};
+
+struct TurnDirection
+{
+};
+
+namespace map_api
+{
+
+using SpeedLimit = std::size_t;
+using LaneFollowsMpp = bool;
+
+} // namespace map_api
+
+} // namespace adp
+
+struct MapApiLaneData
+{
+ MapApiLaneData() = default;
+
+ MapApiLaneData(MapApiLaneData&&) = default;
+
+ MapApiLaneData(const MapApiLaneData&) = default;
+
+ MapApiLaneData& operator=(MapApiLaneData&&) = default;
+
+ MapApiLaneData& operator=(const MapApiLaneData&) = default;
+
+ /// @brief range: [1, n]. Unique ID of the lane
+ LaneIdType lane_id{0U};
+
+ /// @brief range: [1, n]. The IDs of all links that this lane belongs to
+ std::array link_ids;
+
+ /// @brief The IDs of all lane from which this lane can be reached in longitudinal direction
+ std::array predecessor_lanes;
+
+ /// @brief The IDs of all lane that can be reached from this lane in longitudinal direction
+ std::array successor_lanes;
+
+ /// @brief The center line of this lane
+ std::array center_line;
+
+ /// @brief The innermost left boundary at the beginning of this lane
+ LaneBoundaryId left_boundary_id{0U};
+
+ /// @brief The innermost right boundary at the beginning of this lane
+ LaneBoundaryId right_boundary_id{0U};
+
+ /// @brief The ID of the lane to the left
+ /// @note 0 indicates that there is no lane to the left
+ LaneIdType left_lane_id{0U};
+
+ /// @brief The id of the lane ro the right
+ /// @note 0 indicates that there is no lane to the right
+ LaneIdType right_lane_id{0U};
+
+ /// @brief The type of the lane
+ adp::LaneType lane_type{adp::LaneType::UNKNOWN};
+
+ /// @brief The type of the lane
+ adp::LaneTypeNew lane_type_new{adp::LaneTypeNew::Unknown};
+
+ /// @brief Describes Lane Connection Type and the range on the lane for which it applies
+ map_api::LaneConnectionInfoList lane_connection_info;
+
+ /// @brief Describes Lane Restriction Type and the range on the lane for which it applies
+ map_api::LaneRestrictionInfoList lane_restriction_info;
+
+ /// @brief Describes Shoulder Lane Type and the range on the lane for which it applies
+ /// @note not provided by MapDAL as of 6.08.2021r
+ map_api::ShoulderLaneInfoList shoulder_lane_info;
+
+ /// @brief The turn direction associated with the lane
+ adp::TurnDirection turn_direction;
+ /// @brief unit: [cm]. The width of the current lane
+ /// @details This is the smallest width over the whole lane. When the lane is splitting or
+ /// merging, the width can be 0.
+ /// The width is also set to 0 when no width is available.
+ LaneWidth width_in_cm{0U};
+
+ /// @brief unit: [m]. The length of the current lane
+ map_api::LengthM length_in_m{0.0};
+
+ /// @brief The speed limits on the current lane
+ std::array speed_limits;
+
+ /// @brief struct describing whether the lane is part of calculated Most Probable Path, or if yes within a range
+ adp::map_api::LaneFollowsMpp lane_follows_mpp;
+
+ /// @brief Boolean flag describing whether lane is fully attributed
+ bool is_fully_attributed{false};
+
+ /// @brief array containing the IDs of all left lane boundaries ordered from curb to middle
+ std::array left_lane_boundaries_ids;
+
+ /// @brief array containing the IDs of all right lane boundaries ordered from curb to middle
+ std::array right_lane_boundaries_ids;
+
+ /// @brief links associated with current lane
+ std::array link_associations;
+
+ /// @brief array of lane ranges where lane can be used in both directions.
+ std::array used_in_both_directions;
+};
+
+struct LaneGroupData
+{
+};
+
+struct MapApiLanesStamped
+{
+ MapApiLanesStamped() = default;
+
+ MapApiLanesStamped(MapApiLanesStamped&&) = default;
+
+ MapApiLanesStamped(const MapApiLanesStamped&) = default;
+
+ MapApiLanesStamped& operator=(MapApiLanesStamped&&) = default;
+
+ MapApiLanesStamped& operator=(const MapApiLanesStamped&) = default;
+
+ StdTimestamp time_stamp{0, 0, StdTimestampSyncState::kStdTimestampSyncState_Invalid};
+
+ /// @brief A name of the coordinate frame, used while fetching data.
+ ///
+ /// Depending on the driving scenario, different coordinate frames can be used.
+ /// Case "map_debug" : for Highway scenario it is an NTM planar coordinate system.
+ /// Case: "local_map_frame": for Urban scenario it is a vehicle's local coordinate system.
+ std::array frame_id;
+
+ /// @brief Current projection id.
+ ///
+ /// In case of NTM geodetic reference system, a zone can be of an arbitrary size, thus doesn't have a fixed
+ /// descriptor. This variable provides an index of the zone, in which the vehicle is currently located.
+ ///
+ /// range: [0, n]
+ std::uint32_t projection_id{};
+
+ /// @brief Describes the different kinds of quality levels of interface data. (placeholder for future concrete
+ /// implementation, for now we just initialize by not available)
+ EventDataQualifier event_data_qualifier{EventDataQualifier::kEventDataQualifier_EventDataNotAvailable};
+
+ /// @brief An array, containing lane boundaries, which refer to lanes from the given parent data structure. Lane
+ /// boundary indicates edge of the lane.
+ std::array lane_boundaries;
+
+ /// @brief All lanes from HD map for a relevant piece of road.
+ std::array lanes;
+
+ std::array lane_groups;
+
+ std::uint32_t x;
+ std::size_t hash_value;
+};
+
+template
+class IpcBridgeInterface : public Trait::Base
+{
+ public:
+ using Trait::Base::Base;
+
+ typename Trait::template Event map_api_lanes_stamped_{*this, "map_api_lanes_stamped"};
+};
+
+using IpcBridgeProxy = AsProxy;
+using IpcBridgeSkeleton = AsSkeleton;
+
+} // namespace score::mw::com
+
+#endif // SCORE_IPC_BRIDGE_DATATYPE_H
diff --git a/ebclfsa/example/ipc_bridge/etc/logging.json b/ebclfsa/example/ipc_bridge/etc/logging.json
new file mode 100644
index 0000000000..ac6589ca35
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge/etc/logging.json
@@ -0,0 +1,8 @@
+{
+ "appId": "IPBR",
+ "appDesc": "ipc_bridge",
+ "logLevel": "kDebug",
+ "logLevelThresholdConsole": "kDebug",
+ "logMode": "kRemote|kConsole",
+ "dynamicDatarouterIdentifiers" : true
+}
diff --git a/ebclfsa/example/ipc_bridge/etc/mw_com_config.json b/ebclfsa/example/ipc_bridge/etc/mw_com_config.json
new file mode 100644
index 0000000000..f9a7701535
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge/etc/mw_com_config.json
@@ -0,0 +1,63 @@
+{
+ "serviceTypes": [
+ {
+ "serviceTypeName": "/bmw/adp/MapApiLanesStamped",
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
+ "bindings": [
+ {
+ "binding": "SHM",
+ "serviceId": 6432,
+ "events": [
+ {
+ "eventName": "map_api_lanes_stamped",
+ "eventId": 1
+ },
+ {
+ "eventName": "dummy_data_stamped",
+ "eventId": 2
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "serviceInstances": [
+ {
+ "instanceSpecifier": "xpad/cp60/MapApiLanesStamped",
+ "serviceTypeName": "/bmw/adp/MapApiLanesStamped",
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
+ "instances": [
+ {
+ "instanceId": 1,
+ "allowedConsumer": {
+ "QM": [
+ 4002,
+ 0
+ ]
+ },
+ "allowedProvider": {
+ "QM": [
+ 4001,
+ 0
+ ]
+ },
+ "asil-level": "QM",
+ "binding": "SHM",
+ "events": [
+ {
+ "eventName": "map_api_lanes_stamped",
+ "numberOfSampleSlots": 10,
+ "maxSubscribers": 3
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/ebclfsa/example/ipc_bridge/main.cpp b/ebclfsa/example/ipc_bridge/main.cpp
new file mode 100644
index 0000000000..ca3ea37d16
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge/main.cpp
@@ -0,0 +1,131 @@
+/********************************************************************************
+ * Copyright (c) 2025 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
+ ********************************************************************************/
+#include "assert_handler.h"
+#include "sample_sender_receiver.h"
+
+#include
+
+#include
+#include
+
+#include "score/mw/com/types.h"
+#include "score/mw/com/runtime.h"
+
+using namespace std::chrono_literals;
+
+struct Params
+{
+ score::cpp::optional mode;
+ score::cpp::optional instance_manifest;
+ score::cpp::optional cycle_time;
+ score::cpp::optional cycle_num;
+ bool check_sample_hash;
+};
+
+template
+score::cpp::optional GetValueIfProvided(const boost::program_options::variables_map& args, std::string arg_string)
+{
+ return (args.count(arg_string) > 0U) ? static_cast(args[arg_string].as())
+ : score::cpp::optional();
+}
+
+Params ParseCommandLineArguments(const int argc, const char** argv)
+{
+ namespace po = boost::program_options;
+
+ po::options_description options;
+
+ options.add_options()("help,h", "Display the help message");
+ options.add_options()(
+ "num-cycles,n",
+ po::value()->default_value(0U),
+ "Number of cycles that are executed before determining success or failure. 0 indicates no limit.");
+ options.add_options()("mode,m",
+ po::value(),
+ "Set to either send/skeleton or recv/proxy to determine the role of the process");
+ options.add_options()("cycle-time,t", po::value(), "Cycle time in milliseconds for sending/polling");
+ options.add_options()(
+ "service_instance_manifest,s", po::value(), "Path to the com configuration file");
+ options.add_options()(
+ "disable-hash-check,d",
+ po::bool_switch(),
+ "Do not check the sample hash value in the receiver. If true, the sample hash is not checked.");
+
+ po::variables_map args;
+ const auto parsed_args =
+ po::command_line_parser{argc, argv}
+ .options(options)
+ .style(po::command_line_style::unix_style | po::command_line_style::allow_long_disguise)
+ .run();
+ po::store(parsed_args, args);
+
+ if (args.count("help") > 0U)
+ {
+ std::cerr << options << std::endl;
+ throw std::runtime_error("Could not parse command line arguments");
+ }
+
+ return {GetValueIfProvided(args, "mode"),
+ GetValueIfProvided(args, "service_instance_manifest"),
+ GetValueIfProvided(args, "cycle-time"),
+ GetValueIfProvided(args, "num-cycles"),
+ args.count("disable-hash-check") == 0U};
+}
+
+int main(const int argc, const char** argv)
+{
+ score::mw::com::SetupAssertHandler();
+ Params params = ParseCommandLineArguments(argc, argv);
+
+ if (!params.mode.has_value() || !params.cycle_num.has_value() || !params.cycle_time.has_value())
+ {
+ std::cerr << "Mode, number of cycles and cycle time should be specified" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ if (params.instance_manifest.has_value())
+ {
+ const std::string& manifest_path = params.instance_manifest.value();
+ score::StringLiteral runtime_args[2u] = {"-service_instance_manifest", manifest_path.c_str()};
+ score::mw::com::runtime::InitializeRuntime(2, runtime_args);
+ }
+
+ const auto mode = params.mode.value();
+ const auto cycles = params.cycle_num.value();
+ const auto cycle_time = params.cycle_time.value();
+ const auto check_sample_hash = params.check_sample_hash;
+
+ score::mw::com::EventSenderReceiver event_sender_receiver{};
+
+ const auto instance_specifier_result = score::mw::com::InstanceSpecifier::Create("xpad/cp60/MapApiLanesStamped");
+ if (!instance_specifier_result.has_value())
+ {
+ std::cerr << "Invalid instance specifier, terminating." << std::endl;
+ return EXIT_FAILURE;
+ }
+ const auto& instance_specifier = instance_specifier_result.value();
+
+ if (mode == "send" || mode == "skeleton")
+ {
+ return event_sender_receiver.RunAsSkeleton(instance_specifier, cycle_time, cycles);
+ }
+ else if (mode == "recv" || mode == "proxy")
+ {
+ return event_sender_receiver.RunAsProxy(instance_specifier, cycle_time, cycles, false, check_sample_hash);
+ }
+ else
+ {
+ std::cerr << "Unknown mode " << mode << ", terminating." << std::endl;
+ return EXIT_FAILURE;
+ }
+}
diff --git a/ebclfsa/example/ipc_bridge/sample_sender_receiver.cpp b/ebclfsa/example/ipc_bridge/sample_sender_receiver.cpp
new file mode 100644
index 0000000000..db24972df2
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge/sample_sender_receiver.cpp
@@ -0,0 +1,463 @@
+/********************************************************************************
+ * Copyright (c) 2025 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
+ ********************************************************************************/
+#include "sample_sender_receiver.h"
+#include "score/mw/com/impl/generic_proxy.h"
+#include "score/mw/com/impl/generic_proxy_event.h"
+#include "score/mw/com/impl/handle_type.h"
+
+#include "score/concurrency/notification.h"
+
+#include "score/mw/com/impl/proxy_event.h"
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace std::chrono_literals;
+
+namespace score::mw::com
+{
+
+namespace
+{
+
+constexpr std::size_t START_HASH = 64738U;
+
+std::ostream& operator<<(std::ostream& stream, const InstanceSpecifier& instance_specifier)
+{
+ stream << instance_specifier.ToString();
+ return stream;
+}
+
+template
+void ToStringImpl(std::ostream& o, T t)
+{
+ o << t;
+}
+
+template
+void ToStringImpl(std::ostream& o, T t, Args... args)
+{
+ ToStringImpl(o, t);
+ ToStringImpl(o, args...);
+}
+
+template
+std::string ToString(Args... args)
+{
+ std::ostringstream oss;
+ ToStringImpl(oss, args...);
+ return oss.str();
+}
+
+void HashArray(const std::array& array, std::size_t& seed)
+{
+ const std::ptrdiff_t buffer_size =
+ reinterpret_cast(&*array.cend()) - reinterpret_cast(&*array.cbegin());
+ SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(buffer_size > 0);
+ seed = score::cpp::hash_bytes_fnv1a(static_cast(array.data()), static_cast(buffer_size), seed);
+}
+
+class SampleReceiver
+{
+ public:
+ explicit SampleReceiver(const InstanceSpecifier& instance_specifier, bool check_sample_hash = true)
+ : instance_specifier_{instance_specifier},
+ last_received_{},
+ received_{0U},
+ check_sample_hash_{check_sample_hash}
+ {
+ }
+
+ void ReceiveSample(const MapApiLanesStamped& map) noexcept
+ {
+ std::cout << ToString(instance_specifier_, ": Received sample: ", map.x, "\n");
+
+ if (CheckReceivedSample(map))
+ {
+ received_ += 1U;
+ }
+ last_received_ = map.x;
+ }
+
+ std::size_t GetReceivedSampleCount() const noexcept
+ {
+ return received_;
+ }
+
+ private:
+ bool CheckReceivedSample(const MapApiLanesStamped& map) const noexcept
+ {
+ if (last_received_.has_value())
+ {
+ if (map.x <= last_received_.value())
+ {
+ std::cerr << ToString(instance_specifier_,
+ ": The received sample is out of order. Expected that ",
+ map.x,
+ " > ",
+ last_received_.value(),
+ "\n");
+ return false;
+ }
+ }
+
+ if (check_sample_hash_)
+ {
+ std::size_t hash_value = START_HASH;
+ for (const MapApiLaneData& lane : map.lanes)
+ {
+ HashArray(lane.successor_lanes, hash_value);
+ }
+
+ if (hash_value != map.hash_value)
+ {
+ std::cerr << ToString(instance_specifier_,
+ ": Unexpected data received, hash comparison failed: ",
+ hash_value,
+ ", expected ",
+ map.hash_value,
+ "\n");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ const score::mw::com::InstanceSpecifier& instance_specifier_;
+ score::cpp::optional last_received_;
+ std::size_t received_;
+ bool check_sample_hash_;
+};
+
+score::cpp::optional>> GetMapApiLanesStampedProxyEvent(
+ IpcBridgeProxy& proxy)
+{
+ return proxy.map_api_lanes_stamped_;
+}
+
+score::cpp::optional> GetMapApiLanesStampedProxyEvent(
+ GenericProxy& generic_proxy)
+{
+ const std::string event_name{"map_api_lanes_stamped"};
+ auto event_it = generic_proxy.GetEvents().find(event_name);
+ if (event_it == generic_proxy.GetEvents().cend())
+ {
+ std::cerr << "Could not find event " << event_name << " in generic proxy event map\n";
+ return {};
+ }
+ return event_it->second;
+}
+
+/// \brief Function that returns the value pointed to by a pointer
+const MapApiLanesStamped& GetSamplePtrValue(const MapApiLanesStamped* const sample_ptr)
+{
+ return *sample_ptr;
+}
+
+/// \brief Function that casts and returns the value pointed to by a void pointer
+///
+/// Assumes that the object in memory being pointed to is of type MapApiLanesStamped.
+const MapApiLanesStamped& GetSamplePtrValue(const void* const void_ptr)
+{
+ auto* const typed_ptr = static_cast(void_ptr);
+ return *typed_ptr;
+}
+
+/// \brief Function that extracts the underlying pointer to const from a SamplePtr and casts away the const. Only used
+/// in death test to check that we can't modify the SamplePtr!
+template
+SampleType* ExtractNonConstPointer(const SamplePtr& sample) noexcept
+{
+ const SampleType* sample_const_ptr = sample.get();
+
+ // The underlying shared memory in which the SamplePtr is stored (i.e. the data section) is opened read-only by the
+ // operating system when we open and mmap the memory into our consumer process. However, the SampleType itself is
+ // not a const object (although the SamplePtr holds a pointer to const). The standard states that "Modifying a const
+ // object through a non-const access path and referring to a volatile object through a non-volatile glvalue results
+ // in undefined behavior." (https://en.cppreference.com/w/cpp/language/const_cast). We are _not_ modifying a const
+ // object. We are modifying a non-const object that is pointer to by a pointer to const. Therefore, modifying the
+ // underlying object after using const cast is not undefined behaviour. We expect that the failure should occur
+ // since the memory in which the object is allocated is in read-only memory.
+ auto* sample_non_const_ptr = const_cast(sample_const_ptr);
+ return sample_non_const_ptr;
+}
+
+void ModifySampleValue(const SamplePtr& sample)
+{
+ auto* const sample_non_const_ptr = ExtractNonConstPointer(sample);
+ sample_non_const_ptr->x += 1;
+}
+
+void ModifySampleValue(const SamplePtr& sample)
+{
+ auto* const sample_non_const_ptr = ExtractNonConstPointer(sample);
+
+ auto* const typed_ptr = static_cast(sample_non_const_ptr);
+ typed_ptr->x += 1;
+}
+
+template
+score::Result GetHandleFromSpecifier(const InstanceSpecifier& instance_specifier)
+{
+ std::cout << ToString(instance_specifier, ": Running as proxy, looking for services\n");
+ ServiceHandleContainer handles{};
+ do
+ {
+ auto handles_result = ProxyType::FindService(instance_specifier);
+ if (!handles_result.has_value())
+ {
+ return MakeUnexpected(std::move(handles_result.error()));
+ }
+ handles = std::move(handles_result).value();
+ if (handles.size() == 0)
+ {
+ std::this_thread::sleep_for(500ms);
+ }
+ } while (handles.size() == 0);
+
+ std::cout << ToString(instance_specifier, ": Found service, instantiating proxy\n");
+ return handles.front();
+}
+
+Result> PrepareMapLaneSample(IpcBridgeSkeleton& skeleton,
+ const std::size_t cycle)
+{
+ const std::default_random_engine::result_type seed{static_cast(
+ std::chrono::steady_clock::now().time_since_epoch().count())};
+ std::default_random_engine rng{seed};
+
+ auto sample_result = skeleton.map_api_lanes_stamped_.Allocate();
+ if (!sample_result.has_value())
+ {
+ return sample_result;
+ }
+ auto sample = std::move(sample_result).value();
+ sample->hash_value = START_HASH;
+ sample->x = static_cast(cycle);
+
+ std::cout << ToString("Sending sample: ", sample->x, "\n");
+ for (MapApiLaneData& lane : sample->lanes)
+ {
+ for (LaneIdType& successor : lane.successor_lanes)
+ {
+ successor = std::uniform_int_distribution()(rng);
+ }
+
+ HashArray(lane.successor_lanes, sample->hash_value);
+ }
+ return sample;
+}
+
+} // namespace
+
+template
+int EventSenderReceiver::RunAsProxy(const score::mw::com::InstanceSpecifier& instance_specifier,
+ const score::cpp::optional cycle_time,
+ const std::size_t num_cycles,
+ bool try_writing_to_data_segment,
+ bool check_sample_hash)
+{
+ // For a GenericProxy, the SampleType will be void. For a regular proxy, it will by MapApiLanesStamped.
+ using SampleType =
+ typename std::conditional::value, void, MapApiLanesStamped>::type;
+ constexpr std::size_t SAMPLES_PER_CYCLE = 2U;
+
+ auto handle_result = GetHandleFromSpecifier(instance_specifier);
+ if (!handle_result.has_value())
+ {
+ std::cerr << "Unable to find service: " << instance_specifier
+ << ". Failed with error: " << handle_result.error() << ", bailing!\n";
+ return EXIT_FAILURE;
+ }
+ auto handle = handle_result.value();
+
+ auto proxy_result = ProxyType::Create(std::move(handle));
+ if (!proxy_result.has_value())
+ {
+ std::cerr << "Unable to construct proxy: " << proxy_result.error() << ", bailing!\n";
+ return EXIT_FAILURE;
+ }
+ auto& proxy = proxy_result.value();
+
+ auto map_api_lanes_stamped_event_optional = GetMapApiLanesStampedProxyEvent(proxy);
+ if (!map_api_lanes_stamped_event_optional.has_value())
+ {
+ std::cerr << "Could not get MapApiLanesStamped proxy event\n";
+ return EXIT_FAILURE;
+ }
+ auto& map_api_lanes_stamped_event = map_api_lanes_stamped_event_optional.value().get();
+
+ concurrency::Notification event_received;
+ if (!cycle_time.has_value())
+ {
+ map_api_lanes_stamped_event.SetReceiveHandler([&event_received, &instance_specifier]() {
+ std::cout << ToString(instance_specifier, ": Callback called\n");
+ event_received.notify();
+ });
+ }
+
+ std::cout << ToString(instance_specifier, ": Subscribing to service\n");
+ map_api_lanes_stamped_event.Subscribe(SAMPLES_PER_CYCLE);
+
+ score::cpp::optional last_received{};
+ SampleReceiver receiver{instance_specifier, check_sample_hash};
+ for (std::size_t cycle = 0U; cycle < num_cycles;)
+ {
+ const auto cycle_start_time = std::chrono::steady_clock::now();
+ if (cycle_time.has_value())
+ {
+ std::this_thread::sleep_for(*cycle_time);
+ }
+
+ const auto received_before = receiver.GetReceivedSampleCount();
+ Result num_samples_received = map_api_lanes_stamped_event.GetNewSamples(
+ [&receiver, try_writing_to_data_segment](SamplePtr sample) noexcept {
+ if (try_writing_to_data_segment)
+ {
+ // Try writing to the data segment (in which the sample data is stored). Used in a death test to
+ // ensure that this is not possible.
+ ModifySampleValue(sample);
+ }
+
+ // For the GenericProxy case, the void pointer managed by the SamplePtr will be cast to
+ // MapApiLanesStamped.
+ const MapApiLanesStamped& sample_value = GetSamplePtrValue(sample.get());
+ receiver.ReceiveSample(sample_value);
+ },
+ SAMPLES_PER_CYCLE);
+ const auto received = receiver.GetReceivedSampleCount() - received_before;
+
+ const bool get_new_samples_api_error = !num_samples_received.has_value();
+ const bool mismatch_api_returned_receive_count_vs_sample_callbacks = *num_samples_received != received;
+ const bool receive_handler_called_without_new_samples = *num_samples_received == 0 && !cycle_time.has_value();
+
+ if (get_new_samples_api_error || mismatch_api_returned_receive_count_vs_sample_callbacks ||
+ receive_handler_called_without_new_samples)
+ {
+ std::stringstream ss;
+ ss << instance_specifier << ": Error in cycle " << cycle << " during sample reception: ";
+ if (!get_new_samples_api_error)
+ {
+ if (mismatch_api_returned_receive_count_vs_sample_callbacks)
+ {
+ ss << "number of received samples doesn't match to what IPC claims: " << *num_samples_received
+ << " vs " << received;
+ }
+ else
+ {
+ ss << "expected at least one new sample, since event-notifier has been called, but "
+ "GetNewSamples() didn't provide one! ";
+ }
+ }
+ else
+ {
+ ss << std::move(num_samples_received).error();
+ }
+ ss << ", terminating.\n";
+ std::cerr << ss.str();
+
+ map_api_lanes_stamped_event.Unsubscribe();
+ return EXIT_FAILURE;
+ }
+
+ if (*num_samples_received >= 1U)
+ {
+ std::cout << ToString(instance_specifier, ": Proxy received valid data\n");
+ cycle += *num_samples_received;
+ }
+
+ const auto cycle_duration = std::chrono::steady_clock::now() - cycle_start_time;
+
+ std::cout << ToString(instance_specifier,
+ ": Cycle duration ",
+ std::chrono::duration_cast(cycle_duration).count(),
+ "ms\n");
+
+ event_received.reset();
+ }
+
+ std::cout << ToString(instance_specifier, ": Unsubscribing...\n");
+ map_api_lanes_stamped_event.Unsubscribe();
+ std::cout << ToString(instance_specifier, ": and terminating, bye bye\n");
+ return EXIT_SUCCESS;
+}
+
+int EventSenderReceiver::RunAsSkeleton(const score::mw::com::InstanceSpecifier& instance_specifier,
+ const std::chrono::milliseconds cycle_time,
+ const std::size_t num_cycles)
+{
+ auto create_result = IpcBridgeSkeleton::Create(instance_specifier);
+ if (!create_result.has_value())
+ {
+ std::cerr << "Unable to construct skeleton: " << create_result.error() << ", bailing!\n";
+ return EXIT_FAILURE;
+ }
+ auto& skeleton = create_result.value();
+
+ const auto offer_result = skeleton.OfferService();
+ if (!offer_result.has_value())
+ {
+ std::cerr << "Unable to offer service for skeleton: " << offer_result.error() << ", bailing!\n";
+ return EXIT_FAILURE;
+ }
+ std::cout << "Starting to send data\n";
+
+ for (std::size_t cycle = 0U; cycle < num_cycles || num_cycles == 0U; ++cycle)
+ {
+ auto sample_result = PrepareMapLaneSample(skeleton, cycle);
+ if (!sample_result.has_value())
+ {
+ std::cerr << "No sample received. Exiting.\n";
+ return EXIT_FAILURE;
+ }
+ auto sample = std::move(sample_result).value();
+
+ {
+ std::lock_guard lock{event_sending_mutex_};
+ skeleton.map_api_lanes_stamped_.Send(std::move(sample));
+ event_published_ = true;
+ }
+ std::this_thread::sleep_for(cycle_time);
+ }
+
+ std::cout << "Stop offering service...";
+ skeleton.StopOfferService();
+ std::cout << "and terminating, bye bye\n";
+
+ return EXIT_SUCCESS;
+}
+
+template int EventSenderReceiver::RunAsProxy>(
+ const score::mw::com::InstanceSpecifier&,
+ const score::cpp::optional,
+ const std::size_t,
+ bool,
+ bool);
+template int EventSenderReceiver::RunAsProxy(
+ const score::mw::com::InstanceSpecifier&,
+ const score::cpp::optional,
+ const std::size_t,
+ bool,
+ bool);
+
+} // namespace score::mw::com
diff --git a/ebclfsa/example/ipc_bridge/sample_sender_receiver.h b/ebclfsa/example/ipc_bridge/sample_sender_receiver.h
new file mode 100644
index 0000000000..541ad6decb
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge/sample_sender_receiver.h
@@ -0,0 +1,54 @@
+/********************************************************************************
+ * Copyright (c) 2025 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
+ ********************************************************************************/
+#ifndef SCORE_MW_COM_IPC_BRIDGE_SAMPLE_SENDER_RECEIVER_H
+#define SCORE_MW_COM_IPC_BRIDGE_SAMPLE_SENDER_RECEIVER_H
+
+#include "datatype.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace score::mw::com
+{
+
+class EventSenderReceiver
+{
+ public:
+ int RunAsSkeleton(const score::mw::com::InstanceSpecifier& instance_specifier,
+ const std::chrono::milliseconds cycle_time,
+ const std::size_t num_cycles);
+
+ template >
+ int RunAsProxy(const score::mw::com::InstanceSpecifier& instance_specifier,
+ const score::cpp::optional cycle_time,
+ const std::size_t num_cycles,
+ bool try_writing_to_data_segment = false,
+ bool check_sample_hash = true);
+
+ private:
+ std::mutex event_sending_mutex_{};
+ std::atomic event_published_{false};
+
+ std::mutex map_lanes_mutex_{};
+ std::vector> map_lanes_list_{};
+};
+
+} // namespace score::mw::com
+
+#endif // SCORE_MW_COM_IPC_BRIDGE_SAMPLE_SENDER_RECEIVER_H
diff --git a/ebclfsa/example/ipc_bridge_hi_wrapper/BUILD b/ebclfsa/example/ipc_bridge_hi_wrapper/BUILD
new file mode 100644
index 0000000000..7248b4a8f7
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge_hi_wrapper/BUILD
@@ -0,0 +1,118 @@
+# *******************************************************************************
+# Copyright (c) 2025 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("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER_WARNING_FEATURES")
+
+genrule(
+ name = "ipc_bridge_cpp_sil",
+ srcs = ["//example/ipc_bridge:ipc_bridge_cpp"],
+ outs = ["ipc_bridge_cpp_sil"],
+ cmd = "cp $(SRCS) $@ && \
+ chmod ugo+w $@ && \
+ $(execpath @gcc_toolchain_gcc//:elf-enabler) $@ && \
+ chmod ugo-w $@",
+ tools = ["@gcc_toolchain_gcc//:elf-enabler"],
+)
+
+genrule(
+ name = "hi_app",
+ srcs = [
+ ":ipc_bridge_hi_wrapper",
+ ":ipc_bridge_cpp_sil"
+ ],
+ outs = ["hi_app"],
+ cmd = "cp $(location :ipc_bridge_hi_wrapper) $@ && \
+ chmod ugo+w $@ && \
+ $(execpath @gcc_toolchain_gcc//:elf-enabler) $@ && \
+ chmod ugo-w $@",
+ tools = ["@gcc_toolchain_gcc//:elf-enabler"],
+)
+
+cc_binary(
+ name = "ipc_bridge_hi_wrapper",
+ srcs = [
+ "main.cc",
+ ],
+ features = COMPILER_WARNING_FEATURES,
+ deps = [
+ "//example/ipc_bridge:ipc_bridge_cpp",
+ ],
+)
+
+genrule(
+ name = "fetch-fastdev-archive",
+ srcs = [],
+ outs = ["fastdev-archive.tgz"],
+ cmd = "wget -O $@ https://linux.elektrobit.com/tmp/score/fastdev-ubuntu-ebcl-deb-qemu-arm64.tgz"
+)
+
+genrule(
+ name = "fastdev-image",
+ srcs = [":fetch-fastdev-archive"],
+ outs = [
+ "deb-qemuarm64/fastdev-ubuntu-ebcl-deb-qemuarm64.wic",
+ "deb-qemuarm64/fastdev-ubuntu-ebcl-deb-qemuarm64-vmlinux"
+ ],
+ cmd = "tar xzf $(location :fetch-fastdev-archive) -C $(RULEDIR)",
+)
+
+genrule(
+ name = "upload",
+ srcs = [
+ ":ipc_bridge_cpp_sil",
+ "//example/ipc_bridge:ipc_bridge_cpp",
+ ":hi_app",
+ ":fastdev-image",
+ "mw_com_config.json",
+ "run_qemu.sh",
+ "logging.json"
+ ],
+ cmd = " \
+ mkdir -p $(RULEDIR)/deb-qemuarm64-modified &&\
+ cp $(RULEDIR)/deb-qemuarm64/* $(RULEDIR)/deb-qemuarm64-modified/ &&\
+ $(location run_qemu.sh) $(RULEDIR)/deb-qemuarm64-modified -pidfile $(RULEDIR)/qemu.pid > $(RULEDIR)/qemu_upload.log &\
+ sleep 30 ; \
+ sshpass -p linux scp -o StrictHostKeyChecking=no -P 2222 $(location :ipc_bridge_cpp_sil) root@localhost:/usr/bin &&\
+ sshpass -p linux scp -o StrictHostKeyChecking=no -P 2222 $(location //example/ipc_bridge:ipc_bridge_cpp) root@localhost:/usr/bin &&\
+ sshpass -p linux scp -o StrictHostKeyChecking=no -P 2222 $(location :hi_app) root@localhost:/usr/bin &&\
+ sshpass -p linux scp -o StrictHostKeyChecking=no -P 2222 $(location mw_com_config.json) root@localhost:/etc/ &&\
+ sshpass -p linux scp -o StrictHostKeyChecking=no -P 2222 $(location logging.json) root@localhost:/etc/ &&\
+ sshpass -p linux ssh -o StrictHostKeyChecking=no -p 2222 root@localhost sync &&\
+ sshpass -p linux ssh -o StrictHostKeyChecking=no -p 2222 root@localhost crinit-ctl poweroff || true \
+ sleep 5 \
+ ",
+ outs = [
+ "qemu_upload.log",
+ "deb-qemuarm64-modified/fastdev-ubuntu-ebcl-deb-qemuarm64.wic",
+ "deb-qemuarm64-modified/fastdev-ubuntu-ebcl-deb-qemuarm64-vmlinux"
+ ],
+)
+
+genrule(
+ name = "run_example",
+ srcs = [
+ "deb-qemuarm64-modified/fastdev-ubuntu-ebcl-deb-qemuarm64.wic",
+ "deb-qemuarm64-modified/fastdev-ubuntu-ebcl-deb-qemuarm64-vmlinux",
+ "run_qemu.sh"
+ ],
+ cmd = " \
+ $(location run_qemu.sh) $(RULEDIR)/deb-qemuarm64-modified -pidfile $(RULEDIR)/qemu.pid > $(RULEDIR)/qemu_run.log &\
+ sleep 10 ; \
+ sshpass -p linux ssh -o StrictHostKeyChecking=no -p 2222 root@localhost ipc_bridge_cpp -n 10 -m send -t 200 -s /etc/mw_com_config.json > $(RULEDIR)/ssh_run.log && \
+ sshpass -p linux ssh -o StrictHostKeyChecking=no -p 2222 root@localhost crinit-ctl poweroff || true \
+ sleep 5 \
+ ",
+ outs = [
+ "qemu_run.log",
+ "ssh_run.log",
+ ],
+)
diff --git a/ebclfsa/example/ipc_bridge_hi_wrapper/logging.json b/ebclfsa/example/ipc_bridge_hi_wrapper/logging.json
new file mode 100644
index 0000000000..54646e1055
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge_hi_wrapper/logging.json
@@ -0,0 +1,8 @@
+{
+ "appId": "IPBR",
+ "appDesc": "ipc_bridge",
+ "logLevel": "kInfo",
+ "logLevelThresholdConsole": "kInfo",
+ "logMode": "kRemote|kConsole",
+ "dynamicDatarouterIdentifiers" : true
+}
diff --git a/ebclfsa/example/ipc_bridge_hi_wrapper/main.cc b/ebclfsa/example/ipc_bridge_hi_wrapper/main.cc
new file mode 100644
index 0000000000..d0909dd65f
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge_hi_wrapper/main.cc
@@ -0,0 +1,38 @@
+/********************************************************************************
+ * Copyright (c) 2025 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
+ ********************************************************************************/
+#include
+#include
+#include
+
+int main() {
+ std::cout << "HI_App: Starting ipc_bridge_cpp_sil" << std::endl;
+
+ const char *c_args[] = {
+ "/usr/bin/ipc_bridge_cpp_sil",
+ "-n", "10",
+ "-m", "recv",
+ "-t", "200",
+ "-s", "/etc/mw_com_config.json",
+ nullptr
+ };
+
+ execve("/usr/bin/ipc_bridge_cpp_sil", const_cast(c_args), nullptr);
+
+ std::cerr << "execve failed, sleeping... Reason: " << strerror(errno)
+ << std::endl;
+ while (true) {
+ sleep(10);
+ }
+ return 0;
+}
+
diff --git a/ebclfsa/example/ipc_bridge_hi_wrapper/mw_com_config.json b/ebclfsa/example/ipc_bridge_hi_wrapper/mw_com_config.json
new file mode 100644
index 0000000000..f9a7701535
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge_hi_wrapper/mw_com_config.json
@@ -0,0 +1,63 @@
+{
+ "serviceTypes": [
+ {
+ "serviceTypeName": "/bmw/adp/MapApiLanesStamped",
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
+ "bindings": [
+ {
+ "binding": "SHM",
+ "serviceId": 6432,
+ "events": [
+ {
+ "eventName": "map_api_lanes_stamped",
+ "eventId": 1
+ },
+ {
+ "eventName": "dummy_data_stamped",
+ "eventId": 2
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "serviceInstances": [
+ {
+ "instanceSpecifier": "xpad/cp60/MapApiLanesStamped",
+ "serviceTypeName": "/bmw/adp/MapApiLanesStamped",
+ "version": {
+ "major": 1,
+ "minor": 0
+ },
+ "instances": [
+ {
+ "instanceId": 1,
+ "allowedConsumer": {
+ "QM": [
+ 4002,
+ 0
+ ]
+ },
+ "allowedProvider": {
+ "QM": [
+ 4001,
+ 0
+ ]
+ },
+ "asil-level": "QM",
+ "binding": "SHM",
+ "events": [
+ {
+ "eventName": "map_api_lanes_stamped",
+ "numberOfSampleSlots": 10,
+ "maxSubscribers": 3
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/ebclfsa/example/ipc_bridge_hi_wrapper/run_qemu.sh b/ebclfsa/example/ipc_bridge_hi_wrapper/run_qemu.sh
new file mode 100755
index 0000000000..627c81ba41
--- /dev/null
+++ b/ebclfsa/example/ipc_bridge_hi_wrapper/run_qemu.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+set -xu
+
+if [ -z "$1" ]; then
+ echo "Usage: $0 "
+ exit 1
+fi
+BASEFOLDER=$1
+IMAGE="${BASEFOLDER}/fastdev-ubuntu-ebcl-deb-qemuarm64.wic"
+KERNEL="${BASEFOLDER}/fastdev-ubuntu-ebcl-deb-qemuarm64-vmlinux"
+if [ ! -d "${BASEFOLDER}" ] || [ ! -f "${IMAGE}" ] || [ ! -f "${KERNEL}" ] ; then
+ echo "Run \"bazel build --config=aarch64 --spawn_strategy=local //score/mw/com/example/ipc_bridge_hi_wrapper:fastdev-image\" first to fetch the image"
+fi
+
+MACHINE="virt,virtualization=true,gic-version=3"
+CPU="cortex-a53"
+SMP="8"
+MEM="4G"
+KERNEL_ARGS=("-append" "root=/dev/vda1 sdk_enable lisa_syscall_whitelist=2026 rw sharedmem.enable_sharedmem=0 init=/usr/bin/ebclfsa-cflinit")
+DISK_ARGS="-device virtio-blk-device,drive=vd0 -drive if=none,format=raw,file=${IMAGE},id=vd0"
+NETWORK_ARGS="-netdev user,id=net0,net=192.168.7.0/24,dhcpstart=192.168.7.2,dns=192.168.7.3,host=192.168.7.5,hostfwd=tcp::2222-:22,hostfwd=tcp::3333-:3333 -device virtio-net-device,netdev=net0 "
+
+if ! command -v qemu-system-aarch64 > /dev/null; then
+ echo "Please install qemu-system-aarch64"
+ exit 1
+fi
+
+chmod +w ${IMAGE}
+
+exec qemu-system-aarch64 -m "${MEM}" -machine "${MACHINE}" -cpu "${CPU}" \
+ -smp "${SMP}" -kernel "${KERNEL}" "${KERNEL_ARGS[@]}" ${DISK_ARGS} \
+ ${NETWORK_ARGS} -nographic ${@:2}
diff --git a/ebclfsa/patches/BUILD b/ebclfsa/patches/BUILD
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/ebclfsa/patches/fix_hard_coded_amd64.patch b/ebclfsa/patches/fix_hard_coded_amd64.patch
new file mode 100644
index 0000000000..014b4f80ab
--- /dev/null
+++ b/ebclfsa/patches/fix_hard_coded_amd64.patch
@@ -0,0 +1,13 @@
+diff --git a/MODULE.bazel b/MODULE.bazel
+index a302a84..7917e2b 100644
+--- a/MODULE.bazel
++++ b/MODULE.bazel
+@@ -60,7 +60,7 @@ deb = use_repo_rule("@download_utils//download/deb:defs.bzl", "download_deb")
+ deb(
+ name = "acl-deb",
+ build = "//third_party/acl:acl.BUILD",
+- urls = ["https://archive.ubuntu.com/ubuntu/pool/main/a/acl/libacl1-dev_2.2.52-3build1_amd64.deb"],
++ urls = ["https://ports.ubuntu.com/pool/main/a/acl/libacl1-dev_2.2.52-3build1_arm64.deb"],
+ visibility = ["//visibility:public"],
+ )
+