mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-03 20:54:32 +02:00
refactor(esptool_py): Move binary generation to project level and add utility functions
This commit refactors the esptool_py component to provide utility functions for binary file generation targets instead of creating the targets. Binary generation targets are now moved to the respective projects. The following changes were done in this commit: - Added __idf_build_binary() function to esptool_py to create the binary file generation target. - Added __idf_build_secure_binary() as the secure boot equivalent of the above function. - Top level project build now creates its own binary targets in idf_build_executable() in build.cmake. - Bootloader and esp_tee subprojects create their binary file generation targets in their respective CMakeLists.txt files. - All post-build targets such as the app_size_check target are now created by the respective projects and not esptool_py. - General clean-up of the esptool_py cmake files.
This commit is contained in:
@@ -75,16 +75,36 @@ idf_build_set_property(COMPILE_DEFINITIONS "BOOTLOADER_BUILD=1" APPEND)
|
||||
idf_build_set_property(COMPILE_DEFINITIONS "NON_OS_BUILD=1" APPEND)
|
||||
idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND)
|
||||
|
||||
# Set up the bootloader binary generation targets
|
||||
set(PROJECT_BIN "bootloader.bin")
|
||||
if(CONFIG_SECURE_BOOT_V2_ENABLED AND CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
set(bootloader_unsigned_bin "bootloader-unsigned.bin")
|
||||
else()
|
||||
set(bootloader_unsigned_bin "${PROJECT_BIN}")
|
||||
endif()
|
||||
|
||||
# Set the final binary name as a project property
|
||||
idf_build_set_property(PROJECT_BIN "${PROJECT_BIN}")
|
||||
|
||||
# Generate the unsigned binary from the ELF file.
|
||||
if(CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||
set(target_name "gen_bootloader_binary")
|
||||
__idf_build_binary("${bootloader_unsigned_bin}" "${target_name}")
|
||||
endif()
|
||||
|
||||
idf_component_get_property(main_args esptool_py FLASH_ARGS)
|
||||
idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS)
|
||||
idf_component_get_property(esptool_py_cmd esptool_py ESPTOOLPY_CMD)
|
||||
idf_component_get_property(espsecure_py_cmd esptool_py ESPSECUREPY_CMD)
|
||||
idf_component_get_property(espefuse_py_cmd esptool_py ESPEFUSEPY_CMD)
|
||||
|
||||
# String for printing flash command
|
||||
string(REPLACE ";" " " esptoolpy_write_flash
|
||||
"${ESPTOOLPY} --port=(PORT) --baud=(BAUD) ${main_args} "
|
||||
"${esptool_py_cmd} --port=(PORT) --baud=(BAUD) ${main_args} "
|
||||
"write_flash ${sub_args}")
|
||||
|
||||
string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
|
||||
string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}")
|
||||
string(REPLACE ";" " " espsecurepy "${espsecure_py_cmd}")
|
||||
string(REPLACE ";" " " espefusepy "${espefuse_py_cmd}")
|
||||
|
||||
# Suppress warning: "Manually-specified variables were not used by the project: SECURE_BOOT_SIGNING_KEY"
|
||||
set(ignore_signing_key "${SECURE_BOOT_SIGNING_KEY}")
|
||||
@@ -105,7 +125,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
|
||||
add_custom_command(OUTPUT "${secure_bootloader_key}"
|
||||
COMMAND ${ESPSECUREPY} digest_private_key
|
||||
COMMAND ${espsecure_py_cmd} digest_private_key
|
||||
--keylen "${key_digest_len}"
|
||||
--keyfile "${SECURE_BOOT_SIGNING_KEY}"
|
||||
"${secure_bootloader_key}"
|
||||
@@ -130,7 +150,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
|
||||
add_custom_command(OUTPUT "${bootloader_digest_bin}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}"
|
||||
COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}"
|
||||
COMMAND ${espsecure_py_cmd} digest_secure_bootloader --keyfile "${secure_bootloader_key}"
|
||||
-o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin"
|
||||
MAIN_DEPENDENCY "${CMAKE_BINARY_DIR}/.bin_timestamp"
|
||||
DEPENDS gen_secure_bootloader_key gen_project_binary
|
||||
@@ -139,39 +159,34 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
add_custom_target(gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}")
|
||||
endif()
|
||||
|
||||
# If secure boot is enabled, generate the signed binary from the unsigned one.
|
||||
if(CONFIG_SECURE_BOOT_V2_ENABLED)
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
get_filename_component(secure_boot_signing_key
|
||||
"${SECURE_BOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR "${project_dir}")
|
||||
set(target_name "gen_signed_bootloader")
|
||||
|
||||
if(NOT EXISTS "${secure_boot_signing_key}")
|
||||
message(FATAL_ERROR
|
||||
"Secure Boot Signing Key Not found."
|
||||
"\nGenerate the Secure Boot V2 RSA-PSS 3072 Key."
|
||||
"\nTo generate one, you can use this command:"
|
||||
"\n\t${espsecurepy} generate_signing_key --version 2 ${SECURE_BOOT_SIGNING_KEY}")
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
# The SECURE_BOOT_SIGNING_KEY is passed in from the parent build and
|
||||
# is already an absolute path.
|
||||
if(NOT EXISTS "${SECURE_BOOT_SIGNING_KEY}")
|
||||
message(FATAL_ERROR
|
||||
"Secure Boot Signing Key Not found."
|
||||
"\nGenerate the Secure Boot V2 RSA-PSS 3072 Key."
|
||||
"\nTo generate one, you can use this command:"
|
||||
"\n\t${espsecurepy} generate_signing_key --version 2 your_key.pem"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(bootloader_unsigned_bin "bootloader-unsigned.bin")
|
||||
add_custom_command(OUTPUT ".signed_bin_timestamp"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/${PROJECT_BIN}"
|
||||
"${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
|
||||
COMMAND ${ESPSECUREPY} sign_data --version 2 --keyfile "${secure_boot_signing_key}"
|
||||
-o "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}"
|
||||
"from ${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
|
||||
COMMAND ${CMAKE_COMMAND} -E md5sum "${CMAKE_BINARY_DIR}/${PROJECT_BIN}"
|
||||
> "${CMAKE_BINARY_DIR}/.signed_bin_timestamp"
|
||||
DEPENDS "${build_dir}/.bin_timestamp"
|
||||
VERBATIM
|
||||
COMMENT "Generated the signed Bootloader")
|
||||
set(comment "Generated the signed Bootloader")
|
||||
set(key_arg KEYFILE "${SECURE_BOOT_SIGNING_KEY}")
|
||||
else()
|
||||
add_custom_command(OUTPUT ".signed_bin_timestamp"
|
||||
VERBATIM
|
||||
COMMENT "Bootloader generated but not signed")
|
||||
# If we are not building signed binaries, we don't pass a key.
|
||||
set(comment "Bootloader generated but not signed")
|
||||
set(key_arg "")
|
||||
endif()
|
||||
|
||||
add_custom_target(gen_signed_bootloader ALL DEPENDS "${build_dir}/.signed_bin_timestamp")
|
||||
__idf_build_secure_binary("${bootloader_unsigned_bin}" "${PROJECT_BIN}" "${target_name}"
|
||||
COMMENT "${comment}"
|
||||
${key_arg}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
|
||||
@@ -255,3 +270,19 @@ elseif(CONFIG_SECURE_BOOT_V2_ENABLED AND NOT CONFIG_SECURE_BOOT_FLASH_BOOTLOADER
|
||||
DEPENDS gen_signed_bootloader
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
# Generate bootloader post-build check of the bootloader size against the offset
|
||||
partition_table_add_check_bootloader_size_target(bootloader_check_size
|
||||
DEPENDS gen_project_binary
|
||||
BOOTLOADER_BINARY_PATH "${CMAKE_BINARY_DIR}/${PROJECT_BIN}"
|
||||
RESULT bootloader_check_size_command)
|
||||
add_dependencies(app bootloader_check_size)
|
||||
|
||||
if(CONFIG_SECURE_BOOT_V2_ENABLED AND CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
# Check the size of the bootloader + signature block.
|
||||
partition_table_add_check_bootloader_size_target(bootloader_check_size_signed
|
||||
DEPENDS gen_signed_bootloader
|
||||
BOOTLOADER_BINARY_PATH "${CMAKE_BINARY_DIR}/${PROJECT_BIN}"
|
||||
RESULT bootloader_check_size_signed_command)
|
||||
add_dependencies(app bootloader_check_size_signed)
|
||||
endif()
|
||||
|
@@ -51,37 +51,51 @@ idf_build_set_property(COMPILE_DEFINITIONS "ESP_TEE_BUILD=1" APPEND)
|
||||
idf_build_set_property(COMPILE_DEFINITIONS "NON_OS_BUILD=1" APPEND)
|
||||
idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND)
|
||||
|
||||
if(CONFIG_SECURE_BOOT_V2_ENABLED)
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
get_filename_component(secure_boot_signing_key
|
||||
"${SECURE_BOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR "${project_dir}")
|
||||
# Set up the TEE binary generation targets
|
||||
set(project_bin "esp_tee.bin")
|
||||
if(CONFIG_SECURE_BOOT_V2_ENABLED AND CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
set(esp_tee_unsigned_bin "esp_tee-unsigned.bin")
|
||||
else()
|
||||
set(esp_tee_unsigned_bin "${project_bin}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${secure_boot_signing_key}")
|
||||
message(FATAL_ERROR
|
||||
"Secure Boot Signing Key Not found."
|
||||
"\nGenerate the Secure Boot V2 RSA-PSS 3072 Key."
|
||||
"\nTo generate one, you can use this command:"
|
||||
"\n\t${espsecurepy} generate_signing_key --version 2 ${SECURE_BOOT_SIGNING_KEY}")
|
||||
# Set the final binary name as a project property.
|
||||
idf_build_set_property(PROJECT_BIN "${project_bin}")
|
||||
|
||||
# Generate the unsigned binary from the ELF file.
|
||||
if(CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||
set(target_name "gen_esp_tee_binary")
|
||||
__idf_build_binary("${esp_tee_unsigned_bin}" "${target_name}")
|
||||
endif()
|
||||
|
||||
idf_component_get_property(espsecure_py_cmd esptool_py ESPSECUREPY_CMD)
|
||||
|
||||
# If secure boot is enabled, generate the signed binary from the unsigned one.
|
||||
if(CONFIG_SECURE_BOOT_V2_ENABLED)
|
||||
set(target_name "gen_signed_esp_tee_binary")
|
||||
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
# The SECURE_BOOT_SIGNING_KEY is passed in from the parent build and
|
||||
# is already an absolute path.
|
||||
if(NOT EXISTS "${SECURE_BOOT_SIGNING_KEY}")
|
||||
message(FATAL_ERROR
|
||||
"Secure Boot Signing Key Not found."
|
||||
"\nGenerate the Secure Boot V2 RSA-PSS 3072 Key."
|
||||
"\nTo generate one, you can use this command:"
|
||||
"\n\t${espsecure_py_cmd} generate_signing_key --version 2 your_key.pem"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(esp_tee_unsigned_bin "esp_tee-unsigned.bin")
|
||||
add_custom_command(OUTPUT ".signed_bin_timestamp"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/${PROJECT_BIN}"
|
||||
"${CMAKE_BINARY_DIR}/${esp_tee_unsigned_bin}"
|
||||
COMMAND ${ESPSECUREPY} sign_data --version 2 --keyfile "${secure_boot_signing_key}"
|
||||
-o "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${esp_tee_unsigned_bin}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}"
|
||||
"from ${CMAKE_BINARY_DIR}/${esp_tee_unsigned_bin}"
|
||||
COMMAND ${CMAKE_COMMAND} -E md5sum "${CMAKE_BINARY_DIR}/${PROJECT_BIN}"
|
||||
> "${CMAKE_BINARY_DIR}/.signed_bin_timestamp"
|
||||
DEPENDS "${build_dir}/.bin_timestamp"
|
||||
VERBATIM
|
||||
COMMENT "Generated the signed TEE")
|
||||
set(comment "Generated the signed TEE")
|
||||
set(key_arg KEYFILE "${SECURE_BOOT_SIGNING_KEY}")
|
||||
else()
|
||||
add_custom_command(OUTPUT ".signed_bin_timestamp"
|
||||
VERBATIM
|
||||
COMMENT "TEE generated but not signed")
|
||||
# If we are not building signed binaries, we don't pass a key.
|
||||
set(comment "TEE generated but not signed")
|
||||
set(key_arg "")
|
||||
endif()
|
||||
|
||||
add_custom_target(gen_signed_esp_tee ALL DEPENDS "${build_dir}/.signed_bin_timestamp")
|
||||
__idf_build_secure_binary("${esp_tee_unsigned_bin}" "${project_bin}" "${target_name}"
|
||||
COMMENT "${comment}"
|
||||
${key_arg}
|
||||
)
|
||||
endif()
|
||||
|
@@ -17,16 +17,6 @@ if(NOT BOOTLOADER_BUILD)
|
||||
|
||||
|
||||
|
||||
# If anti-rollback option is set then factory partition should not be in Partition Table.
|
||||
# In this case, should be used the partition table with two ota app without the factory.
|
||||
partition_table_get_partition_info(factory_offset "--partition-type app --partition-subtype factory" "offset")
|
||||
partition_table_get_partition_info(test_offset "--partition-type app --partition-subtype test" "offset")
|
||||
if(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK AND (factory_offset OR test_offset))
|
||||
fail_at_build_time(check_table_contents "\
|
||||
ERROR: Anti-rollback option is enabled. Partition table should \
|
||||
consist of two ota app without factory or test partitions.")
|
||||
add_dependencies(app check_table_contents)
|
||||
endif()
|
||||
|
||||
# Generate flasher_args.json for tools that need it. The variables below are used
|
||||
# in configuring the template flasher_args.json.in.
|
||||
@@ -54,31 +44,5 @@ consist of two ota app without factory or test partitions.")
|
||||
CONTENT "${flasher_args_content}")
|
||||
file_generate("${CMAKE_BINARY_DIR}/flasher_args.json"
|
||||
INPUT "${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in")
|
||||
if(CONFIG_APP_BUILD_TYPE_APP_2NDBOOT)
|
||||
# Generate app_check_size_command target to check the app size against the partition table parameters
|
||||
partition_table_add_check_size_target(app_check_size
|
||||
DEPENDS gen_project_binary
|
||||
BINARY_PATH "${build_dir}/${PROJECT_BIN}"
|
||||
PARTITION_TYPE app)
|
||||
add_dependencies(app app_check_size)
|
||||
endif()
|
||||
endif()
|
||||
endif() # NOT BOOTLOADER_BUILD
|
||||
|
||||
if(BOOTLOADER_BUILD)
|
||||
# Generate bootloader post-build check of the bootloader size against the offset
|
||||
partition_table_add_check_bootloader_size_target(bootloader_check_size
|
||||
DEPENDS gen_project_binary
|
||||
BOOTLOADER_BINARY_PATH "${build_dir}/${PROJECT_BIN}"
|
||||
RESULT bootloader_check_size_command)
|
||||
add_dependencies(app bootloader_check_size) # note: in the subproject, so the target is 'app'...
|
||||
|
||||
if(CONFIG_SECURE_BOOT_V2_ENABLED AND CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
# Check the size of the bootloader + signature block.
|
||||
partition_table_add_check_bootloader_size_target(bootloader_check_size_signed
|
||||
DEPENDS gen_signed_bootloader
|
||||
BOOTLOADER_BINARY_PATH "${build_dir}/${PROJECT_BIN}"
|
||||
RESULT bootloader_check_size_signed_command)
|
||||
add_dependencies(app bootloader_check_size_signed) # note: in the subproject, so the target is 'app'...
|
||||
endif()
|
||||
endif()
|
||||
|
@@ -112,79 +112,6 @@ idf_build_get_property(build_dir BUILD_DIR)
|
||||
idf_build_get_property(elf_name EXECUTABLE_NAME GENERATOR_EXPRESSION)
|
||||
idf_build_get_property(elf EXECUTABLE GENERATOR_EXPRESSION)
|
||||
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES AND NOT non_os_build)
|
||||
set(unsigned_project_binary "${elf_name}-unsigned.bin")
|
||||
else()
|
||||
set(unsigned_project_binary "${elf_name}.bin")
|
||||
endif()
|
||||
|
||||
set(PROJECT_BIN "${elf_name}.bin")
|
||||
|
||||
#
|
||||
# Add 'app.bin' target - generates with elf2image
|
||||
#
|
||||
if(CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||
add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
|
||||
COMMAND ${ESPTOOLPY} elf2image ${esptool_elf2image_args}
|
||||
-o "${build_dir}/${unsigned_project_binary}" "$<TARGET_FILE:$<GENEX_EVAL:${elf}>>"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generated ${build_dir}/${unsigned_project_binary}"
|
||||
COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${unsigned_project_binary}" > "${build_dir}/.bin_timestamp"
|
||||
DEPENDS "$<TARGET_FILE:$<GENEX_EVAL:${elf}>>"
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY ${build_dir}
|
||||
COMMENT "Generating binary image from built executable"
|
||||
)
|
||||
add_custom_target(gen_project_binary DEPENDS "${build_dir}/.bin_timestamp")
|
||||
endif()
|
||||
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY ADDITIONAL_CLEAN_FILES
|
||||
"${build_dir}/${unsigned_project_binary}"
|
||||
)
|
||||
|
||||
if(CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||
add_custom_target(app ALL DEPENDS gen_project_binary)
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
set(secure_boot_version "1")
|
||||
elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME)
|
||||
set(secure_boot_version "2")
|
||||
endif()
|
||||
|
||||
if(NOT non_os_build AND CONFIG_SECURE_SIGNED_APPS)
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
# for locally signed secure boot image, add a signing step to get from unsigned app to signed app
|
||||
get_filename_component(secure_boot_signing_key "${CONFIG_SECURE_BOOT_SIGNING_KEY}"
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
add_custom_command(OUTPUT "${build_dir}/.signed_bin_timestamp"
|
||||
COMMAND ${ESPSECUREPY} sign_data --version ${secure_boot_version} --keyfile ${secure_boot_signing_key}
|
||||
-o "${build_dir}/${PROJECT_BIN}" "${build_dir}/${unsigned_project_binary}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}"
|
||||
"from ${build_dir}/${unsigned_project_binary}"
|
||||
COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${PROJECT_BIN}" > "${build_dir}/.signed_bin_timestamp"
|
||||
DEPENDS "${build_dir}/.bin_timestamp"
|
||||
VERBATIM
|
||||
COMMENT "Generating signed binary image"
|
||||
)
|
||||
add_custom_target(gen_signed_project_binary DEPENDS "${build_dir}/.signed_bin_timestamp")
|
||||
add_dependencies(gen_project_binary gen_signed_project_binary)
|
||||
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY ADDITIONAL_CLEAN_FILES
|
||||
"${build_dir}/${PROJECT_BIN}"
|
||||
)
|
||||
else()
|
||||
string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
|
||||
add_custom_command(TARGET app POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"App built but not signed. Sign app before flashing"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"\t${espsecurepy} sign_data --keyfile KEYFILE --version ${secure_boot_version} \
|
||||
${build_dir}/${PROJECT_BIN}"
|
||||
VERBATIM)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_custom_target(erase_flash
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
@@ -781,6 +708,147 @@ function(__ensure_esptool_py_setup)
|
||||
endfunction()
|
||||
|
||||
|
||||
# __idf_build_binary
|
||||
#
|
||||
# @brief Sets up the primary target for generating a .bin file from an .elf file.
|
||||
#
|
||||
# This function creates the custom command and target required to generate a
|
||||
# project binary (`.bin`) file from the final `.elf` executable. It uses `esptool.py
|
||||
# elf2image` to perform the conversion and manages dependencies to ensure the
|
||||
# binary is regenerated whenever the ELF file changes.
|
||||
#
|
||||
# @param[in] OUTPUT_BIN_FILENAME The name of the output binary file to generate.
|
||||
# @param[in] TARGET_NAME The unique name for the custom target that
|
||||
# generates the binary.
|
||||
function(__idf_build_binary OUTPUT_BIN_FILENAME TARGET_NAME)
|
||||
__ensure_esptool_py_setup()
|
||||
|
||||
idf_build_get_property(build_dir BUILD_DIR)
|
||||
idf_build_get_property(elf EXECUTABLE GENERATOR_EXPRESSION)
|
||||
idf_component_get_property(esptool_py_cmd esptool_py ESPTOOLPY_CMD)
|
||||
|
||||
# Get esptool.py arguments for elf2image target
|
||||
idf_component_get_property(esptool_elf2image_args esptool_py ESPTOOL_PY_ELF2IMAGE_ARGS)
|
||||
|
||||
# Create a custom command and target to generate binary from elf file
|
||||
add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
|
||||
COMMAND ${esptool_py_cmd} elf2image ${esptool_elf2image_args}
|
||||
-o "${build_dir}/${OUTPUT_BIN_FILENAME}" "$<TARGET_FILE:$<GENEX_EVAL:${elf}>>"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generated ${build_dir}/${OUTPUT_BIN_FILENAME}"
|
||||
COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${OUTPUT_BIN_FILENAME}" > "${build_dir}/.bin_timestamp"
|
||||
DEPENDS "$<TARGET_FILE:$<GENEX_EVAL:${elf}>>"
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY ${build_dir}
|
||||
COMMENT "Generating binary image from built executable"
|
||||
)
|
||||
# Create a custom target to generate the binary file
|
||||
add_custom_target(${TARGET_NAME} DEPENDS "${build_dir}/.bin_timestamp")
|
||||
|
||||
# We need to create a gen_project_binary target for backward compatibility
|
||||
# since many other components depend on it. Add the new target as a dependency
|
||||
# to the gen_project_binary target.
|
||||
if(NOT TARGET gen_project_binary)
|
||||
add_custom_target(gen_project_binary DEPENDS ${TARGET_NAME})
|
||||
else()
|
||||
add_dependencies(gen_project_binary ${TARGET_NAME})
|
||||
endif()
|
||||
|
||||
# Add an 'app' alias that is part of the default build
|
||||
if(NOT TARGET app)
|
||||
add_custom_target(app ALL DEPENDS gen_project_binary)
|
||||
else()
|
||||
add_dependencies(app gen_project_binary)
|
||||
endif()
|
||||
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY ADDITIONAL_CLEAN_FILES
|
||||
"${build_dir}/${OUTPUT_BIN_FILENAME}"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# __idf_build_secure_binary
|
||||
#
|
||||
# @brief Sets up targets for generating a signed binary for Secure Boot.
|
||||
#
|
||||
# If Secure Boot is enabled, this function adds a custom command to sign the
|
||||
# previously generated application binary using `espsecure.py`. It creates a
|
||||
# target that depends on the unsigned binary and produces a signed one, which
|
||||
# is required for the bootloader to authenticate the application.
|
||||
#
|
||||
# @param[in] UNSIGNED_BIN_FILENAME The name of the unsigned input binary file.
|
||||
# @param[in] SIGNED_BIN_FILENAME The name of the signed output binary file.
|
||||
# @param[in] TARGET_NAME The unique name for the custom target that
|
||||
# generates the signed binary.
|
||||
# @param[in, optional] KEYFILE Path to the keyfile for signing.
|
||||
# @param[in, optional] COMMENT Custom message to display during build.
|
||||
function(__idf_build_secure_binary UNSIGNED_BIN_FILENAME SIGNED_BIN_FILENAME TARGET_NAME)
|
||||
cmake_parse_arguments(arg "" "KEYFILE;COMMENT" "" ${ARGN})
|
||||
|
||||
__ensure_esptool_py_setup()
|
||||
|
||||
idf_build_get_property(build_dir BUILD_DIR)
|
||||
idf_component_get_property(espsecure_py_cmd esptool_py ESPSECUREPY_CMD)
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
set(secure_boot_version "1")
|
||||
elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME)
|
||||
set(secure_boot_version "2")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
if(arg_KEYFILE)
|
||||
# If a keyfile is provided, use it for signing.
|
||||
set(secure_boot_signing_key "${arg_KEYFILE}")
|
||||
else()
|
||||
# for locally signed secure boot image, add a signing step to get from unsigned app to signed app
|
||||
idf_build_get_property(project_dir PROJECT_DIR)
|
||||
get_filename_component(secure_boot_signing_key "${CONFIG_SECURE_BOOT_SIGNING_KEY}"
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
endif()
|
||||
|
||||
if(arg_COMMENT)
|
||||
set(comment_text "${arg_COMMENT}")
|
||||
else()
|
||||
set(comment_text "Generating signed binary image")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT "${build_dir}/.signed_bin_timestamp"
|
||||
COMMAND ${espsecure_py_cmd} sign_data
|
||||
--version ${secure_boot_version} --keyfile "${secure_boot_signing_key}"
|
||||
-o "${build_dir}/${SIGNED_BIN_FILENAME}" "${build_dir}/${UNSIGNED_BIN_FILENAME}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${SIGNED_BIN_FILENAME}"
|
||||
"from ${build_dir}/${UNSIGNED_BIN_FILENAME}"
|
||||
COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${SIGNED_BIN_FILENAME}"
|
||||
> "${build_dir}/.signed_bin_timestamp"
|
||||
DEPENDS "${build_dir}/.bin_timestamp"
|
||||
VERBATIM
|
||||
COMMENT "${comment_text}"
|
||||
)
|
||||
add_custom_target(${TARGET_NAME} DEPENDS "${build_dir}/.signed_bin_timestamp")
|
||||
|
||||
# Add the new target as a dependency to the gen_project_binary target.
|
||||
if(NOT TARGET gen_project_binary)
|
||||
add_custom_target(gen_project_binary DEPENDS ${TARGET_NAME})
|
||||
else()
|
||||
add_dependencies(gen_project_binary ${TARGET_NAME})
|
||||
endif()
|
||||
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY ADDITIONAL_CLEAN_FILES
|
||||
"${build_dir}/${SIGNED_BIN_FILENAME}"
|
||||
)
|
||||
else()
|
||||
string(REPLACE ";" " " espsecurepy "${espsecure_py_cmd}")
|
||||
add_custom_command(TARGET app POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"App built but not signed. Sign app before flashing"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"\t${espsecurepy} sign_data --keyfile KEYFILE --version ${secure_boot_version} \
|
||||
${build_dir}/${UNSIGNED_BIN_FILENAME}"
|
||||
VERBATIM)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# __esptool_py_setup_main_flash_target
|
||||
#
|
||||
# @brief Sets up the main `flash` target and its dependencies.
|
||||
|
@@ -783,9 +783,51 @@ function(idf_build_executable elf)
|
||||
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
if(NOT bootloader_build AND NOT esp_tee_build AND NOT "${target}" STREQUAL "linux")
|
||||
# Check if esptool_py component is available before calling its functions
|
||||
if(TARGET idf::esptool_py)
|
||||
# This is the main orchestrator for generating binaries and flash targets
|
||||
# It is responsible for -
|
||||
# - Setting up the binary generation targets
|
||||
# - Setting up the signed binary generation targets
|
||||
# - Setting up the main 'flash' target
|
||||
# - Setting up the app-flash and flash targets
|
||||
# - Setting up the app_check_size target
|
||||
#
|
||||
# Note: We need to wrap this code in a if(NOT BOOTLOADER_BUILD AND NOT ESP_TEE_BUILD) block
|
||||
# because the bootloader and esp_tee subprojects also call our overridden project()
|
||||
# macro.
|
||||
#
|
||||
# Note: We need to have this block here instead of in project.cmake because
|
||||
# idf_build_executable() is called directly when ESP-IDF is compiled
|
||||
# as a library (idf_as_lib).
|
||||
if(NOT bootloader_build AND NOT esp_tee_build)
|
||||
# All of the following logic for generating binaries and flash targets
|
||||
# depends on the esptool_py component. For some builds (such as those
|
||||
# that are built for the linux target), this component may not be included.
|
||||
# We must guard these calls to ensure they only run when esptool_py is part
|
||||
# of the build. We also only do this if CONFIG_APP_BUILD_GENERATE_BINARIES is set.
|
||||
if(TARGET idf::esptool_py AND CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||
# Determine the output filename for the binary.
|
||||
idf_build_get_property(elf_name EXECUTABLE_NAME GENERATOR_EXPRESSION)
|
||||
idf_build_get_property(non_os_build NON_OS_BUILD)
|
||||
|
||||
set(project_bin "${elf_name}.bin")
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES AND NOT non_os_build)
|
||||
set(project_bin_unsigned "${elf_name}-unsigned.bin")
|
||||
else()
|
||||
set(project_bin_unsigned "${project_bin}")
|
||||
endif()
|
||||
|
||||
idf_build_set_property(PROJECT_BIN "${project_bin}")
|
||||
|
||||
# Create the binary file generation target for the main project
|
||||
set(target_name "gen_${CMAKE_PROJECT_NAME}_binary")
|
||||
__idf_build_binary("${project_bin_unsigned}" "${target_name}")
|
||||
|
||||
# Generate the signed binary file generation target for the main project
|
||||
if(NOT non_os_build AND CONFIG_SECURE_SIGNED_APPS)
|
||||
set(signed_target_name "gen_signed_${CMAKE_PROJECT_NAME}_binary")
|
||||
__idf_build_secure_binary("${project_bin_unsigned}" "${project_bin}" "${signed_target_name}")
|
||||
endif()
|
||||
|
||||
# The following block is placed here to ensure that the application binary is added to the 'flash'
|
||||
# target's properties *before* __esptool_py_setup_main_flash_target is called.
|
||||
# This is because __esptool_py_setup_main_flash_target copies properties from the 'flash'
|
||||
@@ -795,19 +837,42 @@ function(idf_build_executable elf)
|
||||
#
|
||||
# Set up app-flash and flash targets. The app-flash target is specifically for flashing
|
||||
# just the application, while the flash target is for flashing the entire system.
|
||||
if(CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||
idf_build_get_property(build_dir BUILD_DIR)
|
||||
idf_build_get_property(project_bin PROJECT_BIN)
|
||||
partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset")
|
||||
esptool_py_custom_target(app-flash app "app")
|
||||
idf_build_get_property(build_dir BUILD_DIR)
|
||||
idf_build_get_property(project_bin PROJECT_BIN)
|
||||
partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset")
|
||||
esptool_py_custom_target(app-flash app "app")
|
||||
|
||||
esptool_py_flash_target_image(app-flash app "${app_partition_offset}" "${build_dir}/${project_bin}")
|
||||
esptool_py_flash_target_image(flash app "${app_partition_offset}" "${build_dir}/${project_bin}")
|
||||
esptool_py_flash_target_image(app-flash app "${app_partition_offset}" "${build_dir}/${project_bin}")
|
||||
esptool_py_flash_target_image(flash app "${app_partition_offset}" "${build_dir}/${project_bin}")
|
||||
|
||||
# Setup the main flash target and dependencies
|
||||
__esptool_py_setup_main_flash_target()
|
||||
|
||||
# Create the following post-build targets after __idf_build_binary() is called to ensure that the
|
||||
# app target is available.
|
||||
|
||||
# If anti-rollback option is set then factory partition should not be in Partition Table.
|
||||
# In this case, should be used the partition table with two ota app without the factory.
|
||||
partition_table_get_partition_info(factory_offset
|
||||
"--partition-type app --partition-subtype factory" "offset")
|
||||
partition_table_get_partition_info(test_offset "--partition-type app --partition-subtype test" "offset")
|
||||
if(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK AND (factory_offset OR test_offset))
|
||||
fail_at_build_time(check_table_contents "\
|
||||
ERROR: Anti-rollback option is enabled. Partition table should \
|
||||
consist of two ota app without factory or test partitions.")
|
||||
add_dependencies(app check_table_contents)
|
||||
endif()
|
||||
|
||||
__esptool_py_setup_main_flash_target()
|
||||
endif()
|
||||
endif()
|
||||
if(CONFIG_APP_BUILD_TYPE_APP_2NDBOOT)
|
||||
# Generate app_check_size_command target to check the app size against the partition table parameters
|
||||
partition_table_add_check_size_target(app_check_size
|
||||
DEPENDS gen_project_binary
|
||||
BINARY_PATH "${build_dir}/${project_bin}"
|
||||
PARTITION_TYPE app)
|
||||
add_dependencies(app app_check_size)
|
||||
endif()
|
||||
endif() # if(TARGET idf::esptool_py AND CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||
endif() # if(NOT bootloader_build AND NOT esp_tee_build)
|
||||
endfunction()
|
||||
|
||||
# idf_build_get_config
|
||||
|
Reference in New Issue
Block a user