tfa-next: add static and lint checks

    1. Copyright exists on new files (error) + are correctly dated
       (warn)
    2. Line endings are Unix style, not Windows
    3. Cargo fmt --check - returns error if format issues found
    4. Clippy - various lints, both error + warn

Checks 1+2 call the pre-existing scripts in the static-checks/ dir, 3+4
are newly implemented checks in the next-checks/ dir.

clippy is currently set to only fail on DENY level errors[1]. There are
many warnings currently in the prototype RF-A, however in future we
should look to enable the '-Dwarnings' flag to turn WARN into fail.

clippy is set to run twice for simplicity: once for fvp, once for qemu.
The '--all-features' flag to clippy exists and would allow a single run,
however rust/build.rs contains a check to ensure the Rust flag `--cfg
platform=${PLAT}` is set (where $PLAT is an env var passed to the make
command). This would mean some additional work is required to enable
'--all-features'. This work should be considered for future scaling to
additional platforms however is beyond the scope of this patch.

1: https://rust-lang.github.io/rust-clippy/master/index.html?levels=deny

Signed-off-by: Zachary Leaf <zachary.leaf@arm.com>
Change-Id: I31876f2d547d90c6d255ab1ebe8f8b205a6951fe
diff --git a/script/next-checks/next-checks-cargo-fmt.sh b/script/next-checks/next-checks-cargo-fmt.sh
new file mode 100755
index 0000000..4db97c9
--- /dev/null
+++ b/script/next-checks/next-checks-cargo-fmt.sh
@@ -0,0 +1,41 @@
+
+#!/usr/bin/env bash
+#
+# Copyright (c) 2024 Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+this_dir="$(readlink -f "$(dirname "$0")")"
+. $this_dir/../static-checks/common.sh
+
+TF_ROOT="$1"
+
+TEST_CASE="Rust cargo fmt checks"
+
+echo "# ${TEST_CASE}"
+
+LOG_FILE=`mktemp -t common.XXXX`
+
+EXIT_VALUE=0
+
+cargo fmt --manifest-path=${TF_ROOT}/rust/Cargo.toml --all -- --check  &> "$LOG_FILE"
+
+if [ "$?" -ne 0 ]; then
+    EXIT_VALUE=1
+fi
+
+echo >> "$LOG_TEST_FILENAME"
+echo "****** $TEST_CASE ******" >> "$LOG_TEST_FILENAME"
+echo >> "$LOG_TEST_FILENAME"
+if [[ "$EXIT_VALUE" == 0 ]]; then
+  echo "Result : SUCCESS" >> "$LOG_TEST_FILENAME"
+else
+  echo "Result : FAILURE" >> "$LOG_TEST_FILENAME"
+fi
+echo >> "$LOG_TEST_FILENAME"
+cat "$LOG_FILE" >> "$LOG_TEST_FILENAME"
+
+rm "$LOG_FILE"
+
+exit "$EXIT_VALUE"
diff --git a/script/next-checks/next-checks-clippy.sh b/script/next-checks/next-checks-clippy.sh
new file mode 100755
index 0000000..b7a644a
--- /dev/null
+++ b/script/next-checks/next-checks-clippy.sh
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2024 Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+this_dir="$(readlink -f "$(dirname "$0")")"
+. $this_dir/../static-checks/common.sh
+
+TF_ROOT="$1"
+TEST_CASE="Rust clippy checks"
+LOG_FILE=`mktemp -t common.XXXX`
+EXIT_VALUE=0
+
+echo "# ${TEST_CASE}"
+echo >> "$LOG_TEST_FILENAME"
+echo "****** $TEST_CASE ******" >> "$LOG_TEST_FILENAME"
+echo >> "$LOG_TEST_FILENAME"
+echo "Platforms:" >> "$LOG_TEST_FILENAME"
+
+for plat in "fvp" "qemu"
+do
+    echo >> $LOG_FILE
+    echo "############### ${TEST_CASE} - platform: ${plat}" >> "$LOG_FILE"
+    echo >> $LOG_FILE
+    make -C ${TF_ROOT}/rust PLAT=${plat} clippy >> "$LOG_FILE" 2>&1
+
+    if [ "$?" -ne 0 ]; then
+        echo -e "  ${plat}\t: FAIL" >> "$LOG_TEST_FILENAME"
+        EXIT_VALUE=1
+    else
+        echo -e "  ${plat}\t: PASS" >> "$LOG_TEST_FILENAME"
+    fi
+done
+
+echo >> "$LOG_TEST_FILENAME"
+if [[ "$EXIT_VALUE" == 0 ]]; then
+  echo "Result : SUCCESS" >> "$LOG_TEST_FILENAME"
+else
+  echo "Result : FAILURE" >> "$LOG_TEST_FILENAME"
+fi
+echo >> "$LOG_TEST_FILENAME"
+cat "$LOG_FILE" >> "$LOG_TEST_FILENAME"
+
+rm "$LOG_FILE"
+
+exit "$EXIT_VALUE"
diff --git a/script/next-checks/next-checks.sh b/script/next-checks/next-checks.sh
new file mode 100755
index 0000000..89df456
--- /dev/null
+++ b/script/next-checks/next-checks.sh
@@ -0,0 +1,108 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2024 Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+echo '----------------------------------------------'
+echo '-- Running Rust formatting and lint checks  --'
+echo '----------------------------------------------'
+
+export LOG_TEST_FILENAME=$(pwd)/next-checks.log
+export RUSTUP_HOME=/usr/local/rustup
+
+# For local runs, we require GERRIT_BRANCH to be set to get the merge-base/diff
+# between the checked out commit and the tip of $GERRIT_BRANCH - for running
+# next tests, usually this will be tfa-next
+export GERRIT_BRANCH=${GERRIT_BRANCH:="tfa-next"}
+
+if [ "$IS_CONTINUOUS_INTEGRATION" == 1 ]; then
+    # git operations e.g. ${get_merge_base} rely on access to tfa-next branch,
+    # we need to access via SSH for that to work currently
+    SSH_PARAMS="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o PubkeyAcceptedKeyTypes=+ssh-rsa -p 29418 -i ${CI_BOT_KEY}"
+    REPO_SSH_URL="ssh://${CI_BOT_USERNAME}@review.trustedfirmware.org:29418/TF-A/trusted-firmware-a"
+    export GIT_SSH_COMMAND="ssh ${SSH_PARAMS}"
+    git remote set-url origin ${REPO_SSH_URL}
+    git fetch origin
+fi
+
+# Find the absolute path of the scripts' top directory
+cd "$(dirname "$0")/../.."
+export CI_ROOT=$(pwd)
+cd -
+
+. $CI_ROOT/script/static-checks/common.sh
+
+echo
+echo "###### Rust checks ######" > "$LOG_TEST_FILENAME"
+echo >> "$LOG_TEST_FILENAME"
+
+echo "Patch series being checked:" >> "$LOG_TEST_FILENAME"
+git log --oneline $(get_merge_base)..HEAD >> "$LOG_TEST_FILENAME"
+echo >> "$LOG_TEST_FILENAME"
+echo "Base branch reference commit:" >> "$LOG_TEST_FILENAME"
+git log --oneline -1 $(get_merge_base) >> "$LOG_TEST_FILENAME"
+
+echo >> "$LOG_TEST_FILENAME"
+
+ERROR_COUNT=0
+
+# Ensure all the files contain a copyright
+
+"$CI_ROOT"/script/static-checks/static-checks-check-copyright.sh .
+
+if [ "$?" != 0 ]; then
+  echo "Copyright test: FAILURE"
+  ((ERROR_COUNT++))
+else
+  echo "Copyright test: PASS"
+fi
+echo
+
+# Check line endings
+
+if [ "$IS_CONTINUOUS_INTEGRATION" == 1 ]; then
+    "$CI_ROOT"/script/static-checks/static-checks-coding-style-line-endings.sh . patch
+else
+    "$CI_ROOT"/script/static-checks/static-checks-coding-style-line-endings.sh
+fi
+
+if [ "$?" != 0 ]; then
+  echo "Line ending test: FAILURE"
+  ((ERROR_COUNT++))
+else
+  echo "Line ending test: PASS"
+fi
+echo
+
+# Check coding style with cargo fmt
+
+"$CI_ROOT"/script/next-checks/next-checks-cargo-fmt.sh .
+
+if [ "$?" != 0 ]; then
+  echo "cargo fmt test: FAILURE"
+  ((ERROR_COUNT++))
+else
+  echo "cargo fmt test: PASS"
+fi
+echo
+
+# Check lints with clippy
+
+"$CI_ROOT"/script/next-checks/next-checks-clippy.sh .
+
+if [ "$?" != 0 ]; then
+  echo "Rust clippy: FAILURE"
+  ((ERROR_COUNT++))
+else
+  echo "Rust clippy: PASS"
+fi
+echo
+
+if [ "$ERROR_COUNT" != 0 ]; then
+  echo "Some static checks have failed."
+  exit 1
+fi
+
+exit 0
diff --git a/script/static-checks/check-copyright.py b/script/static-checks/check-copyright.py
index a05b4ca..2bdfa93 100755
--- a/script/static-checks/check-copyright.py
+++ b/script/static-checks/check-copyright.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2024, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -28,7 +28,7 @@
 # File extensions to check
 VALID_FILE_EXTENSIONS = ('.c', '.conf', '.dts', '.dtsi', '.editorconfig',
                          '.h', '.i', '.ld', 'Makefile', '.mk', '.msvc',
-                         '.py', '.S', '.scat', '.sh')
+                         '.py', '.S', '.scat', '.sh', '.rs')
 
 # Paths inside the tree to ignore. Hidden folders and files are always ignored.
 # They mustn't end in '/'.
diff --git a/script/static-checks/static-checks-coding-style-line-endings.sh b/script/static-checks/static-checks-coding-style-line-endings.sh
index 9c0cda7..66763bc 100755
--- a/script/static-checks/static-checks-coding-style-line-endings.sh
+++ b/script/static-checks/static-checks-coding-style-line-endings.sh
@@ -22,7 +22,7 @@
     shopt -s globstar
     parent=$(get_merge_base)
     git diff $parent..HEAD --no-ext-diff --unified=0 --exit-code -a \
-      --no-prefix **/*.{S,c,h,i,dts,dtsi,rst,mk} Makefile | \
+      --no-prefix **/*.{S,c,h,i,dts,dtsi,rst,mk,rs} Makefile | \
       awk '/^\+/ && /\r$/' &> "$LOG_FILE"
 else
   # For all the source and doc files
@@ -37,6 +37,7 @@
       -name '*.rst' -or \
       -name 'Makefile' -or \
       -name '*.mk' \
+      -name '*.rs' \
   -\) -exec grep --files-with-matches $'\r$' {} \; &> "$LOG_FILE"
 fi