1#------------------------------------------------------------------------------- 2# Copyright (c) 2020-2023, Arm Limited. All rights reserved. 3# 4# SPDX-License-Identifier: BSD-3-Clause 5# 6#------------------------------------------------------------------------------- 7 8cmake_minimum_required(VERSION 3.15) 9find_package(Python3) 10 11############################### Manifest lists declaration ##################### 12list(APPEND MANIFEST_LISTS ${TFM_MANIFEST_LIST}) 13 14if (TFM_EXTRA_MANIFEST_LIST_FILES) 15 list(APPEND MANIFEST_LISTS ${TFM_EXTRA_MANIFEST_LIST_FILES}) 16endif() 17 18if (TFM_EXTRAS_REPO_EXTRA_MANIFEST_LIST) 19 set(TMP_MANIFEST_LISTS ${TFM_EXTRAS_REPO_EXTRA_MANIFEST_LIST}) 20 list(TRANSFORM TMP_MANIFEST_LISTS PREPEND ${TFM_EXTRAS_REPO_PATH}/) 21 list(APPEND MANIFEST_LISTS ${TMP_MANIFEST_LISTS}) 22endif() 23 24# Remove any duplicate entries to prevent same path appended twice in case of mulitiple runs 25list(REMOVE_DUPLICATES MANIFEST_LISTS) 26list(REMOVE_DUPLICATES TFM_EXTRA_GENERATED_FILE_LIST_PATH) 27 28############################### File list declaration ########################## 29set(GENERATED_FILE_LISTS ${CMAKE_CURRENT_SOURCE_DIR}/tfm_generated_file_list.yaml) 30set(GENERATED_FILE_LISTS ${GENERATED_FILE_LISTS} ${TFM_EXTRA_GENERATED_FILE_LIST_PATH}) 31 32############################### Functions declaration ########################## 33# Parses the given YAML "files" to find out all the items of the given "field" 34# and put them to the "output_variable" as a list. 35function(parse_field_from_yaml files field output_variable) 36 set(local_variable "") 37 foreach(yaml_file ${files}) 38 # Load the lines that refer to the key we selected 39 file(STRINGS ${yaml_file} temp_variable REGEX " *\"${field}\":") 40 # Take only the value of the key 41 list(TRANSFORM temp_variable REPLACE " *\"${field}\": *" ";") 42 # Remove all commas 43 list(TRANSFORM temp_variable REPLACE "," "") 44 # Remove all quote marks 45 list(TRANSFORM temp_variable REPLACE "\"" "") 46 list(APPEND local_variable ${temp_variable}) 47 endforeach() 48 set(${output_variable} ${local_variable} PARENT_SCOPE) 49endfunction() 50 51############################### Dependency generation ########################## 52# Get all the manifest files from manifest lists 53foreach(MANIFEST_LIST ${MANIFEST_LISTS}) 54 if (NOT EXISTS ${MANIFEST_LIST}) 55 message(FATAL_ERROR "Manifest list ${MANIFEST_LIST} doesn't exist") 56 endif() 57 58 59 # Get the path of the manifest list 60 get_filename_component(MANIFEST_LIST_PATH ${MANIFEST_LIST} DIRECTORY) 61 62 # Get all the "manifest" 63 parse_field_from_yaml(${MANIFEST_LIST} manifest MANIFESTS) 64 65 foreach(MANIFEST ${MANIFESTS}) 66 # Convert to absolute paths 67 if (NOT IS_ABSOLUTE ${MANIFEST}) 68 # First try relative to the manifest 69 if (EXISTS "${MANIFEST_LIST_PATH}/${MANIFEST}") 70 get_filename_component(MANIFEST "${MANIFEST_LIST_PATH}/${MANIFEST}" ABSOLUTE) 71 # Then try relative to the root TF-M source directory 72 elseif (EXISTS "${CMAKE_SOURCE_DIR}/${MANIFEST}") 73 get_filename_component(MANIFEST "${CMAKE_SOURCE_DIR}/${MANIFEST}" ABSOLUTE) 74 endif() 75 endif() 76 list(APPEND MANIFEST_FILES ${MANIFEST}) 77 endforeach() 78endforeach() 79 80parse_field_from_yaml("${GENERATED_FILE_LISTS}" template TEMPLATE_FILES) 81# Replace relative paths with absolute paths 82# Paths used in GENERATED_FILE_LISTS are all relative to TF-M root (${CMAKE_SOURCE_DIR}) 83list(TRANSFORM TEMPLATE_FILES REPLACE "^([^/\\][^:].*)" "${CMAKE_SOURCE_DIR}/\\1") 84# Append the fixed templates that are not in the GENERATED_FILE_LISTS 85list(APPEND TEMPLATE_FILES 86 ${CMAKE_CURRENT_SOURCE_DIR}/templates/manifestfilename.template 87 ${CMAKE_CURRENT_SOURCE_DIR}/templates/partition_intermedia.template 88 ${CMAKE_CURRENT_SOURCE_DIR}/templates/partition_load_info.template 89 ${CMAKE_CURRENT_SOURCE_DIR}/config_impl.cmake.template 90) 91 92############################### Generate Manifest config header ################ 93 94# The function appends the given `config` to the `out_var` variable. 95# Supported `type` are [BOOL, STRING]. 96# The format of contents appended is 97# #cmakedefine01 config for BOOL types 98# #cmakedefine config @config@ for STRING types 99function(append_manifest_config out_var config type) 100 # Operate on a local var and write back to the out_var later 101 set(local_var ${${out_var}}) 102 103 # Avoid duplications of configs 104 string(FIND "${local_var}" ${config} config_exists) 105 if(${config_exists} EQUAL -1) # Not found 106 if (${type} STREQUAL "BOOL") 107 string(APPEND local_var "#cmakedefine01 ${config}\r\n") 108 elseif(${type} STREQUAL "STRING") 109 string(APPEND local_var "#cmakedefine ${config} @${config}@\r\n") 110 else() 111 message(FATAL_ERROR "Unsupported config type: ${type}") 112 endif() 113 endif() 114 115 set(${out_var} ${local_var} PARENT_SCOPE) 116endfunction() 117 118# The following build configurations are required to pass to manifest tool via the config header 119# - The isolation level 120# - The SPM backend 121# - "conditional" attributes for every Secure Partition in manifest lists 122append_manifest_config(MANIFEST_CONFIG_H_CONTENT TFM_ISOLATION_LEVEL STRING) 123append_manifest_config(MANIFEST_CONFIG_H_CONTENT CONFIG_TFM_SPM_BACKEND STRING) 124 125parse_field_from_yaml("${MANIFEST_LISTS}" conditional CONDITIONS) 126foreach(CON ${CONDITIONS}) 127 append_manifest_config(MANIFEST_CONFIG_H_CONTENT ${CON} BOOL) 128endforeach() 129 130# Generate the config header 131file(WRITE 132 ${CMAKE_CURRENT_BINARY_DIR}/manifest_config.h.in 133 ${MANIFEST_CONFIG_H_CONTENT}) 134 135configure_file(${CMAKE_CURRENT_BINARY_DIR}/manifest_config.h.in 136 ${CMAKE_CURRENT_BINARY_DIR}/manifest_config.h) 137 138############################### Command declaration ############################ 139 140# Workaround for heap support 141if ("${TEST_PSA_API}" STREQUAL "IPC") 142 execute_process( 143 WORKING_DIRECTORY ${PSA_ARCH_TESTS_PATH}/api-tests 144 COMMAND ${Python3_EXECUTABLE} tools/scripts/manifest_update.py 145 ) 146endif() 147 148if (CONFIG_TFM_PARSE_MANIFEST_QUIET) 149 set(PARSE_MANIFEST_QUIET_FLAG "-q") 150else() 151 set(PARSE_MANIFEST_QUIET_FLAG "") 152endif() 153 154set(MANIFEST_COMMAND 155 ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tfm_parse_manifest_list.py 156 -m ${MANIFEST_LISTS} 157 -f ${GENERATED_FILE_LISTS} 158 -c ${CMAKE_CURRENT_BINARY_DIR}/manifest_config.h 159 -o ${CMAKE_BINARY_DIR}/generated 160 ${PARSE_MANIFEST_QUIET_FLAG}) 161 162add_custom_command( 163 OUTPUT ${CMAKE_BINARY_DIR}/generated 164 COMMAND ${MANIFEST_COMMAND} 165 DEPENDS ${MANIFEST_LISTS} ${GENERATED_FILE_LISTS} 166 ${MANIFEST_FILES} ${TEMPLATE_FILES} 167) 168 169add_custom_target( 170 manifest_tool 171 DEPENDS ${CMAKE_BINARY_DIR}/generated 172) 173 174# The files need to be generated before cmake will allow them to be used as 175# sources. Due to issue with custom_command scoping the easiest way to do this 176# is to run the script at cmake-time. 177execute_process( 178 COMMAND ${MANIFEST_COMMAND} 179 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 180 RESULT_VARIABLE RET 181) 182 183if(RET EQUAL 0) 184 include(${CMAKE_BINARY_DIR}/generated/tools/config_impl.cmake) 185else() 186 message(FATAL_ERROR "Manifest tool failed to generate files!") 187endif() 188