diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake index 0d35ea59e8..0f33f732e7 100644 --- a/components/esptool_py/project_include.cmake +++ b/components/esptool_py/project_include.cmake @@ -167,23 +167,118 @@ endif() idf_component_set_property(esptool_py FLASH_ARGS "${esptool_flash_main_args}") idf_component_set_property(esptool_py FLASH_SUB_ARGS "${ESPTOOLPY_FLASH_OPTIONS}") +function(esptool_py_partition_needs_encryption retencrypted partition_name) + # Check if encryption is enabled + if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + # Encryption is enabled, get partition type, subtype and encrypted flag to + # determine whether it needs encryption or not. + partition_table_get_partition_info(type "--partition-name ${partition_name}" "type") + partition_table_get_partition_info(subtype "--partition-name ${partition_name}" "subtype") + partition_table_get_partition_info(encrypted "--partition-name ${partition_name}" "encrypted") + + # As defined in gen_esp32part.py file: + # Types: + # - APP 0x00 + # - DATA 0x01 + # Subtypes: + # - ota 0x00 + # - nvs 0x02 + # If the partition is an app, an OTA or an NVS partition, then it should be + # encrypted + if( + (${type} EQUAL 0) OR + (${type} EQUAL 1 AND ${subtype} EQUAL 0) OR + (${type} EQUAL 1 AND ${subtype} EQUAL 2) + ) + set(encrypted TRUE) + endif() + + # Return 'encrypted' value to the caller + set(${retencrypted} ${encrypted} PARENT_SCOPE) + else() + # Encryption not enabled, return false + set(${retencrypted} FALSE PARENT_SCOPE) + endif() + +endfunction() + +function(esptool_py_flash_to_partition target_name partition_name binary_path) + # Retrieve the offset for the partition to flash the image on + partition_table_get_partition_info(offset "--partition-name ${partition_name}" "offset") + + if(NOT offset) + message(FATAL_ERROR "Could not find offset of partition ${partition_name}") + endif() + + # Check whether the partition needs encryption or not + esptool_py_partition_needs_encryption(encrypted ${partition_name}) + + # The image name is also the partition name + esptool_py_flash_target_image(${target_name} ${partition_name} ${offset} + ${binary_path} ${encrypted}) +endfunction() + +# This function takes a fifth optional parameter: "encrypted". As its name +# states, it marks whether the image should be flashed as encrypted or not. +# If this parameter is provided, it should either be set to TRUE or FALSE, +# if it is not provided, its value will be set to TRUE if build macro +# CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT is set, FALSE else function(esptool_py_flash_target_image target_name image_name offset image) idf_build_get_property(build_dir BUILD_DIR) file(RELATIVE_PATH image ${build_dir} ${image}) + # Check if 'encrypted' parameter is provided + if(${ARGC} GREATER 4) + set(encrypted ${ARGV4}) + # If not, flash encryption mode marks whether the image should be encrypted + elseif(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + set(encrypted TRUE) + else() + set(encrypted FALSE) + endif() + + # 'encrypted' is an uppercase boolean: TRUE or FALSE. + # In order to keep consistent with other entries in + # FLASH_ENTRY property, convert them to 'true' and + # 'false' respectively. + string(TOLOWER ${encrypted} lowerencrypted) + + # In the following snippet of code, some properties are defined for our + # current target. These properties will be used to generate the actual + # target_name_args files using the target_name_args.in files. + # Please see function esptool_py_flash_target above for more information + # about these properties and how they are used. + + # Add the image file, with its offset, to the list of files to + # flash to the target. No matter whether flash encryption is + # enabled or not, plain binaries (non-encrypted) need to be + # generated set_property(TARGET ${target_name} APPEND PROPERTY FLASH_FILE "\"${offset}\" : \"${image}\"") set_property(TARGET ${target_name} APPEND PROPERTY FLASH_ENTRY - "\"${image_name}\" : { \"offset\" : \"${offset}\", \"file\" : \"${image}\" }") + "\"${image_name}\" : { \"offset\" : \"${offset}\", \"file\" : \"${image}\",\ + \"encrypted\" : \"${lowerencrypted}\" }") set_property(TARGET ${target_name} APPEND PROPERTY IMAGES "${offset} ${image}") if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + # When flash encryption mode is enabled, if the current binary needs to + # be encrypted, do the same as previously but prefixing target names with + # "encrypted-". + if(${encrypted}) set_property(TARGET encrypted-${target_name} APPEND PROPERTY FLASH_FILE - "\"${offset}\" : \"${image}\"") + "\"${offset}\" : \"${image}\"") set_property(TARGET encrypted-${target_name} APPEND PROPERTY FLASH_ENTRY - "\"${image_name}\" : { \"offset\" : \"${offset}\", \"file\" : \"${image}\" }") - set_property(TARGET encrypted-${target_name} APPEND PROPERTY IMAGES "${offset} ${image}") + "\"${image_name}\" : { \"offset\" : \"${offset}\", \"file\" : \"${image}\" , \ +\"encrypted\" : \"${lowerencrypted}\" }") + + set_property(TARGET encrypted-${target_name} APPEND PROPERTY ENCRYPTED_IMAGES "${offset} ${image}") + else() + # The target doesn't need to be encrypted, thus, add the current file + # to the NON_ENCRYPTED_IMAGES property + set_property(TARGET encrypted-${target_name} APPEND PROPERTY NON_ENCRYPTED_IMAGES "${offset} ${image}") + endif() endif() + endfunction() function(esptool_py_flash_target target_name main_args sub_args) @@ -208,15 +303,35 @@ function(esptool_py_flash_target target_name main_args sub_args) set_target_properties(${target_name} PROPERTIES SUB_ARGS "${sub_args}") + # Create the expression that contains the list of file names to pass + # to esptool script set(flash_args_content "$, >\n\ $,\n>") + # Write the previous expression to the target_name_args.in file file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${target_name}_args.in" - CONTENT "${flash_args_content}") + CONTENT "${flash_args_content}") + + # Generate the actual expression value from the content of the file + # we just wrote file(GENERATE OUTPUT "${build_dir}/${target_name}_args" INPUT "${CMAKE_CURRENT_BINARY_DIR}/${target_name}_args.in") - if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + # Check if 'encrypted' parameter is provided + if(${ARGC} GREATER 3) + set(encrypted ${ARGV3}) + # If not, flash encryption mode marks whether the image should be encrypted + elseif(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + set(encrypted TRUE) + else() + set(encrypted FALSE) + endif() + + # If the file needs to be encrypted, create a target file that lets the user + # flash this partition independently from other files. + # For example, if 'target_name' is app-flash and 'encrypted' is TRUE, + # 'build' directory will contain a file name 'encrypted_app-flash_args' + if(${encrypted}) add_custom_target(encrypted-${target_name} COMMAND ${CMAKE_COMMAND} -D IDF_PATH="${idf_path}" @@ -228,13 +343,42 @@ $,\n>") USES_TERMINAL ) - set_target_properties(encrypted-${target_name} PROPERTIES SUB_ARGS "${sub_args};--encrypt") + # Generate the parameters for esptool.py command + # In case we have both non encrypted and encrypted files to flash, we + # can use --encrypt-files parameter to specify which ones should be + # encrypted. + # If we only have encrypted images to flash, we must use legacy + # --encrypt parameter. + # As the properties ENCRYPTED_IMAGES and NON_ENCRYPTED_IMAGES have not + # been geenrated yet, we must use CMake expression generator to test + # which esptool.py options we can use. - set(flash_args_content "$, >\n\ -$,\n>") + # The variable has_non_encrypted_image will be evaluated to "1" if some + # images must not be encrypted. This variable will be used in the next + # expression + set(has_non_encrypted_images "$>") + # Prepare esptool arguments (--encrypt or --encrypt-files) + set_target_properties(encrypted-${target_name} PROPERTIES SUB_ARGS "${sub_args};\ +$") + + # Generate the list of files to pass to esptool + set(encrypted_files "$,\n>") + set(non_encrypted_files "$,\n>") + + # Put both lists together, use --encrypted-files if we do also have + # plain images to flash + set(flash_args_content "$, >\ +${non_encrypted_files}\n\ +$\ +${encrypted_files}") + + # The expression is ready to be geenrated, write it to the file which + # extension is .in file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/encrypted_${target_name}_args.in" - CONTENT "${flash_args_content}") + CONTENT "${flash_args_content}") + + # Generate the actual string from the content of the file we just wrote file(GENERATE OUTPUT "${build_dir}/encrypted_${target_name}_args" INPUT "${CMAKE_CURRENT_BINARY_DIR}/encrypted_${target_name}_args.in") else() @@ -242,7 +386,6 @@ $,\n>") "CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT to be enabled.") endif() - endfunction() diff --git a/components/partition_table/parttool.py b/components/partition_table/parttool.py index 7644d06a58..704be0f6c7 100755 --- a/components/partition_table/parttool.py +++ b/components/partition_table/parttool.py @@ -215,6 +215,8 @@ def _get_partition_info(target, partition_id, info): for p in partitions: info_dict = { "name": '{}'.format(p.name), + "type": '{}'.format(p.type), + "subtype": '{}'.format(p.subtype), "offset": '0x{:x}'.format(p.offset), "size": '0x{:x}'.format(p.size), "encrypted": '{}'.format(p.encrypted) @@ -276,7 +278,7 @@ def main(): print_partition_info_subparser = subparsers.add_parser("get_partition_info", help="get partition information", parents=[partition_selection_parser]) print_partition_info_subparser.add_argument("--info", help="type of partition information to get", - choices=["name", "offset", "size", "encrypted"], default=["offset", "size"], nargs="+") + choices=["name", "type", "subtype", "offset", "size", "encrypted"], default=["offset", "size"], nargs="+") print_partition_info_subparser.add_argument('--part_list', help="Get a list of partitions suitable for a given type", action='store_true') args = parser.parse_args() diff --git a/components/spiffs/project_include.cmake b/components/spiffs/project_include.cmake index 3b86db5d11..18ee0995da 100644 --- a/components/spiffs/project_include.cmake +++ b/components/spiffs/project_include.cmake @@ -49,13 +49,15 @@ function(spiffs_create_partition_image partition base_dir) idf_component_get_property(main_args esptool_py FLASH_ARGS) idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS) - esptool_py_flash_target(${partition}-flash "${main_args}" "${sub_args}") - esptool_py_flash_target_image(${partition}-flash "${partition}" "${offset}" "${image_file}") + # Last (optional) parameter is the encryption for the target. In our + # case, spiffs is not encrypt so pass FALSE to the function. + esptool_py_flash_target(${partition}-flash "${main_args}" "${sub_args}" FALSE) + esptool_py_flash_to_partition(${partition}-flash "${partition}" "${image_file}") add_dependencies(${partition}-flash spiffs_${partition}_bin) if(arg_FLASH_IN_PROJECT) - esptool_py_flash_target_image(flash "${partition}" "${offset}" "${image_file}") + esptool_py_flash_to_partition(flash "${partition}" "${image_file}") add_dependencies(flash spiffs_${partition}_bin) endif() else()