TF-RMM Release v0.1.0

This is the first external release of TF-RMM and provides a reference
implementation of Realm Management Monitor (RMM) as specified by the
RMM Beta0 specification[1].

The `docs/readme.rst` has more details about the project and
`docs/getting_started/getting-started.rst` has details on how to get
started with TF-RMM.

[1] https://developer.arm.com/documentation/den0137/1-0bet0/?lang=en

Signed-off-by: Soby Mathew <soby.mathew@arm.com>
Change-Id: I205ef14c015e4a37ae9ae1a64e4cd22eb8da746e
diff --git a/tools/checkpatch/CheckPatch.cmake b/tools/checkpatch/CheckPatch.cmake
new file mode 100644
index 0000000..51830cb
--- /dev/null
+++ b/tools/checkpatch/CheckPatch.cmake
@@ -0,0 +1,162 @@
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+#
+
+#
+# This script is called from main CMakeLists.txt to determine if code complies
+# to coding standards as mentioned in docs/getting_started/coding-standard.rst
+#
+# Runs checkpatch.pl on entire codebase if variable CHECKCODEBASE_RUN is defined.
+#
+# Runs checkpatch.pl on new commits if variable CHECKCODEBASE_RUN is defined.
+#
+find_package(Git REQUIRED)
+find_package(Perl REQUIRED)
+find_program(CHECKPATCH_EXECUTABLE "checkpatch.pl"
+  PATHS ${CMAKE_SOURCE_DIR}
+  PATH_SUFFIXES tools/checkpatch
+  DOC "Path to checkpatch.pl"
+  )
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/tools/common")
+include(GitUtils)
+
+#
+# List of directories and files to exclude from checking for target checkcodebase
+#
+list(APPEND glob_excludes "^.git")
+list(APPEND glob_excludes "^out")
+list(APPEND glob_excludes "^build")
+list(APPEND glob_excludes "^ext")
+list(APPEND glob_excludes "^tools")
+list(APPEND glob_excludes ".patch$")
+list(APPEND glob_excludes ".md$")
+list(APPEND glob_excludes "~$")
+list(APPEND glob_excludes ".swp$")
+list(APPEND glob_excludes "^cscope.")
+
+set(total_errors "0")
+set(total_warnings "0")
+
+# Check if pre-reqs met
+if(PERL_NOT_FOUND OR NOT EXISTS ${CHECKPATCH_EXECUTABLE})
+  message(FATAL_ERROR "required dependencies not found")
+endif()
+
+#
+# checkpatch_get_stats: Parse and returns number of errors and warnings
+#
+function(checkpatch_get_stats stats_arg errors_ret warnings_ret)
+  string(FIND "${stats_arg}" "total:" idx REVERSE)
+  string(LENGTH "${stats_arg}" len)
+  string(SUBSTRING "${stats_arg}" ${idx} ${len} last_line)
+
+  string(REPLACE " " ";" last_line_list ${last_line})
+  list(GET last_line_list 1 errors)
+  list(GET last_line_list 3 warnings)
+
+  set(${errors_ret} ${errors} PARENT_SCOPE)
+  set(${warnings_ret} ${warnings} PARENT_SCOPE)
+endfunction()
+
+#
+# print_stats_and_exit: Print summary of all errors and warnings.
+# If there are errors call message(FATAL_ERROR)
+#
+function(print_stats_and_exit check_type total_errors total_warnings)
+  message(STATUS "${check_type}: total errors: ${total_errors} "
+    "warnings: ${total_warnings}")
+
+  if(${total_errors} GREATER 0)
+    message(FATAL_ERROR "${check_type}: FAILED")
+  endif()
+
+  message(STATUS "${check_type}: PASSED")
+endfunction()
+
+#
+# Run checkpatch on entire codebase. This verifies all files in this repository
+# except the files listed in "glob_excludes".
+#
+# Exits with FATAL_ERROR upon errors. Warnings are ignored (temporary)
+#
+if(CHECKCODEBASE_RUN)
+  set(source_files "")
+
+  if (GIT_FOUND AND IS_DIRECTORY .git)
+    Git_Get_All_Files(source_files)
+  else()
+    file(GLOB_RECURSE source_files RELATIVE ${CMAKE_SOURCE_DIR} "*")
+  endif()
+
+  # Filter out 'glob_excludes'
+  foreach(exclude IN LISTS glob_excludes)
+    list(FILTER source_files EXCLUDE REGEX "${exclude}")
+  endforeach()
+
+  if(NOT source_files)
+    message(STATUS "checkcodebase: No files to check")
+    return()
+  endif()
+
+  foreach(source_file ${source_files})
+    execute_process(
+      COMMAND ${CMAKE_COMMAND} -E echo "Checking file ${source_file}"
+      )
+
+    execute_process(
+      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+      COMMAND ${CHECKPATCH_EXECUTABLE} -f ${source_file}
+      OUTPUT_VARIABLE checkpatch_output
+      RESULT_VARIABLE checkpatch_rc
+      ECHO_OUTPUT_VARIABLE
+      OUTPUT_STRIP_TRAILING_WHITESPACE
+      )
+
+    # checkpatch.pl failed for this file. Collect no.of errors and warnings
+    if(${checkpatch_rc})
+      checkpatch_get_stats("${checkpatch_output}" errors warnings)
+      MATH(EXPR total_errors "${total_errors}+${errors}")
+      MATH(EXPR total_warnings "${total_warnings}+${warnings}")
+    endif()
+  endforeach()
+
+  print_stats_and_exit("checkcodebase" ${total_errors}, ${total_warnings})
+endif()
+
+#
+# Run checkpatch on pending commits.
+#
+# Exits with FATAL_ERROR upon errors.
+#
+if(CHECKPATCH_RUN)
+  if(GIT_NOT_FOUND OR NOT IS_DIRECTORY .git)
+    message(FATAL_ERROR "Required dependencies Git not found")
+  endif()
+
+  # Get list of commits to check
+  Git_Get_Pending_Commits(pending_commits)
+
+  foreach(commit IN LISTS pending_commits)
+    message(STATUS "Checking commit: ${commit}")
+
+    execute_process(
+      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+      COMMAND ${GIT_EXECUTABLE} diff --format=email "${commit}~..${commit}"
+      COMMAND ${CHECKPATCH_EXECUTABLE} -
+      OUTPUT_VARIABLE checkpatch_output
+      RESULT_VARIABLE checkpatch_rc
+      ECHO_OUTPUT_VARIABLE
+      )
+
+    # checkpatch.pl failed for this commit. Collect no.of errors and warnings
+    if(${checkpatch_rc})
+      checkpatch_get_stats("${checkpatch_output}" errors warnings)
+      MATH(EXPR total_errors "${total_errors}+${errors}")
+      MATH(EXPR total_warnings "${total_warnings}+${warnings}")
+    endif()
+  endforeach()
+
+  print_stats_and_exit("checkpatch" ${total_errors}, ${total_warnings})
+endif()