aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/Common/BuildSphinxDoc.cmake30
-rw-r--r--cmake/SphinxCopyDoc.cmake14
-rw-r--r--cmake/SphinxDesignDocStatus.cmake208
-rw-r--r--docs/index.rst.in (renamed from docs/index.rst)19
-rw-r--r--docs/processes/tfm_design_proposal_process.rst151
5 files changed, 409 insertions, 13 deletions
diff --git a/cmake/Common/BuildSphinxDoc.cmake b/cmake/Common/BuildSphinxDoc.cmake
index 68887ff217..997de3b9c7 100644
--- a/cmake/Common/BuildSphinxDoc.cmake
+++ b/cmake/Common/BuildSphinxDoc.cmake
@@ -78,6 +78,9 @@ if (NOT SPHINX_NODOC)
set(SPHINXCFG_TEMPLATE_FILE "${TFM_ROOT_DIR}/docs/conf.py.in")
set(SPHINXCFG_CONFIGURED_FILE "${SPHINXCFG_OUTPUT_PATH}/conf.py")
+ set(SPHINX_TEMPLATE_INDEX_FILE "${TFM_ROOT_DIR}/docs/index.rst.in")
+ set(SPHINX_CONFIGURED_INDEX_FILE "${SPHINX_TMP_DOC_DIR}/index.rst")
+ set(SPHINX_DESIGN_DOC_ROOT "${TFM_ROOT_DIR}/docs/design_documents")
#Version ID of TF-M.
#TODO: this shall not be hard-coded here. We need a process to define the
@@ -85,11 +88,34 @@ if (NOT SPHINX_NODOC)
set(SPHINXCFG_TFM_VERSION "1.0.0-Beta")
set(SPHINXCFG_TFM_VERSION_FULL "Version 1.0.0-Beta")
+ get_filename_component(_NDX_FILE_DIR ${SPHINX_CONFIGURED_INDEX_FILE} DIRECTORY )
+
+ #This command does not generates the specifyed output file and thus it will
+ #allways be run. Any other command or target depending on the "run-allways"
+ #output will be alwways executed too.
+ add_custom_command(OUTPUT run-allways
+ COMMAND "${CMAKE_COMMAND}" -E echo)
+
#Using add_custom_command allows CMake to generate proper clean commands
#for document generation.
add_custom_command(OUTPUT "${SPHINX_TMP_DOC_DIR}"
- COMMAND "${CMAKE_COMMAND}" -D TFM_ROOT_DIR=${TFM_ROOT_DIR} -D DST_DIR=${SPHINX_TMP_DOC_DIR} -P "${TFM_ROOT_DIR}/cmake/SphinxCopyDoc.cmake"
+ "${SPHINX_CONFIGURED_INDEX_FILE}"
+ #Create target directory for SPHINX_CONFIGURED_INDEX_FILE. Needed
+ #by the next command.
+ COMMAND "${CMAKE_COMMAND}" -E make_directory "${_NDX_FILE_DIR}"
+ #Fill out index.rst template
+ COMMAND "${CMAKE_COMMAND}" -D TFM_ROOT_DIR=${TFM_ROOT_DIR}
+ -D SPHINX_TEMPLATE_INDEX_FILE=${SPHINX_TEMPLATE_INDEX_FILE}
+ -D SPHINX_CONFIGURED_INDEX_FILE=${SPHINX_CONFIGURED_INDEX_FILE}
+ -D SPHINX_DESIGN_DOC_ROOT=${SPHINX_DESIGN_DOC_ROOT}
+ -P "${TFM_ROOT_DIR}/cmake/SphinxDesignDocStatus.cmake"
+ #Copy document files to temp direcotry
+ COMMAND "${CMAKE_COMMAND}" -D TFM_ROOT_DIR=${TFM_ROOT_DIR}
+ -D DST_DIR=${SPHINX_TMP_DOC_DIR}
+ -D BINARY_DIR=${CMAKE_BINARY_DIR}
+ -P "${TFM_ROOT_DIR}/cmake/SphinxCopyDoc.cmake"
WORKING_DIRECTORY "${TFM_ROOT_DIR}"
+ DEPENDS run-allways
VERBATIM
)
@@ -100,7 +126,7 @@ if (NOT SPHINX_NODOC)
add_custom_command(OUTPUT "${SPHINXCFG_OUTPUT_PATH}/html"
COMMAND "${SPHINX_EXECUTABLE}" -c "${SPHINXCFG_OUTPUT_PATH}" -b html "${SPHINX_TMP_DOC_DIR}" "${SPHINXCFG_OUTPUT_PATH}/html"
WORKING_DIRECTORY "${TFM_ROOT_DIR}"
- DEPENDS create_sphinx_input
+ DEPENDS create_sphinx_input run-allways
COMMENT "Running Sphinx to generate user guide (HTML)."
VERBATIM
)
diff --git a/cmake/SphinxCopyDoc.cmake b/cmake/SphinxCopyDoc.cmake
index 0dc1b71327..e95757c739 100644
--- a/cmake/SphinxCopyDoc.cmake
+++ b/cmake/SphinxCopyDoc.cmake
@@ -26,10 +26,10 @@
#
#Usage:
# cmake -DDST_DIR=<path to destination> -DTFM_ROOT_DIR=<path to tf-m root> \
-# -P SphinxCopyDoc.cmake
+# -DBINARY_DIR=${CMAKE_BINARY_DIR} -P SphinxCopyDoc.cmake
#Check input parameters
-foreach(_PARAM IN ITEMS TFM_ROOT_DIR DST_DIR)
+foreach(_PARAM IN ITEMS TFM_ROOT_DIR DST_DIR BINARY_DIR)
if (NOT DEFINED ${_PARAM})
message(FATAL_ERROR "Variable ${_PARAM} is undefined. Please add -D${_PARAM}=<...> when calling this script.")
endif()
@@ -47,14 +47,14 @@ file(GLOB_RECURSE _COPY_FILES
"${TFM_ROOT_DIR}/*.jpg"
"${TFM_ROOT_DIR}/dco.txt")
-#Subtract exluded files from copy files
-list(REMOVE_ITEM _COPY_FILES "docs/index.rst")
+#Remove intermediate and final document build outputs.
+foreach(_PATH IN ITEMS BINARY_DIR DST_DIR)
+ file(RELATIVE_PATH _REL_DIR ${TFM_ROOT_DIR} ${${_PATH}})
+ list(FILTER _COPY_FILES EXCLUDE REGEX "${_REL_DIR}/.*")
+endforeach()
#Copy files with directory tree.
foreach(_FILE ${_COPY_FILES})
get_filename_component(_DIR ${_FILE} DIRECTORY)
file(COPY ${_FILE} DESTINATION "${DST_DIR}/${_DIR}")
endforeach()
-
-#Copy index.rst to the top level
-file(COPY "${TFM_ROOT_DIR}/docs/index.rst" DESTINATION "${DST_DIR}")
diff --git a/cmake/SphinxDesignDocStatus.cmake b/cmake/SphinxDesignDocStatus.cmake
new file mode 100644
index 0000000000..e76c448a6c
--- /dev/null
+++ b/cmake/SphinxDesignDocStatus.cmake
@@ -0,0 +1,208 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2019, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#A script to fill out the "toctree" file lists in index.rst.in to put design
+#documents into the correct section based on their state.
+#
+#First rst files are parsed under a defined directory, to identify document
+#status based on value of the ":Status:" field. Each state will have a list
+#being generated to which matching documents are added. These lists are used
+#then to fill template values using configure_file()
+#
+#Functions are used whenever possible to avoid global variable name space
+#pollution.
+#
+
+Include(CMakeParseArguments)
+
+#This function will search for .rst files in a given directory, read them and
+#check if the “:Status:” field is defined in them. Then will add each file to a
+#list with a name matching the status value.
+#See the definition of _STATE_VALUES below for a list of valid state values.
+#Files with missing or invalid state value will be placed on the "unknown" list.
+#State value comparison is case insensitive.
+#
+#The output lists will have the prefix specified in the PREFIX parameter.
+#
+#Inputs:
+# DIR Directory to scan for rst files.
+# PREFIX The prefix of output list variables.
+#
+#Outputs:
+# <prefix>_<state> - list; will hold all files with a valid state value.
+# <prefix>_unknown - list; all files with missing or invalid state
+# value.
+#Examples
+# sphinx_categorize_rst(DIR ${TFM_ROOT_DIR}/docs/design_documents
+# PREFIX "DESIGN_DOCS")
+#
+function(sphinx_categorize_rst)
+ #Valid state values. "unknown" is used as a quard to detect invalid status
+ #values.
+ set(_STATE_VALUES "draft" "rejected" "accepted" "detailed" "unknown")
+
+ #No option (on/off) arguments
+ set( _OPTIONS_ARGS )
+ #Single option arguments (e.g. PROJ_NAME "bubu_project")
+ set( _ONE_VALUE_ARGS DIR PREFIX)
+ #List arguments (e.g. LANGUAGES C ASM CXX)
+ set( _MULTI_VALUE_ARGS )
+
+ cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}"
+ "${_MULTI_VALUE_ARGS}" ${ARGN} )
+
+ #Check parameters
+ foreach(_PARAM IN LISTS _ONE_VALUE_ARGS)
+ if (NOT DEFINED _MY_PARAMS_${_PARAM})
+ message(FATAL_ERROR "Parameter ${_PARAM} is missing!")
+ endif()
+ endforeach()
+
+ #Search for .rst files
+ file(GLOB_RECURSE _RST_FILES
+ LIST_DIRECTORIES False
+ ${_MY_PARAMS_DIR}/**.rst)
+
+ #Loop over .rst files
+ foreach(_FILE IN LISTS _RST_FILES)
+ #Read the file and return the first status line.
+ file(STRINGS ${_FILE} _CONTENT REGEX ":Status:" LIMIT_COUNT 1)
+
+ #Nothing read -> the field is missing
+ if (_CONTENT STREQUAL "")
+ list(APPEND _STATUS_UNKNOWN ${_FILE})
+ else()
+ #convert to upper case for case insensitive matching.
+ string(TOUPPER ${_CONTENT} _CONTENT)
+
+ #loop over status values
+ foreach(_STATUS IN LISTS _STATE_VALUES)
+ #convert to upper case for case insensitive matching.
+ string(TOUPPER ${_STATUS} _STATUS)
+ #does status match the value from the file?
+ if (_CONTENT MATCHES ":STATUS:[ ]*${_STATUS}")
+ #add it to the list
+ list(APPEND _STATUS_${_STATUS} ${_FILE})
+ #and exit the loop
+ break()
+ endif()
+ #"unknown" status is used as a quard and is an invalid value.
+ #If we reach it the file has invalid status value.
+ if (_STATUS STREQUAL "UNKNOWN")
+ #add the file to the unknown list
+ list(APPEND _STATUS_${_STATUS} ${_FILE})
+ endif()
+ endforeach()
+ endif()
+ endforeach()
+
+ #return the lists to the caller
+ foreach(_STATUS IN LISTS _STATE_VALUES)
+ string(TOUPPER ${_STATUS} _STATUS)
+
+ if (DEFINED _STATUS_${_STATUS})
+ set(${_MY_PARAMS_PREFIX}_${_STATUS} ${_STATUS_${_STATUS}}
+ PARENT_SCOPE)
+ endif()
+ endforeach()
+endfunction()
+
+#Configure (fill in) the Sphinx index.rst.in template file.
+#Call sphinx_categorize_rst() to get the .rst files sorted to lists, and then
+#create the list of files for each design document section (convert the CMake
+#lists to properly formatted text).
+#Finally call configure_file() to fill in the values.
+#
+#Inputs:
+# SRC Full path to template index file
+# DST Full patch to configured output file.
+#....DOC_DIR Path to design documents directory.
+# DOC_ROOT Path to root directory of documentation
+#
+#Outputs:
+# Configured <DST> file.
+#
+#Examples
+# sphinx_categorize_rst(DIR ${TFM_ROOT_DIR}/docs/design_documents
+# PREFIX "DESIGN_DOCS")
+#
+function(sphinx_configure_index)
+ set(_STATE_VALUES "draft" "rejected" "accepted" "detailed" "unknown")
+
+ #No option (on/off) arguments
+ set( _OPTIONS_ARGS )
+ #Single option arguments (e.g. PROJ_NAME "bubu_project")
+ set( _ONE_VALUE_ARGS SRC DST DOC_ROOT DOC_DIR)
+ #List arguments (e.g. LANGUAGES C ASM CXX)
+ set( _MULTI_VALUE_ARGS )
+
+ cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}"
+ "${_MULTI_VALUE_ARGS}" ${ARGN} )
+
+ #Check parameters
+ foreach(_PARAM IN LISTS _ONE_VALUE_ARGS)
+ if (NOT DEFINED _MY_PARAMS_${_PARAM})
+ message(FATAL_ERROR "Parameter ${_PARAM} is missing!")
+ endif()
+ endforeach()
+
+ #Assign design documents to lists based on their status
+ sphinx_categorize_rst(DIR ${_MY_PARAMS_DOC_DIR} PREFIX "_DD")
+
+ #Look for invalid documents
+ if (DEFINED _DD_UNKNOWN)
+ string(REPLACE ";" "\n \t" _DD_UNKNOWN "${_DD_UNKNOWN}")
+ message(FATAL_ERROR " The following documents have no or invalid status:\n \t${_DD_UNKNOWN}")
+ endif()
+
+ #The document root must be an absolute path
+ get_filename_component(_MY_PARAMS_DOC_ROOT "${_MY_PARAMS_DOC_ROOT}"
+ ABSOLUTE)
+
+ #Loop over status lists
+ foreach(_STATUS IN ITEMS "DRAFT" "DETAILED" "ACCEPTED" "REJECTED")
+ #Create an empty file list for this status
+ set(${_STATUS}_DD_LIST "")
+ #If the source list is empty go to next iteration
+ if (NOT DEFINED _DD_${_STATUS})
+ continue()
+ endif()
+
+ #Loop over files on the list of this status
+ foreach(_FILE IN LISTS _DD_${_STATUS})
+ #Get the path of the file relative to the document root
+ file(RELATIVE_PATH _REL_FILE ${_MY_PARAMS_DOC_ROOT} ${_FILE})
+ #Detailed and Draft files go to the same section
+ if (_STATUS STREQUAL "DETAILED")
+ set(_STATUS "DRAFT")
+ endif()
+
+ #Append the file to the output string
+ string(APPEND ${_STATUS}_DD_LIST "\n ${_REL_FILE}")
+ endforeach()
+ endforeach()
+
+ #Call configure file to fill out the template.
+ configure_file(${_MY_PARAMS_SRC} ${_MY_PARAMS_DST} @ONLY)
+endfunction()
+
+#If being run in script mode (cmake -P) and not included.
+if (DEFINED CMAKE_SCRIPT_MODE_FILE
+ AND (CMAKE_CURRENT_LIST_FILE STREQUAL CMAKE_SCRIPT_MODE_FILE))
+ #Check input variables.
+ foreach(_PARAM IN ITEMS SPHINX_TEMPLATE_INDEX_FILE SPHINX_CONFIGURED_INDEX_FILE
+ SPHINX_DESIGN_DOC_ROOT TFM_ROOT_DIR)
+ if (NOT DEFINED ${_PARAM})
+ message(FATAL_ERROR "Parameter ${_PARAM} is not set!")
+ endif()
+ endforeach()
+
+ sphinx_configure_index(SRC ${SPHINX_TEMPLATE_INDEX_FILE}
+ DST ${SPHINX_CONFIGURED_INDEX_FILE}
+ DOC_DIR ${SPHINX_DESIGN_DOC_ROOT}
+ DOC_ROOT ${TFM_ROOT_DIR})
+endif()
diff --git a/docs/index.rst b/docs/index.rst.in
index f9c1282979..e2151a468a 100644
--- a/docs/index.rst
+++ b/docs/index.rst.in
@@ -3,8 +3,11 @@
..
The build-system will copy all documents into a temporary directory tree
before the documentation is built.
- This fill will be copied to the top level and thus please use relative paths
+ This file will be copied to the top level and thus please use relative paths
as if this file would be in <TFM_ROOT_DIR>.
+
+ The values between @ characters will be filled in by CMake.
+
Welcome to TF-M's documentation!
================================
@@ -29,6 +32,14 @@ Welcome to TF-M's documentation!
.. toctree::
:maxdepth: 2
+ :caption: Processes
+ :glob:
+ :hidden:
+
+ docs/processes/**
+
+.. toctree::
+ :maxdepth: 2
:caption: Secure services
:glob:
:hidden:
@@ -57,7 +68,7 @@ Welcome to TF-M's documentation!
:glob:
:hidden:
- docs/design_documents/*
+ @ACCEPTED_DD_LIST@
.. toctree::
:caption: Draft design documents
@@ -65,7 +76,7 @@ Welcome to TF-M's documentation!
:glob:
:hidden:
- docs/design_documents/drafts/*
+ @DRAFT_DD_LIST@
.. toctree::
:caption: Rejected design documents
@@ -73,7 +84,7 @@ Welcome to TF-M's documentation!
:glob:
:hidden:
- docs/design_documents/rejected/*
+ @REJECTED_DD_LIST@
.. include:: readme.rst
diff --git a/docs/processes/tfm_design_proposal_process.rst b/docs/processes/tfm_design_proposal_process.rst
new file mode 100644
index 0000000000..478220e0b4
--- /dev/null
+++ b/docs/processes/tfm_design_proposal_process.rst
@@ -0,0 +1,151 @@
+Design proposal process
+=======================
+
+:Author: Gyorgy Szing
+:Organisation: Arm Limited
+:Contact: Gyorgy Szing <gyorgy.szing@arm.com>
+
+Purpose and Content
+-------------------
+This document describes the steps of changing Trusted Firmware design. It
+specifies:
+
+ - the documentation format to be used
+ - the information which shall be captured
+ - the steps of the process
+ - and the location where the information shall be captured during the process.
+
+General
+-------
+The Trusted Firmware project uses the
+`reStructuredText <http://docutils.sourceforge.net/rst.html>`_ format with
+`Sphinx <http://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html>`_
+extensions for documentation. Design documents shall be captured in this format.
+
+Design documents are kept under version control at the project's
+`Gerrit server <https://review.trustedfirmware.org>`_. All decisions made and
+important information gathered during the design discussion, which is not part
+of the design document shall be captured as Gerrit comments or notes for
+archiving purposes. To meet this requirement this process encourages the use of
+the Gerrit web UI for communication.
+
+
+Status of a document
+---------------------
+The status of the document is captured in a *reST filed* called *Status*.
+Bibliographic fields like the *Status* shall be kept near to the top of the
+document after the document title.
+
+Example document fragment::
+
+ TF-M Crypto Service design
+ --------------------------
+
+ :Author: Antonio de Angelis
+ :Organization: Arm Limited
+ :Contact: Antonio de Angelis <antonio.deangelis@arm.com>
+ :Status: Draft
+
+Design documents are kept in three different sections of the documentation
+reflecting the status of the document. The status of the document determines
+the section it is in. Open (*Draft* and *Detailed* status) and accepted design
+documents shall be put to the ``docs/design_documents``
+directory and rejected documents to the ``docs/design_documents/rejected``
+directory.
+
+Preparation
+-------------
+In order to work on TF-M documentation the TF-M git repository has to be
+available locally. Setting up the documentation tools will allow pre-viewing the
+documentation file in preparation.
+For information on what tools are needed please refer to
+:doc:`sw requirements </docs/user_guides/tfm_sw_requirement>`. To see how to get
+a local copy of the TF-M repository please see
+:doc:`build instructions </docs/user_guides/tfm_build_instruction>`
+
+Process steps
+-------------
+
+- Write the design proposal in the format that is described in this document
+ with the status set to *Draft*. Put it to the ``docs/design_documents``
+ directory and create a pull request.
+- Start an e-mail thread on the
+ `TF-M mailing list <mailto:tf-m@lists.trustedfirmware.org>`_ for discussing
+ the proposal.
+- Build initial consensus within the community about the proposed design
+ change, rework it according to the feedbacks and identify members who would
+ like to participate in the detailed review.
+- When the "short list" of members who are willing to participate in the
+ detailed review is established, set the *Status* field to *Detailed* and
+ push the change to Gerrit.
+- Add the members of the "short list" to the Gerrit review as reviewers.
+- The detailed discussion then takes place in the Gerrit review and gets
+ recorded there.
+ Additional changes are submitted as new commits to the review.
+- When the proposal is accepted, the status field is set to *Accepted*, the
+ change updated and merged.
+- If at any point the proposal is rejected its status field is set to
+ *Rejected*, and the document is moved to the *rejected design documents*
+ section.
+
+.. uml::
+
+ @startuml
+ !define DRAFT_DIR **docs/design_documents/**
+ !define REJECTED_DIR **docs/design_documents/rejected/**
+ !define GERRIT_URL https://review.trustedfirmware.org
+ !define GERRIT_LINK [[GERRIT_URL trustedfirmware.org]]
+ !define MAINTAINER_RST_URL https://git.trustedfirmware.org/trusted-firmware-m.git/tree/maintainers.rst
+ !define TFM_MAILING_LIST mailto:tf-m@lists.trustedfirmware.org
+ !define NO_DECISION **no**
+ !define YES_DECISION **yes**
+ !define STATUS_DRAFT **Draft**
+ !define STATUS_DETAILED **Detailed**
+ !define STATUS_REJECTED **Rejected**
+ !define STATUS_ACCEPTED **Accepted**
+
+ title Design Proposal Process
+
+ start
+ :Create first draft.in [[http://docutils.sourceforge.net/rst.html ReST format]];
+ :Set it's status to STATUS_DRAFT.;
+
+ :Add your document under DRAFT_DIR.;
+ :Create pull-request at GERRIT_LINK.;
+ partition "Initial review." {
+ :Start an e-mail thread at [[TFM_MAILING_LIST tf-m mailing list]].;
+ repeat
+ :Build initial consensus within the
+ community about the proposed design change.;
+ :Gather developers interested in detailed review.;
+ repeat while (Ready for detailed review?)
+ }
+
+ partition "Detailed review." {
+ :Set document status to STATUS_DETAILED.;
+ :Add reviewers to pull request.;
+
+ repeat
+ :Discuss design in Gerrit comments/notes.;
+ :Log the result of discussions over
+ other communication channels
+ as Gerrit comments/notes.;
+ :Push new document version if needed.;
+ repeat while (Consensus reached?)
+ }
+
+ if (Design is rejected?) then (YES_DECISION)
+ :Set document status to STATUS_REJECTED.;
+ :Move the document to REJECTED_DIR.;
+ else (NO_DECISION)
+ :Sets the document status to STATUS_ACCEPTED.;
+ endif
+
+ ://Submit// the pull-request.;
+ stop
+
+ @enduml
+
+--------------
+
+*Copyright (c) 2019, Arm Limited. All rights reserved.*