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/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