Merge branch 'bugfix/fix_secure_boot_support' into 'master'

Fixes to secure boot support in CMake

See merge request idf/esp-idf!4977
This commit is contained in:
Angus Gratton 2019-06-28 15:38:59 +08:00
commit 265d7dc4e5
12 changed files with 294 additions and 240 deletions

View file

@ -34,7 +34,7 @@ if(NOT BOOTLOADER_BUILD)
${otadata_size} ${blank_otadata_file})
add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file})
add_dependencies(app blank_ota_data)
add_dependencies(flash blank_ota_data)
set(otatool_py ${python} ${COMPONENT_DIR}/otatool.py)

View file

@ -1,13 +1,21 @@
idf_component_register()
idf_component_register(PRIV_REQUIRES partition_table)
# Do not generate flash file when building bootloader or is in early expansion of the build
if(BOOTLOADER_BUILD)
return()
endif()
# When secure boot is enabled, do not flash bootloader along with invocation of `idf.py flash`
if(NOT CONFIG_SECURE_BOOT_ENABLED)
set(flash_bootloader FLASH_IN_PROJECT)
endif()
# Set values used in flash_bootloader_args.in and generate flash file
# for bootloader
esptool_py_flash_project_args(bootloader 0x1000
${BOOTLOADER_BUILD_DIR}/bootloader.bin
FLASH_IN_PROJECT
FLASH_FILE_TEMPLATE flash_bootloader_args.in)
${flash_bootloader}
FLASH_FILE_TEMPLATE flash_bootloader_args.in)
esptool_py_custom_target(bootloader-flash bootloader "bootloader")
add_dependencies(bootloader partition_table)

View file

