ci: add a capability to clone and build RMM
Add a support to clone the RMM repository using
local CI and also add necessary hooks to build RMM.
Also, created a build config to build RMM along with
TF-A and TFTF.
Also, update run_local_ci script to pass missing paramters
like no_tfm_tests and no_tfm_extras.
Change-Id: Ib5020bcc25f87aa3f7edaf85ff4675cad03e675d
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
diff --git a/group/rmm-l1-build-tests/fvp-default,fvp-default,fvp-default:nil b/group/rmm-l1-build-tests/fvp-default,fvp-default,fvp-default:nil
new file mode 100644
index 0000000..8e42dc9
--- /dev/null
+++ b/group/rmm-l1-build-tests/fvp-default,fvp-default,fvp-default:nil
@@ -0,0 +1,5 @@
+#
+# Copyright (c) 2025 Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
diff --git a/rmm_config/fvp-default b/rmm_config/fvp-default
new file mode 100644
index 0000000..f25d21e
--- /dev/null
+++ b/rmm_config/fvp-default
@@ -0,0 +1 @@
+PLAT=fvp
diff --git a/script/build_package.sh b/script/build_package.sh
index 46ef0b5..3cd116f 100755
--- a/script/build_package.sh
+++ b/script/build_package.sh
@@ -24,6 +24,7 @@
scp_tools_root="${scp_tools_root:-$workspace/scp_tools}"
cc_root="${cc_root:-$ccpathspec}"
spm_root="${spm_root:-$workspace/spm}"
+rmm_root="${rmm_root:-$workspace/tf-rmm}"
scp_tf_tools_root="$scp_tools_root/scp_tf_tools"
@@ -33,6 +34,7 @@
scp_refspec="$SCP_REFSPEC"
scp_tools_commit="${SCP_TOOLS_COMMIT:-master}"
spm_refspec="$SPM_REFSPEC"
+rmm_refspec="$RMM_REFSPEC"
test_config="${TEST_CONFIG:?}"
test_group="${TEST_GROUP:?}"
@@ -513,6 +515,16 @@
)
}
+get_rmm_opt() {
+ (
+ name="${1:?}"
+ if config_valid "$rmm_config_file"; then
+ source "$rmm_config_file"
+ echo "${!name}"
+ fi
+ )
+}
+
build_tf() {
(
env_file="$workspace/tf.env"
@@ -893,6 +905,56 @@
)
}
+build_rmm() {
+ (
+ env_file="$workspace/rmm.env"
+ config_file="${rmm_build_config:-$rmm_config_file}"
+
+ # Build fiptool and all targets by default
+ build_targets="${rmm_build_targets}"
+ export CROSS_COMPILE="${aarch64_none_elf_prefix}"
+
+ source "$config_file"
+
+ if [ -f "$env_file" ]; then
+ set -a
+ source "$env_file"
+ set +a
+ fi
+
+ cd "$rmm_root"
+
+ if [ -f "$rmm_root/requirements.txt" ]; then
+ export PATH="$HOME/.local/bin:$PATH"
+ python3 -m pip install --upgrade pip
+ python3 -m pip install -r "$rmm_root/requirements.txt"
+ fi
+
+ # Always distclean when running on Jenkins. Skip distclean when running
+ # locally and explicitly requested.
+ if upon "$jenkins_run" || not_upon "$dont_clean"; then
+ # Remove 'rmm\build' folder
+ echo "Removing $rmm_build_root..."
+ rm -rf $rmm_build_root
+ fi
+
+ # Log build command line. It is left unfolded on purpose to assist
+ # copying to clipboard.
+ cat <<EOF | log_separator >/dev/null
+
+Build command line:
+ cmake -DRMM_CONFIG=${plat}_defcfg $cmake_gen -S $rmm_root -B $rmm_build_root -DCMAKE_BUILD_TYPE=$cmake_build_type
+ cmake --build $rmm_build_root $make_j_opts -v
+EOF
+ if not_upon "$local_ci"; then
+ connect_debugger=0
+ fi
+
+ cmake -DRMM_CONFIG=${plat}_defcfg $cmake_gen -S $rmm_root -B $rmm_build_root -DCMAKE_BUILD_TYPE=$cmake_build_type
+ cmake --build $rmm_build_root $make_j_opts -v 3>&1 &>>"$build_log" || fail_build
+ )
+}
+
# Set metadata for the whole package so that it can be used by both Jenkins and
# shell
set_package_var() {
@@ -1157,6 +1219,7 @@
scp_config="$(echo "$build_configs" | awk -F, '{print $3}')"
scp_tools_config="$(echo "$build_configs" | awk -F, '{print $4}')"
spm_config="$(echo "$build_configs" | awk -F, '{print $5}')"
+rmm_config="$(echo "$build_configs" | awk -F, '{print $6}')"
test_config_file="$ci_root/group/$test_group/$test_config"
@@ -1165,6 +1228,7 @@
scp_config_file="$ci_root/scp_config/$scp_config"
scp_tools_config_file="$ci_root/scp_tools_config/$scp_tools_config"
spm_config_file="$ci_root/spm_config/$spm_config"
+rmm_config_file="$ci_root/rmm_config/$rmm_config"
# File that keeps track of applied patches
tf_patch_record="$workspace/tf_patches"
@@ -1216,6 +1280,18 @@
echo
fi
+# File that keeps track of applied patches
+rmm_patch_record="$workspace/rmm_patches"
+
+if ! config_valid "$rmm_config"; then
+ rmm_config=
+else
+ echo "Trusted Firmware RMM config:"
+ echo
+ sort "$rmm_config_file" | sed '/^\s*$/d;s/^/\t/'
+ echo
+fi
+
if ! config_valid "$run_config"; then
run_config=
fi
@@ -1311,6 +1387,15 @@
show_head "$spm_root"
fi
+if [ "$rmm_config" ] && assert_can_git_clone "rmm_root"; then
+ # If the Trusted Firmware TF repository has already been checked out,
+ # use that location. Otherwise, clone one ourselves.
+ echo "Cloning TF-RMM..."
+ clone_url="${RMM_CHECKOUT_LOC:-$rmm_src_repo_url}" where="$rmm_root" \
+ refspec="$RMM_REFSPEC" clone_repo &>>"$build_log"
+ show_head "$rmm_root"
+fi
+
if [ "$run_config" ]; then
# Get candidates for run config
run_config_candidates="$("$ci_root/script/gen_run_config_candidates.py" \
@@ -1355,6 +1440,27 @@
source "$ci_root/script/install_python_deps.sh"
fi
+# Print CMake version
+cmake_ver=$(echo `cmake --version | sed -n '1p'`)
+echo "Using $cmake_ver"
+
+# Check for Ninja
+if [ -x "$(command -v ninja)" ]; then
+ # Print Ninja version
+ ninja_ver=$(echo `ninja --version | sed -n '1p'`)
+ echo "Using ninja $ninja_ver"
+ export cmake_gen="-G Ninja"
+else
+ echo 'Ninja is not installed'
+ export cmake_gen=""
+fi
+
+undo_rmm_patches() {
+ pushd "$rmm_root"
+ patch_record="$rmm_patch_record" undo_patch_record
+ popd
+}
+
modes="${bin_mode:-debug release}"
for mode in $modes; do
echo "===== Building package in mode: $mode ====="
@@ -1364,9 +1470,11 @@
if [ "$mode" = "debug" ]; then
export bin_mode="debug"
+ cmake_build_type="Debug"
DEBUG=1
else
export bin_mode="release"
+ cmake_build_type="Release"
DEBUG=0
fi
@@ -1508,6 +1616,44 @@
)
fi
+ # TF RMM build
+ if config_valid "$rmm_config"; then
+ (
+ echo "##########"
+
+ plat_utils="$(get_rmm_opt PLAT_UTILS)"
+ if [ -z ${plat_utils} ]; then
+ # Source platform-specific utilities.
+ plat="$(get_rmm_opt PLAT)"
+ plat_utils="$ci_root/${plat}_utils.sh"
+ else
+ # Source platform-specific utilities by
+ # using plat_utils name.
+ plat_utils="$ci_root/${plat_utils}.sh"
+ fi
+
+ if [ -f "$plat_utils" ]; then
+ source "$plat_utils"
+ fi
+
+ archive="$build_archive"
+ rmm_build_root="$rmm_root/build"
+
+ echo "Building Trusted Firmware RMM ($mode) ..." |& log_separator
+
+ #call_hook pre_rmm_build
+ build_rmm
+
+ # Collect all rmm.* files: rmm.img, rmm.elf, rmm.dump, rmm.map
+ from="$rmm_build_root" to="$archive" collect_build_artefacts
+
+ # Clear any local changes made by applied patches
+ undo_rmm_patches
+
+ echo "##########"
+ )
+ fi
+
# TF build
if config_valid "$tf_config"; then
(
diff --git a/script/clone_repos.sh b/script/clone_repos.sh
index 3f5466a..0aab33d 100755
--- a/script/clone_repos.sh
+++ b/script/clone_repos.sh
@@ -479,6 +479,12 @@
loc="TF_M_EXTRAS_PATH" clone_and_sync
fi
+RMM_EXTRAS_REFSPEC="${rmm_refspec:-$RMM_REFSPEC}"
+if not_upon "$no_rmm"; then
+ url="$rmm_src_repo_url" name="tf-rmm" ref="RMM_REFSPEC" \
+ loc="RMM_PATH" clone_and_sync
+fi
+
if [ "$GERRIT_BRANCH" ]; then
# If this CI run was in response to a Gerrit commit, post a comment back
# to the patch set calling out everything that we've done so far. This
diff --git a/script/run_local_ci.sh b/script/run_local_ci.sh
index a909c14..ba3156f 100755
--- a/script/run_local_ci.sh
+++ b/script/run_local_ci.sh
@@ -352,6 +352,33 @@
let "++local_count"
fi
+if [ -z "$rmm_root" ]; then
+ in_red "NOTE: NOT using local work tree for RMM"
+else
+ rmm_root="$(readlink -f $rmm_root)"
+ rmm_refspec=
+ in_green "Using local work tree for RMM"
+ let "++local_count"
+fi
+
+if [ -z "$tfm_tests_root" ]; then
+ in_red "NOTE: NOT using local work tree for TF-M-TESTS"
+else
+ tfm_tests_root="$(readlink -f $tfm_tests_root)"
+ tfm_tests_refspec=
+ in_green "Using local work tree for TF-M-TESTS"
+ let "++local_count"
+fi
+
+if [ -z "$tfm_extras_root" ]; then
+ in_red "NOTE: NOT using local work tree for TF-M-EXTRAS"
+else
+ tfm_extras_root="$(readlink -f $tfm_extras_root)"
+ tfm_extras_refspec=
+ in_green "Using local work tree for TF-M-EXTRAS"
+ let "++local_count"
+fi
+
# User preferences
[ "$connect_debugger" ] && [ "$connect_debugger" -eq 1 ] && user_connect_debugger=1
user_test_run="${user_connect_debugger:-$test_run}"
@@ -392,7 +419,8 @@
fi
# Use clone_repos.sh to clone and share repositories that aren't local.
-no_tf="$tf_root" no_tftf="$tftf_root" no_spm="$spm_root" no_ci="$ci_root" no_cc="$import_cc" \
+no_tf="$tf_root" no_tftf="$tftf_root" no_spm="$spm_root" no_rmm="$rmm_root" \
+no_ci="$ci_root" no_cc="$import_cc" no_tfm_tests="$tfm_tests_root" no_tfm_extras="$tfm_extras_root" \
bash $minus_x "$ci_root/script/clone_repos.sh"
set -a
diff --git a/utils.sh b/utils.sh
index 433bbe9..d05ad75 100644
--- a/utils.sh
+++ b/utils.sh
@@ -566,6 +566,8 @@
scp_src_repo_url="${scp_src_repo_url:-$scp_src_repo_default}"
spm_src_repo_url="${spm_src_repo_url:-$SPM_SRC_REPO_URL}"
spm_src_repo_url="${spm_src_repo_url:-https://$tforg_gerrit_url/hafnium/hafnium}"
+rmm_src_repo_url="${rmm_src_repo_url:-$RMM_SRC_REPO_URL}"
+rmm_src_repo_url="${rmm_src_repo_url:-https://$tforg_gerrit_url/TF-RMM/tf-rmm}"
tf_m_tests_src_repo_url="${tf_m_tests_src_repo_url:-$TF_M_TESTS_REPO_URL}"
tf_m_tests_src_repo_url="${tf_m_tests_src_repo_url:-https://$tforg_gerrit_url/TF-M/tf-m-tests}"
tf_m_extras_src_repo_url="${tf_m_extras_src_repo_url:-$TF_M_EXTRAS_REPO_URL}"