cmake: enhance UUID handling
Before this change SP_UUID_LE was needed as an input parameter for
export_ep(). SP_UUID_LE is used in manifest files and was set with
different methods in opteesp and sp deployments. The former used cmake
code to generate it from the SP_UUID while the latter used hand defined
values.
This change makes the two deployment types work the same way. For
this the following is done:
- UUID manipulation routines are moved to a dedicated cmake file
- export_sp is changed to generate the LE UUID format internally using
the new UUID services mentioned above
- TargetCompileDefinitions.cmake is changed to use the new UUID
services, and to stop setting the SP_UUID_LE variable.
Change-Id: I18f4b97bb560e1ebbce3acb8aed8c3912ab05a3f
Signed-off-by: Gyorgy Szing <Gyorgy.Szing@arm.com>
diff --git a/tools/cmake/common/ExportSp.cmake b/tools/cmake/common/ExportSp.cmake
index bad02b2..1c6d9db 100644
--- a/tools/cmake/common/ExportSp.cmake
+++ b/tools/cmake/common/ExportSp.cmake
@@ -5,6 +5,8 @@
#
#-------------------------------------------------------------------------------
+include(${CMAKE_CURRENT_LIST_DIR}/Uuid.cmake)
+
#[===[.rst:
.. cmake:command:: export_sp
@@ -12,7 +14,6 @@
export_sp(
SP_UUID_CANON <uuid_str_canon>
- SP_UUID_LE <uuid_le_bytes>
SP_NAME <name> MK_IN <.mk path>
DTS_IN <DTS path>
DTS_MEM_REGIONS <Memory region manifest path>
@@ -28,9 +29,6 @@
The UUID of the SP binary a canonical string. When not set use the
SP_UUID_CANON as the SP_BIN_UUID_CANON.
- ``SP_UUID_LE``
- The UUID of the SP as four 32 bit little-endian unsigned integers.
-
``SP_NAME``
The name of the SP.
@@ -61,9 +59,6 @@
# We use the same UUID for the binary and FF-A if the UUID of the SP binary is not set
set(EXPORT_SP_BIN_UUID_CANON ${EXPORT_SP_UUID_CANON})
endif()
- if(NOT DEFINED EXPORT_SP_UUID_LE)
- message(FATAL_ERROR "export_sp: mandatory parameter SP_UUID_LE not defined!")
- endif()
if(NOT DEFINED EXPORT_SP_NAME)
message(FATAL_ERROR "export_sp: mandatory parameter SP_NAME not defined!")
endif()
@@ -77,7 +72,11 @@
endif()
# In the SP manifest DT the UUID format is four uint32 numbers (little-endian)
- set(EXPORT_SP_UUID_DT "${EXPORT_SP_UUID_LE}")
+ # Create a litte endian 4 digit octests representation.
+ uuid_canon_to_le_words(UUID ${EXPORT_SP_UUID_CANON} RES _le_words)
+ list(JOIN _le_words " 0x" _uuid_le)
+ set(SP_UUID_LE " 0x${_uuid_le}" PARENT_SCOPE)
+ set(EXPORT_SP_UUID_DT " 0x${_uuid_le}")
# As the .dtsi is meant to be included in .dts file, it shouldn't contain a separate
# /dts-v1/ tag and its node should be unique, i.e. the SP name.
diff --git a/tools/cmake/common/TargetCompileDefinitions.cmake b/tools/cmake/common/TargetCompileDefinitions.cmake
index f401a40..069c382 100644
--- a/tools/cmake/common/TargetCompileDefinitions.cmake
+++ b/tools/cmake/common/TargetCompileDefinitions.cmake
@@ -4,57 +4,8 @@
# SPDX-License-Identifier: BSD-3-Clause
#
#-------------------------------------------------------------------------------
-macro(generate_uuid_formats uuid)
- #Create a list of byte
- string(REGEX MATCHALL "([A-Za-z0-9][A-Za-z0-9])" SEPARATED_HEX "${uuid}")
- list(JOIN SEPARATED_HEX ", 0x" UUID_BYTES )
- #Generate the uuid_byte string
- #{ 0x01, 0x10, 0x9c, 0xf8, 0xe5, 0xca, 0x44, 0x6f,
- # 0x9b, 0x55, 0xf3, 0xcd, 0xc6, 0x51, 0x10, 0xc8, }
- string(PREPEND UUID_BYTES "{0x")
- string(APPEND UUID_BYTES "}")
-
- #Split the list of bytes in to the struct fields
- list(SUBLIST SEPARATED_HEX 0 4 uuid_timeLow)
- list(SUBLIST SEPARATED_HEX 4 2 uuid_timeMid)
- list(SUBLIST SEPARATED_HEX 6 2 uuid_timeHiAndVersion)
- list(SUBLIST SEPARATED_HEX 8 8 uuid_clockSeqAndNode)
-
- #Combine the bytes in the fields
- list(JOIN uuid_timeLow "" uuid_timeLow )
- string(PREPEND uuid_timeLow "0x")
-
- list(JOIN uuid_timeMid "" uuid_timeMid )
- string(PREPEND uuid_timeMid " 0x")
-
- list(JOIN uuid_timeHiAndVersion "" uuid_timeHiAndVersion )
- string(PREPEND uuid_timeHiAndVersion " 0x")
-
- list(JOIN uuid_clockSeqAndNode ", 0x" uuid_clockSeqAndNode )
- string(PREPEND uuid_clockSeqAndNode " 0x")
-
- #Combine the different fields into one uuid_struct string
- #{ 0x01109cf8, 0xe5ca, 0x446f, \
- #{ 0x9b, 0x55, 0xf3, 0xcd, 0xc6, 0x51, 0x10, 0xc8 } }
-
- string(CONCAT UUID_STRUCT "{" ${uuid_timeLow} "," ${uuid_timeMid}
- "," ${uuid_timeHiAndVersion} ", {" ${uuid_clockSeqAndNode} "}}")
-
- # Swith endianess
- list(SUBLIST SEPARATED_HEX 0 4 hex1)
- list(SUBLIST SEPARATED_HEX 4 4 hex2)
- list(SUBLIST SEPARATED_HEX 8 4 hex3)
- list(SUBLIST SEPARATED_HEX 12 4 hex4)
-
- list(REVERSE hex1)
- list(REVERSE hex2)
- list(REVERSE hex3)
- list(REVERSE hex4)
- string(CONCAT UUID_LE " 0x" ${hex1} " 0x" ${hex2} " 0x" ${hex3}
- " 0x" ${hex4})
-
-endmacro()
+include(${CMAKE_CURRENT_LIST_DIR}/Uuid.cmake)
#[===[.rst:
.. cmake:command:: set_target_uuids
@@ -74,31 +25,41 @@
``SP_NAME``
The name of the SP.
-OUTPUTS:
-
-``SP_UUID_LE``
-SP_UUID converted to little-endian binary format.
-
#]===]
function (set_target_uuids)
set(options)
- set(oneValueArgs SP_UUID SP_NAME)
+ set(oneValueArgs TGT SP_UUID)
set(multiValueArgs)
- cmake_parse_arguments(TARGET "${options}" "${oneValueArgs}"
+ cmake_parse_arguments(_MY_PARAMS "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN} )
- if(NOT DEFINED TARGET_SP_UUID)
- message(FATAL_ERROR "set_target_uuids: mandatory parameter SP_UUID not defined!")
- endif()
- if(NOT DEFINED TARGET_SP_NAME)
- message(FATAL_ERROR "set_target_uuids: mandatory parameter SP_NAME not defined!")
- endif()
+ check_args(SP_UUID TGT)
- generate_uuid_formats(${TARGET_SP_UUID})
- target_compile_definitions(${TARGET_SP_NAME}
- PRIVATE OPTEE_SP_UUID=${UUID_STRUCT}
+ # Convert the UUID to a C char array initializer e.g.
+ # { 0x01, 0x10, 0x9c, 0xf8, 0xe5, 0xca, 0x44, 0x6f,
+ # 0x9b, 0x55, 0xf3, 0xcd, 0xc6, 0x51, 0x10, 0xc8, }
+ # and "pass it" to C files.
+ uuid_canon_to_octets(UUID ${_MY_PARAMS_SP_UUID} RES UUID_OCTETS)
+ list(JOIN UUID_OCTETS ", 0x" UUID_BYTES )
+ set(UUID_BYTES "{ 0x${UUID_BYTES} }")
+ target_compile_definitions(${_MY_PARAMS_TGT}
PRIVATE OPTEE_SP_UUID_BYTES=${UUID_BYTES}
)
- set(SP_UUID_LE ${UUID_LE} PARENT_SCOPE)
+
+ # Create a UUID structure with the UUID fileds
+ # { 0x01109cf8, 0xe5ca, 0x446f, \
+ # { 0x9b, 0x55, 0xf3, 0xcd, 0xc6, 0x51, 0x10, 0xc8 } }
+ # and "pass it" to C files
+ uuid_canon_to_fields(UUID ${_MY_PARAMS_SP_UUID}
+ TIME_LOW "_uuid_timeLow"
+ TIME_MID "_uuid_timeMid"
+ TIME_HI_AND_VER "_uuid_timeHiAndVersion"
+ CLOCK_AND_SEQ "_uuid_clockSeqAndNode")
+ string(REGEX MATCHALL ".." _uuid_clockSeqAndNode "${_uuid_clockSeqAndNode}")
+ list(JOIN _uuid_clockSeqAndNode ", 0x" _uuid_clockSeqAndNode)
+ set(UUID_STRUCT "{ 0x${_uuid_timeLow}, 0x${_uuid_timeMid}, 0x${_uuid_timeHiAndVersion}, { 0x${_uuid_clockSeqAndNode} }}")
+ target_compile_definitions(${_MY_PARAMS_TGT}
+ PRIVATE OPTEE_SP_UUID=${UUID_STRUCT}
+ )
endfunction()
diff --git a/tools/cmake/common/Uuid.cmake b/tools/cmake/common/Uuid.cmake
new file mode 100644
index 0000000..d66a7a3
--- /dev/null
+++ b/tools/cmake/common/Uuid.cmake
@@ -0,0 +1,166 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+include_guard()
+
+#[===[.rst:
+RFC 4122 compatible UUID manipulation routines
+---------------------------------------------
+
+The functionality in this file allows manipulating (which mostly means conversion) of UUID strings
+to various formats used in the TS build system.
+
+#]===]
+
+#[===[.rst:
+.. cmake:command:: uuid_canon_to_octets
+
+ .. code-block:: cmake
+
+ uuid_canon_to_octets(UUID <canonical UUID string> RES <output variable name>)
+
+ Convert a canonical UUID string to list of bytes, where each byte is represented as a two digit
+ hex octet without any prefix of suffix. Order of bytes will match the order of octets in the
+ canonical string left to right.
+
+ INPUTS:
+
+ ``UUID``
+ Canonical UUID string.
+
+ OUTPUTS:
+
+ ``RES``
+ Name of variable to store the result to. The result is a list of strings, where each list item
+ is a two digit hex digit, without any prefix or suffix.
+
+#]===]
+function(uuid_canon_to_octets)
+ set(options)
+ set(oneValueArgs UUID RES)
+ set(multiValueArgs)
+ cmake_parse_arguments(_MY_PARAMS "${options}" "${oneValueArgs}"
+ "${multiValueArgs}" ${ARGN} )
+
+ check_args(UUID RES)
+
+ string(REGEX MATCHALL "([A-Za-z0-9][A-Za-z0-9])" _hex_bytes "${_MY_PARAMS_UUID}")
+ list(LENGTH _hex_bytes _len)
+ if(NOT _len EQUAL 16)
+ message(FATAL_ERROR "Failed to convert UUID \"${_MY_PARAMS_UUID}\" to bytes. Failed to get exactly 16 octets.")
+ endif()
+ set(${_MY_PARAMS_RES} ${_hex_bytes} PARENT_SCOPE)
+endfunction()
+
+#[===[.rst:
+.. cmake:command:: uuid_canon_to_fields
+
+ .. code-block:: cmake
+
+ uuid_canon_to_fields(UUID <canonical UUIdD string> TIME_LOW <output variable name> TIME_MID <output variable name>
+ TIME_HI_AND_VER <output variable name> CLOCK_AND_SEQ <output variable name>)
+
+ Convert a canonical UUID string to UUID fields. Each field is a
+
+ INPUTS:
+
+ ``UUID``
+ Canonical UUID string.
+
+ OUTPUTS:
+ ``TIME_LOW``
+ Name of variable to store the time low filed.
+
+ ``TIME_MID``
+ Name of variable to store the time mid filed.
+
+ ``TIME_HI_AND_VER``
+ Name of variable to store the time hi and version filed.
+
+ ``CLOCK_AND_SEQ``
+ Name of variable to store the clock and sequence filed.
+
+#]===]
+function(uuid_canon_to_fields)
+ set(options)
+ set(oneValueArgs UUID TIME_LOW TIME_MID TIME_HI_AND_VER CLOCK_AND_SEQ)
+ set(multiValueArgs)
+ cmake_parse_arguments(_MY_PARAMS "${options}" "${oneValueArgs}"
+ "${multiValueArgs}" ${ARGN} )
+
+ check_args(UUID TIME_LOW TIME_MID TIME_HI_AND_VER CLOCK_AND_SEQ)
+ uuid_canon_to_octets(UUID ${_MY_PARAMS_UUID} RES _uuid_octets)
+
+ #Split the list of bytes in to the struct fields
+ list(SUBLIST _uuid_octets 0 4 _uuid_timeLow)
+ list(JOIN _uuid_timeLow "" _uuid_timeLow)
+
+ list(SUBLIST _uuid_octets 4 2 _uuid_timeMid)
+ list(JOIN _uuid_timeMid "" _uuid_timeMid)
+
+ list(SUBLIST _uuid_octets 6 2 _uuid_timeHiAndVersion)
+ list(JOIN _uuid_timeHiAndVersion "" _uuid_timeHiAndVersion)
+
+ list(SUBLIST _uuid_octets 8 8 _uuid_clockSeqAndNode)
+ list(JOIN _uuid_clockSeqAndNode "" _uuid_clockSeqAndNode)
+
+ set(${_MY_PARAMS_TIME_LOW} ${_uuid_timeLow} PARENT_SCOPE)
+ set(${_MY_PARAMS_TIME_MID} ${_uuid_timeMid} PARENT_SCOPE)
+ set(${_MY_PARAMS_TIME_HI_AND_VER} ${_uuid_timeHiAndVersion} PARENT_SCOPE)
+ set(${_MY_PARAMS_CLOCK_AND_SEQ} ${_uuid_clockSeqAndNode} PARENT_SCOPE)
+endfunction()
+
+#[===[.rst:
+.. cmake:command:: uuid_canon_to_le_words
+
+ .. code-block:: cmake
+
+ uuid_canon_to_le_words(UUID <canonical UUID string> RES <output variable name>)
+
+ Convert a canonical UUID string to list of 32bit wide little-endian numbers represented
+ as hex strings.
+
+ INPUTS:
+
+ ``UUID``
+ Canonical UUID string.
+
+ ``RES``
+ Name of variable to store the result to.
+
+#]===]
+function(uuid_canon_to_le_words)
+ set(options)
+ set(oneValueArgs UUID RES)
+ set(multiValueArgs)
+ cmake_parse_arguments(_MY_PARAMS "${options}" "${oneValueArgs}"
+ "${multiValueArgs}" ${ARGN} )
+
+ check_args(UUID RES)
+ uuid_canon_to_octets(UUID ${_MY_PARAMS_UUID} RES _uuid_octets)
+
+ # Separate 32 bit chunks
+ list(SUBLIST _uuid_octets 0 4 _word1)
+ list(SUBLIST _uuid_octets 4 4 _word2)
+ list(SUBLIST _uuid_octets 8 4 _word3)
+ list(SUBLIST _uuid_octets 12 4 _word4)
+
+ # Reverse octet order each word
+ list(REVERSE _word1)
+ list(REVERSE _word2)
+ list(REVERSE _word3)
+ list(REVERSE _word4)
+
+ # Concatenate octets of each word to a single string
+ list(JOIN _word1 "" _word1)
+ list(JOIN _word2 "" _word2)
+ list(JOIN _word3 "" _word3)
+ list(JOIN _word4 "" _word4)
+
+ # Return the result
+ set(${_MY_PARAMS_RES} "${_word1}" "${_word2}" "${_word3}" "${_word4}" PARENT_SCOPE)
+endfunction()