@ -1,32 +1,10 @@
# Do not generate flash file when building bootloader or is in early expansion of the build
set(BOOTLOADER_OFFSET 0x1000)
# Do not generate flash file when building bootloader
if(BOOTLOADER_BUILD)
return()
endif()
idf_build_get_property(project_dir PROJECT_DIR)
# This is for tracking the top level project path
if(BOOTLOADER_BUILD)
set(main_project_path "${CMAKE_BINARY_DIR}/../..")
else()
set(main_project_path "${project_dir}")
endif()
get_filename_component(secure_boot_signing_key
"${CONFIG_SECURE_BOOT_SIGNING_KEY}"
ABSOLUTE BASE_DIR "${main_project_path}")
if(NOT EXISTS ${secure_boot_signing_key})
# If the signing key is not found, create a phony gen_secure_boot_signing_key target that
# fails the build. fail_at_build_time also touches CMakeCache.txt to cause a cmake run next time
# (to pick up a new signing key if one exists, etc.)
fail_at_build_time(gen_secure_boot_signing_key
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
"\tespsecure.py generate_signing_key ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
else()
add_custom_target(gen_secure_boot_signing_key)
endif()
# Glue to build the bootloader subproject binary as an external
# cmake project under this one
#
@ -39,41 +17,104 @@ set(bootloader_binary_files
"${BOOTLOADER_BUILD_DIR}/bootloader.map"
)
# These additional files may get generated
if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
set(bootloader_binary_files
${bootloader_binary_files}
"${BOOTLOADER_BUILD_DIR}/bootloader-reflash-digest.bin"
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-192.bin"
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-256.bin"
)
idf_build_get_property(project_dir PROJECT_DIR)
# There are some additional processing when CONFIG_CONFIG_SECURE_SIGNED_APPS. This happens
# when either CONFIG_SECURE_BOOT_ENABLED or SECURE_BOOT_BUILD_SIGNED_BINARIES.
# For both cases, the user either sets binaries to be signed during build or not
# using CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES.
#
# Regardless, pass the main project's keys (signing/verification) to the bootloader subproject
# via config.
if(CONFIG_SECURE_SIGNED_APPS)
add_custom_target(gen_secure_boot_keys)
if(CONFIG_SECURE_BOOT_ENABLED)
# Check that the configuration is sane
if((CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) OR
(NOT CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND NOT CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH))
fail_at_build_time(bootloader "Invalid bootloader target: bad sdkconfig?")
endif()
if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
set(bootloader_binary_files
${bootloader_binary_files}
"${BOOTLOADER_BUILD_DIR}/bootloader-reflash-digest.bin"
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-192.bin"
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-256.bin"
)
endif()
endif()
# Since keys are usually given relative to main project dir, get the absolute paths to the keys
# for use by the bootloader subproject. Replace the values in config with these absolute paths,
# so that bootloader subproject does not need to assume main project dir to obtain path to the keys.
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
get_filename_component(secure_boot_signing_key
"${CONFIG_SECURE_BOOT_SIGNING_KEY}"
ABSOLUTE BASE_DIR "${project_dir}")
if(NOT EXISTS ${secure_boot_signing_key})
# If the signing key is not found, create a phony gen_secure_boot_signing_key target that
# fails the build. fail_at_build_time causes a cmake run next time
# (to pick up a new signing key if one exists, etc.)
fail_at_build_time(gen_secure_boot_signing_key
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
"\tespsecure.py generate_signing_key ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
else()
add_custom_target(gen_secure_boot_signing_key)
endif()
set(SECURE_BOOT_SIGNING_KEY ${secure_boot_signing_key}) # needed by some other components
set(sign_key_arg "-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}")
add_dependencies(gen_secure_boot_keys gen_secure_boot_signing_key)
else()
get_filename_component(secure_boot_verification_key
${CONFIG_SECURE_BOOT_VERIFICATION_KEY}
ABSOLUTE BASE_DIR "${project_dir}")
if(NOT EXISTS ${secure_boot_verification_key})
# If the verification key is not found, create a phony gen_secure_boot_verification_key target that
# fails the build. fail_at_build_time causes a cmake run next time
# (to pick up a new verification key if one exists, etc.)
fail_at_build_time(gen_secure_boot_verification_key
"Secure Boot Verification Public Key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} does not exist."
"\tThis can be extracted from the private signing key."
"\tSee docs/security/secure-boot.rst for details.")
else()
add_custom_target(gen_secure_boot_verification_key)
endif()
set(ver_key_arg "-DSECURE_BOOT_VERIFICATION_KEY=${secure_boot_verification_key}")
add_dependencies(gen_secure_boot_keys gen_secure_boot_verification_key)
endif()
endif()
if((NOT CONFIG_SECURE_BOOT_ENABLED) OR
CONFIG_SECURE_BOOTLOADER_REFLASHABLE OR
CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
idf_build_get_property(idf_path IDF_PATH)
idf_build_get_property(sdkconfig SDKCONFIG)
idf_build_get_property(idf_target IDF_TARGET)
externalproject_add(bootloader
# TODO: support overriding the bootloader in COMPONENT_PATHS
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject"
BINARY_DIR "${BOOTLOADER_BUILD_DIR}"
CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target}
-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}
-DPYTHON_DEPS_CHECKED=1
-DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR}
# LEGACY_INCLUDE_COMMON_HEADERS has to be passed in via cache variable since
# the bootloader common component requirements depends on this and
# config variables are not available before project() call.
-DLEGACY_INCLUDE_COMMON_HEADERS=${CONFIG_LEGACY_INCLUDE_COMMON_HEADERS}
INSTALL_COMMAND ""
BUILD_ALWAYS 1 # no easy way around this...
BUILD_BYPRODUCTS ${bootloader_binary_files}
DEPENDS gen_secure_boot_signing_key
)
else()
fail_at_build_time(bootloader "Invalid bootloader target: bad sdkconfig?")
idf_build_get_property(idf_path IDF_PATH)
idf_build_get_property(idf_target IDF_TARGET)
idf_build_get_property(sdkconfig SDKCONFIG)
externalproject_add(bootloader
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject"
BINARY_DIR "${BOOTLOADER_BUILD_DIR}"
CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target}
-DPYTHON_DEPS_CHECKED=1
-DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR}
${sign_key_arg} ${ver_key_arg}
# LEGACY_INCLUDE_COMMON_HEADERS has to be passed in via cache variable since
# the bootloader common component requirements depends on this and
# config variables are not available before project() call.
-DLEGACY_INCLUDE_COMMON_HEADERS=${CONFIG_LEGACY_INCLUDE_COMMON_HEADERS}
INSTALL_COMMAND ""
BUILD_ALWAYS 1 # no easy way around this...
BUILD_BYPRODUCTS ${bootloader_binary_files}
)
if(CONFIG_SECURE_SIGNED_APPS)
add_dependencies(bootloader gen_secure_boot_keys)
endif()
# this is a hack due to an (annoying) shortcoming in cmake, it can't

View file

