# Build the RD-V3 Reference Platform Software Stack

## In this learning path

- [Introduction](https://learn.arm.com/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/)
- [Learn about the Arm RD-V3 Platform](https://learn.arm.com/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/1_introduction_rdv3/)
- [Understand the CSS-V3 boot flow and firmware stack](https://learn.arm.com/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/2_rdv3_bootseq/)
- [Build the RD-V3 Reference Platform Software Stack](https://learn.arm.com/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/3_rdv3_sw_build/)
- [Simulate RD-V3 Boot Flow on Arm FVP](https://learn.arm.com/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/4_rdv3_on_fvp/)
- [Simulate Dual Chip RD-V3-R1 Platform](https://learn.arm.com/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/5_rdv3_modify/)
- [Next Steps](https://learn.arm.com/learning-paths/servers-and-cloud-computing/neoverse-rdv3-swstack/_next-steps/)

## Building the RD-V3 Reference Platform Software Stack
In this module, you’ll set up your development environment on any Arm-based server and build the firmware stack required to simulate the RD-V3 platform. This Learning Path was tested on an AWS `m7g.4xlarge` Arm-based instance running Ubuntu 22.04.

## Step 1: Set up your development environment
First, check that your system is current and install the required dependencies:

```
sudo apt update
sudo apt install -y curl git
```

Configure git (optional):

```
git config --global user.name "<your-name>"
git config --global user.email "<your-email@example.com>"
```

## Step 2: Fetch the source code
The RD‑V3 platform firmware stack consists of multiple components, most maintained in separate Git repositories, such as:
- TF‑A
- SCP/MCP
- RSE (TF-M)
- UEFI (EDK II)
- Linux kernel
- Buildroot
- kvmtool (lkvm)
- RMM (optional)

Use the repo tool with the RD-V3 manifest to sync these sources from multiple upstreams consistently (typically to a pinned release tag). It simplifies syncing the full platform software stack from multiple upstreams.

If `repo` is not installed, you can download it and add it to your `PATH`:

```
mkdir -p ~/.bin
PATH="${HOME}/.bin:${PATH}"
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo
chmod a+rx ~/.bin/repo
```

Once ready, create a workspace and initialize the repo manifest. This Learning Path uses a pinned manifest to ensure reproducibility across different environments. This locks all component repositories to known-good commits that are validated and aligned with a specific FVP version.

For this session, use `pinned-rdv3.xml` and `RD-INFRA-2025.07.03`:

```
cd ~
mkdir rdv3
cd rdv3
```

Initialize and sync the source code tree:

```
repo init -u https://git.gitlab.arm.com/infra-solutions/reference-design/infra-refdesign-manifests.git -m pinned-rdv3.xml -b refs/tags/RD-INFRA-2025.07.03 --depth=1
repo sync -c -j $(nproc) --fetch-submodules --force-sync --no-clone-bundle --retry-fetches=5
```

Once synced, the output should look like:

```
__output__ Syncing:  95% (19/20), done in 2m36.453s
__output__ Syncing: 100% (83/83) 2:52 | 1 job | 0:01 platsw/edk2-platforms @ uefi/edk2/edk2-platformsrepo sync has finished successfully.
```

**Note**: As of the time of writing, the latest release tag is `RD-INFRA-2025.07.03`. Newer tags might be available in future updates.

This manifest fetches the required sources, including:
- TF‑A
- SCP / RSE firmware
- EDK II (UEFI)
- Linux kernel
- Buildroot and platform scripts

## Step 3: Build the Docker Image
There are two supported methods for building the reference firmware stack: **host-based** and **container-based**.
- The **host-based** build installs all required dependencies directly on your local system and executes the build natively.
- The **container-based** build runs the compilation process inside a pre-configured Docker image, ensuring consistent results and isolation from host environment issues.

In this Learning Path, you will use the **container-based** approach.

The container image uses your host source directory (`~/rdv3`) and performs the build inside Docker. Ensure Docker is installed on your machine. You can follow this [installation guide](https://learn.arm.com/install-guides/docker/).

After Docker is installed, you’re ready to build the container image.

The `container.sh` script is a wrapper that builds the container using default settings for the Dockerfile and image name. You can customize these by using the `-f` (Dockerfile) and `-i` (image name) options, or by editing the script directly.

To view all available options:

```
cd ~/rdv3/container-scripts
./container.sh -h
```

To build the container image:

```
./container.sh build
```

The build procedure can take a few minutes, depending on network bandwidth and CPU performance. This Learning Path was tested on an AWS `m7g.4xlarge` instance, and the build took 250 seconds.

Expected output:

```
__output__ Building docker image: rdinfra-builder ...
__output__ [+] Building 239.7s (19/19) FINISHED docker:default
__output__ => [internal] load build definition from rd-infra-arm64 0.0s
__output__ => => transferring dockerfile: 4.50kB 0.0s
__output__ => [internal] load metadata for docker.io/library/ubuntu:jammy-20240911.1 1.0s
__output__ => [internal] load .dockerignore 0.0s
__output__ => => transferring context: 2B 0.0s
__output__ => [internal] load build context 0.0s
__output__ => => transferring context: 10.80kB 0.0s
__output__ => [ 1/14] FROM docker.io/library/ubuntu:jammy-20240911.1@sha256:0e5e4a57c2499249aafc3b40fcd541e9a456aab7296681a3994d631587203f97 1.7s
```

Verify the image:

```
docker images
```

You should see a docker image called `rdinfra-builder`:

```
__output__ REPOSITORY        TAG       IMAGE ID       CREATED         SIZE
__output__ rdinfra-builder   latest    3a395c5a0b60   4 minutes ago   8.12GB
```

Quick interactive test:

```
./container.sh -v ~/rdv3 run
```

This script mounts your source directory (`~/rdv3`) into the container and opens a shell session at that location. Inside the container, you should see a prompt like this:

```
__output__ Running docker image: rdinfra-builder ...
__output__ To run a command as administrator (user "root"), use "sudo <command>".
__output__ See "man sudo_root" for details.
__output__ 
__output__ your-username:hostname:/home/your-username/rdv3$
```

You can explore the container environment if you wish, then type `exit` to return to the host.

## Step 4: Build firmware
Building the full firmware stack involves compiling several components and packaging them for simulation. The following command runs build and then package inside the Docker image:
- **build** compiles all individual components of the firmware stack, including TF‑A, SCP, RSE, UEFI, Linux kernel, and rootfs
- **package** consolidates outputs into simulation-ready artifacts for FVP

Ensure you’re back in the host OS, then run:

```
cd ~/rdv3
docker run --rm \
  -v "$PWD:$PWD" \
  -w "$PWD" \
  --mount type=volume,dst="$HOME" \
  --env ARCADE_USER="$(id -un)" \
  --env ARCADE_UID="$(id -u)" \
  --env ARCADE_GID="$(id -g)" \
  -t -i rdinfra-builder \
  bash -c "./build-scripts/rdinfra/build-test-buildroot.sh -p rdv3 build && \
           ./build-scripts/rdinfra/build-test-buildroot.sh -p rdv3 package"
```

The build artifacts will be placed under `~/rdv3/output/rdv3/rdv3/`, where the last `rdv3` in the directory path corresponds to the selected platform name.

Inspect the artifacts:

```
ls ~/rdv3/output/rdv3/rdv3 -al
```

Expected output:

```
__output__ total 7092
__output__ drwxr-xr-x 2 ubuntu ubuntu    4096 Aug 12 13:15 .
__output__ drwxr-xr-x 4 ubuntu ubuntu    4096 Aug 12 13:15 ..
__output__ lrwxrwxrwx 1 ubuntu ubuntu      25 Aug 12 13:15 Image -> ../components/linux/Image
__output__ lrwxrwxrwx 1 ubuntu ubuntu      35 Aug 12 13:15 Image.defconfig -> ../components/linux/Image.defconfig
__output__ -rw-r--r-- 1 ubuntu ubuntu 7250838 Aug 12 13:15 fip-uefi.bin
__output__ lrwxrwxrwx 1 ubuntu ubuntu      32 Aug 12 13:15 lcp_ramfw.bin -> ../components/rdv3/lcp_ramfw.bin
```

Reference mapping:

| Component                | Output Files                              | Description                    |
|--------------------------|-------------------------------------------|--------------------------------|
| TF‑A                     | `bl1.bin`, `bl2.bin`, `bl31.bin`, `fip.bin` | Entry-level boot firmware      |
| SCP and RSE firmware     | `scp.bin`, `mcp_rom.bin`, etc.          | Platform power/control         |
| UEFI                     | `uefi.bin`, `flash0.img`                 | Boot device enumeration        |
| Linux kernel             | `Image`                                   | OS payload                     |
| Initrd                   | `rootfs.cpio.gz`                          | Minimal filesystem             |

## Optional: run the build manually from inside the container
You can also build from within an interactive container session (useful for debugging or partial builds):

Start your docker container. In your running container shell:

```
cd ~/rdv3
./build-scripts/rdinfra/build-test-buildroot.sh -p rdv3 build
./build-scripts/rdinfra/build-test-buildroot.sh -p rdv3 package
```

You’ve now prepared and built the full RD-V3 firmware stack. In the next section, you’ll install the appropriate FVP and simulate the full boot sequence, bringing the firmware to life on a virtual platform.
