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()