@ -29,8 +29,6 @@ project(bootloader)
idf_build_set_property(COMPILE_DEFINITIONS "-DBOOTLOADER_BUILD=1" APPEND)
idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND)
set(secure_boot_signing_key ${SECURE_BOOT_SIGNING_KEY})
string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}")
set(esptoolpy_write_flash "${ESPTOOLPY_WRITE_FLASH_STR}")
@ -53,7 +51,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
add_custom_command(OUTPUT "${secure_bootloader_key}"
COMMAND ${ESPSECUREPY} digest_private_key
--keylen "${key_digest_len}"
--keyfile "${secure_boot_signing_key}"
--keyfile "${SECURE_BOOT_SIGNING_KEY}"
"${secure_bootloader_key}"
VERBATIM)
@ -67,7 +65,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
"\nTo generate one, you can use this command:"
"\n\t${espsecurepy} generate_flash_encryption_key ${secure_bootloader_key}"
"\nIf a signing key is present, then instead use:"
"\n\t${ESPSECUREPY} digest_private_key "
"\n\t${espsecurepy} digest_private_key "
"--keylen (192/256) --keyfile KEYFILE "
"${secure_bootloader_key}")
endif()
@ -78,14 +76,14 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}"
COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}"
-o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin"
DEPENDS gen_secure_bootloader_key "${CMAKE_BINARY_DIR}/bootloader.bin"
DEPENDS gen_secure_bootloader_key gen_project_binary
VERBATIM)
add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}")
endif()
if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
add_custom_command(TARGET bootloader POST_BUILD
add_custom_command(TARGET bootloader.elf POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo
@ -97,9 +95,8 @@ if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
COMMAND ${CMAKE_COMMAND} -E echo
"* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device"
VERBATIM)
elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
add_custom_command(TARGET bootloader POST_BUILD
add_custom_command(TARGET bootloader.elf POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo

View file

@ -19,40 +19,6 @@ if(BOOTLOADER_BUILD)
"src/${IDF_TARGET}/flash_encrypt.c"
"src/${IDF_TARGET}/secure_boot_signatures.c"
"src/${IDF_TARGET}/secure_boot.c")
if(CONFIG_SECURE_SIGNED_APPS)
get_filename_component(secure_boot_verification_key
"signature_verification_key.bin"
ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}")
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
add_custom_command(OUTPUT "${secure_boot_verification_key}"
COMMAND ${ESPSECUREPY}
extract_public_key --keyfile "${secure_boot_signing_key}"
"${secure_boot_verification_key}"
DEPENDS gen_secure_boot_signing_key
VERBATIM)
else()
get_filename_component(orig_secure_boot_verification_key
"${CONFIG_SECURE_BOOT_VERIFICATION_KEY}"
ABSOLUTE BASE_DIR "${main_project_path}")
if(NOT EXISTS ${orig_secure_boot_verification_key})
message(FATAL_ERROR
"Secure Boot Verification Public Key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} does not exist."
"\nThis can be extracted from the private signing key."
"\nSee docs/security/secure-boot.rst for details.")
endif()
add_custom_command(OUTPUT "${secure_boot_verification_key}"
COMMAND ${CMAKE_COMMAND} -E copy "${orig_secure_boot_verification_key}"
"${secure_boot_verification_key}"
DEPENDS "${orig_secure_boot_verification_key}"
VERBATIM)
endif()
set(embed_files "${secure_boot_verification_key}")
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${secure_boot_verification_key}")
endif()
else()
list(APPEND srcs
"src/idf/bootloader_sha.c"
@ -67,5 +33,33 @@ idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${include_dirs}"
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
REQUIRES "${requires}"
PRIV_REQUIRES "${priv_requires}"
EMBED_FILES "${embed_files}")
PRIV_REQUIRES "${priv_requires}")
if(BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS)
# Whether CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES or not, we need verification key to embed
# in the library.
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
# We generate the key from the signing key. The signing key is passed from the main project.
get_filename_component(secure_boot_signing_key
"${SECURE_BOOT_SIGNING_KEY}"
ABSOLUTE BASE_DIR "${project_dir}")
get_filename_component(secure_boot_verification_key
"signature_verification_key.bin"
ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
add_custom_command(OUTPUT "${secure_boot_verification_key}"
COMMAND ${ESPSECUREPY}
extract_public_key --keyfile "${secure_boot_signing_key}"
"${secure_boot_verification_key}"
VERBATIM)
else()
# We expect to 'inherit' the verification key passed from main project.
get_filename_component(secure_boot_verification_key
${SECURE_BOOT_VERIFICATION_KEY}
ABSOLUTE BASE_DIR "${project_dir}")
endif()
target_add_binary_data(${COMPONENT_LIB} "${secure_boot_verification_key}" "BINARY")
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${secure_boot_verification_key}")
endif()

View file

@ -53,7 +53,7 @@ if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION)
COMMAND ${CMAKE_OBJCOPY} -O binary phy_init_data.obj ${phy_init_data_bin}
)
add_custom_target(phy_init_data ALL DEPENDS ${phy_init_data_bin})
add_dependencies(app phy_init_data)
add_dependencies(flash phy_init_data)
esptool_py_flash_project_args(phy ${phy_partition_offset} ${phy_init_data_bin} FLASH_IN_PROJECT)
endif()

