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/cmake/Modules/ArmConfigOption.cmake b/cmake/Modules/ArmConfigOption.cmake
new file mode 100644
index 0000000..07b80c7
--- /dev/null
+++ b/cmake/Modules/ArmConfigOption.cmake
@@ -0,0 +1,449 @@
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+#
+
+#[=======================================================================[.rst:
+ArmConfigOption
+---------------
+
+.. default-domain:: cmake
+
+.. command:: arm_config_option
+
+Create a configuration option with more flexibility than offered by
+:module:`cmake_dependent_option() <module:CMakeDependentOption>`.
+
+.. code:: cmake
+
+    arm_config_option(NAME <name> HELP <help> [TYPE <type>] [DEFAULT <default>]
+                      [[STRINGS <strings>...] [FREEFORM]] [ADVANCED]
+                      [[DEPENDS <depends>] [ELSE <else>]] [FORCE <force>])
+
+This helper function is intended to simplify some of the complex mechanics
+involved in creating a robust, scalable configuration system for medium to
+large projects. It incorporates basic dependency resolution, overridable default
+values, and stronger typing in order to provide a smoother experience for both
+build system developers and users.
+
+Basics
+^^^^^^
+
+Every configuration option has one of the following types:
+
+- ``BOOL`` for booleans (shows as a toggle option)
+- ``STRING`` for strings (shows as a text box)
+- ``PATH`` for directory paths (shows as a directory chooser)
+- ``FILEPATH`` for file paths (shows as a file chooser)
+
+These are the types supported by the :prop_cache:`TYPE <prop_cache:TYPE>` cache
+entry property. It's important to choose the right type for the option in order
+to provide a consistent user experience.
+
+By default, any configuration option that does not specify a type (by providing
+a value to the ``TYPE`` argument) is ``BOOL``, unless the ``STRINGS`` argument
+has been provided. For example:
+
+.. code:: cmake
+
+    arm_config_option(NAME XYZ ... TYPE BOOL) # BOOL
+    arm_config_option(NAME XYZ ... TYPE STRING) # STRING
+    arm_config_option(NAME XYZ ... TYPE PATH) # PATH
+    arm_config_option(NAME XYZ ... TYPE FILEPATH) # FILEPATH
+
+    arm_config_option(NAME XYZ ...) # BOOL
+    arm_config_option(NAME XYZ ... STRINGS ...) # STRING
+
+Likewise, every configuration option has a (default) default value, dependent on
+its type:
+
+.. code:: cmake
+
+    arm_config_option(NAME XYZ ... TYPE BOOL) # FALSE
+    arm_config_option(NAME XYZ ... TYPE STRING) # ""
+    arm_config_option(NAME XYZ ... TYPE PATH) # ""
+    arm_config_option(NAME XYZ ... TYPE FILEPATH) # ""
+
+    arm_config_option(NAME XYZ ...) # FALSE
+    arm_config_option(NAME XYZ ... STRINGS X Y Z) # "X"
+
+Note that the default value of configuration options with a ``STRINGS`` list
+will use the first element of the list as the default.
+
+The default value can be overridden by providing a value to the ``DEFAULT``
+argument:
+
+.. code:: cmake
+
+    arm_config_option(NAME XYZ ... TYPE BOOL DEFAULT TRUE) # TRUE
+    arm_config_option(NAME XYZ ... TYPE STRING DEFAULT "x") # "x"
+    arm_config_option(NAME XYZ ... TYPE PATH DEFAULT "./x") # "./x"
+    arm_config_option(NAME XYZ ... TYPE FILEPATH DEFAULT "./x.txt") # "./x.txt"
+
+For options with a ``STRINGS`` list, the value provided to the ``DEFAULT``
+argument must exist within the list unless the ``FREEFORM`` argument has been
+provided. Freeform string list options permit values outside of the list:
+
+.. code:: cmake
+
+    arm_config_option(NAME XYZ ... STRINGS X Y Z) # "X"
+    arm_config_option(NAME XYZ ... STRINGS X Y Z DEFAULT Z) # "Z"
+    arm_config_option(NAME XYZ ... STRINGS X Y Z DEFAULT A FREEFORM) # "A"
+    arm_config_option(NAME XYZ ... STRINGS X Y Z DEFAULT A) # ERROR
+
+Configuration options can be marked as "advanced" by using the ``ADVANCED``
+flag. In CMake's user interfaces, this hides the configuration option behind the
+"advanced" toggle:
+
+    arm_config_option(NAME XYZ ...) # Always visible
+    arm_config_option(NAME XYZ ... ADVANCED) # Visible only when requested
+
+Some basic usage examples follow:
+
+.. code:: cmake
+
+    arm_config_option(
+        NAME MYPROJECT_ENABLE_FOO
+        HELP "Enable the foo feature.")
+
+    arm_config_option(
+        NAME MYPROJECT_ENABLE_BAR
+        HELP "Enable the bar feature."
+        ADVANCED)
+
+    arm_config_option(
+        NAME MYPROJECT_BAZ_NAME
+        HELP "Name of the baz."
+        TYPE STRING
+        DEFAULT "Baz")
+
+    arm_config_option(
+        NAME MYPROJECT_BAZ_TYPE
+        HELP "Type of the baz."
+        STRINGS "Surly" "Bewildered" "Aloof")
+
+    if(MYPROJECT_ENABLE_FOO)
+        message(STATUS "The foo feature is enabled!")
+    endif()
+
+    if(MYPROJECT_ENABLE_BAR)
+        message(STATUS "The bar feature is enabled!")
+    endif()
+
+    message(STATUS "The name of the baz is: ${MYPROJECT_BAZ_NAME}!")
+    message(STATUS "The type of the baz is: ${MYPROJECT_BAZ_TYPE}!")
+
+Dependencies
+^^^^^^^^^^^^
+
+Dependencies between options can be modelled using the ``DEPENDS`` argument.
+This argument takes an expression in :ref:`Condition Syntax`, which determines
+whether the option will be shown.
+
+For example, if you have a feature flag ``foo``, and you have a feature flag
+``bar`` that only makes sense if ``foo`` is enabled, you might use:
+
+.. code:: cmake
+
+    arm_config_option(
+        NAME MYPROJECT_ENABLE_FOO
+        HELP "Enable the foo feature.")
+
+    arm_config_option(
+        NAME MYPROJECT_ENABLE_BAR
+        HELP "Enable the bar feature."
+        DEPENDS MYPROJECT_ENABLE_FOO)
+
+Configuration options whose dependencies have not been met are hidden from the
+GUI (that is, the cache variable is given the ``INTERNAL`` type), and the
+default value is restored.
+
+If you need a value *other* than the default to be set if the dependency is not
+met, then use the ``ELSE`` argument:
+
+.. code:: cmake
+
+    arm_config_option(
+        NAME STACK_SIZE
+        HELP "Stack size (in bytes)."
+        TYPE STRING
+        DEFAULT 512)
+
+    arm_config_option(
+        NAME HEAP_SIZE
+        HELP "Heap size (in bytes)."
+        DEFAULT 65536)
+
+    arm_config_option(
+      NAME STACKHEAP_SIZE
+      HELP "Stackheap size."
+      DEFAULT 65536
+      DEPENDS ((STACK_SIZE EQUAL 0) AND (HEAP_SIZE EQUAL 0))
+      ELSE 0)
+
+In some cases you may need to forcibly overwrite the value of a configuration
+option under certain conditions. You can do this using the ``FORCE`` argument
+which, like ``DEPENDS``, accepts :ref:`Condition Syntax`. This is typically only
+useful for augmenting existing cache variables.
+
+In the following example, ``FORCE`` is used to forcibly override the default
+value of :variable:`CMAKE_BUILD_TYPE <variable:CMAKE_BUILD_TYPE>` (``""``) with
+a new default defined by the build system configuration:
+
+.. code:: cmake
+
+    arm_config_option(
+        NAME CMAKE_BUILD_TYPE
+        HELP "Build type."
+        STRINGS "Debug" "RelWithDebInfo" "MinSizeRel" "Release"
+        DEFAULT "MinSizeRel"
+        FORCE NOT CMAKE_BUILD_TYPE)
+
+Detecting Changes
+^^^^^^^^^^^^^^^^^
+
+In some cases it's useful to know whether a configuration option has been
+modified. Any configuration option created with this function has an associated
+``${NAME}_CHANGED`` cache variable, which can be used to detect whether the
+value of ``${NAME}`` has changed between the last configuration run and the
+current one.
+
+For example:
+
+.. code:: cmake
+
+    arm_config_option(
+        NAME ENABLE_FEATURE
+        HELP "Enable the feature.")
+
+    if(ENABLE_FEATURE_CHANGED)
+        message(STATUS "The feature's been toggled!")
+    endif()
+
+Fine-Grained Control
+^^^^^^^^^^^^^^^^^^^^
+
+Additional facilities for fine-grained control over defaults and forced values
+are provided by the :command:`arm_config_option_override`.
+#]=======================================================================]
+
+include_guard()
+
+function(arm_config_option)
+    set(_options "FREEFORM;ADVANCED")
+    set(_single_args "NAME;HELP;TYPE")
+    set(_multi_args "DEFAULT;STRINGS;DEPENDS;ELSE;FORCE")
+
+    cmake_parse_arguments(
+        arg "${_options}" "${_single_args}" "${_multi_args}" ${ARGN})
+
+    if("DEFAULT" IN_LIST arg_KEYWORDS_MISSING_VALUES)
+        set(arg_DEFAULT "")
+    endif()
+
+    #
+    # Attempt to derive the type from the other arguments given. Passing STRINGS
+    # implies a type of STRING, otherwise the type is BOOL.
+    #
+
+    if(NOT DEFINED arg_TYPE)
+        if(DEFINED arg_STRINGS)
+            set(arg_TYPE "STRING")
+        else()
+            set(arg_TYPE "BOOL")
+        endif()
+    endif()
+
+    #
+    # Identify a reasonable default if one has not been provided. For BOOL this
+    # is FALSE. If STRINGS has been provided then we take the first entry in the
+    # list. For any other type we use an empty string.
+    #
+
+    if(NOT DEFINED arg_DEFAULT)
+        if(arg_TYPE MATCHES "BOOL")
+            set(arg_DEFAULT "FALSE")
+        elseif(DEFINED arg_STRINGS)
+            list(GET arg_STRINGS 0 arg_DEFAULT)
+        else()
+            set(arg_DEFAULT "")
+        endif()
+    endif()
+
+    #
+    # If no dependency condition is provided, it is implicitly TRUE.
+    #
+
+    if(NOT DEFINED arg_DEPENDS)
+        set(arg_DEPENDS "TRUE")
+    endif()
+
+    if(${arg_DEPENDS})
+        #
+        # If an internal cache variable exists by this name but the dependency
+        # condition holds, it's because it previously didn't. We need to
+        # forcibly update the variable to make it visible again.
+        #
+
+        if(DEFINED "${arg_NAME}")
+            get_property(type CACHE "${arg_NAME}" PROPERTY TYPE)
+
+            if(type STREQUAL "INTERNAL")
+                set(arg_FORCE TRUE)
+            endif()
+        endif()
+
+        #
+        # If a force variable exists, take on its value and hide the cache
+        # variable. Otherwise, if a default variable exists, just take on its
+        # value.
+        #
+
+        if(DEFINED "${arg_NAME}_FORCE")
+            set(arg_TYPE "INTERNAL")
+            set(arg_DEFAULT "${${arg_NAME}_FORCE}")
+        elseif(DEFINED "${arg_NAME}_INIT")
+            set(arg_DEFAULT "${${arg_NAME}_INIT}")
+        endif()
+    else()
+        #
+        # If the dependency condition doesn't hold, hide the cache variable from
+        # the user.
+        #
+
+        set(arg_TYPE "INTERNAL")
+
+        #
+        # If an else value has been given, now is the time to adopt it.
+        #
+
+        if(DEFINED arg_ELSE)
+            set(arg_DEFAULT "${arg_ELSE}")
+        endif()
+    endif()
+
+    #
+    # Try to detect whether the user has overridden an already
+    # forcibly-overriden variable. We throw an error in this situation to avoid
+    # a split-brain configuration, where the variable expands to two values
+    # depending on which side of this function call you are on.
+    #
+    # This usually happens if the user has defined the value on the command
+    # line, as these options are replaced every time reconfiguration
+    # happens.
+    #
+
+    if((DEFINED "${arg_NAME}") AND
+        (DEFINED "${arg_NAME}_FORCE") AND
+        (NOT "${${arg_NAME}_FORCE}" STREQUAL "${${arg_NAME}}"))
+        set(value "${${arg_NAME}}")
+        unset("${arg_NAME}" CACHE)
+
+        if(${arg_DEPENDS})
+            message(FATAL_ERROR
+                "Overridden configuration option detected!\n"
+
+                "The configuration option `${arg_NAME}` cannot be given "
+                "the value `${value}` because it has been forcibly set to "
+                "`${arg_DEFAULT}`.")
+        else()
+            string(REPLACE ";" " " dependency "${arg_DEPENDS}")
+
+            message(FATAL_ERROR
+                "Impossible configuration detected!\n"
+
+                "The configuration option `${arg_NAME}` cannot be given "
+                "the value `${value}` because it has been forcibly set to "
+                "`${arg_DEFAULT}` due to an unmet dependency:\n"
+
+                "${dependency}")
+        endif()
+    endif()
+
+    #
+    # The official documentation says that `INTERNAL` implies `FORCE`, but this
+    # does not seem to be the case in some situations, so let's be safe.
+    #
+
+    if(arg_TYPE STREQUAL "INTERNAL")
+        set(arg_FORCE TRUE)
+    endif()
+
+    #
+    # If we're being asked to forcibly update the cache variable, append FORCE
+    # to the set() call.
+    #
+
+    if((DEFINED arg_FORCE) AND (${arg_FORCE}))
+        set(force "FORCE")
+    else()
+        unset(force)
+
+        #
+        # Clear the forced-value variable so that we don't accidentally flag
+        # this
+        #
+
+        unset("${arg_NAME}_FORCE" CACHE)
+    endif()
+
+    #
+    # Update the change-tracking variable.
+    #
+
+    set(old "${${arg_NAME}_NEW}")
+    set(new "${${arg_NAME}}")
+
+    if(NOT old STREQUAL new)
+        set(changed TRUE)
+    else()
+        set(changed FALSE)
+    endif()
+
+    set("${arg_NAME}_OLD" "${old}"
+        CACHE INTERNAL "Previous value of ${arg_NAME}." FORCE)
+
+    set("${arg_NAME}_NEW" "${new}"
+        CACHE INTERNAL "Latest value of ${arg_NAME}." FORCE)
+
+    set("${arg_NAME}_CHANGED" ${changed}
+        CACHE INTERNAL "Has ${arg_NAME} just changed?" FORCE)
+
+    #
+    # Create the cache variable.
+    #
+
+    set("${arg_NAME}" "${arg_DEFAULT}"
+        CACHE "${arg_TYPE}" "${arg_HELP}" ${force})
+
+    if(arg_ADVANCED)
+        mark_as_advanced("${arg_NAME}")
+    endif()
+
+    #
+    # If we've been given a list of valid values, update the STRINGS property of
+    # the cache variable with that list.
+    #
+
+    if(DEFINED arg_STRINGS)
+        set_property(CACHE "${arg_NAME}" PROPERTY STRINGS ${arg_STRINGS})
+
+        #
+        # If we haven't been asked to offer a freeform text box, let the user
+        # know if they've provided something out of bounds.
+        #
+
+        if((NOT arg_FREEFORM) AND (NOT "${${arg_NAME}}" IN_LIST arg_STRINGS))
+            set(strings "")
+
+            foreach(string IN LISTS arg_STRINGS)
+                string(APPEND strings "\"${string}\" ")
+            endforeach()
+
+            message(FATAL_ERROR
+                "Invalid value for `${arg_NAME}`!\n"
+
+                "This configuration supports the following values: ${strings}")
+        endif()
+    endif()
+endfunction()
diff --git a/cmake/Modules/ArmConfigOptionOverride.cmake b/cmake/Modules/ArmConfigOptionOverride.cmake
new file mode 100644
index 0000000..8e5b270
--- /dev/null
+++ b/cmake/Modules/ArmConfigOptionOverride.cmake
@@ -0,0 +1,94 @@
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+#
+
+#[=======================================================================[.rst:
+ArmConfigOptionOverride
+-----------------------
+
+.. default-domain:: cmake
+
+.. command:: arm_config_option_override
+
+Override the default or final value of a configuration option defined by
+:command:`arm_config_option`.
+
+.. note::
+
+    Configuration options can only be overridden if their dependencies are met.
+    This ensures the configuration space is always in a valid state.
+
+Override Default Value
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: cmake
+
+    arm_config_option_override(NAME <name> DEFAULT <default>)
+
+Overrides the default value of the configuration option ``<name>`` with the
+value ``<default>``.
+
+For example:
+
+.. code:: cmake
+
+    arm_config_option_override(
+        NAME MYPROJECT_USE_FOO
+        DEFAULT TRUE)
+
+    arm_config_option(
+        NAME MYPROJECT_USE_FOO
+        HELP "Use foo.")
+
+In this situation, the configuration option ``USE_FOO`` is created with a
+default value of ``FALSE``, but will use the overridden default value of
+``TRUE``. This is most often useful in larger projects where certain default
+values make more sense under certain conditions.
+
+Forcibly Override Value
+=======================
+
+.. code:: cmake
+
+    arm_config_option_override(NAME <name> FORCE <force>)
+
+Forcibly overrides the value of the configuration option ``<name>`` with
+``<force>``.
+
+For example:
+
+.. code:: cmake
+
+    arm_config_option_override(
+        NAME MYPROJECT_USE_FOO
+        FORCE TRUE)
+
+    arm_config_option(
+        NAME MYPROJECT_USE_FOO
+        HELP "Use foo.")
+
+In this situation, ``USE_FOO`` will be forcibly set to ``TRUE``, and it will be
+hidden from the GUI. Users may also no longer configure this value themselves.
+Attempting to change the value of the configuration option will cause a
+configuration failure, and the previous value will be restored.
+#]=======================================================================]
+
+include_guard()
+
+function(arm_config_option_override)
+    set(_options "")
+    set(_single_args "NAME;DEFAULT;FORCE")
+    set(_multi_args "")
+
+    cmake_parse_arguments(arg "${_options}" "${_single_args}" "${_multi_args}"
+                          ${ARGN})
+
+    if(DEFINED arg_FORCE)
+        set("${arg_NAME}_FORCE" "${arg_FORCE}" CACHE INTERNAL
+            "Forced value for `${arg_NAME}`." FORCE)
+    elseif(DEFINED arg_DEFAULT)
+        set("${arg_NAME}_INIT" "${arg_DEFAULT}" CACHE INTERNAL
+            "Default value for `${arg_NAME}`." FORCE)
+    endif()
+endfunction()
diff --git a/cmake/Modules/ArmPreprocessSource.cmake b/cmake/Modules/ArmPreprocessSource.cmake
new file mode 100644
index 0000000..a3f511b
--- /dev/null
+++ b/cmake/Modules/ArmPreprocessSource.cmake
@@ -0,0 +1,168 @@
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+#
+
+#[=======================================================================[.rst:
+ArmPreprocessSource
+-------------------
+
+.. default-domain:: cmake
+
+.. command:: arm_preprocess_source
+
+Preprocess a file with the C preprocessor.
+
+.. code:: cmake
+
+    arm_preprocess_source(<target> <source>)
+
+Creates a target ``<target>`` which preprocesses an input file ``<source>``. The
+target created by this macro can then be used as a dependency for a higher-level
+target. The output file can be retrieved from the :prop_tgt:`LOCATION_<CONFIG>
+<prop_tgt:LOCATION_<CONFIG>>` target property.
+
+The following target properties are passed to the preprocessor:
+
+- :prop_tgt:`COMPILE_OPTIONS <prop_tgt:COMPILE_OPTIONS>`
+- :prop_tgt:`COMPILE_DEFINITIONS <prop_tgt:COMPILE_DEFINITIONS>`
+- :prop_tgt:`INCLUDE_DIRECTORIES <prop_tgt:INCLUDE_DIRECTORIES>`
+
+.. note::
+
+    The created target automatically inherits :variable:`CMAKE_C_FLAGS
+    <variable:CMAKE_<LANG>_FLAGS>` and :variable:`CMAKE_C_FLAGS_<CONFIG>
+    <variable:CMAKE_<LANG>_FLAGS_<CONFIG>>`.
+
+For example, if you wish to preprocess a file while providing the preprocessor
+definition ``-DFOO=BAR``, you would use:
+
+.. code:: cmake
+
+    arm_preprocess_source(foo "bar.ld.S")
+
+    set_target_properties(foo PROPERTIES
+        COMPILE_DEFINITIONS "FOO=BAR")
+
+    get_target_property(location foo LOCATION_${CMAKE_BUILD_TYPE})
+
+    message(STATUS "My preprocessed file is here: ${location}")
+
+For processing linker scripts specifically, see the
+:command:`arm_target_linker_script` command instead.
+#]=======================================================================]
+
+include_guard()
+
+macro(arm_preprocess_source target source)
+    #
+    # We start by trying to get the source file relative to the current source
+    # directory, which means that we can mirror where it goes in the binary
+    # directory. This just replicates what CMake does with source files it's
+    # aware of.
+    #
+
+    get_filename_component(preprocessed_source "${source}.i" ABSOLUTE)
+    file(RELATIVE_PATH preprocessed_source "${CMAKE_CURRENT_SOURCE_DIR}"
+        "${preprocessed_source}")
+
+    #
+    # If we're using a multi-config generator, we need to place the output file
+    # into the correct configuration directory.
+    #
+
+    get_property(multi_config GLOBAL
+        PROPERTY "GENERATOR_IS_MULTI_CONFIG")
+
+    if(multi_config)
+        string(PREPEND preprocessed_source "$<CONFIG>/")
+    endif()
+
+    #
+    # Make the source path absolute so that we don't need to care which
+    # working directory the preprocessor uses.
+    #
+
+    string(PREPEND preprocessed_source "${CMAKE_CURRENT_BINARY_DIR}/")
+
+    #
+    # Create a single target for all configurations. It's differentiated based
+    # on the generator expression in the dependency.
+    #
+
+    add_custom_target(${target}
+        DEPENDS "${preprocessed_source}")
+
+    #
+    # Now that we've got that out of the way, we need to generate the
+    # preprocessing command for each of the enabled configurations. Multi-config
+    # generators will use `CMAKE_CONFIGURATION_TYPES`, whereas single-config
+    # generators will use `CMAKE_BUILD_TYPE`. Only one is ever non-empty.
+    #
+
+    foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES CMAKE_BUILD_TYPE)
+        #
+        # CMake provides the `CMAKE_C_CREATE_PREPROCESSED_SOURCE` variable,
+        # which describes the command line required to preprocess a C source
+        # file. This variable is in a format similar to this:
+        #
+        # <CMAKE_C_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> >
+        # <PREPROCESSED_SOURCE>
+        #
+        # We do some processing on this variable to convert these
+        # bracket-surrounded names to variables we set. For example, `<DEFINES>`
+        # is replaced with `${DEFINES}`. We then need to do some string
+        # replacement magic to expand that string out to the value of the actual
+        # variable.
+        #
+        # The values for some of these, namely include directories, definitions
+        # and other compiler options, come from properties set on the target by
+        # the caller. These are typically taken from the target that this
+        # preprocessed source file belongs to.
+        #
+
+        set(command ${CMAKE_C_CREATE_PREPROCESSED_SOURCE})
+        string(REPLACE " " ";" command ${command})
+
+        get_filename_component(SOURCE "${source}" ABSOLUTE)
+        string(REPLACE "$<CONFIG>" "${config}" PREPROCESSED_SOURCE
+            "${preprocessed_source}")
+
+        separate_arguments(FLAGS UNIX_COMMAND
+            "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${config}} -P -x c")
+
+        if(CMAKE_C_COMPILER_TARGET)
+            if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+                list(APPEND FLAGS "-target" "${CMAKE_C_COMPILER_TARGET}")
+            endif()
+        endif()
+
+        unset(DEFINES)
+        unset(INCLUDES)
+
+        list(APPEND FLAGS "$<TARGET_PROPERTY:${target},COMPILE_OPTIONS>")
+        list(APPEND DEFINES "$<TARGET_PROPERTY:${target},COMPILE_DEFINITIONS>")
+        list(APPEND INCLUDES "$<TARGET_PROPERTY:${target},INCLUDE_DIRECTORIES>")
+
+        set(DEFINES "$<$<BOOL:${DEFINES}>:-D$<JOIN:${DEFINES},$<SEMICOLON>-D>>")
+        set(INCLUDES "$<$<BOOL:${INCLUDES}>:-I$<JOIN:${INCLUDES},$<SEMICOLON>-I>>")
+
+        string(REGEX REPLACE "<([[A-Z_]+)>" "\${\\1}" command "${command}")
+        string(REGEX MATCH "\\\${[^}]*}" match "${command}")
+
+        while(match)
+            string(REGEX REPLACE "\\\${(.*)}" "\\1" variable "${match}")
+            string(REPLACE "\${${variable}}" "${${variable}}" command "${command}")
+            string(REGEX MATCH "\\\${[^}]*}" match "${command}")
+        endwhile()
+
+        add_custom_command(
+            OUTPUT "${PREPROCESSED_SOURCE}"
+            MAIN_DEPENDENCY ${source}
+            COMMAND "${command}"
+            VERBATIM COMMAND_EXPAND_LISTS)
+
+        set_target_properties(${target} PROPERTIES
+            LOCATION_${config} "${PREPROCESSED_SOURCE}")
+    endforeach()
+endmacro()
diff --git a/cmake/Modules/ArmTargetLinkerScript.cmake b/cmake/Modules/ArmTargetLinkerScript.cmake
new file mode 100644
index 0000000..087fe8e
--- /dev/null
+++ b/cmake/Modules/ArmTargetLinkerScript.cmake
@@ -0,0 +1,89 @@
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+#
+
+#[=======================================================================[.rst:
+ArmTargetLinkerScript
+---------------------
+
+.. default-domain:: cmake
+
+.. command:: arm_target_linker_script
+
+Set the linker script for a target.
+
+.. code:: cmake
+
+    arm_target_linker_script(<target> <script>)
+
+Sets the linker script of the target ``<target>`` to the script ``<script>``,
+which is first preprocessed with the C preprocessor.
+
+Properties for the linker script target may be set on `<target>-lds`.
+
+Example usage:
+
+.. code:: cmake
+
+    add_executable(my-executable "main.c")
+
+    arm_target_linker_script(my-executable "linker.lds")
+
+    set_target_properties(my-executable-lds
+        PROPERTIES COMPILE_DEFINITIONS "__LINKER__")
+
+.. note::
+
+    When preprocessing, the linker script given to this macro automatically
+    inherits :variable:`CMAKE_C_FLAGS <variable:CMAKE_<LANG>_FLAGS>` and
+    :variable:`CMAKE_C_FLAGS_<CONFIG> <variable:CMAKE_<LANG>_FLAGS_<CONFIG>>`.
+
+    It also inherits the following properties from the target ``<target>``:
+
+    - :prop_tgt:`COMPILE_OPTIONS <prop_tgt:COMPILE_OPTIONS>`
+    - :prop_tgt:`COMPILE_DEFINITIONS <prop_tgt:COMPILE_DEFINITIONS>`
+    - :prop_tgt:`INCLUDE_DIRECTORIES <prop_tgt:INCLUDE_DIRECTORIES>`
+#]=======================================================================]
+
+include_guard()
+
+include(ArmPreprocessSource)
+
+macro(arm_target_linker_script target script)
+    set(subtarget "${target}-lds")
+
+    #
+    # Preprocess the linker script before doing anything else.
+    #
+
+    arm_preprocess_source(${subtarget} "${script}")
+
+    set_target_properties(${subtarget}
+        PROPERTIES
+            COMPILE_OPTIONS
+                "$<TARGET_PROPERTY:${target},COMPILE_OPTIONS>"
+            COMPILE_DEFINITIONS
+                "$<TARGET_PROPERTY:${target},COMPILE_DEFINITIONS>"
+            INCLUDE_DIRECTORIES
+                "$<TARGET_PROPERTY:${target},INCLUDE_DIRECTORIES>")
+
+    #
+    # Add the linker script to the dependencies of the target.
+    #
+
+    add_dependencies(${target} ${subtarget})
+
+    set(location "$<TARGET_PROPERTY:${subtarget},LOCATION_$<CONFIG>>")
+
+    set_target_properties(${target}
+        PROPERTIES INTERFACE_LINK_DEPENDS "${location}")
+
+    if(CMAKE_C_COMPILER_ID STREQUAL "ARMClang")
+        target_link_options(${target}
+            PUBLIC "LINKER:--scatter" "LINKER:${location}")
+    else()
+        target_link_options(${target}
+            PUBLIC "LINKER:-T" "LINKER:${location}")
+    endif()
+endmacro()
diff --git a/cmake/Modules/FindMbedTLS.cmake b/cmake/Modules/FindMbedTLS.cmake
new file mode 100644
index 0000000..89fb237
--- /dev/null
+++ b/cmake/Modules/FindMbedTLS.cmake
@@ -0,0 +1,60 @@
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+#
+
+#[=======================================================================[.rst:
+FindMbedTLS
+===========
+
+TODO: documentation.
+#]=======================================================================]
+
+include(FindPackageHandleStandardArgs)
+
+find_path(MbedTLS_INCLUDE_DIR
+    NAMES "mbedtls/build_info.h")
+
+if(MbedTLS_INCLUDE_DIR)
+    mark_as_advanced(MbedTLS_INCLUDE_DIR)
+
+    set(MbedTLS_FOUND TRUE)
+endif()
+
+find_library(MbedTLS_Crypto_LIBRARY "mbedcrypto" PATHS "library" "lib")
+find_library(MbedTLS_TLS_LIBRARY "mbedtls" PATHS "library" "lib")
+find_library(MbedTLS_X509_LIBRARY "mbedx509" PATHS "library" "lib")
+
+foreach(component IN ITEMS Crypto TLS X509)
+    if(MbedTLS_${component}_LIBRARY)
+        mark_as_advanced(MbedTLS_${component}_LIBRARY)
+
+        set(MbedTLS_${component}_FOUND TRUE)
+    endif()
+endforeach()
+
+find_package_handle_standard_args(MbedTLS HANDLE_COMPONENTS
+    REQUIRED_VARS MbedTLS_FOUND MbedTLS_INCLUDE_DIR)
+
+if(MbedTLS_FOUND)
+    add_library(MbedTLS INTERFACE)
+
+    target_include_directories(MbedTLS
+        INTERFACE "${MbedTLS_INCLUDE_DIR}"
+                  "${RMM_SOURCE_DIR}/configs/mbedtls")
+
+    target_compile_definitions(MbedTLS
+        INTERFACE "MBEDTLS_CONFIG_FILE=<mbedtls_config.h>")
+
+    foreach(component IN ITEMS Crypto TLS X509)
+        if(MbedTLS_${component}_LIBRARY)
+            add_library(MbedTLS::${component} UNKNOWN IMPORTED)
+
+            set_target_properties(MbedTLS::${component}
+                PROPERTIES IMPORTED_LOCATION "${MbedTLS_${component}_LIBRARY}")
+
+            target_link_libraries(MbedTLS::${component}
+                INTERFACE MbedTLS)
+        endif()
+    endforeach()
+endif()
diff --git a/cmake/Modules/FindPlantUML.cmake b/cmake/Modules/FindPlantUML.cmake
new file mode 100644
index 0000000..331c221c76
--- /dev/null
+++ b/cmake/Modules/FindPlantUML.cmake
@@ -0,0 +1,60 @@
+#-------------------------------------------------------------------------------
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+#-------------------------------------------------------------------------------
+
+#FindPlantuml
+#-----------
+#PlantUML is a diagram generation tool. It can generate various UML and non-UML
+#diagrams. See: http://plantuml.com/
+#
+#This module checks PlantUML availability and checks if the Java runtime is
+#available.
+#For Windows PlantUML is distributed as a jar archive and thus there is no
+#standard install location where it could be searched for.
+#Most Linux distributions come with a proper PlantUML package which installs
+#a shell script to easy starting PlantUML, but the location of the .jar file
+#is hidden.
+#Thus there is no standard location to search for the .jar file and this module
+#depends on user input.
+#
+#This module has the following parameters:
+#   PLANTUML_JAR_PATH   = variable specifying where the PlantUML java archive
+#                         (plantuml.jar) can be found. If it is not defined,
+#                         the environment variable with the same name is used.
+#                         If both is missing, that is an error.
+#
+#This module defines the following variables:
+#   PLANTUML_VERSION        = The version reported by "plantuml.jar -version"
+#   PLANTUML_FOUND          = Was the .jar file found and sucesfuly executed.
+#
+
+#include(Common/Utils)
+
+find_package(Java 1.8 COMPONENTS Runtime)
+if(Java_Runtime_FOUND)
+	#Check if the jar file is at the user defined location.
+	#Prefer the cmake variable to the environment setting.
+	if (NOT DEFINED PLANTUML_JAR_PATH)
+		if (DEFINED ENV{PLANTUML_JAR_PATH})
+			set(PLANTUML_JAR_PATH "$ENV{PLANTUML_JAR_PATH}" CACHE STRING "PLANTUML location." )
+		endif()
+	endif()
+
+	if (NOT DEFINED PLANTUML_JAR_PATH)
+		message(STATUS "PLANTUML_JAR_PATH variable is missing, PlantUML jar location is unknown.")
+	else()
+		#Get plantuml version
+		execute_process(COMMAND "${Java_JAVA_EXECUTABLE}" "-jar" "${PLANTUML_JAR_PATH}" "-version" OUTPUT_VARIABLE _PLANTUML_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
+		#Parse plantuml output
+		if(_PLANTUML_VERSION)
+			if(_PLANTUML_VERSION MATCHES ".*PlantUML version ([0-9.]+).*")
+				string(REGEX REPLACE ".*PlantUML version ([0-9.]+).*" "\\1" PLANTUML_VERSION "${_PLANTUML_VERSION}")
+			endif()
+		endif()
+	endif()
+endif()
+
+#Set "standard" find module return values
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PlantUML REQUIRED_VARS PLANTUML_JAR_PATH PLANTUML_VERSION VERSION_VAR PLANTUML_VERSION)
diff --git a/cmake/Modules/FindPythonModules.cmake b/cmake/Modules/FindPythonModules.cmake
new file mode 100644
index 0000000..625bfec
--- /dev/null
+++ b/cmake/Modules/FindPythonModules.cmake
@@ -0,0 +1,61 @@
+#-------------------------------------------------------------------------------
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+#-------------------------------------------------------------------------------
+
+#FindPythonModules
+#-----------
+#This module checks availability of Python modules.
+#
+#This module has the following parameters:
+#   PYTHON_EXECUTABLE - Location of python interpreter.
+#   COMPONENTS        - List of python modules to look for.
+#
+#This module defines the following variables:
+#   PY_XXX       - Cached string variable with the location of the module.
+#   PY_XXX_FOUND - Set if the module is available.
+#
+#   Where XXX is the upper case name of the module.
+#
+#Examples
+#   To look for m2r and report error if not found
+#       find_module(PythonModules COMPONENTS m2r)
+#       if (PY_M2R_FOUND)
+#           do something
+#       endif()
+#
+#   To look for m2r and do not report error if not found
+#       find_module(PythonModules OPTIONAL_COMPONENTS m2r)
+#       if (PY_M2R_FOUND)
+#           do something
+#       endif()
+
+if(NOT DEFINED PYTHON_EXECUTABLE)
+	message(FATAL_ERROR "FindPythonModules: mandatory parameter PYTHON_EXECUTABLE is missing.")
+endif()
+
+foreach(_mod ${PythonModules_FIND_COMPONENTS})
+	string(TOUPPER ${_mod} _mod_upper)
+	string(REPLACE "-" "_" _modname "${_mod}")
+	if (NOT PY_${_mod_upper})
+		#Execute python and try to include the module.
+		execute_process(
+			COMMAND ${PYTHON_EXECUTABLE} -c "import ${_modname}; print(${_modname}.__file__);"
+			RESULT_VARIABLE ${_mod}_status
+			OUTPUT_VARIABLE ${_mod}_path
+			ERROR_QUIET
+			OUTPUT_STRIP_TRAILING_WHITESPACE)
+		#If suceeded
+		if(NOT ${_mod}_status)
+			#Avoid trouble with directory separator on windows.
+			set("PY_${_mod_upper}" "${${_mod}_path}" CACHE STRING
+				"Location of Python module ${_mod}")
+		endif()
+	endif()
+	#Set "standard" find module return values
+	include(FindPackageHandleStandardArgs)
+	find_package_handle_standard_args(PY_${_mod_upper}
+		REQUIRED_VARS PY_${_mod_upper}
+		NAME_MISMATCHED
+		FAIL_MESSAGE "Can not find Python module ${_mod}")
+endforeach()
diff --git a/cmake/Modules/FindSphinx.cmake b/cmake/Modules/FindSphinx.cmake
new file mode 100644
index 0000000..7acab08
--- /dev/null
+++ b/cmake/Modules/FindSphinx.cmake
@@ -0,0 +1,90 @@
+#-------------------------------------------------------------------------------
+# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
+#-------------------------------------------------------------------------------
+
+#FindSphinx
+#-----------
+#Sphinx is a document generation tool written in Python.
+#See http://www.sphinx-doc.org/en/master/
+#
+#This module checks availability of the Sphinx document generator
+#(sphinx-build) and it's dependences (Python).
+#Sphinx is distributed as pip package or on Linux as a distribution specific
+#package (i.e. python-sphinx for Ubuntu). Independent of the distribution
+#method this module expects sphix-build to be either available on the PATH,
+#or to be located in a host OS specific standard location.
+#
+#This modules has the following parameters:
+#   SPHINX_PATH   = variable specifying where sphinx-build can be found.
+#                         If it is not defined the environment variable with
+#                         the same name is used. If that is also undefined,
+#                         then OS specific standard locations will be
+#                         searched.
+#
+# This modules defines the following variables:
+#   SPHINX_VERSION   = The version reported by "sphinx-build --version"
+#   SPHINX_FOUND     = True is sphinx-build was found and executed fine
+#
+
+Include(CMakeParseArguments)
+
+#Sphinx needs Python.
+find_package(PythonInterp 3)
+if (NOT PYTHONINTERP_FOUND)
+	message(STATUS "Can not find Python3.x interpreter. Pyhton3 must be installed and available on the PATH.")
+	message(STATUS "Sphinx documentation targets will not be created.")
+	return()
+endif()
+
+if (NOT DEFINED SPHINX_PATH)
+	if (DEFINED $ENV{SPHINX_PATH})
+	set(SPHINX_PATH $ENV{SPHINX_PATH})
+	endif()
+endif()
+
+
+if (DEFINED SPHINX_PATH)
+	#Find the Sphinx executable. Search only at SPHINX_PATH.
+	find_program(SPHINX_EXECUTABLE
+		NAMES sphinx-build
+		DOC "Sphinx Documentation Builder (sphinx-doc.org)"
+		PATH ${SPHINX_PATH}
+		NO_DEFAULT_PATH
+		NO_CMAKE_ENVIRONMENT_PATH
+		NO_CMAKE_PATH
+		NO_SYSTEM_ENVIRONMENT_PATH
+		NO_CMAKE_SYSTEM_PATH
+		NO_CMAKE_FIND_ROOT_PATH
+	)
+	if (SPHINX_EXECUTABLE-NOTFOUND)
+		message(STATUS "Failed to find sphinx-build at ${SPHINX_PATH}.")
+		message(STATUS "Sphinx documentation targets will not be created.")
+		return()
+	endif()
+else()
+	#Find the Sphinx executable. Search OS specific default locations.
+	find_program(SPHINX_EXECUTABLE
+	  NAMES sphinx-build
+	  DOC "Sphinx Documentation Builder (sphinx-doc.org)"
+	)
+
+	if (SPHINX_EXECUTABLE-NOTFOUND)
+		message(STATUS "Failed to find sphinx-build at OS specific default locations.")
+		message(STATUS "Sphinx documentation targets will not be created.")
+		return()
+	endif()
+endif()
+
+#Get Sphinx version
+execute_process(COMMAND "${SPHINX_EXECUTABLE}" "--version" OUTPUT_VARIABLE _SPHINX_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
+#Parse output
+if(_SPHINX_VERSION)
+	if(_SPHINX_VERSION MATCHES ".*sphinx-build[^0-9.]*([0-9.]+).*")
+		string(REGEX REPLACE ".*sphinx-build ([0-9.]+).*" "\\1" SPHINX_VERSION "${_SPHINX_VERSION}")
+	endif()
+endif()
+
+#Set "standard" find module return values
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Sphinx REQUIRED_VARS SPHINX_EXECUTABLE SPHINX_VERSION VERSION_VAR SPHINX_VERSION)