# Environment Setup

## In this learning path

- [Introduction](https://learn.arm.com/learning-paths/servers-and-cloud-computing/refinfra-quick-start/)
- [Environment Setup](https://learn.arm.com/learning-paths/servers-and-cloud-computing/refinfra-quick-start/environment-setup-1/)
- [Build the software stack](https://learn.arm.com/learning-paths/servers-and-cloud-computing/refinfra-quick-start/build-2/)
- [Test With FVP](https://learn.arm.com/learning-paths/servers-and-cloud-computing/refinfra-quick-start/test-with-fvp-3/)
- [Next Steps](https://learn.arm.com/learning-paths/servers-and-cloud-computing/refinfra-quick-start/_next-steps/)

Arm has developed a suite of [Neoverse Reference Designs](https://developer.arm.com/Tools%20and%20Software/Neoverse%20Reference%20Design) compute sub-systems. They are supported by free-of-charge [Arm Ecosystem FVPs](https://developer.arm.com/downloads/-/arm-ecosystem-fvps), and complete [software stacks](https://gitlab.arm.com/infra-solutions) to illustrate how these systems boot to Linux. This learning path is based on the `Neoverse N2` Reference Design (`RD-N2`).

## Before you begin

You can use either an AArch64 or x86_64 host machine running **Ubuntu Linux 22.04**. 64GB of free disk space and 32GB of RAM is minimum requirement to sync and build the platform software stack. 48GB of RAM is recommended.

Follow the instructions to set up your environment using the information found at the [Neoverse RD-N2 documentation site](https://neoverse-reference-design.docs.arm.com/en/latest/platforms/rdn2.html).

Install [docker](https://learn.arm.com/install-guides/docker/docker-engine/) on your machine.

### Install repository

Start by obtaining the repo tool to simplify the checkout of source code that spans multiple repositories.

### Repo tool

First, refresh the list of available packages and install repo:

```
sudo apt-get update
sudo apt-get install repo
```

Verify your installation:

```
repo version
```

The output looks like this:

```
__output__/usr/bin/repo:681: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
__output__  now = datetime.datetime.utcnow()
__output__ <repo not installed>
__output__ repo launcher version 2.36
__output__       (from /usr/bin/repo)
__output__ git 2.43.0
__output__ Python 3.12.3 (main, Jun 18 2025, 17:59:45) [GCC 13.3.0]
__output__ OS Linux 6.8.0-1031-aws (#33-Ubuntu SMP Fri Jun 20 17:58:11 UTC 2025)
__output__ CPU aarch64 (aarch64)
__output__ Bug reports: https://issues.gerritcodereview.com/issues/new?component=1370071
```

### Fetch source code

Create a new directory in to which you can download the source code, build the stack, and then obtain the manifest file.

To obtain the manifest, choose a tag of the platform reference firmware. [RD-INFRA-2025.07.03](https://neoverse-reference-design.docs.arm.com/en/latest/releases/RD-INFRA-2025.07.03/release_note.html) is used here, although it is recommended to use the latest version available. See the [release notes](https://neoverse-reference-design.docs.arm.com/en/latest/) for more information.

Specify the platform you would like with the manifest. In the [manifest repo](https://git.gitlab.arm.com/infra-solutions/reference-design/infra-refdesign-manifests) there are a number of available platforms. In this case, select `pinned-rdn2.xml`.

```
mkdir rd-infra
cd rd-infra/
repo init -u https://git.gitlab.arm.com/infra-solutions/reference-design/infra-refdesign-manifests.git -m pinned-rdn2.xml -b refs/tags/RD-INFRA-2025.07.03
```

Now look at what the configured manifest contains:

```
cat .repo/manifest.xml
```

The file content should look like:

```
__output__<?xml version="1.0" encoding="UTF-8"?>
__output__<!--
__output__DO NOT EDIT THIS FILE!  It is generated by repo and changes will be discarded.
__output__If you want to use a different manifest, use `repo init -m <file>` instead.
__output__If you want to customize your checkout by overriding manifest settings, use
__output__the local_manifests/ directory instead.
__output__For more information on repo manifests, check out:
__output__https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
__output__-->
__output__<manifest>
  <include name="pinned-rdn2.xml" />
</manifest>
```

The `manifest.xml` file points to `pinned-rdn2.xml` so let us examine that one next:

```
cat .repo/manifests/pinned-rdn2.xml
```

The contents of `pinned-rdn2.xml` are shown below:

```
__output__<?xml version="1.0" encoding="UTF-8"?>
__output__<manifest>
  __output__<remote fetch="https://git.gitlab.arm.com/infra-solutions/reference-design/" name="arm"/>
  __output__<remote fetch="https://github.com/" name="github"/>
  __output__<remote fetch="https://git.savannah.gnu.org" name="gnugit"/>
  __output__<remote fetch="https://git.kernel.org" name="kernel"/>
  __output__<remote fetch="https://git.trustedfirmware.org" name="tforg"/>
  
  __output__<project remote="arm" name="platsw/scp-firmware" path="scp" revision="refs/tags/RD-INFRA-2024.12.20"/>
  __output__<project remote="arm" name="platsw/trusted-firmware-a" path="tf-a" revision="refs/tags/RD-INFRA-2024.12.20"/>
  __output__<project remote="arm" name="platsw/edk2" path="uefi/edk2" revision="refs/tags/RD-INFRA-2024.12.20"/>
  __output__<project remote="arm" name="platsw/edk2-platforms" path="uefi/edk2/edk2-platforms" revision="refs/tags/RD-INFRA-2024.12.20"/>
  __output__<project remote="arm" name="platsw/linux" path="linux" revision="refs/tags/RD-INFRA-2024.12.20"/>
  __output__<project remote="arm" name="scripts/build-scripts" path="build-scripts" revision="refs/tags/RD-INFRA-2024.12.20"/>
  __output__<project remote="arm" name="scripts/model-scripts" path="model-scripts" revision="refs/tags/RD-INFRA-2024.12.20"/>
  __output__<project remote="arm" name="scripts/container-scripts" path="container-scripts" revision="refs/tags/RD-INFRA-2024.12.20"/>
  __output__<project remote="arm" name="valsw/kvm-unit-tests" path="validation/sys-test/kvm-unit-tests" revision="refs/tags/RD-INFRA-2024.12.20"/>
  __output__<project remote="arm" name="platsw/buildroot" path="buildroot" revision="refs/tags/RD-INFRA-2024.12.20"/>
  
  __output__<project remote="tforg" name="TF-A/tf-a-tests.git" path="validation/comp-test/trusted-firmware-tf" revision="6f9e14a0e3a9e14051cf6235a49b06bae32823d9"/>
  __output__<project remote="github" name="acpica/acpica" path="tools/acpica" revision="refs/tags/G20240322"/>
  __output__<project remote="github" name="ARMmbed/mbedtls.git" path="mbedtls" revision="refs/tags/mbedtls-3.6.2"/>
  __output__<project remote="github" name="mirror/busybox" path="busybox" revision="refs/tags/1_36_1"/>
  __output__<project remote="gnugit" name="git/grub.git" path="grub" revision="refs/tags/grub-2.04"/>
  __output__<project remote="kernel" name="pub/scm/linux/kernel/git/jejb/efitools" path="tools/efitools" revision="refs/tags/v1.9.2"/>
  __output__<project remote="kernel" name="pub/scm/linux/kernel/git/will/kvmtool" path="kvmtool" revision="da4cfc3e540341b84c4bbad705b5a15865bc1f80"/>
__output__</manifest>
```

The manifest defines repositories of firmware sources, build and model scripts, linux, and tooling.

Fetch the sources with the `repo sync` command. This will take a few minutes to complete.

```
repo sync -c -j $(nproc) --fetch-submodules --force-sync --no-clone-bundle
```

The output from running this command looks like:

```
__output__... A new version of repo (2.54) is available.
__output__... New version is available at: /home/ubuntu/rdn2-infra/.repo/repo/repo
__output__... The launcher is run from: /usr/bin/repo
__output__!!! The launcher is not writable.  Please talk to your sysadmin or distro
__output__!!! to get an update installed.

__output__Fetching: 100% (17/17), done in 8m16.653s
__output__Fetching: 100% (17/17), done in 17.218s
__output__Fetching: 100% (17/17), done in 14.719s
__output__Fetching: 100% (7/7), done in 12.526s
__output__Fetching: 100% (1/1), done in 0.385s
__output__Updating files: 100% (84978/84978), done.ting files:  17% (14646/84978)
__output__Checking out:  27% (16/59), done in 8.804s
__output__Checking out:  28% (17/59), done in 0.779s
__output__Updating files: 100% (18459/18459), done.ptoPkg/Library/OpensslLib/openssl/pyca-cryptographyUpdating files:  42% (10441/24326)
__output__Updating files: 100% (24326/24326), done.ptoPkg/Library/OpensslLib/openssl/fuzz/corporaUpdating files:  54% (13137/24326)
__output__Checking out:  30% (18/59), done in 1.675s
__output__Checking out:  11% (7/59), done in 0.874s
__output__Checking out:   1% (1/59), done in 0.004s
__output__repo sync has finished successfully.
```

Now you should have all the code.

### Docker container setup

Set up a docker container in which to perform the build. A container execution script is provided. See the help for more information.

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

The output from help should look like:

```
__output__Usage: ./container.sh [OPTIONS] [COMMAND]

__output__If no options are provided the script uses the default values
__output__defined in the 'Defaults' section.

__output__Available options are:
__output__  -v  <path> absolute path to mount into the container;
__output__  -f  <file> docker file name;
__output__  -i  <name> docker image name;
__output__  -o  overwrites a previously-built image;
__output__  -h  displays this help message and exits;

__output__Available commands are:
__output__  build  builds the docker image;
__output__  run    runs the container in interactive mode;
```

Build the default configuration:

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

Verify that the container has been built:

```
docker image list
```

The output from this command looks like:

```
__output__REPOSITORY        TAG              IMAGE ID       CREATED         SIZE
__output__rdinfra-builder   latest           e11c8e27a4c6   7 days ago     8.12GB
__output__ubuntu            jammy-20230624   5a81c4b8502e   6 months ago    77.8MB
```

The appearance of the output is like a standard ubuntu container based on the latest release with the rdinfra-builder container built on top. Let’s run and enter the container:

```
docker run --rm \
  -v /home/ubuntu/rd-infra/:/home/ubuntu/rd-infra/ \
  -w /home/ubuntu/rd-infra/ \
  -e ARCADE_USER=$(id -un) \
  -e ARCADE_UID=$(id -u) \
  -e ARCADE_GID=$(id -g) \
  -it rdinfra-builder bash
```

This command puts you in the running container where you can run `ls` to list the contents:

```
__output__ubuntu@923218f076f5:/$ ls
__output__bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
```

You can exit the container like any login shell.

You can use the container script to run and enter the container. Mount the source checkout into the container so you can do a build without having to copy the source in and build the targets out:

```
./container.sh -v /home/ubuntu/rd-infra/ run
```

### Host-based builds

If you do choose to build this on the host, you need to obtain all the pre-requisites that would otherwise be installed in the container during its creation.

The build system provides a script for this that you must run as `root`:

```
sudo ./build-scripts/rdinfra/install_prerequisites.sh
```