View file

@ -1,50 +1,72 @@
idf_component_register(REQUIRES bootloader)
string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS}")
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS
"${ESPTOOLPY_FLASH_PROJECT_OPTIONS}"
)
if(NOT BOOTLOADER_BUILD)
string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_FLASH_OPTIONS}")
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS
"${ESPTOOLPY_FLASH_PROJECT_OPTIONS}"
)
if(CONFIG_SECURE_BOOT_ENABLED)
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS "")
if(CONFIG_SECURE_BOOT_ENABLED)
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS "")
endif()
# Generate the flash project args and the flasher args json file using the accumulated values
# from esptool_py_flash_project_args calls. The file is first configured using configure_file() for all variable values,
# and then generated using file(GENERATE... for generator expressions.
configure_file(${COMPONENT_DIR}/flash_project_args.in
${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in)
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flash_project_args
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2)
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
configure_file(${COMPONENT_DIR}/flash_encrypted_project_args.in
${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in2
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in)
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flash_encrypted_project_args
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in2)
endif()
configure_file(${COMPONENT_DIR}/flasher_args.json.in
${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in)
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flasher_args.json
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2)
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in"
"${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2"
"${CMAKE_BINARY_DIR}/flash_project_args"
"${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in"
"${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2"
"${CMAKE_BINARY_DIR}/flasher_args.json")
idf_build_get_property(build_dir BUILD_DIR)
partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset")
esptool_py_flash_project_args(app ${app_partition_offset} ${build_dir}/${PROJECT_BIN} FLASH_IN_PROJECT)
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_app_args.in "--encrypt ${app_partition_offset} ${PROJECT_BIN}")
esptool_py_flash_project_args(encrypted_app ${app_partition_offset} ${build_dir}/${PROJECT_BIN}
FLASH_FILE_TEMPLATE ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_app_args.in)
endif()
add_dependencies(flash partition_table)
# 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")
if(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK AND factory_offset)
fail_at_build_time(check_table_contents
"ERROR: Anti-rollback option is enabled. Partition table should consist of two ota app without factory partition.")
add_dependencies(app check_table_contents)
endif()
endif()
# Generate the flash project args and the flasher args json file using the accumulated values
# from esptool_py_flash_project_args calls. The file is first configured using configure_file() for all variable values,
# and then generated using file(GENERATE... for generator expressions.
configure_file(${COMPONENT_DIR}/flash_project_args.in
${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in)
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flash_project_args
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2)
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
configure_file(${COMPONENT_DIR}/flash_encrypted_project_args.in
${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in2
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in)
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flash_encrypted_project_args
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in2)
endif()
configure_file(${COMPONENT_DIR}/flasher_args.json.in
${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in)
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flasher_args.json
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2)
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in"
"${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2"
"${CMAKE_BINARY_DIR}/flash_project_args"
"${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in"
"${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2"
"${CMAKE_BINARY_DIR}/flasher_args.json")

View file

@ -31,7 +31,7 @@ else()
set(ESPTOOLPY_COMPRESSED_OPT -u)
endif()
set(ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS
set(ESPTOOLPY_FLASH_OPTIONS
--flash_mode ${ESPFLASHMODE}
--flash_freq ${ESPFLASHFREQ}
--flash_size ${ESPFLASHSIZE}
@ -40,19 +40,18 @@ set(ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS
# String for printing flash command
string(REPLACE ";" " " ESPTOOLPY_WRITE_FLASH_STR
"${ESPTOOLPY} --port (PORT) --baud (BAUD) --before ${ESPTOOLPY_BEFORE} --after ${ESPTOOLPY_AFTER} "
"write_flash ${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS} ${ESPTOOLPY_EXTRA_FLASH_OPTIONS} ${ESPTOOLPY_COMPRESSED_OPT}")
if(CONFIG_SECURE_BOOT_ENABLED AND
NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION AND
NOT BOOTLOADER_BUILD)
set(ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS
${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS} --secure-pad)
endif()
"write_flash ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_EXTRA_FLASH_OPTIONS} ${ESPTOOLPY_COMPRESSED_OPT}")
if(NOT BOOTLOADER_BUILD)
set(ESPTOOLPY_ELF2IMAGE_OPTIONS --elf-sha256-offset 0xb0)
endif()
if(CONFIG_SECURE_BOOT_ENABLED AND
NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION
AND NOT BOOTLOADER_BUILD)
set(ESPTOOLPY_ELF2IMAGE_OPTIONS ${ESPTOOLPY_ELF2IMAGE_OPTIONS} --secure-pad)
endif()
if(CONFIG_ESPTOOLPY_FLASHSIZE_DETECT)
# Set ESPFLASHSIZE to 'detect' *after* elf2image options are generated,
# as elf2image can't have 'detect' as an option...
@ -76,7 +75,7 @@ set(PROJECT_BIN "${elf_name}.bin")
# Add 'app.bin' target - generates with elf2image
#
add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS} ${ESPTOOLPY_ELF2IMAGE_OPTIONS}
COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_ELF2IMAGE_OPTIONS}
-o "${build_dir}/${unsigned_project_binary}" "${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"
@ -87,40 +86,42 @@ add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
)
add_custom_target(gen_project_binary DEPENDS "${build_dir}/.bin_timestamp")
if(NOT BOOTLOADER_BUILD AND
CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${build_dir}/${unsigned_project_binary}"
)
# for locally signed secure boot image, add a signing step to get from unsigned app to signed app
add_custom_command(OUTPUT "${build_dir}/.signed_bin_timestamp"
COMMAND ${ESPSECUREPY} sign_data --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)
endif()
add_custom_target(app ALL DEPENDS gen_project_binary)
if(NOT BOOTLOADER_BUILD)
add_custom_target(app ALL DEPENDS gen_project_binary)
else()
add_custom_target(bootloader ALL DEPENDS gen_project_binary)
endif()
if(NOT BOOTLOADER_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
add_custom_command(OUTPUT "${build_dir}/.signed_bin_timestamp"
COMMAND ${ESPSECUREPY} sign_data --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)
if(NOT BOOTLOADER_BUILD AND
CONFIG_SECURE_BOOT_ENABLED AND
NOT CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
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 ${build_dir}/${elf_bin}"
VERBATIM)
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
APPEND PROPERTY ADDITIONAL_MAKE_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 ${build_dir}/${PROJECT_BIN}"
VERBATIM)
endif()
endif()
#
@ -142,7 +143,6 @@ endfunction()
esptool_py_custom_target(flash project "app;partition_table;bootloader")
esptool_py_custom_target(app-flash app "app")
esptool_py_custom_target(bootloader-flash bootloader "bootloader")
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
esptool_py_custom_target(encrypted-flash encrypted_project "app;partition_table;bootloader")

View file

@ -40,19 +40,6 @@ add_custom_command(OUTPUT "${build_dir}/partition_table/${unsigned_partition_bin
DEPENDS ${partition_csv} "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py"
VERBATIM)
# Add signing steps
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
add_custom_target(gen_unsigned_partition_bin ALL DEPENDS
"${build_dir}/partition_table/${unsigned_partition_bin}")
add_custom_command(OUTPUT "${build_dir}/partition_table/${final_partition_bin}"
COMMAND ${ESPSECUREPY} sign_data --keyfile "${secure_boot_signing_key}"
-o "${build_dir}/partition_table/${final_partition_bin}"
"${build_dir}/partition_table/${unsigned_partition_bin}"
DEPENDS "${build_dir}/partition_table/${unsigned_partition_bin}"
VERBATIM)
endif()
if(EXISTS ${partition_csv})
add_custom_target(partition_table ALL DEPENDS "${build_dir}/partition_table/${final_partition_bin}")
else()
@ -64,29 +51,29 @@ else()
"Either change partition table in menuconfig or create this input file.")
endif()
if(CONFIG_SECURE_BOOT_ENABLED AND
NOT CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
add_custom_command(TARGET partition_table POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
"Partition table built but not signed. Sign partition data before flashing:"
COMMAND ${CMAKE_COMMAND} -E echo
"\t${ESPSECUREPY} sign_data --keyfile KEYFILE ${CMAKE_CURRENT_BINARY_DIR}/${final_partition_bin}"
VERBATIM)
endif()
# Add signing steps
if(CONFIG_SECURE_SIGNED_APPS)
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
add_custom_target(gen_unsigned_partition_bin ALL DEPENDS
"${build_dir}/partition_table/${unsigned_partition_bin}")
# 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")
if(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK AND factory_offset)
fail_at_build_time(check_table_contents
"ERROR: Anti-rollback option is enabled. Partition table should consist of two ota app without factory partition.")
add_dependencies(bootloader check_table_contents)
add_dependencies(app check_table_contents)
add_custom_command(OUTPUT "${build_dir}/partition_table/${final_partition_bin}"
COMMAND ${ESPSECUREPY} sign_data --keyfile "${SECURE_BOOT_SIGNING_KEY}"
-o "${build_dir}/partition_table/${final_partition_bin}"
"${build_dir}/partition_table/${unsigned_partition_bin}"
DEPENDS "${build_dir}/partition_table/${unsigned_partition_bin}"
VERBATIM)
else()
string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
add_custom_command(TARGET partition_table POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
"Partition table built but not signed. Sign partition data before flashing:"
COMMAND ${CMAKE_COMMAND} -E echo
"\t${espsecurepy} sign_data --keyfile KEYFILE ${build_dir}/partition_table/${final_partition_bin}"
VERBATIM)
endif()
endif()
add_dependencies(bootloader partition_table)
add_dependencies(app partition_table)
# Use global properties ESPTOOL_WRITE_FLASH_ARGS to pass this info to build
# the list of esptool write arguments for flashing
set_property(GLOBAL APPEND_STRING PROPERTY
@ -95,13 +82,3 @@ set_property(GLOBAL APPEND_STRING PROPERTY
esptool_py_flash_project_args(partition_table ${PARTITION_TABLE_OFFSET}
${build_dir}/partition_table/partition-table.bin FLASH_IN_PROJECT)
partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset")
esptool_py_flash_project_args(app ${app_partition_offset} ${build_dir}/${PROJECT_BIN} FLASH_IN_PROJECT)
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_app_args.in "--encrypt ${app_partition_offset} ${PROJECT_BIN}")
esptool_py_flash_project_args(encrypted_app ${app_partition_offset} ${build_dir}/${PROJECT_BIN}
FLASH_FILE_TEMPLATE ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_app_args.in)
endif()

View file

@ -2,8 +2,6 @@
The following features are not yet supported with the CMake-based build system:
- Eclipse IDE Documentation
- Secure Boot
- Flash Encryption
Support for these features will be available before CMake becomes the default build system.

View file

@ -488,6 +488,17 @@ endmenu\n" >> ${IDF_PATH}/Kconfig;
print_status "Can set -D twice: globally and for subcommand, only if values are the same"
idf.py -DAAA=BBB -DCCC=EEE build -DAAA=BBB -DCCC=EEE || failure "It should be allowed to set -D twice (globally and for subcommand) if values are the same"
print_status "Fail on build time works"
clean_build_dir
cp CMakeLists.txt CMakeLists.txt.bak
printf "\nif(NOT EXISTS \"\${CMAKE_CURRENT_LIST_DIR}/hello.txt\") \nfail_at_build_time(test_file \"hello.txt does not exists\") \nendif()" >> CMakeLists.txt
! idf.py build || failure "Build should fail if requirements are not satisfied"
touch hello.txt
idf.py build || failure "Build succeeds once requirements are satisfied"
rm -rf hello.txt CMakeLists.txt
mv CMakeLists.txt.bak CMakeLists.txt
rm -rf CMakeLists.txt.bak
print_status "All tests completed"
if [ -n "${FAILURES}" ]; then
echo "Some failures were detected:"

View file

@ -201,9 +201,15 @@ function(fail_at_build_time target_name message_line0)
foreach(message_line ${ARGN})
set(message_lines ${message_lines} COMMAND ${CMAKE_COMMAND} -E echo "${message_line}")
endforeach()
# Generate a timestamp file that gets included. When deleted on build, this forces CMake
# to rerun.
string(RANDOM filename)
set(filename "${CMAKE_CURRENT_BINARY_DIR}/${filename}.cmake")
file(WRITE "${filename}" "")
include("${filename}")
add_custom_target(${target_name} ALL
${message_lines}
COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/CMakeCache.txt"
COMMAND ${CMAKE_COMMAND} -E remove "${filename}"
COMMAND ${CMAKE_COMMAND} -P ${idf_path}/tools/cmake/scripts/fail.cmake
VERBATIM)
endfunction()